diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 67d88f8e27e0..a04683fe87c1 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -11482,6 +11482,7 @@ void Document::Destroy() { } if (IsStaticDocument()) { + RemoveProperty(nsGkAtoms::printisfocuseddoc); RemoveProperty(nsGkAtoms::printselectionranges); } @@ -13118,11 +13119,39 @@ static nsINode* GetCorrespondingNodeInDocument(const nsINode* aOrigNode, static void CachePrintSelectionRanges(const Document& aSourceDoc, Document& aStaticClone) { MOZ_ASSERT(aStaticClone.IsStaticDocument()); + MOZ_ASSERT(!aStaticClone.GetProperty(nsGkAtoms::printisfocuseddoc)); MOZ_ASSERT(!aStaticClone.GetProperty(nsGkAtoms::printselectionranges)); + bool sourceDocIsStatic = aSourceDoc.IsStaticDocument(); + + // When the user opts to "Print Selection Only", the print code prefers any + // selection in the static clone corresponding to the focused frame. If this + // is that static clone, flag it for the printing code: + const bool isFocusedDoc = [&] { + if (sourceDocIsStatic) { + return bool(aSourceDoc.GetProperty(nsGkAtoms::printisfocuseddoc)); + } + nsPIDOMWindowOuter* window = aSourceDoc.GetWindow(); + if (!window) { + return false; + } + nsCOMPtr rootWindow = window->GetPrivateRoot(); + if (!rootWindow) { + return false; + } + nsCOMPtr focusedWindow; + nsFocusManager::GetFocusedDescendant(rootWindow, + nsFocusManager::eIncludeAllDescendants, + getter_AddRefs(focusedWindow)); + return focusedWindow && focusedWindow->GetExtantDoc() == &aSourceDoc; + }(); + if (isFocusedDoc) { + aStaticClone.SetProperty(nsGkAtoms::printisfocuseddoc, + reinterpret_cast(true)); + } + const Selection* origSelection = nullptr; const nsTArray>* origRanges = nullptr; - bool sourceDocIsStatic = aSourceDoc.IsStaticDocument(); if (sourceDocIsStatic) { origRanges = static_cast>*>( diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp index 2257f9772ac0..0ce2006885af 100644 --- a/layout/printing/nsPrintJob.cpp +++ b/layout/printing/nsPrintJob.cpp @@ -206,15 +206,14 @@ static bool IsParentAFrameSet(nsIDocShell* aParent) { * @param aPrintData nsPrintData for the current print, must not be null. */ static void BuildNestedPrintObjects(const UniquePtr& aParentPO, - const RefPtr& aFocusedDoc, RefPtr& aPrintData) { MOZ_ASSERT(aParentPO); MOZ_ASSERT(aPrintData); - // If aParentPO is for an iframe and its original document is focusedDoc then - // always set as the selection root. + // If aParentPO is for an iframe and its original document was the document + // that had focus then always set as the selection root. if (aParentPO->mFrameType == eIFrame && - aParentPO->mDocument->GetOriginalDocument() == aFocusedDoc) { + aParentPO->mDocument->GetProperty(nsGkAtoms::printisfocuseddoc)) { aPrintData->mSelectionRoot = aParentPO.get(); } else if (!aPrintData->mSelectionRoot && aParentPO->HasSelection()) { // If there is no focused iframe but there is a selection in one or more @@ -255,7 +254,7 @@ static void BuildNestedPrintObjects(const UniquePtr& aParentPO, } aPrintData->mPrintDocList.AppendElement(childPO.get()); - BuildNestedPrintObjects(childPO, aFocusedDoc, aPrintData); + BuildNestedPrintObjects(childPO, aPrintData); aParentPO->mKids.AppendElement(std::move(childPO)); } } @@ -496,9 +495,6 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview, printData->mPrintProgressListeners.AppendObject(aWebProgressListener); } - // Get the document from the currently focused window. - RefPtr focusedDoc = FindFocusedDocument(aDoc); - // Get the docshell for this documentviewer nsCOMPtr docShell(do_QueryReferent(mDocShell, &rv)); NS_ENSURE_SUCCESS(rv, rv); @@ -522,7 +518,7 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview, printData->mPrintObject->mFrameType = printData->mIsParentAFrameSet ? eFrameSet : eDoc; - BuildNestedPrintObjects(printData->mPrintObject, focusedDoc, printData); + BuildNestedPrintObjects(printData->mPrintObject, printData); } // The nsAutoScriptBlocker above will now have been destroyed, which may @@ -2074,47 +2070,6 @@ void nsPrintJob::SetIsPrintPreview(bool aIsPrintPreview) { } } -Document* nsPrintJob::FindFocusedDocument(Document* aDoc) const { - nsFocusManager* fm = nsFocusManager::GetFocusManager(); - NS_ENSURE_TRUE(fm, nullptr); - - nsPIDOMWindowOuter* window = aDoc->GetOriginalDocument()->GetWindow(); - NS_ENSURE_TRUE(window, nullptr); - - nsCOMPtr rootWindow = window->GetPrivateRoot(); - NS_ENSURE_TRUE(rootWindow, nullptr); - - nsCOMPtr focusedWindow; - nsFocusManager::GetFocusedDescendant(rootWindow, - nsFocusManager::eIncludeAllDescendants, - getter_AddRefs(focusedWindow)); - NS_ENSURE_TRUE(focusedWindow, nullptr); - - if (IsWindowsInOurSubTree(focusedWindow)) { - return focusedWindow->GetDoc(); - } - - return nullptr; -} - -//--------------------------------------------------------------------- -bool nsPrintJob::IsWindowsInOurSubTree(nsPIDOMWindowOuter* window) const { - if (window) { - nsCOMPtr ourDocShell(do_QueryReferent(mDocShell)); - if (ourDocShell) { - BrowsingContext* ourBC = ourDocShell->GetBrowsingContext(); - BrowsingContext* bc = window->GetBrowsingContext(); - while (bc) { - if (bc == ourBC) { - return true; - } - bc = bc->GetParent(); - } - } - } - return false; -} - //------------------------------------------------------- bool nsPrintJob::DonePrintingSheets(nsPrintObject* aPO, nsresult aResult) { // NS_ASSERTION(aPO, "Pointer is null!"); diff --git a/layout/printing/nsPrintJob.h b/layout/printing/nsPrintJob.h index 656f04a2c68b..461751aee84b 100644 --- a/layout/printing/nsPrintJob.h +++ b/layout/printing/nsPrintJob.h @@ -176,16 +176,6 @@ class nsPrintJob final : public nsIWebProgressListener, nsresult StartPagePrintTimer(const mozilla::UniquePtr& aPO); - bool IsWindowsInOurSubTree(nsPIDOMWindowOuter* aDOMWindow) const; - - /** - * @return The document from the focused windows for a document viewer. - * - * FIXME: This is somewhat unsound, this looks at the original document, which - * could've mutated after print was initiated. - */ - Document* FindFocusedDocument(Document* aDoc) const; - /// Customizes the behaviour of GetDisplayTitleAndURL. enum class DocTitleDefault : uint32_t { eDocURLElseFallback, eFallback }; @@ -243,13 +233,6 @@ class nsPrintJob final : public nsIWebProgressListener, void PageDone(nsresult aResult); - // The document that we were originally created for in order to print it or - // create a print preview of it. This may belong to mDocViewerPrint or may - // belong to a different docViewer in a different docShell. In reality, this - // also may not be the original document that the user selected to print (see - // the comment documenting Initialize() above). - RefPtr mOriginalDoc; - // The docViewer that owns us, and its docShell. nsCOMPtr mDocViewerPrint; nsWeakPtr mDocShell; diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py index e0432fff8789..f114d19eefae 100644 --- a/xpcom/ds/StaticAtoms.py +++ b/xpcom/ds/StaticAtoms.py @@ -1020,6 +1020,7 @@ STATIC_ATOMS = [ Atom("previewDiv", "preview-div"), Atom("primary", "primary"), Atom("print", "print"), + Atom("printisfocuseddoc", "printisfocuseddoc"), Atom("printselectionranges", "printselectionranges"), Atom("priority", "priority"), Atom("processingInstruction", "processing-instruction"),