Bug 1432651 part 2 - If nsPrintingProxy::ShowPrintDialog creates an RemotePrintJobChild, store it on the nsPrintJob. r=bobowen draft
authorJonathan Watt <jwatt@jwatt.org>
Tue, 23 Jan 2018 23:48:39 +0000
changeset 723865 91b5aa7fe7865714ea01a58fda367a0a0e9faa7c
parent 723864 2cbdf13fed2405243556aa27e7d1e12f1c71e049
child 723866 96259d00ef77f8606a5d84104bad78ec4055ebef
push id96561
push userjwatt@jwatt.org
push dateTue, 23 Jan 2018 23:51:24 +0000
reviewersbobowen
bugs1432651
milestone60.0a1
Bug 1432651 part 2 - If nsPrintingProxy::ShowPrintDialog creates an RemotePrintJobChild, store it on the nsPrintJob. r=bobowen Following on from part 1, the second of the two places where we can create an RemotePrintJobChild is under nsPrintingProxy::ShowPrintDialog. This patch makes nsPrintingProxy::ShowPrintDialog set the RemotePrintJobChild on the nsPrintJob for the print operation so that we can now get our RemotePrintJobChild from the nsPrintJob rather than from an nsIPrintSettings. Since nsPrintingProxy can't access the nsPrintJob directly, this patch adds methods to the XPIDL interface nsIWebBrowserPrint (implemented by the document's nsDocumentViewer) to pass the RemotePrintJobChild through to the nsPrintJob. This isn't ideal, but unfortunately it's hard to avoid since we use XPIDL heavily in the printing code to allow it to be scripted by the browser UI. MozReview-Commit-ID: CwJwGfCcUjZ
layout/base/nsDocumentViewer.cpp
layout/printing/nsPrintJob.h
toolkit/components/browser/nsIWebBrowserPrint.idl
toolkit/components/printingui/ipc/PrintDataUtils.cpp
toolkit/components/printingui/ipc/nsPrintingProxy.cpp
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3,16 +3,17 @@
 /* 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/. */
 
 /* container for a document and its presentation */
 
 #include "gfxContext.h"
 #include "mozilla/layout/RemotePrintJobChild.h"
+#include "mozilla/NotNull.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/ServoStyleSet.h"
 #include "nsAutoPtr.h"
 #include "nscore.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
