Loading dom/clients/manager/ClientOpenWindowUtils.cpp +19 −19 Original line number Diff line number Diff line Loading @@ -406,38 +406,38 @@ RefPtr<ClientOpPromise> ClientOpenWindow(const ClientOpenWindowArgs& aArgs) { return promise.forget(); #endif // MOZ_WIDGET_ANDROID RefPtr<BrowsingContextCallbackReceivedPromise::Private> browsingContextReadyPromise = new BrowsingContextCallbackReceivedPromise::Private(__func__); RefPtr<nsIBrowsingContextReadyCallback> callback = new nsBrowsingContextReadyCallback(browsingContextReadyPromise); RefPtr<nsOpenWindowInfo> openInfo = new nsOpenWindowInfo(); openInfo->mBrowsingContextReadyCallback = callback; openInfo->mOriginAttributes = principal->OriginAttributesRef(); openInfo->mIsRemote = true; openInfo->OnBrowsingContextReady( [argsValidated, promise](BrowsingContext* aBC) { if (aBC) { WaitForLoad(argsValidated, aBC, promise); } else { // in case of failure, reject the original promise CopyableErrorResult result; result.ThrowTypeError("Unable to open window"); promise->Reject(result, __func__); } }); RefPtr<BrowsingContext> bc; ErrorResult errResult; OpenWindow(argsValidated, openInfo, getter_AddRefs(bc), errResult); if (NS_WARN_IF(errResult.Failed())) { // Reject the promise immediately without waiting for the callback. openInfo->mBrowsingContextReadyCallback = nullptr; promise->Reject(errResult, __func__); return promise; } // If we immediately got a BrowsingContext back, we can invoke the ready // callback ourselves. browsingContextReadyPromise->Then( GetCurrentSerialEventTarget(), __func__, [argsValidated, promise](const RefPtr<BrowsingContext>& aBC) { WaitForLoad(argsValidated, aBC, promise); }, [promise]() { // in case of failure, reject the original promise CopyableErrorResult result; result.ThrowTypeError("Unable to open window"); promise->Reject(result, __func__); }); if (bc) { if (nsCOMPtr cb = openInfo->mBrowsingContextReadyCallback.forget()) { cb->BrowsingContextReady(bc); } browsingContextReadyPromise->Resolve(bc, __func__); } return promise; } Loading dom/ipc/ContentParent.cpp +78 −74 Original line number Diff line number Diff line Loading @@ -5133,10 +5133,10 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( const bool& aForWindowDotPrint, nsIURI* aURIToLoad, const nsCString& aFeatures, const float& aFullZoom, BrowserParent* aNextRemoteBrowser, const nsString& aName, nsresult& aResult, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, bool aLoadURI, nsIContentSecurityPolicy* aCsp, const OriginAttributes& aOriginAttributes) { nsCOMPtr<nsIRemoteTab>& aNewRemoteTab, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, bool aLoadURI, nsIContentSecurityPolicy* aCsp, const OriginAttributes& aOriginAttributes) { // The content process should never be in charge of computing whether or // not a window should be private - the parent will do that. const uint32_t badFlags = nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW | Loading @@ -5156,7 +5156,6 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( openInfo->mOriginAttributes = aOriginAttributes; MOZ_ASSERT_IF(aForWindowDotPrint, aForPrinting); MOZ_ASSERT_IF(aSetOpener, !aLoadURI); RefPtr<BrowserParent> topParent = BrowserParent::GetFrom(aThisTab); while (topParent && topParent->GetBrowserBridgeParent()) { Loading Loading @@ -5255,8 +5254,16 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( } RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(el); if (NS_SUCCEEDED(aResult) && frameLoaderOwner) { MOZ_ASSERT_IF(aNextRemoteBrowser, BrowserParent::GetFrom(el) == aNextRemoteBrowser); RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); if (frameLoader) { aNewRemoteTab = frameLoader->GetRemoteTab(); // At this point, it's possible the inserted frameloader hasn't gone // through layout yet. To ensure that the dimensions that we send down // when telling the frameloader to display will be correct (instead of // falling back to a 10x10 default), we force layout if necessary to get // the most up-to-date dimensions. See bug 1358712 for details. frameLoader->ForceLayoutIfNecessary(); } } else if (NS_SUCCEEDED(aResult) && !frameLoaderOwner) { // Fall through to the normal window opening code path when there is no // window which we can open a new tab in. Loading @@ -5278,52 +5285,62 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( return IPC_OK(); } // If we're going to perform a load, pre-configure the nsDocShellLoadState // which we'll use to perform the load. We'll start the load from the // `OnBrowsingContextReady` callback when it's inserted into the DOM. RefPtr<nsDocShellLoadState> loadState; if (aURIToLoad && aLoadURI) { loadState = MakeRefPtr<nsDocShellLoadState>(aURIToLoad); loadState->SetReferrerInfo(aReferrerInfo); loadState->SetTriggeringPrincipal(aTriggeringPrincipal); loadState->SetCsp(aCsp); uint32_t loadFlags = nsIWebNavigation::LOAD_FLAGS_NONE; if (!aTriggeringPrincipal->IsSystemPrincipal()) { loadFlags |= nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD; } loadState->SetLoadFlags(loadFlags); } // Register a callback to be called when the newly created window is inserted // into the DOM. We'll use this to configure the BrowsingContext's name and // potentially start a load in it. openInfo->OnBrowsingContextReady( [aName, loadState, nextRemoteBrowser = RefPtr{aNextRemoteBrowser}]( BrowsingContext* aBrowsingContext) { if (NS_WARN_IF(!aBrowsingContext)) { return; aResult = pwwatch->OpenWindowWithRemoteTab(thisBrowserHost, aFeatures, aCalledFromJS, aFullZoom, openInfo, getter_AddRefs(aNewRemoteTab)); if (NS_WARN_IF(NS_FAILED(aResult))) { return IPC_OK(); } MOZ_ASSERT(aNewRemoteTab); RefPtr<BrowserHost> newBrowserHost = BrowserHost::GetFrom(aNewRemoteTab); RefPtr<BrowserParent> newBrowserParent = newBrowserHost->GetActor(); // At this point, it's possible the inserted frameloader hasn't gone through // layout yet. To ensure that the dimensions that we send down when telling // the frameloader to display will be correct (instead of falling back to a // 10x10 default), we force layout if necessary to get the most up-to-date // dimensions. See bug 1358712 for details. // // This involves doing a bit of gymnastics in order to get at the FrameLoader, // so we scope this to avoid polluting the main function scope. { nsCOMPtr<Element> frameElement = newBrowserHost->GetOwnerElement(); MOZ_ASSERT(frameElement); RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(frameElement); MOZ_ASSERT(frameLoaderOwner); RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); MOZ_ASSERT(frameLoader); frameLoader->ForceLayoutIfNecessary(); } MOZ_ASSERT_IF( nextRemoteBrowser, nextRemoteBrowser->GetBrowsingContext() == aBrowsingContext); // If we were passed a name for the window which would override the default, // we should send it down to the new tab. if (nsContentUtils::IsOverridingWindowName(aName)) { MOZ_ALWAYS_SUCCEEDS(aBrowsingContext->SetName(aName)); MOZ_ALWAYS_SUCCEEDS(newBrowserHost->GetBrowsingContext()->SetName(aName)); } if (loadState) { // Ensure that we've performed layout out the new window's browser // before we start loading in it. if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(aBrowsingContext->GetEmbedderElement())) { if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) { fl->ForceLayoutIfNecessary(); MOZ_ASSERT(newBrowserHost->GetBrowsingContext()->OriginAttributesRef() == aOriginAttributes); if (aURIToLoad && aLoadURI) { nsCOMPtr<mozIDOMWindowProxy> openerWindow; if (aSetOpener && topParent) { openerWindow = topParent->GetParentWindowOuter(); } nsCOMPtr<nsIBrowserDOMWindow> newBrowserDOMWin = newBrowserParent->GetBrowserDOMWindow(); if (NS_WARN_IF(!newBrowserDOMWin)) { aResult = NS_ERROR_ABORT; return IPC_OK(); } aBrowsingContext->LoadURI(loadState); RefPtr<BrowsingContext> bc; aResult = newBrowserDOMWin->OpenURI( aURIToLoad, openInfo, nsIBrowserDOMWindow::OPEN_CURRENTWINDOW, nsIBrowserDOMWindow::OPEN_NEW, aTriggeringPrincipal, aCsp, getter_AddRefs(bc)); } }); aResult = pwwatch->OpenWindowWithRemoteTab( thisBrowserHost, aFeatures, aCalledFromJS, aFullZoom, openInfo); return IPC_OK(); } Loading Loading @@ -5409,40 +5426,26 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindow( } } if (newTab->GetOwnerElement()) { return IPC_FAIL( this, "New BrowserParent must not have been inserted into the DOM"); } BrowserParent::AutoUseNewTab aunt(newTab); nsCOMPtr<nsIRemoteTab> newRemoteTab; int32_t openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW; mozilla::ipc::IPCResult ipcResult = CommonCreateWindow( aThisTab, parent, newBCOpenerId != 0, aChromeFlags, aCalledFromJS, aWidthSpecified, aForPrinting, aForPrintPreview, aURIToLoad, aFeatures, aFullZoom, newTab, VoidString(), rv, &cwi.windowOpened(), openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ false, aCsp, aOriginAttributes); aFullZoom, newTab, VoidString(), rv, newRemoteTab, &cwi.windowOpened(), openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ false, aCsp, aOriginAttributes); if (!ipcResult) { return ipcResult; } if (NS_WARN_IF(NS_FAILED(rv)) || !cwi.windowOpened()) { if (NS_WARN_IF(NS_FAILED(rv)) || !newRemoteTab) { return IPC_OK(); } // At this point, it's possible the inserted frameloader hasn't gone through // layout yet. To ensure that the dimensions that we send down when telling // the frameloader to display will be correct (instead of falling back to a // 10x10 default), we force layout if necessary to get the most up-to-date // dimensions. See bug 1358712 for details. RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(newTab->GetOwnerElement()); MOZ_DIAGNOSTIC_ASSERT(frameLoaderOwner, "The new tab must have been inserted"); RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); MOZ_DIAGNOSTIC_ASSERT(frameLoader, "The new tab should have a frameLoader"); frameLoader->ForceLayoutIfNecessary(); MOZ_ASSERT(BrowserHost::GetFrom(newRemoteTab.get()) == newTab->GetBrowserHost()); newTab->SwapFrameScriptsFrom(cwi.frameScripts()); newTab->MaybeShowFrame(); Loading Loading @@ -5473,7 +5476,8 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess( return IPC_OK(); } bool windowIsNew = true; nsCOMPtr<nsIRemoteTab> newRemoteTab; bool windowIsNew; int32_t openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW; // If we have enough data, check the schemes of the loader and loadee Loading Loading @@ -5506,9 +5510,9 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess( aThisTab, parent, /* aSetOpener = */ false, aChromeFlags, aCalledFromJS, aWidthSpecified, /* aForPrinting = */ false, /* aForPrintPreview = */ false, aURIToLoad, aFeatures, aFullZoom, /* aNextRemoteBrowser = */ nullptr, aName, rv, &windowIsNew, openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ true, aCsp, aOriginAttributes); /* aNextRemoteBrowser = */ nullptr, aName, rv, newRemoteTab, &windowIsNew, openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ true, aCsp, aOriginAttributes); if (!ipcResult) { return ipcResult; } Loading dom/ipc/ContentParent.h +2 −1 Original line number Diff line number Diff line Loading @@ -768,7 +768,8 @@ class ContentParent final const bool& aForWindowDotPrint, nsIURI* aURIToLoad, const nsCString& aFeatures, const float& aFullZoom, BrowserParent* aNextRemoteBrowser, const nsString& aName, nsresult& aResult, bool* aWindowIsNew, int32_t& aOpenLocation, nsresult& aResult, nsCOMPtr<nsIRemoteTab>& aNewRemoteTab, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, bool aLoadUri, nsIContentSecurityPolicy* aCsp, const OriginAttributes& aOriginAttributes); Loading toolkit/components/windowwatcher/nsOpenWindowInfo.cpp +23 −40 Original line number Diff line number Diff line Loading @@ -8,7 +8,6 @@ #include "mozilla/OriginAttributes.h" #include "mozilla/dom/ToJSValue.h" #include "mozilla/dom/BrowserParent.h" #include "nsThreadUtils.h" NS_IMPL_ISUPPORTS(nsOpenWindowInfo, nsIOpenWindowInfo) Loading Loading @@ -45,11 +44,11 @@ NS_IMETHODIMP nsOpenWindowInfo::GetScriptableOriginAttributes( return NS_OK; } const mozilla::OriginAttributes& nsOpenWindowInfo::GetOriginAttributes() { const OriginAttributes& nsOpenWindowInfo::GetOriginAttributes() { return mOriginAttributes; } mozilla::dom::BrowserParent* nsOpenWindowInfo::GetNextRemoteBrowser() { BrowserParent* nsOpenWindowInfo::GetNextRemoteBrowser() { return mNextRemoteBrowser; } Loading @@ -58,48 +57,32 @@ nsOpenWindowInfo::BrowsingContextReadyCallback() { return mBrowsingContextReadyCallback; } namespace { class nsBrowsingContextReadyCallback final : public nsIBrowsingContextReadyCallback { public: NS_DECL_ISUPPORTS NS_IMPL_ISUPPORTS(nsBrowsingContextReadyCallback, nsIBrowsingContextReadyCallback) explicit nsBrowsingContextReadyCallback( std::function<void(mozilla::dom::BrowsingContext*)>&& aCallback) : mCallback(aCallback) {} nsBrowsingContextReadyCallback::nsBrowsingContextReadyCallback( RefPtr<BrowsingContextCallbackReceivedPromise::Private> aPromise) : mPromise(std::move(aPromise)) {} NS_IMETHOD BrowsingContextReady(mozilla::dom::BrowsingContext* aBC) override { if (!mCallback) { return NS_OK; nsBrowsingContextReadyCallback::~nsBrowsingContextReadyCallback() { if (mPromise) { mPromise->Reject(NS_ERROR_FAILURE, __func__); } // Spin the event loop to make sure everything's been initialized before we // invoke the callback. NS_DispatchToMainThread(NS_NewRunnableFunction( "BrowsingContextReadyCallback", [callback = std::move(mCallback), bc = RefPtr{aBC}] { callback(bc); })); mCallback = nullptr; return NS_OK; mPromise = nullptr; } private: ~nsBrowsingContextReadyCallback() { BrowsingContextReady(nullptr); } std::function<void(mozilla::dom::BrowsingContext*)> mCallback; }; NS_IMPL_ISUPPORTS(nsBrowsingContextReadyCallback, nsIBrowsingContextReadyCallback) } // namespace nsresult nsOpenWindowInfo::OnBrowsingContextReady( std::function<void(mozilla::dom::BrowsingContext*)>&& aCallback) { if (mBrowsingContextReadyCallback) { return NS_ERROR_ALREADY_INITIALIZED; NS_IMETHODIMP nsBrowsingContextReadyCallback::BrowsingContextReady( BrowsingContext* aBC) { MOZ_DIAGNOSTIC_ASSERT(mPromise, "The 'browsing context ready' callback is null"); if (!mPromise) { return NS_OK; } if (aBC) { mPromise->Resolve(aBC, __func__); } else { mPromise->Reject(NS_ERROR_FAILURE, __func__); } mBrowsingContextReadyCallback = mozilla::MakeAndAddRef<nsBrowsingContextReadyCallback>( std::move(aCallback)); mPromise = nullptr; return NS_OK; } toolkit/components/windowwatcher/nsOpenWindowInfo.h +16 −3 Original line number Diff line number Diff line Loading @@ -27,11 +27,24 @@ class nsOpenWindowInfo : public nsIOpenWindowInfo { RefPtr<mozilla::dom::BrowsingContext> mParent; RefPtr<nsIBrowsingContextReadyCallback> mBrowsingContextReadyCallback; nsresult OnBrowsingContextReady( std::function<void(mozilla::dom::BrowsingContext*)>&& aCallback); private: virtual ~nsOpenWindowInfo() = default; }; class nsBrowsingContextReadyCallback : public nsIBrowsingContextReadyCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSIBROWSINGCONTEXTREADYCALLBACK explicit nsBrowsingContextReadyCallback( RefPtr<mozilla::dom::BrowsingContextCallbackReceivedPromise::Private> aPromise); private: virtual ~nsBrowsingContextReadyCallback(); RefPtr<mozilla::dom::BrowsingContextCallbackReceivedPromise::Private> mPromise; }; #endif // nsOpenWindowInfo_h Loading
dom/clients/manager/ClientOpenWindowUtils.cpp +19 −19 Original line number Diff line number Diff line Loading @@ -406,38 +406,38 @@ RefPtr<ClientOpPromise> ClientOpenWindow(const ClientOpenWindowArgs& aArgs) { return promise.forget(); #endif // MOZ_WIDGET_ANDROID RefPtr<BrowsingContextCallbackReceivedPromise::Private> browsingContextReadyPromise = new BrowsingContextCallbackReceivedPromise::Private(__func__); RefPtr<nsIBrowsingContextReadyCallback> callback = new nsBrowsingContextReadyCallback(browsingContextReadyPromise); RefPtr<nsOpenWindowInfo> openInfo = new nsOpenWindowInfo(); openInfo->mBrowsingContextReadyCallback = callback; openInfo->mOriginAttributes = principal->OriginAttributesRef(); openInfo->mIsRemote = true; openInfo->OnBrowsingContextReady( [argsValidated, promise](BrowsingContext* aBC) { if (aBC) { WaitForLoad(argsValidated, aBC, promise); } else { // in case of failure, reject the original promise CopyableErrorResult result; result.ThrowTypeError("Unable to open window"); promise->Reject(result, __func__); } }); RefPtr<BrowsingContext> bc; ErrorResult errResult; OpenWindow(argsValidated, openInfo, getter_AddRefs(bc), errResult); if (NS_WARN_IF(errResult.Failed())) { // Reject the promise immediately without waiting for the callback. openInfo->mBrowsingContextReadyCallback = nullptr; promise->Reject(errResult, __func__); return promise; } // If we immediately got a BrowsingContext back, we can invoke the ready // callback ourselves. browsingContextReadyPromise->Then( GetCurrentSerialEventTarget(), __func__, [argsValidated, promise](const RefPtr<BrowsingContext>& aBC) { WaitForLoad(argsValidated, aBC, promise); }, [promise]() { // in case of failure, reject the original promise CopyableErrorResult result; result.ThrowTypeError("Unable to open window"); promise->Reject(result, __func__); }); if (bc) { if (nsCOMPtr cb = openInfo->mBrowsingContextReadyCallback.forget()) { cb->BrowsingContextReady(bc); } browsingContextReadyPromise->Resolve(bc, __func__); } return promise; } Loading
dom/ipc/ContentParent.cpp +78 −74 Original line number Diff line number Diff line Loading @@ -5133,10 +5133,10 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( const bool& aForWindowDotPrint, nsIURI* aURIToLoad, const nsCString& aFeatures, const float& aFullZoom, BrowserParent* aNextRemoteBrowser, const nsString& aName, nsresult& aResult, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, bool aLoadURI, nsIContentSecurityPolicy* aCsp, const OriginAttributes& aOriginAttributes) { nsCOMPtr<nsIRemoteTab>& aNewRemoteTab, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, bool aLoadURI, nsIContentSecurityPolicy* aCsp, const OriginAttributes& aOriginAttributes) { // The content process should never be in charge of computing whether or // not a window should be private - the parent will do that. const uint32_t badFlags = nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW | Loading @@ -5156,7 +5156,6 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( openInfo->mOriginAttributes = aOriginAttributes; MOZ_ASSERT_IF(aForWindowDotPrint, aForPrinting); MOZ_ASSERT_IF(aSetOpener, !aLoadURI); RefPtr<BrowserParent> topParent = BrowserParent::GetFrom(aThisTab); while (topParent && topParent->GetBrowserBridgeParent()) { Loading Loading @@ -5255,8 +5254,16 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( } RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(el); if (NS_SUCCEEDED(aResult) && frameLoaderOwner) { MOZ_ASSERT_IF(aNextRemoteBrowser, BrowserParent::GetFrom(el) == aNextRemoteBrowser); RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); if (frameLoader) { aNewRemoteTab = frameLoader->GetRemoteTab(); // At this point, it's possible the inserted frameloader hasn't gone // through layout yet. To ensure that the dimensions that we send down // when telling the frameloader to display will be correct (instead of // falling back to a 10x10 default), we force layout if necessary to get // the most up-to-date dimensions. See bug 1358712 for details. frameLoader->ForceLayoutIfNecessary(); } } else if (NS_SUCCEEDED(aResult) && !frameLoaderOwner) { // Fall through to the normal window opening code path when there is no // window which we can open a new tab in. Loading @@ -5278,52 +5285,62 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( return IPC_OK(); } // If we're going to perform a load, pre-configure the nsDocShellLoadState // which we'll use to perform the load. We'll start the load from the // `OnBrowsingContextReady` callback when it's inserted into the DOM. RefPtr<nsDocShellLoadState> loadState; if (aURIToLoad && aLoadURI) { loadState = MakeRefPtr<nsDocShellLoadState>(aURIToLoad); loadState->SetReferrerInfo(aReferrerInfo); loadState->SetTriggeringPrincipal(aTriggeringPrincipal); loadState->SetCsp(aCsp); uint32_t loadFlags = nsIWebNavigation::LOAD_FLAGS_NONE; if (!aTriggeringPrincipal->IsSystemPrincipal()) { loadFlags |= nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD; } loadState->SetLoadFlags(loadFlags); } // Register a callback to be called when the newly created window is inserted // into the DOM. We'll use this to configure the BrowsingContext's name and // potentially start a load in it. openInfo->OnBrowsingContextReady( [aName, loadState, nextRemoteBrowser = RefPtr{aNextRemoteBrowser}]( BrowsingContext* aBrowsingContext) { if (NS_WARN_IF(!aBrowsingContext)) { return; aResult = pwwatch->OpenWindowWithRemoteTab(thisBrowserHost, aFeatures, aCalledFromJS, aFullZoom, openInfo, getter_AddRefs(aNewRemoteTab)); if (NS_WARN_IF(NS_FAILED(aResult))) { return IPC_OK(); } MOZ_ASSERT(aNewRemoteTab); RefPtr<BrowserHost> newBrowserHost = BrowserHost::GetFrom(aNewRemoteTab); RefPtr<BrowserParent> newBrowserParent = newBrowserHost->GetActor(); // At this point, it's possible the inserted frameloader hasn't gone through // layout yet. To ensure that the dimensions that we send down when telling // the frameloader to display will be correct (instead of falling back to a // 10x10 default), we force layout if necessary to get the most up-to-date // dimensions. See bug 1358712 for details. // // This involves doing a bit of gymnastics in order to get at the FrameLoader, // so we scope this to avoid polluting the main function scope. { nsCOMPtr<Element> frameElement = newBrowserHost->GetOwnerElement(); MOZ_ASSERT(frameElement); RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(frameElement); MOZ_ASSERT(frameLoaderOwner); RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); MOZ_ASSERT(frameLoader); frameLoader->ForceLayoutIfNecessary(); } MOZ_ASSERT_IF( nextRemoteBrowser, nextRemoteBrowser->GetBrowsingContext() == aBrowsingContext); // If we were passed a name for the window which would override the default, // we should send it down to the new tab. if (nsContentUtils::IsOverridingWindowName(aName)) { MOZ_ALWAYS_SUCCEEDS(aBrowsingContext->SetName(aName)); MOZ_ALWAYS_SUCCEEDS(newBrowserHost->GetBrowsingContext()->SetName(aName)); } if (loadState) { // Ensure that we've performed layout out the new window's browser // before we start loading in it. if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(aBrowsingContext->GetEmbedderElement())) { if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) { fl->ForceLayoutIfNecessary(); MOZ_ASSERT(newBrowserHost->GetBrowsingContext()->OriginAttributesRef() == aOriginAttributes); if (aURIToLoad && aLoadURI) { nsCOMPtr<mozIDOMWindowProxy> openerWindow; if (aSetOpener && topParent) { openerWindow = topParent->GetParentWindowOuter(); } nsCOMPtr<nsIBrowserDOMWindow> newBrowserDOMWin = newBrowserParent->GetBrowserDOMWindow(); if (NS_WARN_IF(!newBrowserDOMWin)) { aResult = NS_ERROR_ABORT; return IPC_OK(); } aBrowsingContext->LoadURI(loadState); RefPtr<BrowsingContext> bc; aResult = newBrowserDOMWin->OpenURI( aURIToLoad, openInfo, nsIBrowserDOMWindow::OPEN_CURRENTWINDOW, nsIBrowserDOMWindow::OPEN_NEW, aTriggeringPrincipal, aCsp, getter_AddRefs(bc)); } }); aResult = pwwatch->OpenWindowWithRemoteTab( thisBrowserHost, aFeatures, aCalledFromJS, aFullZoom, openInfo); return IPC_OK(); } Loading Loading @@ -5409,40 +5426,26 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindow( } } if (newTab->GetOwnerElement()) { return IPC_FAIL( this, "New BrowserParent must not have been inserted into the DOM"); } BrowserParent::AutoUseNewTab aunt(newTab); nsCOMPtr<nsIRemoteTab> newRemoteTab; int32_t openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW; mozilla::ipc::IPCResult ipcResult = CommonCreateWindow( aThisTab, parent, newBCOpenerId != 0, aChromeFlags, aCalledFromJS, aWidthSpecified, aForPrinting, aForPrintPreview, aURIToLoad, aFeatures, aFullZoom, newTab, VoidString(), rv, &cwi.windowOpened(), openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ false, aCsp, aOriginAttributes); aFullZoom, newTab, VoidString(), rv, newRemoteTab, &cwi.windowOpened(), openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ false, aCsp, aOriginAttributes); if (!ipcResult) { return ipcResult; } if (NS_WARN_IF(NS_FAILED(rv)) || !cwi.windowOpened()) { if (NS_WARN_IF(NS_FAILED(rv)) || !newRemoteTab) { return IPC_OK(); } // At this point, it's possible the inserted frameloader hasn't gone through // layout yet. To ensure that the dimensions that we send down when telling // the frameloader to display will be correct (instead of falling back to a // 10x10 default), we force layout if necessary to get the most up-to-date // dimensions. See bug 1358712 for details. RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(newTab->GetOwnerElement()); MOZ_DIAGNOSTIC_ASSERT(frameLoaderOwner, "The new tab must have been inserted"); RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); MOZ_DIAGNOSTIC_ASSERT(frameLoader, "The new tab should have a frameLoader"); frameLoader->ForceLayoutIfNecessary(); MOZ_ASSERT(BrowserHost::GetFrom(newRemoteTab.get()) == newTab->GetBrowserHost()); newTab->SwapFrameScriptsFrom(cwi.frameScripts()); newTab->MaybeShowFrame(); Loading Loading @@ -5473,7 +5476,8 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess( return IPC_OK(); } bool windowIsNew = true; nsCOMPtr<nsIRemoteTab> newRemoteTab; bool windowIsNew; int32_t openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW; // If we have enough data, check the schemes of the loader and loadee Loading Loading @@ -5506,9 +5510,9 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess( aThisTab, parent, /* aSetOpener = */ false, aChromeFlags, aCalledFromJS, aWidthSpecified, /* aForPrinting = */ false, /* aForPrintPreview = */ false, aURIToLoad, aFeatures, aFullZoom, /* aNextRemoteBrowser = */ nullptr, aName, rv, &windowIsNew, openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ true, aCsp, aOriginAttributes); /* aNextRemoteBrowser = */ nullptr, aName, rv, newRemoteTab, &windowIsNew, openLocation, aTriggeringPrincipal, aReferrerInfo, /* aLoadUri = */ true, aCsp, aOriginAttributes); if (!ipcResult) { return ipcResult; } Loading
dom/ipc/ContentParent.h +2 −1 Original line number Diff line number Diff line Loading @@ -768,7 +768,8 @@ class ContentParent final const bool& aForWindowDotPrint, nsIURI* aURIToLoad, const nsCString& aFeatures, const float& aFullZoom, BrowserParent* aNextRemoteBrowser, const nsString& aName, nsresult& aResult, bool* aWindowIsNew, int32_t& aOpenLocation, nsresult& aResult, nsCOMPtr<nsIRemoteTab>& aNewRemoteTab, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, bool aLoadUri, nsIContentSecurityPolicy* aCsp, const OriginAttributes& aOriginAttributes); Loading
toolkit/components/windowwatcher/nsOpenWindowInfo.cpp +23 −40 Original line number Diff line number Diff line Loading @@ -8,7 +8,6 @@ #include "mozilla/OriginAttributes.h" #include "mozilla/dom/ToJSValue.h" #include "mozilla/dom/BrowserParent.h" #include "nsThreadUtils.h" NS_IMPL_ISUPPORTS(nsOpenWindowInfo, nsIOpenWindowInfo) Loading Loading @@ -45,11 +44,11 @@ NS_IMETHODIMP nsOpenWindowInfo::GetScriptableOriginAttributes( return NS_OK; } const mozilla::OriginAttributes& nsOpenWindowInfo::GetOriginAttributes() { const OriginAttributes& nsOpenWindowInfo::GetOriginAttributes() { return mOriginAttributes; } mozilla::dom::BrowserParent* nsOpenWindowInfo::GetNextRemoteBrowser() { BrowserParent* nsOpenWindowInfo::GetNextRemoteBrowser() { return mNextRemoteBrowser; } Loading @@ -58,48 +57,32 @@ nsOpenWindowInfo::BrowsingContextReadyCallback() { return mBrowsingContextReadyCallback; } namespace { class nsBrowsingContextReadyCallback final : public nsIBrowsingContextReadyCallback { public: NS_DECL_ISUPPORTS NS_IMPL_ISUPPORTS(nsBrowsingContextReadyCallback, nsIBrowsingContextReadyCallback) explicit nsBrowsingContextReadyCallback( std::function<void(mozilla::dom::BrowsingContext*)>&& aCallback) : mCallback(aCallback) {} nsBrowsingContextReadyCallback::nsBrowsingContextReadyCallback( RefPtr<BrowsingContextCallbackReceivedPromise::Private> aPromise) : mPromise(std::move(aPromise)) {} NS_IMETHOD BrowsingContextReady(mozilla::dom::BrowsingContext* aBC) override { if (!mCallback) { return NS_OK; nsBrowsingContextReadyCallback::~nsBrowsingContextReadyCallback() { if (mPromise) { mPromise->Reject(NS_ERROR_FAILURE, __func__); } // Spin the event loop to make sure everything's been initialized before we // invoke the callback. NS_DispatchToMainThread(NS_NewRunnableFunction( "BrowsingContextReadyCallback", [callback = std::move(mCallback), bc = RefPtr{aBC}] { callback(bc); })); mCallback = nullptr; return NS_OK; mPromise = nullptr; } private: ~nsBrowsingContextReadyCallback() { BrowsingContextReady(nullptr); } std::function<void(mozilla::dom::BrowsingContext*)> mCallback; }; NS_IMPL_ISUPPORTS(nsBrowsingContextReadyCallback, nsIBrowsingContextReadyCallback) } // namespace nsresult nsOpenWindowInfo::OnBrowsingContextReady( std::function<void(mozilla::dom::BrowsingContext*)>&& aCallback) { if (mBrowsingContextReadyCallback) { return NS_ERROR_ALREADY_INITIALIZED; NS_IMETHODIMP nsBrowsingContextReadyCallback::BrowsingContextReady( BrowsingContext* aBC) { MOZ_DIAGNOSTIC_ASSERT(mPromise, "The 'browsing context ready' callback is null"); if (!mPromise) { return NS_OK; } if (aBC) { mPromise->Resolve(aBC, __func__); } else { mPromise->Reject(NS_ERROR_FAILURE, __func__); } mBrowsingContextReadyCallback = mozilla::MakeAndAddRef<nsBrowsingContextReadyCallback>( std::move(aCallback)); mPromise = nullptr; return NS_OK; }
toolkit/components/windowwatcher/nsOpenWindowInfo.h +16 −3 Original line number Diff line number Diff line Loading @@ -27,11 +27,24 @@ class nsOpenWindowInfo : public nsIOpenWindowInfo { RefPtr<mozilla::dom::BrowsingContext> mParent; RefPtr<nsIBrowsingContextReadyCallback> mBrowsingContextReadyCallback; nsresult OnBrowsingContextReady( std::function<void(mozilla::dom::BrowsingContext*)>&& aCallback); private: virtual ~nsOpenWindowInfo() = default; }; class nsBrowsingContextReadyCallback : public nsIBrowsingContextReadyCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSIBROWSINGCONTEXTREADYCALLBACK explicit nsBrowsingContextReadyCallback( RefPtr<mozilla::dom::BrowsingContextCallbackReceivedPromise::Private> aPromise); private: virtual ~nsBrowsingContextReadyCallback(); RefPtr<mozilla::dom::BrowsingContextCallbackReceivedPromise::Private> mPromise; }; #endif // nsOpenWindowInfo_h