summaryrefslogtreecommitdiffstats
path: root/layout/printing/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'layout/printing/ipc')
-rw-r--r--layout/printing/ipc/PRemotePrintJob.ipdl58
-rw-r--r--layout/printing/ipc/RemotePrintJobChild.cpp155
-rw-r--r--layout/printing/ipc/RemotePrintJobChild.h61
-rw-r--r--layout/printing/ipc/RemotePrintJobParent.cpp244
-rw-r--r--layout/printing/ipc/RemotePrintJobParent.h84
5 files changed, 602 insertions, 0 deletions
diff --git a/layout/printing/ipc/PRemotePrintJob.ipdl b/layout/printing/ipc/PRemotePrintJob.ipdl
new file mode 100644
index 000000000..f6c1de895
--- /dev/null
+++ b/layout/printing/ipc/PRemotePrintJob.ipdl
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PPrinting;
+
+namespace mozilla {
+namespace layout {
+
+async protocol PRemotePrintJob
+{
+ manager PPrinting;
+
+both:
+ // Tell either side to abort printing and clean up.
+ async AbortPrint(nsresult aRv);
+
+parent:
+ // Initialize the real print device with the given information.
+ async InitializePrint(nsString aDocumentTitle, nsString aPrintToFile,
+ int32_t aStartPage, int32_t aEndPage);
+
+ // Translate the stored page recording and play back the events to the real
+ // print device.
+ async ProcessPage(nsCString aPageFileName);
+
+ // This informs the real print device that we've finished, so it can trigger
+ // the actual print.
+ async FinalizePrint();
+
+ // Report a state change to listeners in the parent process.
+ async StateChange(long aStateFlags,
+ nsresult aStatus);
+
+ // Report a progress change to listeners in the parent process.
+ async ProgressChange(long aCurSelfProgress,
+ long aMaxSelfProgress,
+ long aCurTotalProgress,
+ long aMaxTotalProgress);
+
+ // Report a status change to listeners in the parent process.
+ async StatusChange(nsresult aStatus);
+
+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();
+
+ async __delete__();
+};
+
+} // namespace layout
+} // namespace mozilla
diff --git a/layout/printing/ipc/RemotePrintJobChild.cpp b/layout/printing/ipc/RemotePrintJobChild.cpp
new file mode 100644
index 000000000..ffc3c2455
--- /dev/null
+++ b/layout/printing/ipc/RemotePrintJobChild.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RemotePrintJobChild.h"
+
+#include "mozilla/Unused.h"
+#include "nsPagePrintTimer.h"
+#include "nsPrintEngine.h"
+
+namespace mozilla {
+namespace layout {
+
+NS_IMPL_ISUPPORTS(RemotePrintJobChild,
+ nsIWebProgressListener)
+
+RemotePrintJobChild::RemotePrintJobChild()
+{
+ MOZ_COUNT_CTOR(RemotePrintJobChild);
+}
+
+nsresult
+RemotePrintJobChild::InitializePrint(const nsString& aDocumentTitle,
+ const nsString& aPrintToFile,
+ const int32_t& aStartPage,
+ const int32_t& aEndPage)
+{
+ // Print initialization can sometimes display a dialog in the parent, so we
+ // need to spin a nested event loop until initialization completes.
+ Unused << SendInitializePrint(aDocumentTitle, aPrintToFile, aStartPage,
+ aEndPage);
+ while (!mPrintInitialized) {
+ Unused << NS_ProcessNextEvent();
+ }
+
+ return mInitializationResult;
+}
+
+bool
+RemotePrintJobChild::RecvPrintInitializationResult(const nsresult& aRv)
+{
+ mPrintInitialized = true;
+ mInitializationResult = aRv;
+ return true;
+}
+
+void
+RemotePrintJobChild::ProcessPage(const nsCString& aPageFileName)
+{
+ MOZ_ASSERT(mPagePrintTimer);
+
+ mPagePrintTimer->WaitForRemotePrint();
+ Unused << SendProcessPage(aPageFileName);
+}
+
+bool
+RemotePrintJobChild::RecvPageProcessed()
+{
+ MOZ_ASSERT(mPagePrintTimer);
+
+ mPagePrintTimer->RemotePrintFinished();
+ return true;
+}
+
+bool
+RemotePrintJobChild::RecvAbortPrint(const nsresult& aRv)
+{
+ MOZ_ASSERT(mPrintEngine);
+
+ mPrintEngine->CleanupOnFailure(aRv, true);
+ return true;
+}
+
+void
+RemotePrintJobChild::SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer)
+{
+ MOZ_ASSERT(aPagePrintTimer);
+
+ mPagePrintTimer = aPagePrintTimer;
+}
+
+void
+RemotePrintJobChild::SetPrintEngine(nsPrintEngine* aPrintEngine)
+{
+ MOZ_ASSERT(aPrintEngine);
+
+ mPrintEngine = aPrintEngine;
+}
+
+// nsIWebProgressListener
+
+NS_IMETHODIMP
+RemotePrintJobChild::OnStateChange(nsIWebProgress* aProgress,
+ nsIRequest* aRequest, uint32_t aStateFlags,
+ nsresult aStatus)
+{
+ Unused << SendStateChange(aStateFlags, aStatus);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+RemotePrintJobChild::OnProgressChange(nsIWebProgress * aProgress,
+ nsIRequest * aRequest,
+ int32_t aCurSelfProgress,
+ int32_t aMaxSelfProgress,
+ int32_t aCurTotalProgress,
+ int32_t aMaxTotalProgress)
+{
+ Unused << SendProgressChange(aCurSelfProgress, aMaxSelfProgress,
+ aCurTotalProgress, aMaxTotalProgress);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+RemotePrintJobChild::OnLocationChange(nsIWebProgress* aProgress,
+ nsIRequest* aRequest, nsIURI* aURI,
+ uint32_t aFlags)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+RemotePrintJobChild::OnStatusChange(nsIWebProgress* aProgress,
+ nsIRequest* aRequest, nsresult aStatus,
+ const char16_t* aMessage)
+{
+ Unused << SendStatusChange(aStatus);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+RemotePrintJobChild::OnSecurityChange(nsIWebProgress* aProgress,
+ nsIRequest* aRequest, uint32_t aState)
+{
+ return NS_OK;
+}
+
+// End of nsIWebProgressListener
+
+RemotePrintJobChild::~RemotePrintJobChild()
+{
+ MOZ_COUNT_DTOR(RemotePrintJobChild);
+}
+
+void
+RemotePrintJobChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+ mPagePrintTimer = nullptr;
+ mPrintEngine = nullptr;
+}
+
+} // namespace layout
+} // namespace mozilla
diff --git a/layout/printing/ipc/RemotePrintJobChild.h b/layout/printing/ipc/RemotePrintJobChild.h
new file mode 100644
index 000000000..a316815ea
--- /dev/null
+++ b/layout/printing/ipc/RemotePrintJobChild.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_RemotePrintJobChild_h
+#define mozilla_layout_RemotePrintJobChild_h
+
+#include "mozilla/layout/PRemotePrintJobChild.h"
+
+#include "mozilla/RefPtr.h"
+#include "nsIWebProgressListener.h"
+
+class nsPagePrintTimer;
+class nsPrintEngine;
+
+namespace mozilla {
+namespace layout {
+
+class RemotePrintJobChild final : public PRemotePrintJobChild
+ , public nsIWebProgressListener
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEBPROGRESSLISTENER
+
+ RemotePrintJobChild();
+
+ void ActorDestroy(ActorDestroyReason aWhy) final;
+
+ nsresult InitializePrint(const nsString& aDocumentTitle,
+ const nsString& aPrintToFile,
+ const int32_t& aStartPage,
+ const int32_t& aEndPage);
+
+ bool RecvPrintInitializationResult(const nsresult& aRv) final;
+
+ void ProcessPage(const nsCString& aPageFileName);
+
+ bool RecvPageProcessed() final;
+
+ bool RecvAbortPrint(const nsresult& aRv) final;
+
+ void SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer);
+
+ void SetPrintEngine(nsPrintEngine* aPrintEngine);
+
+private:
+ ~RemotePrintJobChild() final;
+
+ bool mPrintInitialized = false;
+ nsresult mInitializationResult = NS_OK;
+ RefPtr<nsPagePrintTimer> mPagePrintTimer;
+ RefPtr<nsPrintEngine> mPrintEngine;
+};
+
+} // namespace layout
+} // namespace mozilla
+
+#endif // mozilla_layout_RemotePrintJobChild_h
diff --git a/layout/printing/ipc/RemotePrintJobParent.cpp b/layout/printing/ipc/RemotePrintJobParent.cpp
new file mode 100644
index 000000000..2f4dbd56e
--- /dev/null
+++ b/layout/printing/ipc/RemotePrintJobParent.cpp
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RemotePrintJobParent.h"
+
+#include <fstream>
+
+#include "gfxContext.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Unused.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsComponentManagerUtils.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsDeviceContext.h"
+#include "nsIDeviceContextSpec.h"
+#include "nsIPrintSettings.h"
+#include "nsIWebProgressListener.h"
+#include "PrintTranslator.h"
+
+namespace mozilla {
+namespace layout {
+
+RemotePrintJobParent::RemotePrintJobParent(nsIPrintSettings* aPrintSettings)
+ : mPrintSettings(aPrintSettings)
+{
+ MOZ_COUNT_CTOR(RemotePrintJobParent);
+}
+
+bool
+RemotePrintJobParent::RecvInitializePrint(const nsString& aDocumentTitle,
+ const nsString& aPrintToFile,
+ const int32_t& aStartPage,
+ const int32_t& aEndPage)
+{
+ nsresult rv = InitializePrintDevice(aDocumentTitle, aPrintToFile, aStartPage,
+ aEndPage);
+ if (NS_FAILED(rv)) {
+ Unused << SendPrintInitializationResult(rv);
+ Unused << Send__delete__(this);
+ return true;
+ }
+
+ mPrintTranslator.reset(new PrintTranslator(mPrintDeviceContext));
+ Unused << SendPrintInitializationResult(NS_OK);
+
+ return true;
+}
+
+nsresult
+RemotePrintJobParent::InitializePrintDevice(const nsString& aDocumentTitle,
+ const nsString& aPrintToFile,
+ const int32_t& aStartPage,
+ const int32_t& aEndPage)
+{
+ nsresult rv;
+ nsCOMPtr<nsIDeviceContextSpec> deviceContextSpec =
+ do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = deviceContextSpec->Init(nullptr, mPrintSettings, false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ mPrintDeviceContext = new nsDeviceContext();
+ rv = mPrintDeviceContext->InitForPrinting(deviceContextSpec);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = mPrintDeviceContext->BeginDocument(aDocumentTitle, aPrintToFile,
+ aStartPage, aEndPage);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+bool
+RemotePrintJobParent::RecvProcessPage(const nsCString& aPageFileName)
+{
+ nsresult rv = PrintPage(aPageFileName);
+
+ if (NS_FAILED(rv)) {
+ Unused << SendAbortPrint(rv);
+ } else {
+ Unused << SendPageProcessed();
+ }
+
+ return true;
+}
+
+nsresult
+RemotePrintJobParent::PrintPage(const nsCString& aPageFileName)
+{
+ MOZ_ASSERT(mPrintDeviceContext);
+
+ nsresult rv = mPrintDeviceContext->BeginPage();
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIFile> recordingFile;
+ rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
+ getter_AddRefs(recordingFile));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = recordingFile->AppendNative(aPageFileName);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsAutoCString recordingPath;
+ rv = recordingFile->GetNativePath(recordingPath);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ std::ifstream recording(recordingPath.get(), std::ifstream::binary);
+ if (!mPrintTranslator->TranslateRecording(recording)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = mPrintDeviceContext->EndPage();
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ recording.close();
+ rv = recordingFile->Remove(/* recursive= */ false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+bool
+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.
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "EndDocument failed");
+ }
+
+
+ Unused << Send__delete__(this);
+ return true;
+}
+
+bool
+RemotePrintJobParent::RecvAbortPrint(const nsresult& aRv)
+{
+ if (mPrintDeviceContext) {
+ Unused << mPrintDeviceContext->AbortDocument();
+ }
+
+ Unused << Send__delete__(this);
+ return true;
+}
+
+bool
+RemotePrintJobParent::RecvStateChange(const long& aStateFlags,
+ const nsresult& aStatus)
+{
+ uint32_t numberOfListeners = mPrintProgressListeners.Length();
+ for (uint32_t i = 0; i < numberOfListeners; ++i) {
+ nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
+ listener->OnStateChange(nullptr, nullptr, aStateFlags, aStatus);
+ }
+
+ return true;
+}
+
+bool
+RemotePrintJobParent::RecvProgressChange(const long& aCurSelfProgress,
+ const long& aMaxSelfProgress,
+ const long& aCurTotalProgress,
+ const long& aMaxTotalProgress)
+{
+ uint32_t numberOfListeners = mPrintProgressListeners.Length();
+ for (uint32_t i = 0; i < numberOfListeners; ++i) {
+ nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
+ listener->OnProgressChange(nullptr, nullptr,
+ aCurSelfProgress, aMaxSelfProgress,
+ aCurTotalProgress, aMaxTotalProgress);
+ }
+
+ return true;
+}
+
+bool
+RemotePrintJobParent::RecvStatusChange(const nsresult& aStatus)
+{
+ uint32_t numberOfListeners = mPrintProgressListeners.Length();
+ for (uint32_t i = 0; i < numberOfListeners; ++i) {
+ nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
+ listener->OnStatusChange(nullptr, nullptr, aStatus, nullptr);
+ }
+
+ return true;
+}
+
+void
+RemotePrintJobParent::RegisterListener(nsIWebProgressListener* aListener)
+{
+ MOZ_ASSERT(aListener);
+
+ mPrintProgressListeners.AppendElement(aListener);
+}
+
+already_AddRefed<nsIPrintSettings>
+RemotePrintJobParent::GetPrintSettings()
+{
+ nsCOMPtr<nsIPrintSettings> printSettings = mPrintSettings;
+ return printSettings.forget();
+}
+
+RemotePrintJobParent::~RemotePrintJobParent()
+{
+ MOZ_COUNT_DTOR(RemotePrintJobParent);
+}
+
+void
+RemotePrintJobParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+}
+
+} // namespace layout
+} // namespace mozilla
+
+
diff --git a/layout/printing/ipc/RemotePrintJobParent.h b/layout/printing/ipc/RemotePrintJobParent.h
new file mode 100644
index 000000000..a96cc7eaa
--- /dev/null
+++ b/layout/printing/ipc/RemotePrintJobParent.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_RemotePrintJobParent_h
+#define mozilla_layout_RemotePrintJobParent_h
+
+#include "mozilla/layout/PRemotePrintJobParent.h"
+
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
+
+class nsDeviceContext;
+class nsIPrintSettings;
+class nsIWebProgressListener;
+class PrintTranslator;
+
+namespace mozilla {
+namespace layout {
+
+class RemotePrintJobParent final : public PRemotePrintJobParent
+{
+public:
+ explicit RemotePrintJobParent(nsIPrintSettings* aPrintSettings);
+
+ void ActorDestroy(ActorDestroyReason aWhy) final;
+
+ bool RecvInitializePrint(const nsString& aDocumentTitle,
+ const nsString& aPrintToFile,
+ const int32_t& aStartPage,
+ const int32_t& aEndPage) final;
+
+ bool RecvProcessPage(const nsCString& aPageFileName) final;
+
+ bool RecvFinalizePrint() final;
+
+ bool RecvAbortPrint(const nsresult& aRv) final;
+
+ bool RecvStateChange(const long& aStateFlags,
+ const nsresult& aStatus) final;
+
+ bool RecvProgressChange(const long& aCurSelfProgress,
+ const long& aMaxSelfProgress,
+ const long& aCurTotalProgress,
+ const long& aMaxTotalProgress) final;
+
+ bool RecvStatusChange(const nsresult& aStatus) final;
+
+ /**
+ * Register a progress listener to receive print progress updates.
+ *
+ * @param aListener the progress listener to register. Must not be null.
+ */
+ void RegisterListener(nsIWebProgressListener* aListener);
+
+ /**
+ * @return the print settings for this remote print job.
+ */
+ already_AddRefed<nsIPrintSettings> GetPrintSettings();
+
+private:
+ ~RemotePrintJobParent() final;
+
+ nsresult InitializePrintDevice(const nsString& aDocumentTitle,
+ const nsString& aPrintToFile,
+ const int32_t& aStartPage,
+ const int32_t& aEndPage);
+
+ nsresult PrintPage(const nsCString& aPageFileName);
+
+ nsCOMPtr<nsIPrintSettings> mPrintSettings;
+ RefPtr<nsDeviceContext> mPrintDeviceContext;
+ UniquePtr<PrintTranslator> mPrintTranslator;
+ nsCOMArray<nsIWebProgressListener> mPrintProgressListeners;
+};
+
+} // namespace layout
+} // namespace mozilla
+
+#endif // mozilla_layout_RemotePrintJobParent_h