@@ -4217,16 +4218,31 @@ nsDocumentViewer::ExitPrintPreview()
   NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
 
   if (GetIsPrintPreview()) {
     ReturnToGalleyPresentation();
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP_(layout::RemotePrintJobChild*)
+nsDocumentViewer::GetRemotePrintJob()
+{
+  return mPrintJob ? mPrintJob->GetRemotePrintJob() : nullptr;
+}
+
+NS_IMETHODIMP_(void)
+nsDocumentViewer::SetRemotePrintJob(layout::RemotePrintJobChild* aRemotePrintJob)
+{
+  MOZ_ASSERT(aRemotePrintJob);
+  MOZ_ASSERT(mPrintJob, "Don't call this unless we're printing");
+
+  mPrintJob->SetRemotePrintJob(WrapNotNull(aRemotePrintJob));
+}
+
 //----------------------------------------------------------------------------------
 // Enumerate all the documents for their titles
 NS_IMETHODIMP
 nsDocumentViewer::EnumerateDocumentNames(uint32_t* aCount,
                                            char16_t*** aResult)
 {
 #ifdef NS_PRINTING
   NS_ENSURE_ARG(aCount);
--- a/layout/printing/nsPrintJob.h
+++ b/layout/printing/nsPrintJob.h
@@ -2,16 +2,17 @@
 /* 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 nsPrintJob_h
 #define nsPrintJob_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/NotNull.h"
 #include "mozilla/UniquePtr.h"
 
 #include "nsCOMPtr.h"
 
 #include "nsPrintObject.h"
 #include "nsPrintData.h"
 #include "nsFrameList.h"
 #include "nsIFrame.h"
@@ -193,16 +194,27 @@ public:
     return mIsCreatingPrintPreview;
   }
 
   void SetDisallowSelectionPrint(bool aDisallowSelectionPrint)
   {
     mDisallowSelectionPrint = aDisallowSelectionPrint;
   }
 
+  RemotePrintJobChild* GetRemotePrintJob()
+  {
+    nsPrintData* data = mPrt ? mPrt : mPrtPreview;
+    return data ? data->mRemotePrintJob.get() : nullptr;
+  }
+  void SetRemotePrintJob(mozilla::NotNull<RemotePrintJobChild*> aRemotePrintJob)
+  {
+    (mPrt ? mPrt : mPrtPreview)->mRemotePrintJob = aRemotePrintJob;
+  }
+
+
 private:
   nsPrintJob& operator=(const nsPrintJob& aOther) = delete;
 
   ~nsPrintJob();
 
   nsresult CommonPrint(bool aIsPrintPreview, nsIPrintSettings* aPrintSettings,
                        nsIWebProgressListener* aWebProgressListener,
                        RemotePrintJobChild* aRemotePrintJob,
--- a/toolkit/components/browser/nsIWebBrowserPrint.idl
+++ b/toolkit/components/browser/nsIWebBrowserPrint.idl
@@ -138,16 +138,29 @@ interface nsIWebBrowserPrint : nsISuppor
 
   /**
    * Cancels the current print 
    * @return void
    */
   void cancel();
 
   /**
+   * Get our document's remote print job, if any.
+   */
+  [notxpcom] RemotePrintJobChildPtr getRemotePrintJob();
+
+  /**
+   * Set our document's remote print job.  The document viewer must already
+   * have an nsPrintJob before this is called, and the passed RemotePrintJob
+   * must not be null.  (We would crash if either of these invariantes were
+   * to be violated.)
+   */
+  [notxpcom] void setRemotePrintJob(in RemotePrintJobChildPtr aPrintJob);
+
+  /**
    * Returns an array of the names of all documents names (Title or URL)
    * and sub-documents. This will return a single item if the attr "isFramesetDocument" is false
    * and may return any number of items is "isFramesetDocument" is true
    *
    * @param  aCount - returns number of printers returned
    * @param  aResult - returns array of names
    * @return void
    */
--- a/toolkit/components/printingui/ipc/PrintDataUtils.cpp
+++ b/toolkit/components/printingui/ipc/PrintDataUtils.cpp
@@ -119,16 +119,27 @@ MockWebBrowserPrint::PrintPreviewNavigat
 }
 
 NS_IMETHODIMP
 MockWebBrowserPrint::Cancel()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP_(layout::RemotePrintJobChild*)
+MockWebBrowserPrint::GetRemotePrintJob()
+{
+  return nullptr;
+}
+
+NS_IMETHODIMP_(void)
+MockWebBrowserPrint::SetRemotePrintJob(layout::RemotePrintJobChild* aRemotePrintJob)
+{
+}
+
 NS_IMETHODIMP
 MockWebBrowserPrint::EnumerateDocumentNames(uint32_t* aCount,
                                             char16_t*** aResult)
 {
   *aCount = 0;
   *aResult = nullptr;
 
   if (mData.printJobName().IsEmpty()) {
--- a/toolkit/components/printingui/ipc/nsPrintingProxy.cpp
+++ b/toolkit/components/printingui/ipc/nsPrintingProxy.cpp
@@ -98,16 +98,23 @@ nsPrintingProxy::ShowPrintDialog(mozIDOM
     do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PrintData inSettings;
   rv = printSettingsSvc->SerializeToPrintData(printSettings, webBrowserPrint,
                                               &inSettings);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // If we already have a RemotePrintJobChild then we need to reuse the same
+  // one.  (If we don't have one, one will be created for us under the
+  // SendShowPrintDialog() call below.)
+  RemotePrintJobChild* remotePrintJob = webBrowserPrint->GetRemotePrintJob();
+
+  inSettings.remotePrintJobChild() = remotePrintJob;
+
   // Now, the waiting game. The parent process should be showing
   // the printing dialog soon. In the meantime, we need to spin a
   // nested event loop while we wait for the results of the dialog
   // to be returned to us.
 
   RefPtr<PrintSettingsDialogChild> dialog = new PrintSettingsDialogChild();
   SendPPrintSettingsDialogConstructor(dialog);
 
@@ -115,16 +122,24 @@ nsPrintingProxy::ShowPrintDialog(mozIDOM
 
   SpinEventLoopUntil([&, dialog]() { return dialog->returned(); });
 
   rv = dialog->result();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = printSettingsSvc->DeserializeToPrintSettings(dialog->data(),
                                                     printSettings);
+
+  if (!remotePrintJob) {
+    // Store the RemotePrintJobChild that was created under the
+    // SendShowPrintDialog() call so that we use the correct one in future:
+    webBrowserPrint->SetRemotePrintJob(
+      static_cast<RemotePrintJobChild*>(dialog->data().remotePrintJobChild()));
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPrintingProxy::ShowProgress(mozIDOMWindowProxy*      parent,
                               nsIWebBrowserPrint*      webBrowserPrint,    // ok to be null
                               nsIPrintSettings*        printSettings,      // ok to be null
                               nsIObserver*             openDialogObserver, // ok to be null