Bug 1339735 - send PDF file name and printing setting to Chrome process
MozReview-Commit-ID: 8d1KhraU0N6
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3799,16 +3799,66 @@ nsDocumentViewer::PrintPDF(const nsAStri
nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
if (xulDoc) {
PR_PL(("Printing XUL documents is not supported"));
return NS_ERROR_FAILURE;
}
nsresult rv = NS_ERROR_FAILURE;
+ // if we are printing another URL, then exit
+ // the reason we check here is because this method can be called while
+ // another is still in here (the printing dialog is a good example).
+ // the only time we can print more than one job at a time is the regression tests
+ if (GetIsPrinting()) {
+ // Let the user know we are not ready to print.
+ rv = NS_ERROR_NOT_AVAILABLE;
+
+ if (mPrintEngine) {
+ mPrintEngine->FirePrintingErrorEvent(rv);
+ }
+
+ return rv;
+ }
+
+ // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
+ MOZ_ASSERT(!mAutoBeforeAndAfterPrint,
+ "We don't want to dispatch nested beforeprint/afterprint");
+ nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint(
+ new AutoPrintEventDispatcher(mDocument));
+ NS_ENSURE_STATE(!GetIsPrinting());
+
+ if (!mPrintEngine) {
+ NS_ENSURE_STATE(mDeviceContext);
+ mPrintEngine = new nsPrintEngine();
+
+ rv = mPrintEngine->Initialize(this, mContainer, mDocument,
+ float(mDeviceContext->AppUnitsPerCSSInch()) /
+ float(mDeviceContext->AppUnitsPerDevPixel()) /
+ mPageZoom,
+#ifdef DEBUG
+ mDebugFile
+#else
+ nullptr
+#endif
+ );
+ if (NS_FAILED(rv)) {
+ mPrintEngine->Destroy();
+ mPrintEngine = nullptr;
+ return rv;
+ }
+ }
+
+ mAutoBeforeAndAfterPrint = autoBeforeAndAfterPrint;
+ mPrintEngine->SetDisallowSelectionPrint(false);
+ rv = mPrintEngine->PrintPDF(aPDFFileName, aPrintSettings);
+ if (NS_FAILED(rv)) {
+ OnDonePrinting();
+ }
+
return rv;
}
NS_IMETHODIMP
nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener)
{
// Printing XUL documents is not supported.
--- a/layout/printing/ipc/PRemotePrintJob.ipdl
+++ b/layout/printing/ipc/PRemotePrintJob.ipdl
@@ -38,21 +38,27 @@ parent:
async ProgressChange(long aCurSelfProgress,
long aMaxSelfProgress,
long aCurTotalProgress,
long aMaxTotalProgress);
// Report a status change to listeners in the parent process.
async StatusChange(nsresult aStatus);
+ // Send PDF file name to print
+ async ProcessPDF(nsCString aPDFFileName);
+
child:
// Inform the child that the print has been initialized in the parent or has
// failed with result aRv.
async PrintInitializationResult(nsresult aRv);
// Inform the child that the latest page has been processed remotely.
async PageProcessed();
+ // Inform the child that PDF has been printed remotely.
+ async PdfProcessed();
+
async __delete__();
};
} // namespace layout
} // namespace mozilla
--- a/layout/printing/ipc/RemotePrintJobChild.cpp
+++ b/layout/printing/ipc/RemotePrintJobChild.cpp
@@ -58,16 +58,31 @@ mozilla::ipc::IPCResult
RemotePrintJobChild::RecvPageProcessed()
{
MOZ_ASSERT(mPagePrintTimer);
mPagePrintTimer->RemotePrintFinished();
return IPC_OK();
}
+void
+RemotePrintJobChild::ProcessPDF(const nsCString& aPDFFileName)
+{
+ Unused << SendProcessPDF(aPDFFileName);
+}
+
+mozilla::ipc::IPCResult
+RemotePrintJobChild::RecvPdfProcessed()
+{
+ MOZ_ASSERT(mPrintEngine);
+
+ mPrintEngine->DonePrintingPDF();
+ return IPC_OK();
+}
+
mozilla::ipc::IPCResult
RemotePrintJobChild::RecvAbortPrint(const nsresult& aRv)
{
MOZ_ASSERT(mPrintEngine);
mPrintEngine->CleanupOnFailure(aRv, true);
return IPC_OK();
}
--- a/layout/printing/ipc/RemotePrintJobChild.h
+++ b/layout/printing/ipc/RemotePrintJobChild.h
@@ -41,16 +41,20 @@ public:
mozilla::ipc::IPCResult RecvPageProcessed() final;
mozilla::ipc::IPCResult RecvAbortPrint(const nsresult& aRv) final;
void SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer);
void SetPrintEngine(nsPrintEngine* aPrintEngine);
+ void ProcessPDF(const nsCString& aPDFFileName);
+
+ mozilla::ipc::IPCResult RecvPdfProcessed() final;
+
private:
~RemotePrintJobChild() final;
bool mPrintInitialized = false;
nsresult mInitializationResult = NS_OK;
RefPtr<nsPagePrintTimer> mPagePrintTimer;
RefPtr<nsPrintEngine> mPrintEngine;
};
--- a/layout/printing/ipc/RemotePrintJobParent.cpp
+++ b/layout/printing/ipc/RemotePrintJobParent.cpp
@@ -139,16 +139,25 @@ RemotePrintJobParent::PrintPage(const ns
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
mozilla::ipc::IPCResult
+RemotePrintJobParent::RecvProcessPDF(const nsCString& aFileName)
+{
+ // XXX TODO: call this in correct place where finish printing
+ Unused << SendPdfProcessed();
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
RemotePrintJobParent::RecvFinalizePrint()
{
// EndDocument is sometimes called in the child even when BeginDocument has
// not been called. See bug 1223332.
if (mPrintDeviceContext) {
DebugOnly<nsresult> rv = mPrintDeviceContext->EndDocument();
// Too late to abort the child just log.
--- a/layout/printing/ipc/RemotePrintJobParent.h
+++ b/layout/printing/ipc/RemotePrintJobParent.h
@@ -31,16 +31,18 @@ public:
mozilla::ipc::IPCResult RecvInitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage) final;
mozilla::ipc::IPCResult RecvProcessPage(const nsCString& aPageFileName) final;
+ mozilla::ipc::IPCResult RecvProcessPDF(const nsCString& aFileName) final;
+
mozilla::ipc::IPCResult RecvFinalizePrint() final;
mozilla::ipc::IPCResult RecvAbortPrint(const nsresult& aRv) final;
mozilla::ipc::IPCResult RecvStateChange(const long& aStateFlags,
const nsresult& aStatus) final;
mozilla::ipc::IPCResult RecvProgressChange(const long& aCurSelfProgress,
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -237,16 +237,18 @@ void nsPrintEngine::Destroy()
{
if (mIsDestroying) {
return;
}
mIsDestroying = true;
mPrt = nullptr;
+ mDevspec = nullptr;
+
#ifdef NS_PRINT_PREVIEW
mPrtPreview = nullptr;
mOldPrtPreview = nullptr;
#endif
mDocViewerPrint = nullptr;
}
//-------------------------------------------------------
@@ -756,16 +758,73 @@ nsPrintEngine::DoCommonPrint(bool
// We will enable scripting later after printing has finished.
scriptSuppressor.Disconnect();
return NS_OK;
}
//---------------------------------------------------------------------------------
NS_IMETHODIMP
+nsPrintEngine::PrintPDF(const nsAString& aPDFFileName,
+ nsIPrintSettings* aPrintSettings)
+{
+ SetIsPrinting(true);
+
+ nsresult rv;
+ nsCOMPtr<nsIPrintSession> printSession;
+ rv = aPrintSettings->GetPrintSession(getter_AddRefs(printSession));
+ if (NS_FAILED(rv) || !printSession) {
+ printSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ aPrintSettings->SetPrintSession(printSession);
+ }
+
+ bool printSilently = true;
+ aPrintSettings->SetPrintSilent(printSilently);
+
+ nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint));
+ NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER);
+ nsPIDOMWindowOuter* domWin = mDocument->GetWindow();
+ NS_ENSURE_TRUE(domWin, NS_ERROR_FAILURE);
+ nsCOMPtr<nsIPrintingPromptService> printPromptService(do_GetService(kPrintingPromptService));
+ if (printPromptService) {
+ rv = printPromptService->ShowPrintDialog(domWin, wbp, aPrintSettings);
+ if (rv == NS_ERROR_NOT_IMPLEMENTED) {
+ // This means the Dialog service was there,
+ // but they choose not to implement this dialog and
+ // are looking for default behavior from the toolkit
+ rv = NS_OK;
+ }
+ } else {
+ // No dialog service available
+ rv = NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ if (NS_FAILED(rv)) {
+ SetIsPrinting(false);
+ return rv;
+ }
+
+ RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
+ printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
+ if (NS_SUCCEEDED(rv) && remotePrintJob) {
+ remotePrintJob->SetPrintEngine(this);
+ } else {
+ SetIsPrinting(false);
+ return rv;
+ }
+
+ mDevspec = new nsDeviceContextSpecProxy();
+ mDevspec->Init(nullptr, aPrintSettings, false);
+ mDevspec->SendPDF(aPDFFileName);
+
+ return rv;
+}
+
+NS_IMETHODIMP
nsPrintEngine::Print(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener)
{
// If we have a print preview document, use that instead of the original
// mDocument. That way animated images etc. get printed using the same state
// as in print preview.
nsCOMPtr<nsIDOMDocument> doc =
do_QueryInterface(mPrtPreview && mPrtPreview->mPrintObject ?
@@ -3073,16 +3132,27 @@ nsPrintEngine::DonePrintingPages(nsPrint
// Release reference to mPagePrintTimer; the timer object destroys itself
// after this returns true
DisconnectPagePrintTimer();
return true;
}
+bool
+nsPrintEngine::DonePrintingPDF()
+{
+ PR_PL(("****** In DV::DonePrintingPDF \n"));
+
+ FirePrintCompletionEvent();
+ SetIsPrinting(false);
+
+ return true;
+}
+
//-------------------------------------------------------
// Recursively sets the PO items to be printed "As Is"
// from the given item down into the tree
void
nsPrintEngine::SetPrintAsIs(nsPrintObject* aPO, bool aAsIs)
{
NS_ASSERTION(aPO, "Pointer is null!");
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -60,16 +60,18 @@ public:
NS_IMETHOD GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected);
NS_IMETHOD GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages);
NS_IMETHOD EnumerateDocumentNames(uint32_t* aCount, char16_t*** aResult);
static nsresult GetGlobalPrintSettings(nsIPrintSettings** aPrintSettings);
NS_IMETHOD GetDoingPrint(bool *aDoingPrint);
NS_IMETHOD GetDoingPrintPreview(bool *aDoingPrintPreview);
NS_IMETHOD GetCurrentPrintSettings(nsIPrintSettings **aCurrentPrintSettings);
+ NS_IMETHOD PrintPDF(const nsAString& aPDFFileName,
+ nsIPrintSettings* aPrintSettings);
// This enum tells indicates what the default should be for the title
// if the title from the document is null
enum eDocTitleDefault {
eDocTitleDefBlank,
eDocTitleDefURLDoc
};
@@ -106,16 +108,17 @@ public:
bool CheckDocumentForPPCaching();
void InstallPrintPreviewListener();
// nsIDocumentViewerPrint Printing Methods
bool HasPrintCallbackCanvas();
bool PrePrintPage();
bool PrintPage(nsPrintObject* aPOect, bool& aInRange);
bool DonePrintingPages(nsPrintObject* aPO, nsresult aResult);
+ bool DonePrintingPDF();
//---------------------------------------------------------------------
void BuildDocTree(nsIDocShell * aParentNode,
nsTArray<nsPrintObject*> * aDocList,
nsPrintObject * aPO);
nsresult ReflowDocList(nsPrintObject * aPO, bool aSetPixelScale);
nsresult ReflowPrintObject(nsPrintObject * aPO);
@@ -273,16 +276,18 @@ protected:
FILE* mDebugFile;
int32_t mLoadCounter;
bool mDidLoadDataForPrinting;
bool mIsDestroying;
bool mDisallowSelectionPrint;
+ nsCOMPtr<nsIDeviceContextSpec> mDevspec;
+
nsresult AfterNetworkPrint(bool aHandleError);
nsresult SetRootView(nsPrintObject* aPO,
bool& aDoReturn,
bool& aDocumentIsTopLevel,
nsSize& aAdjSize);
nsView* GetParentViewForRoot();
bool DoSetPixelScale();
--- a/toolkit/components/printingui/ipc/PrintingParent.cpp
+++ b/toolkit/components/printingui/ipc/PrintingParent.cpp
@@ -113,25 +113,22 @@ PrintingParent::ShowPrintDialog(PBrowser
nsresult rv;
if (remotePrintJob) {
settings = remotePrintJob->GetPrintSettings();
} else {
rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(rv, rv);
}
- // We only want to use the print silently setting from the parent.
- bool printSilently;
- rv = settings->GetPrintSilent(&printSilently);
- NS_ENSURE_SUCCESS(rv, rv);
-
rv = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
NS_ENSURE_SUCCESS(rv, rv);
- rv = settings->SetPrintSilent(printSilently);
+ // We want to use the print silently setting from the child.
+ bool printSilently;
+ rv = settings->GetPrintSilent(&printSilently);
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLString printerName;
settings->GetPrinterName(getter_Copies(printerName));
#ifdef MOZ_X11
// Requesting the default printer name on Linux has been removed in the child,
// because it was causing a sandbox violation (see Bug 1329216).
// If no printer name is set at this point, use the print settings service
--- a/widget/android/nsDeviceContextAndroid.h
+++ b/widget/android/nsDeviceContextAndroid.h
@@ -23,14 +23,15 @@ public:
bool aIsPrintPreview) override;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;
NS_IMETHOD BeginPage() override { return NS_OK; }
NS_IMETHOD EndPage() override { return NS_OK; }
+ NS_IMETHOD SendPDF(const nsAString& aPDFFileName) override { return NS_OK; }
private:
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsIFile> mTempFile;
};
#endif // nsDeviceContextAndroid_h__
--- a/widget/cocoa/nsDeviceContextSpecX.h
+++ b/widget/cocoa/nsDeviceContextSpecX.h
@@ -25,16 +25,19 @@ public:
int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;
NS_IMETHOD BeginPage() override {
return NS_OK;
};
NS_IMETHOD EndPage() override {
return NS_OK;
};
+ NS_IMETHOD SendPDF(const nsAString& aPDFFileName) override {
+ return NS_OK;
+ };
void GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight);
protected:
virtual ~nsDeviceContextSpecX();
protected:
PMPrintSession mPrintSession; // printing context.
--- a/widget/gtk/nsDeviceContextSpecG.h
+++ b/widget/gtk/nsDeviceContextSpecG.h
@@ -35,16 +35,17 @@ public:
NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS,
bool aIsPrintPreview) override;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage, int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;
NS_IMETHOD BeginPage() override { return NS_OK; }
NS_IMETHOD EndPage() override { return NS_OK; }
+ NS_IMETHOD SendPDF(const nsAString& aPDFFileName) override { return NS_OK; }
protected:
virtual ~nsDeviceContextSpecGTK();
nsCOMPtr<nsPrintSettingsGTK> mPrintSettings;
bool mToPrinter : 1; /* If true, print to printer */
bool mIsPPreview : 1; /* If true, is print preview */
char mPath[PATH_MAX]; /* If toPrinter = false, dest file */
char mPrinter[256]; /* Printer name */
--- a/widget/nsDeviceContextSpecProxy.cpp
+++ b/widget/nsDeviceContextSpecProxy.cpp
@@ -225,8 +225,20 @@ NS_IMETHODIMP
nsDeviceContextSpecProxy::EndPage()
{
// Send the page recording to the parent.
mRecorder->Close();
mRemotePrintJob->ProcessPage(mRecordingFileName);
return NS_OK;
}
+
+NS_IMETHODIMP
+nsDeviceContextSpecProxy::SendPDF(const nsAString& aPDFFileName)
+{
+ nsCString pdfname;
+ AppendUTF16toUTF8(aPDFFileName, pdfname);
+ // Send the file name to the parent.
+ mRemotePrintJob->ProcessPDF(pdfname);
+
+ return NS_OK;
+}
+
--- a/widget/nsDeviceContextSpecProxy.h
+++ b/widget/nsDeviceContextSpecProxy.h
@@ -49,16 +49,18 @@ public:
NS_IMETHOD EndDocument() final;
NS_IMETHOD AbortDocument() final;
NS_IMETHOD BeginPage() final;
NS_IMETHOD EndPage() final;
+ NS_IMETHOD SendPDF(const nsAString& aPDFFileName) final;
+
private:
~nsDeviceContextSpecProxy() {}
nsresult CreateUniqueTempPath(nsACString& aFilePath);
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsIPrintSession> mPrintSession;
nsCOMPtr<nsIDeviceContextSpec> mRealDeviceContextSpec;
--- a/widget/nsIDeviceContextSpec.h
+++ b/widget/nsIDeviceContextSpec.h
@@ -73,13 +73,14 @@ public:
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) = 0;
NS_IMETHOD EndDocument() = 0;
NS_IMETHOD AbortDocument() { return EndDocument(); }
NS_IMETHOD BeginPage() = 0;
NS_IMETHOD EndPage() = 0;
+ NS_IMETHOD SendPDF(const nsAString& aPDFFileName) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDeviceContextSpec,
NS_IDEVICE_CONTEXT_SPEC_IID)
#endif
--- a/widget/windows/nsDeviceContextSpecWin.h
+++ b/widget/windows/nsDeviceContextSpecWin.h
@@ -27,16 +27,17 @@ public:
virtual already_AddRefed<PrintTarget> MakePrintTarget() final;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) override { return NS_OK; }
NS_IMETHOD EndDocument() override { return NS_OK; }
NS_IMETHOD BeginPage() override { return NS_OK; }
NS_IMETHOD EndPage() override { return NS_OK; }
+ NS_IMETHOD SendPDF(const nsAString& aPDFFileName) override { return NS_OK; }
NS_IMETHOD Init(nsIWidget* aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override;
float GetDPI() final;
float GetPrintingScale() final;
void GetDriverName(wchar_t *&aDriverName) const { aDriverName = mDriverName; }