mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 1557645 - Clone OOP iframes in the right process. r=nika
This works, though probably we want to do some follow-up tweaks, like the adding of the onload blocker and so on, so that we can avoid the UpdateDimensions hack. We may also want a PrintObject in the nsPrintJob tree, perhaps... Differential Revision: https://phabricator.services.mozilla.com/D90310
This commit is contained in:
parent
3c91b4555b
commit
a4e300194a
@ -26,6 +26,7 @@
|
||||
#include "mozilla/MozPromiseInlines.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsFrameLoaderOwner.h"
|
||||
#include "nsGlobalWindowOuter.h"
|
||||
#include "nsIWebBrowserChrome.h"
|
||||
#include "nsNetUtil.h"
|
||||
@ -1078,7 +1079,9 @@ void CanonicalBrowsingContext::PendingRemotenessChange::Finish() {
|
||||
}
|
||||
|
||||
// Resume the pending load in our new process.
|
||||
newBrowser->ResumeLoad(mPendingSwitchId);
|
||||
if (mPendingSwitchId) {
|
||||
newBrowser->ResumeLoad(mPendingSwitchId);
|
||||
}
|
||||
|
||||
// We did it! The process switch is complete.
|
||||
mPromise->Resolve(newBrowser, __func__);
|
||||
@ -1148,6 +1151,9 @@ CanonicalBrowsingContext::ChangeRemoteness(const nsACString& aRemoteType,
|
||||
"Cannot replace BrowsingContext for subframes");
|
||||
MOZ_DIAGNOSTIC_ASSERT(aSpecificGroupId == 0 || aReplaceBrowsingContext,
|
||||
"Cannot specify group ID unless replacing BC");
|
||||
MOZ_DIAGNOSTIC_ASSERT(aPendingSwitchId || !IsTop(),
|
||||
"Should always have aPendingSwitchId for top-level "
|
||||
"frames");
|
||||
|
||||
if (!AncestorsAreCurrent()) {
|
||||
NS_WARNING("An ancestor context is no longer current");
|
||||
@ -1182,6 +1188,11 @@ CanonicalBrowsingContext::ChangeRemoteness(const nsACString& aRemoteType,
|
||||
// Switching to local. No new process, so perform switch sync.
|
||||
if (embedderBrowser &&
|
||||
aRemoteType.Equals(embedderBrowser->Manager()->GetRemoteType())) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
aPendingSwitchId,
|
||||
"We always have a PendingSwitchId, except for print-preview loads, "
|
||||
"which will never perform a process-switch to being in-process with "
|
||||
"their embedder");
|
||||
if (GetCurrentWindowGlobal()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(GetCurrentWindowGlobal()->IsProcessRoot());
|
||||
RefPtr<BrowserParent> oldBrowser =
|
||||
|
52
dom/base/AutoPrintEventDispatcher.h
Normal file
52
dom/base/AutoPrintEventDispatcher.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* -*- 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_dom_AutoPrintEventDispatcher_h
|
||||
#define mozilla_dom_AutoPrintEventDispatcher_h
|
||||
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class AutoPrintEventDispatcher {
|
||||
// NOTE(emilio): For fission iframes, we dispatch this event in
|
||||
// RecvCloneDocumentTreeIntoSelf.
|
||||
static void CollectInProcessSubdocuments(
|
||||
Document& aDoc, nsTArray<nsCOMPtr<Document>>& aDocs) {
|
||||
aDocs.AppendElement(&aDoc);
|
||||
auto recurse = [&aDocs](Document& aSubDoc) {
|
||||
CollectInProcessSubdocuments(aSubDoc, aDocs);
|
||||
return CallState::Continue;
|
||||
};
|
||||
aDoc.EnumerateSubDocuments(recurse);
|
||||
}
|
||||
|
||||
void DispatchEvent(bool aBefore) {
|
||||
for (nsCOMPtr<Document>& doc : mDocuments) {
|
||||
nsContentUtils::DispatchTrustedEvent(
|
||||
doc, doc->GetWindow(), aBefore ? u"beforeprint"_ns : u"afterprint"_ns,
|
||||
CanBubble::eNo, Cancelable::eNo, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit AutoPrintEventDispatcher(Document& aDoc) {
|
||||
if (!aDoc.IsStaticDocument()) {
|
||||
CollectInProcessSubdocuments(aDoc, mDocuments);
|
||||
}
|
||||
|
||||
DispatchEvent(true);
|
||||
}
|
||||
|
||||
~AutoPrintEventDispatcher() { DispatchEvent(false); }
|
||||
|
||||
AutoTArray<nsCOMPtr<Document>, 8> mDocuments;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif
|
@ -141,6 +141,7 @@ EXPORTS.mozilla.dom += [
|
||||
'AncestorIterator.h',
|
||||
'AnonymousContent.h',
|
||||
'Attr.h',
|
||||
'AutoPrintEventDispatcher.h',
|
||||
'BarProps.h',
|
||||
'BindContext.h',
|
||||
'BodyConsumer.h',
|
||||
|
@ -2754,6 +2754,23 @@ void nsFrameLoader::ActivateFrameEvent(const nsAString& aType, bool aCapture,
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsFrameLoader::DoRemoteStaticClone(nsFrameLoader* aStaticCloneOf) {
|
||||
MOZ_ASSERT(aStaticCloneOf->IsRemoteFrame());
|
||||
MOZ_DIAGNOSTIC_ASSERT(GetBrowsingContext());
|
||||
auto* cc = ContentChild::GetSingleton();
|
||||
if (!cc) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
|
||||
// TODO: Could possibly be implemented without too much effort.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
BrowsingContext* bcToClone = aStaticCloneOf->GetBrowsingContext();
|
||||
if (NS_WARN_IF(!bcToClone)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
cc->SendCloneDocumentTreeInto(bcToClone, GetBrowsingContext());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsFrameLoader::FinishStaticClone(
|
||||
nsFrameLoader* aStaticCloneOf, bool* aOutHasInProcessPrintCallbacks) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
@ -2772,10 +2789,6 @@ nsresult nsFrameLoader::FinishStaticClone(
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aStaticCloneOf->IsRemoteFrame())) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
MaybeCreateDocShell();
|
||||
RefPtr<nsDocShell> docShell = GetDocShell();
|
||||
NS_ENSURE_STATE(docShell);
|
||||
@ -2783,6 +2796,10 @@ nsresult nsFrameLoader::FinishStaticClone(
|
||||
nsCOMPtr<Document> kungFuDeathGrip = docShell->GetDocument();
|
||||
Unused << kungFuDeathGrip;
|
||||
|
||||
if (aStaticCloneOf->IsRemoteFrame()) {
|
||||
return DoRemoteStaticClone(aStaticCloneOf);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
docShell->GetContentViewer(getter_AddRefs(viewer));
|
||||
NS_ENSURE_STATE(viewer);
|
||||
|
@ -149,6 +149,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
||||
nsresult FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
||||
bool* aOutHasInProcessPrintCallbacks);
|
||||
|
||||
nsresult DoRemoteStaticClone(nsFrameLoader* aStaticCloneOf);
|
||||
|
||||
// WebIDL methods
|
||||
|
||||
nsDocShell* GetDocShell(mozilla::ErrorResult& aRv);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "mozilla/AntiTrackingUtils.h"
|
||||
#include "mozilla/ContentBlocking.h"
|
||||
#include "mozilla/dom/AutoPrintEventDispatcher.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/BrowsingContextBinding.h"
|
||||
@ -5207,31 +5208,6 @@ void nsGlobalWindowOuter::StopOuter(ErrorResult& aError) {
|
||||
}
|
||||
}
|
||||
|
||||
static CallState CollectDocuments(Document& aDoc,
|
||||
nsTArray<nsCOMPtr<Document>>& aDocs) {
|
||||
aDocs.AppendElement(&aDoc);
|
||||
auto recurse = [&aDocs](Document& aSubDoc) {
|
||||
return CollectDocuments(aSubDoc, aDocs);
|
||||
};
|
||||
aDoc.EnumerateSubDocuments(recurse);
|
||||
return CallState::Continue;
|
||||
}
|
||||
|
||||
static void DispatchPrintEventToWindowTree(Document& aDoc,
|
||||
const nsAString& aEvent) {
|
||||
if (aDoc.IsStaticDocument()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsCOMPtr<Document>> targets;
|
||||
CollectDocuments(aDoc, targets);
|
||||
for (nsCOMPtr<Document>& doc : targets) {
|
||||
nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent,
|
||||
CanBubble::eNo, Cancelable::eNo,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
static void SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode,
|
||||
bool aIsPrintingOrPP,
|
||||
@ -5442,9 +5418,7 @@ Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
|
||||
}
|
||||
|
||||
// TODO(emilio): Should dispatch this to OOP iframes too.
|
||||
DispatchPrintEventToWindowTree(*docToPrint, u"beforeprint"_ns);
|
||||
auto dispatchAfterPrint = MakeScopeExit(
|
||||
[&] { DispatchPrintEventToWindowTree(*docToPrint, u"afterprint"_ns); });
|
||||
AutoPrintEventDispatcher dispatcher(*docToPrint);
|
||||
|
||||
nsAutoScriptBlocker blockScripts;
|
||||
RefPtr<Document> clone =
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/TouchEvents.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/AutoPrintEventDispatcher.h"
|
||||
#include "mozilla/dom/BrowserBridgeChild.h"
|
||||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
@ -1012,6 +1013,52 @@ mozilla::ipc::IPCResult BrowserChild::RecvResumeLoad(
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvCloneDocumentTreeIntoSelf(
|
||||
const MaybeDiscarded<BrowsingContext>& aSourceBC) {
|
||||
if (NS_WARN_IF(aSourceBC.IsNullOrDiscarded())) {
|
||||
return IPC_OK();
|
||||
}
|
||||
nsCOMPtr<Document> sourceDocument = aSourceBC.get()->GetDocument();
|
||||
if (NS_WARN_IF(!sourceDocument)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
|
||||
if (NS_WARN_IF(!ourDocShell)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
ourDocShell->GetContentViewer(getter_AddRefs(cv));
|
||||
if (NS_WARN_IF(!cv)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
RefPtr<Document> clone;
|
||||
{
|
||||
AutoPrintEventDispatcher dispatcher(*sourceDocument);
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
bool hasInProcessCallbacks = false;
|
||||
clone = sourceDocument->CreateStaticClone(ourDocShell, cv,
|
||||
&hasInProcessCallbacks);
|
||||
if (NS_WARN_IF(!clone)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
}
|
||||
|
||||
// Since the clone document is not parsed-created, we need to initialize
|
||||
// layout manually. This is usually done in ReflowPrintObject for non-remote
|
||||
// documents.
|
||||
if (RefPtr<PresShell> ps = clone->GetPresShell()) {
|
||||
if (!ps->DidInitialize()) {
|
||||
nsresult rv = ps->Initialize();
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void BrowserChild::DoFakeShow(const ParentShowInfo& aParentShowInfo) {
|
||||
OwnerShowInfo ownerInfo{ScreenIntSize(), ScrollbarPreference::Auto,
|
||||
mParentIsActive, nsSizeMode_Normal};
|
||||
|
@ -260,6 +260,9 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
||||
mozilla::ipc::IPCResult RecvResumeLoad(const uint64_t& aPendingSwitchID,
|
||||
const ParentShowInfo&);
|
||||
|
||||
mozilla::ipc::IPCResult RecvCloneDocumentTreeIntoSelf(
|
||||
const MaybeDiscarded<BrowsingContext>& aSourceBC);
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
mozilla::ipc::IPCResult RecvShow(const ParentShowInfo&, const OwnerShowInfo&);
|
||||
|
||||
|
@ -3522,6 +3522,72 @@ bool ContentParent::CanOpenBrowser(const IPCTabContext& aContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CloneIsLegal(ContentParent* aCp, CanonicalBrowsingContext& aSource,
|
||||
CanonicalBrowsingContext& aTarget) {
|
||||
// Source and target must be in the same BCG
|
||||
if (NS_WARN_IF(aSource.Group() != aTarget.Group())) {
|
||||
return false;
|
||||
}
|
||||
// The source and target must be in different toplevel <browser>s
|
||||
if (NS_WARN_IF(aSource.Top() == aTarget.Top())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Neither source nor target must be toplevel.
|
||||
if (NS_WARN_IF(aSource.IsTop()) || NS_WARN_IF(aTarget.IsTop())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Both should be embedded by the same process.
|
||||
auto* sourceEmbedder = aSource.GetParentWindowContext();
|
||||
if (NS_WARN_IF(!sourceEmbedder) ||
|
||||
NS_WARN_IF(sourceEmbedder->GetContentParent() != aCp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* targetEmbedder = aSource.GetParentWindowContext();
|
||||
if (NS_WARN_IF(!targetEmbedder) ||
|
||||
NS_WARN_IF(targetEmbedder->GetContentParent() != aCp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All seems sane.
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvCloneDocumentTreeInto(
|
||||
const MaybeDiscarded<BrowsingContext>& aSource,
|
||||
const MaybeDiscarded<BrowsingContext>& aTarget) {
|
||||
if (aSource.IsNullOrDiscarded() || aTarget.IsNullOrDiscarded()) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
auto* source = aSource.get_canonical();
|
||||
auto* target = aTarget.get_canonical();
|
||||
|
||||
if (!CloneIsLegal(this, *source, *target)) {
|
||||
return IPC_FAIL(this, "Illegal subframe clone");
|
||||
}
|
||||
|
||||
ContentParent* cp = source->GetContentParent();
|
||||
if (NS_WARN_IF(!cp)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
target
|
||||
->ChangeRemoteness(cp->GetRemoteType(), /* aLoadID = */ 0,
|
||||
/* aReplaceBC = */ false, /* aSpecificGroupId = */ 0)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[source = RefPtr{source}](BrowserParent* aBp) {
|
||||
Unused << aBp->SendCloneDocumentTreeIntoSelf(source);
|
||||
},
|
||||
[](nsresult aRv) {
|
||||
NS_WARNING(nsPrintfCString("Remote clone failed: %x\n", aRv).get());
|
||||
});
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvConstructPopupBrowser(
|
||||
ManagedEndpoint<PBrowserParent>&& aBrowserEp,
|
||||
ManagedEndpoint<PWindowGlobalParent>&& aWindowEp, const TabId& aTabId,
|
||||
|
@ -902,6 +902,10 @@ class ContentParent final
|
||||
|
||||
bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*);
|
||||
|
||||
mozilla::ipc::IPCResult RecvCloneDocumentTreeInto(
|
||||
const MaybeDiscarded<BrowsingContext>& aSource,
|
||||
const MaybeDiscarded<BrowsingContext>& aTarget);
|
||||
|
||||
mozilla::ipc::IPCResult RecvConstructPopupBrowser(
|
||||
ManagedEndpoint<PBrowserParent>&& actor,
|
||||
ManagedEndpoint<PWindowGlobalParent>&& windowEp, const TabId& tabId,
|
||||
|
@ -614,6 +614,7 @@ child:
|
||||
async FlushTabState(uint32_t aFlushId, bool aIsFinal);
|
||||
async UpdateEpoch(uint32_t aEpoch);
|
||||
async UpdateSHistory(bool aImmediately);
|
||||
async CloneDocumentTreeIntoSelf(MaybeDiscardedBrowsingContext aBc);
|
||||
|
||||
parent:
|
||||
|
||||
|
@ -453,6 +453,12 @@ parent:
|
||||
WindowGlobalInit windowInit,
|
||||
uint32_t chromeFlags);
|
||||
|
||||
// TODO: Do I need to make this return something to watch for completion?
|
||||
// Guess we'll see how we end up triggering the actual print, for preview
|
||||
// this should be enough...
|
||||
async CloneDocumentTreeInto(MaybeDiscardedBrowsingContext aSourceBc,
|
||||
MaybeDiscardedBrowsingContext aTargetBc);
|
||||
|
||||
child:
|
||||
async ConstructBrowser(ManagedEndpoint<PBrowserChild> browserEp,
|
||||
ManagedEndpoint<PWindowGlobalChild> windowEp,
|
||||
|
@ -180,31 +180,33 @@ void nsSubDocumentFrame::ShowViewer() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PresContext()->IsDynamic()) {
|
||||
// We let the printing code take care of loading the document; just
|
||||
// create the inner view for it to use.
|
||||
RefPtr<nsFrameLoader> frameloader = FrameLoader();
|
||||
if (!frameloader) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!frameloader->IsRemoteFrame() && !PresContext()->IsDynamic()) {
|
||||
// We let the printing code take care of loading the document and
|
||||
// initializing the shell; just create the inner view for it to use.
|
||||
(void)EnsureInnerView();
|
||||
} else {
|
||||
RefPtr<nsFrameLoader> frameloader = FrameLoader();
|
||||
if (frameloader) {
|
||||
AutoWeakFrame weakThis(this);
|
||||
mCallingShow = true;
|
||||
bool didCreateDoc = frameloader->Show(this);
|
||||
if (!weakThis.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
mCallingShow = false;
|
||||
mDidCreateDoc = didCreateDoc;
|
||||
|
||||
if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
|
||||
frameloader->UpdatePositionAndSize(this);
|
||||
}
|
||||
|
||||
if (!weakThis.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
InvalidateFrame();
|
||||
AutoWeakFrame weakThis(this);
|
||||
mCallingShow = true;
|
||||
bool didCreateDoc = frameloader->Show(this);
|
||||
if (!weakThis.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
mCallingShow = false;
|
||||
mDidCreateDoc = didCreateDoc;
|
||||
|
||||
if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
|
||||
frameloader->UpdatePositionAndSize(this);
|
||||
}
|
||||
|
||||
if (!weakThis.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
InvalidateFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,7 +326,9 @@ static void WrapBackgroundColorInOwnLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
void nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) {
|
||||
if (!IsVisibleForPainting()) return;
|
||||
if (!IsVisibleForPainting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsFrameLoader* frameLoader = FrameLoader();
|
||||
bool isRemoteFrame = frameLoader && frameLoader->IsRemoteFrame();
|
||||
@ -920,15 +924,14 @@ void nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||
}
|
||||
|
||||
nsFrameLoader* nsSubDocumentFrame::FrameLoader() const {
|
||||
nsIContent* content = GetContent();
|
||||
if (!content) return nullptr;
|
||||
|
||||
if (!mFrameLoader) {
|
||||
RefPtr<nsFrameLoaderOwner> loaderOwner = do_QueryObject(content);
|
||||
if (loaderOwner) {
|
||||
mFrameLoader = loaderOwner->GetFrameLoader();
|
||||
}
|
||||
if (mFrameLoader) {
|
||||
return mFrameLoader;
|
||||
}
|
||||
|
||||
if (RefPtr<nsFrameLoaderOwner> loaderOwner = do_QueryObject(GetContent())) {
|
||||
mFrameLoader = loaderOwner->GetFrameLoader();
|
||||
}
|
||||
|
||||
return mFrameLoader;
|
||||
}
|
||||
|
||||
|
@ -278,6 +278,10 @@ static void BuildNestedPrintObjects(const UniquePtr<nsPrintObject>& aParentPO,
|
||||
|
||||
for (auto& bc : aParentPO->mDocShell->GetBrowsingContext()->Children()) {
|
||||
nsCOMPtr<nsIDocShell> docShell = bc->GetDocShell();
|
||||
if (!docShell) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<Document> doc = docShell->GetDocument();
|
||||
|
||||
auto childPO = MakeUnique<nsPrintObject>();
|
||||
|
Loading…
Reference in New Issue
Block a user