Merge inbound to mozilla-central. a=merge
authorNoemi Erli <nerli@mozilla.com>
Tue, 11 Jun 2019 00:47:19 +0300
changeset 478078 222e9db6edde5da6401c4894ea7b9ba3376434a8
parent 478077 28fa2a88940e67dfcc9247e928246b1064b6adc5 (current diff)
parent 478023 78a3f864177fe193bb6ee4a14b81cbe84e25435c (diff)
child 478079 2d8f311f6af36602162b984b8aa158bb21965c44
child 478148 7d6e39efd6d33030d75581e0b58bdcfde0943e27
push id113403
push usernerli@mozilla.com
push dateMon, 10 Jun 2019 21:55:07 +0000
treeherdermozilla-inbound@2d8f311f6af3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone69.0a1
first release with
nightly linux32
222e9db6edde / 69.0a1 / 20190610214846 / files
nightly linux64
222e9db6edde / 69.0a1 / 20190610214846 / files
nightly mac
222e9db6edde / 69.0a1 / 20190610214846 / files
nightly win32
222e9db6edde / 69.0a1 / 20190610214846 / files
nightly win64
222e9db6edde / 69.0a1 / 20190610214846 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -515,17 +515,19 @@ bool HTMLCanvasElement::IsPrintCallbackD
 HTMLCanvasElement* HTMLCanvasElement::GetOriginalCanvas() {
   return mOriginalCanvas ? mOriginalCanvas.get() : this;
 }
 
 nsresult HTMLCanvasElement::CopyInnerTo(HTMLCanvasElement* aDest) {
   nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
   NS_ENSURE_SUCCESS(rv, rv);
   if (aDest->OwnerDoc()->IsStaticDocument()) {
-    aDest->mOriginalCanvas = this;
+    // The Firefox print preview code can create a static clone from an
+    // existing static clone, so we may not be the original 'canvas' element.
+    aDest->mOriginalCanvas = GetOriginalCanvas();
 
     // We make sure that the canvas is not zero sized since that would cause
     // the DrawImage call below to return an error, which would cause printing
     // to fail.
     nsIntSize size = GetWidthHeight();
     if (size.height > 0 && size.width > 0) {
       nsCOMPtr<nsISupports> cxt;
       aDest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt));
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -4492,37 +4492,69 @@ Connection::FlushOp::FlushOp(Connection*
     : ConnectionDatastoreOperationBase(aConnection),
       mWriteOptimizer(std::move(aWriteOptimizer)),
       mShadowWrites(gShadowWrites) {}
 
 nsresult Connection::FlushOp::DoDatastoreWork() {
   AssertIsOnConnectionThread();
   MOZ_ASSERT(mConnection);
 
+  class MOZ_STACK_CLASS AutoDetach final {
+    nsCOMPtr<mozIStorageConnection> mConnection;
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+
+   public:
+    explicit AutoDetach(
+        mozIStorageConnection* aConnection MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+        : mConnection(aConnection) {
+      MOZ_ASSERT(aConnection);
+
+      MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+
+    ~AutoDetach() {
+      if (mConnection) {
+        nsresult rv = DetachShadowDatabase(mConnection);
+        Unused << NS_WARN_IF(NS_FAILED(rv));
+      }
+    }
+
+    void release() { mConnection = nullptr; }
+
+   private:
+    explicit AutoDetach(const AutoDetach&) = delete;
+    AutoDetach& operator=(const AutoDetach&) = delete;
+    AutoDetach& operator=(AutoDetach&&) = delete;
+  };
+
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
   nsCOMPtr<mozIStorageConnection> storageConnection =
       mConnection->StorageConnection();
   MOZ_ASSERT(storageConnection);
 
   nsresult rv;
 
   Maybe<MutexAutoLock> shadowDatabaseLock;
 
+  Maybe<AutoDetach> autoDetach;
+
   if (mShadowWrites) {
     MOZ_ASSERT(mConnection->mQuotaClient);
 
     shadowDatabaseLock.emplace(
         mConnection->mQuotaClient->ShadowDatabaseMutex());
 
     rv = AttachShadowDatabase(quotaManager->GetBasePath(), storageConnection);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
+
+    autoDetach.emplace(storageConnection);
   }
 
   CachedStatement stmt;
   rv = mConnection->GetCachedStatement(NS_LITERAL_CSTRING("BEGIN IMMEDIATE;"),
                                        &stmt);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -4562,21 +4594,25 @@ nsresult Connection::FlushOp::DoDatastor
   }
 
   rv = stmt->Execute();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (mShadowWrites) {
+    autoDetach->release();
+
     rv = DetachShadowDatabase(storageConnection);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
+    autoDetach.reset();
+
     shadowDatabaseLock.reset();
   }
 
   rv = usageJournalFile->Remove(false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -374,18 +374,16 @@ class nsDocumentViewer final : public ns
 
 #ifdef NS_PRINTING
   // Called when the DocViewer is notified that the state
   // of Printing or PP has changed
   void SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode,
                                    bool aIsPrintingOrPP, bool aStartAtTop);
 #endif  // NS_PRINTING
 
-  void ReturnToGalleyPresentation();
-
   // Whether we should attach to the top level widget. This is true if we
   // are sharing/recycling a single base widget and not creating multiple
   // child widgets.
   bool ShouldAttachToTopLevel();
 
  protected:
   // Returns the current viewmanager.  Might be null.
   nsViewManager* GetViewManager();
@@ -3623,17 +3621,17 @@ nsDocumentViewer::PrintPreview(nsIPrintS
   return rv;
 #  else
   return NS_ERROR_FAILURE;
 #  endif
 }
 
 //----------------------------------------------------------------------
 NS_IMETHODIMP
-nsDocumentViewer::PrintPreviewNavigate(int16_t aType, int32_t aPageNum) {
+nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
   if (!GetIsPrintPreview() || mPrintJob->GetIsCreatingPrintPreview())
     return NS_ERROR_FAILURE;
 
   nsIScrollableFrame* sf =
       mPrintJob->GetPrintPreviewPresShell()->GetRootScrollFrameAsScrollable();
   if (!sf) return NS_OK;
 
   // Check to see if we can short circut scrolling to the top
@@ -3757,24 +3755,77 @@ nsDocumentViewer::GetDocumentName(nsAStr
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::Cancel() {
   NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
   return mPrintJob->Cancel();
 }
 
+#  if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
+// Reset ESM focus for all descendent doc shells.
+static void ResetFocusState(nsIDocShell* aDocShell) {
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm) {
+    return;
+  }
+
+  nsCOMPtr<nsISimpleEnumerator> docShellEnumerator;
+  aDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent,
+                                   nsIDocShell::ENUMERATE_FORWARDS,
+                                   getter_AddRefs(docShellEnumerator));
+
+  nsCOMPtr<nsISupports> currentContainer;
+  bool hasMoreDocShells;
+  while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells)) &&
+         hasMoreDocShells) {
+    docShellEnumerator->GetNext(getter_AddRefs(currentContainer));
+    nsCOMPtr<nsPIDOMWindowOuter> win = do_GetInterface(currentContainer);
+    if (win) {
+      fm->ClearFocus(win);
+    }
+  }
+}
+#  endif  // NS_PRINTING && NS_PRINT_PREVIEW
+
 NS_IMETHODIMP
 nsDocumentViewer::ExitPrintPreview() {
-  if (GetIsPrinting()) return NS_ERROR_FAILURE;
   NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
 
-  if (GetIsPrintPreview()) {
-    ReturnToGalleyPresentation();
+  if (GetIsPrinting()) {
+    // Block exiting the print preview window if we're in the middle of an
+    // actual print.
+    return NS_ERROR_FAILURE;
+  }
+
+  if (!GetIsPrintPreview()) {
+    NS_ERROR("Wow, we should never get here!");
+    return NS_OK;
   }
+
+#  if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
+  mPrintJob->TurnScriptingOn(true);
+  mPrintJob->Destroy();
+  mPrintJob = nullptr;
+
+  // Nowadays we use a static clone document for printing, and print preview is
+  // in a separate tab that gets closed after print preview finishes.  Probably
+  // nothing below this line is necessary anymore.
+
+  SetIsPrintPreview(false);
+
+  nsCOMPtr<nsIDocShell> docShell(mContainer);
+  ResetFocusState(docShell);
+
+  SetTextZoom(mTextZoom);
+  SetFullZoom(mPageZoom);
+  SetOverrideDPPX(mOverrideDPPX);
+  Show();
+#  endif  // NS_PRINTING && NS_PRINT_PREVIEW
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) {
 #  ifdef NS_PRINTING
   NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages);
   NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
@@ -3971,65 +4022,16 @@ void nsDocumentViewer::IncrementDestroyB
   ++mDestroyBlockedCount;
 }
 
 void nsDocumentViewer::DecrementDestroyBlockedCount() {
   --mDestroyBlockedCount;
 }
 
 //------------------------------------------------------------
-
-#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
-//------------------------------------------------------------
-// Reset ESM focus for all descendent doc shells.
-static void ResetFocusState(nsIDocShell* aDocShell) {
-  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
-  if (!fm) return;
-
-  nsCOMPtr<nsISimpleEnumerator> docShellEnumerator;
-  aDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent,
-                                   nsIDocShell::ENUMERATE_FORWARDS,
-                                   getter_AddRefs(docShellEnumerator));
-
-  nsCOMPtr<nsISupports> currentContainer;
-  bool hasMoreDocShells;
-  while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells)) &&
-         hasMoreDocShells) {
-    docShellEnumerator->GetNext(getter_AddRefs(currentContainer));
-    nsCOMPtr<nsPIDOMWindowOuter> win = do_GetInterface(currentContainer);
-    if (win) fm->ClearFocus(win);
-  }
-}
-#endif  // NS_PRINTING && NS_PRINT_PREVIEW
-
-void nsDocumentViewer::ReturnToGalleyPresentation() {
-#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
-  if (!GetIsPrintPreview()) {
-    NS_ERROR("Wow, we should never get here!");
-    return;
-  }
-
-  SetIsPrintPreview(false);
-
-  mPrintJob->TurnScriptingOn(true);
-  mPrintJob->Destroy();
-  mPrintJob = nullptr;
-
-  nsCOMPtr<nsIDocShell> docShell(mContainer);
-  ResetFocusState(docShell);
-
-  SetTextZoom(mTextZoom);
-  SetFullZoom(mPageZoom);
-  SetOverrideDPPX(mOverrideDPPX);
-  Show();
-
-#endif  // NS_PRINTING && NS_PRINT_PREVIEW
-}
-
-//------------------------------------------------------------
 // This called ONLY when printing has completed and the DV
 // is being notified that it should get rid of the nsPrintJob.
 //
 // BUT, if we are in Print Preview then we want to ignore the
 // notification (we do not get rid of the nsPrintJob)
 //
 // One small caveat:
 //   This IS called from two places in this module for cleaning
--- a/layout/generic/nsPageSequenceFrame.cpp
+++ b/layout/generic/nsPageSequenceFrame.cpp
@@ -553,16 +553,24 @@ nsresult nsPageSequenceFrame::PrePrintNe
         if (!ctx) {
           continue;
         }
 
         // Initialize the context with the new DrawTarget.
         ctx->InitializeWithDrawTarget(nullptr, WrapNotNull(canvasTarget));
 
         // Start the rendering process.
+        // Note: Other than drawing to our CanvasRenderingContext2D, the
+        // callback cannot access or mutate our static clone document.  It is
+        // evaluated in its original context (the window of the original
+        // document) of course, and our canvas has a strong ref to the
+        // original HTMLCanvasElement (in mOriginalCanvas) so that if the
+        // callback calls GetCanvas() on our CanvasRenderingContext2D (passed
+        // to it via a MozCanvasPrintState argument) it will be given the
+        // original 'canvas' element.
         AutoWeakFrame weakFrame = this;
         canvas->DispatchPrintCallback(aCallback);
         NS_ENSURE_STATE(weakFrame.IsAlive());
       }
     }
   }
   uint32_t doneCounter = 0;
   for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0; i--) {
--- a/layout/printing/nsPrintJob.cpp
+++ b/layout/printing/nsPrintJob.cpp
@@ -810,25 +810,16 @@ nsresult nsPrintJob::DoCommonPrint(bool 
   // Check to see if there is a "regular" selection
   bool isSelection = IsThereARangeSelection(printData->mCurrentFocusWin);
 
   // Get the docshell for this documentviewer
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   {
-    if (aIsPrintPreview) {
-      nsCOMPtr<nsIContentViewer> viewer;
-      docShell->GetContentViewer(getter_AddRefs(viewer));
-      if (viewer && viewer->GetDocument() &&
-          viewer->GetDocument()->IsShowing()) {
-        viewer->GetDocument()->OnPageHide(false, nullptr);
-      }
-    }
-
     nsAutoScriptBlocker scriptBlocker;
     printData->mPrintObject = MakeUnique<nsPrintObject>();
     rv = printData->mPrintObject->InitAsRootObject(docShell, aSourceDoc,
                                                    aIsPrintPreview);
     NS_ENSURE_SUCCESS(rv, rv);
 
     NS_ENSURE_TRUE(
         printData->mPrintDocList.AppendElement(printData->mPrintObject.get()),
@@ -2627,26 +2618,16 @@ void nsPrintJob::SetIsPrinting(bool aIsP
 void nsPrintJob::SetIsPrintPreview(bool aIsPrintPreview) {
   mIsDoingPrintPreview = aIsPrintPreview;
 
   if (mDocViewerPrint) {
     mDocViewerPrint->SetIsPrintPreview(aIsPrintPreview);
   }
 }
 
-//---------------------------------------------------------------------
-void nsPrintJob::CleanupDocTitleArray(char16_t**& aArray, int32_t& aCount) {
-  for (int32_t i = aCount - 1; i >= 0; i--) {
-    free(aArray[i]);
-  }
-  free(aArray);
-  aArray = nullptr;
-  aCount = 0;
-}
-
 /** ---------------------------------------------------
  *  Get the Focused Frame for a documentviewer
  */
 already_AddRefed<nsPIDOMWindowOuter> nsPrintJob::FindFocusedDOMWindow() const {
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   NS_ENSURE_TRUE(fm, nullptr);
 
   nsPIDOMWindowOuter* window = mOriginalDoc->GetWindow();
--- a/layout/printing/nsPrintJob.h
+++ b/layout/printing/nsPrintJob.h
@@ -180,17 +180,16 @@ class nsPrintJob final : public nsIObser
   nsresult CleanupOnFailure(nsresult aResult, bool aIsPrinting);
   // If FinishPrintPreview() fails, caller may need to reset the state of the
   // object, for example by calling CleanupOnFailure().
   nsresult FinishPrintPreview();
   void SetURLAndTitleOnProgressParams(
       const mozilla::UniquePtr<nsPrintObject>& aPO,
       nsIPrintProgressParams* aParams);
   void EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront);
-  void CleanupDocTitleArray(char16_t**& aArray, int32_t& aCount);
 
   bool IsThereARangeSelection(nsPIDOMWindowOuter* aDOMWin);
 
   void FirePrintingErrorEvent(nsresult aPrintError);
   //---------------------------------------------------------------------
 
   // Timer Methods
   nsresult StartPagePrintTimer(const mozilla::UniquePtr<nsPrintObject>& aPO);
--- a/layout/printing/nsPrintObject.cpp
+++ b/layout/printing/nsPrintObject.cpp
@@ -60,16 +60,23 @@ nsPrintObject::~nsPrintObject() {
 
 //------------------------------------------------------------------
 nsresult nsPrintObject::InitAsRootObject(nsIDocShell* aDocShell, Document* aDoc,
                                          bool aForPrintPreview) {
   NS_ENSURE_STATE(aDocShell);
   NS_ENSURE_STATE(aDoc);
 
   if (aForPrintPreview) {
+    nsCOMPtr<nsIContentViewer> viewer;
+    aDocShell->GetContentViewer(getter_AddRefs(viewer));
+    if (viewer && viewer->GetDocument() && viewer->GetDocument()->IsShowing()) {
+      // We're about to discard this document, and it needs mIsShowing to be
+      // false to avoid triggering the assertion in its dtor.
+      viewer->GetDocument()->OnPageHide(false, nullptr);
+    }
     mDocShell = aDocShell;
   } else {
     // When doing an actual print, we create a BrowsingContext/nsDocShell that
     // is detached from any browser window or tab.
 
     // Create a new BrowsingContext to create our DocShell in.
     RefPtr<BrowsingContext> bc = BrowsingContext::Create(
         /* aParent */ nullptr,
--- a/toolkit/actors/PrintingChild.jsm
+++ b/toolkit/actors/PrintingChild.jsm
@@ -387,17 +387,17 @@ class PrintingChild extends ActorChild {
   updatePageCount() {
     let numPages = this.docShell.initOrReusePrintPreviewViewer().printPreviewNumPages;
     this.mm.sendAsyncMessage("Printing:Preview:UpdatePageCount", {
       numPages,
     });
   }
 
   navigate(navType, pageNum) {
-    this.docShell.initOrReusePrintPreviewViewer().printPreviewNavigate(navType, pageNum);
+    this.docShell.initOrReusePrintPreviewViewer().printPreviewScrollToPage(navType, pageNum);
   }
 }
 
 PrintingChild.prototype.QueryInterface =
   ChromeUtils.generateQI([Ci.nsIPrintingPromptService]);
 
 function PrintingListener(global) {
   this.global = global;
--- a/toolkit/components/browser/nsIWebBrowserPrint.idl
+++ b/toolkit/components/browser/nsIWebBrowserPrint.idl
@@ -97,23 +97,21 @@ interface nsIWebBrowserPrint : nsISuppor
    * @param aWPListener - is updated during the printpreview
    * @return void
    */
   void printPreview(in nsIPrintSettings aThePrintSettings,
                     in mozIDOMWindowProxy aChildDOMWin,
                     in nsIWebProgressListener aWPListener);
 
   /**
-   * Print Preview - Navigates within the window
-   *
    * @param aNavType - navigation enum
    * @param aPageNum - page num to navigate to when aNavType = ePrintPreviewGoToPageNum
    * @return void
    */
-  void printPreviewNavigate(in short aNavType, in long aPageNum);
+  void printPreviewScrollToPage(in short aNavType, in long aPageNum);
 
   /**
    * Cancels the current print
    * @return void
    */
   void cancel();
 
   /**
--- a/toolkit/components/printingui/ipc/PrintDataUtils.cpp
+++ b/toolkit/components/printingui/ipc/PrintDataUtils.cpp
@@ -81,17 +81,18 @@ MockWebBrowserPrint::Print(nsIPrintSetti
 NS_IMETHODIMP
 MockWebBrowserPrint::PrintPreview(nsIPrintSettings* aThePrintSettings,
                                   mozIDOMWindowProxy* aChildDOMWin,
                                   nsIWebProgressListener* aWPListener) {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-MockWebBrowserPrint::PrintPreviewNavigate(int16_t aNavType, int32_t aPageNum) {
+MockWebBrowserPrint::PrintPreviewScrollToPage(int16_t aNavType,
+                                              int32_t aPageNum) {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 MockWebBrowserPrint::Cancel() { return NS_ERROR_NOT_IMPLEMENTED; }
 
 NS_IMETHODIMP
 MockWebBrowserPrint::ExitPrintPreview() { return NS_ERROR_NOT_IMPLEMENTED; }
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -326,20 +326,21 @@ int GetDebugChildPauseTime() {
 }  // namespace
 
 nsresult XRE_InitChildProcess(int aArgc, char* aArgv[],
                               const XREChildData* aChildData) {
   NS_ENSURE_ARG_MIN(aArgc, 2);
   NS_ENSURE_ARG_POINTER(aArgv);
   NS_ENSURE_ARG_POINTER(aArgv[0]);
   MOZ_ASSERT(aChildData);
-  NS_SetCurrentThreadName("MainThread");
 
   recordreplay::Initialize(aArgc, aArgv);
 
+  NS_SetCurrentThreadName("MainThread");
+
 #ifdef MOZ_ASAN_REPORTER
   // In ASan reporter builds, we need to set ASan's log_path as early as
   // possible, so it dumps its errors into files there instead of using
   // the default stderr location. Since this is crucial for ASan reporter
   // to work at all (and we don't want people to use a non-functional
   // ASan reporter build), all failures while setting log_path are fatal.
   //
   // We receive this log_path via the ASAN_REPORTER_PATH environment variable