☠☠ backed out by 14f84d3b3233 ☠ ☠ | |
author | Michael Layzell <michael@thelayzells.com> |
Thu, 15 Jun 2017 13:28:11 -0400 | |
changeset 365251 | 2029cb6bce8660c14d9a98b74ab0e36c9adab4b6 |
parent 365250 | 0169e09f60304d074424804812ebe83c5372e2f5 |
child 365252 | 36d662fbab77e831c6c7bf0c3bd734020bb76a87 |
push id | 91717 |
push user | michael@thelayzells.com |
push date | Wed, 21 Jun 2017 18:23:40 +0000 |
treeherder | mozilla-inbound@44532a19e524 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | billm, smaug |
bugs | 1343728 |
milestone | 56.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -852,64 +852,144 @@ ContentChild::ProvideWindowCommon(TabChi PRenderFrameChild* renderFrame = newChild->SendPRenderFrameConstructor(); TextureFactoryIdentifier textureFactoryIdentifier; uint64_t layersId = 0; CompositorOptions compositorOptions; uint32_t maxTouchPoints = 0; DimensionInfo dimensionInfo; + nsCOMPtr<nsPIDOMWindowInner> parentTopInnerWindow; + if (aParent) { + nsCOMPtr<nsPIDOMWindowOuter> parentTopWindow = + nsPIDOMWindowOuter::From(aParent)->GetTop(); + if (parentTopWindow) { + parentTopInnerWindow = parentTopWindow->GetCurrentInnerWindow(); + } + } + + // Send down the request to open the window. + RefPtr<CreateWindowPromise> windowCreated; if (aIframeMoz) { MOZ_ASSERT(aTabOpener); nsAutoCString url; if (aURI) { aURI->GetSpec(url); } else { // We can't actually send a nullptr up as the URI, since IPDL doesn't let us // send nullptr's for primitives. We indicate that the nsString for the URI // should be converted to a nullptr by voiding the string. url.SetIsVoid(true); } - newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame, NS_ConvertUTF8toUTF16(url), - name, NS_ConvertUTF8toUTF16(features), - aWindowIsNew, &textureFactoryIdentifier, - &layersId, &compositorOptions, &maxTouchPoints); + // NOTE: BrowserFrameOpenWindowPromise is the same type as + // CreateWindowPromise, and this code depends on that fact. + windowCreated = + newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame, NS_ConvertUTF8toUTF16(url), + name, NS_ConvertUTF8toUTF16(features)); } else { nsAutoCString baseURIString; float fullZoom; rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - if (!SendCreateWindow(aTabOpener, newChild, renderFrame, - aChromeFlags, aCalledFromJS, aPositionSpecified, - aSizeSpecified, - features, - baseURIString, - fullZoom, - &rv, - aWindowIsNew, - &frameScripts, - &urlToLoad, - &textureFactoryIdentifier, - &layersId, - &compositorOptions, - &maxTouchPoints, - &dimensionInfo)) { - PRenderFrameChild::Send__delete__(renderFrame); - return NS_ERROR_NOT_AVAILABLE; + windowCreated = + SendCreateWindow(aTabOpener, newChild, renderFrame, + aChromeFlags, aCalledFromJS, aPositionSpecified, + aSizeSpecified, + features, + baseURIString, + fullZoom); + } + + // Await the promise being resolved. When the promise is resolved, we'll set + // the `ready` local variable, which will cause us to exit our nested event + // loop. + // + // NOTE: We need to run this callback on the StableStateEventTarget because we + // need to resolve our runnable and exit from the nested event loop before + // processing any events which were sent after the reply to CreateWindow was + // sent. + bool ready = false; + windowCreated->Then(nsContentUtils::GetStableStateEventTarget(), __func__, + [&] (const CreatedWindowInfo& info) { + MOZ_RELEASE_ASSERT(NS_IsMainThread(), + "windowCreated->Then must run on the main thread"); + rv = info.rv(); + *aWindowIsNew = info.windowOpened(); + frameScripts = info.frameScripts(); + urlToLoad = info.urlToLoad(); + textureFactoryIdentifier = info.textureFactoryIdentifier(); + layersId = info.layersId(); + compositorOptions = info.compositorOptions(); + maxTouchPoints = info.maxTouchPoints(); + dimensionInfo = info.dimensions(); + ready = true; + }, + [&] (const CreateWindowPromise::RejectValueType aReason) { + MOZ_RELEASE_ASSERT(NS_IsMainThread(), + "windowCreated->Then must run on the main thread"); + NS_WARNING("windowCreated promise rejected"); + rv = NS_ERROR_NOT_AVAILABLE; + ready = true; + }); + + // ======================= + // Begin Nested Event Loop + // ======================= + + // We have to wait for a response from either SendCreateWindow or + // SendBrowserFrameOpenWindow with information we're going to need to return + // from this function, So we spin a nested event loop until they get back to + // us. + + // Prevent the docshell from becoming active while the nested event loop is + // spinning. + newChild->AddPendingDocShellBlocker(); + auto removePendingDocShellBlocker = MakeScopeExit([&] { + if (newChild) { + newChild->RemovePendingDocShellBlocker(); } - - if (NS_FAILED(rv)) { - PRenderFrameChild::Send__delete__(renderFrame); - return rv; - } + }); + + // Suspend our window if we have one to make sure we don't re-enter it. + if (parentTopInnerWindow) { + parentTopInnerWindow->Suspend(); } + + { + AutoNoJSAPI nojsapi; + + // Spin the event loop until we get a response. Callers of this function + // already have to guard against an inner event loop spinning in the + // non-e10s case because of the need to spin one to create a new chrome + // window. + SpinEventLoopUntil([&] () { return ready; }); + MOZ_RELEASE_ASSERT(ready, + "We are on the main thread, so we should not exit this " + "loop without ready being true."); + } + + if (parentTopInnerWindow) { + parentTopInnerWindow->Resume(); + } + + // ===================== + // End Nested Event Loop + // ===================== + + // Handle the error which we got back from the parent process, if we got + // one. + if (NS_FAILED(rv)) { + PRenderFrameChild::Send__delete__(renderFrame); + return rv; + } + if (!*aWindowIsNew) { PRenderFrameChild::Send__delete__(renderFrame); return NS_ERROR_ABORT; } if (layersId == 0) { // if renderFrame is invalid. PRenderFrameChild::Send__delete__(renderFrame); renderFrame = nullptr;
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -4625,83 +4625,88 @@ ContentParent::RecvCreateWindow(PBrowser PRenderFrameParent* aRenderFrame, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, - nsresult* aResult, - bool* aWindowIsNew, - InfallibleTArray<FrameScriptInfo>* aFrameScripts, - nsCString* aURLToLoad, - TextureFactoryIdentifier* aTextureFactoryIdentifier, - uint64_t* aLayersId, - CompositorOptions* aCompositorOptions, - uint32_t* aMaxTouchPoints, - DimensionInfo* aDimensions) -{ + CreateWindowResolver&& aResolve) +{ + nsresult rv = NS_OK; + CreatedWindowInfo cwi; + // We always expect to open a new window here. If we don't, it's an error. - *aWindowIsNew = true; - *aResult = NS_OK; + cwi.windowOpened() = true; + cwi.layersId() = 0; + cwi.maxTouchPoints() = 0; + + // Make sure to resolve the resolver when this function exits, even if we + // failed to generate a valid response. + auto resolveOnExit = MakeScopeExit([&] { + // Copy over the nsresult, and then resolve. + cwi.rv() = rv; + aResolve(cwi); + }); TabParent* newTab = TabParent::GetFrom(aNewTab); MOZ_ASSERT(newTab); auto destroyNewTabOnError = MakeScopeExit([&] { - if (!*aWindowIsNew || NS_FAILED(*aResult)) { + // We always expect to open a new window here. If we don't, it's an error. + if (!cwi.windowOpened() || NS_FAILED(rv)) { if (newTab) { newTab->Destroy(); } } }); // Content has requested that we open this new content window, so // we must have an opener. newTab->SetHasContentOpener(true); - TabParent::AutoUseNewTab aunt(newTab, aURLToLoad); + TabParent::AutoUseNewTab aunt(newTab, &cwi.urlToLoad()); const uint64_t nextTabParentId = ++sNextTabParentId; sNextTabParents.Put(nextTabParentId, newTab); nsCOMPtr<nsITabParent> newRemoteTab; mozilla::ipc::IPCResult ipcResult = CommonCreateWindow(aThisTab, /* aSetOpener = */ true, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, nullptr, aFeatures, aBaseURI, aFullZoom, - nextTabParentId, NullString(), *aResult, - newRemoteTab, aWindowIsNew); + nextTabParentId, NullString(), rv, + newRemoteTab, &cwi.windowOpened()); if (!ipcResult) { return ipcResult; } - if (NS_WARN_IF(NS_FAILED(*aResult))) { + if (NS_WARN_IF(NS_FAILED(rv))) { return IPC_OK(); } if (sNextTabParents.GetAndRemove(nextTabParentId).valueOr(nullptr)) { - *aWindowIsNew = false; + cwi.windowOpened() = false; } MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab); - newTab->SwapFrameScriptsFrom(*aFrameScripts); + newTab->SwapFrameScriptsFrom(cwi.frameScripts()); RenderFrameParent* rfp = static_cast<RenderFrameParent*>(aRenderFrame); if (!newTab->SetRenderFrame(rfp) || - !newTab->GetRenderFrameInfo(aTextureFactoryIdentifier, aLayersId)) { - *aResult = NS_ERROR_FAILURE; - } - *aCompositorOptions = rfp->GetCompositorOptions(); + !newTab->GetRenderFrameInfo(&cwi.textureFactoryIdentifier(), &cwi.layersId())) { + rv = NS_ERROR_FAILURE; + } + cwi.compositorOptions() = rfp->GetCompositorOptions(); nsCOMPtr<nsIWidget> widget = newTab->GetWidget(); - *aMaxTouchPoints = widget ? widget->GetMaxTouchPoints() : 0; - - // NOTE: widget must be set for this to return a meaningful value. - *aDimensions = widget ? newTab->GetDimensionInfo() : DimensionInfo(); + if (widget) { + cwi.maxTouchPoints() = widget->GetMaxTouchPoints(); + cwi.dimensions() = newTab->GetDimensionInfo(); + } return IPC_OK(); } mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess( PBrowserParent* aThisTab, const uint32_t& aChromeFlags,
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -531,25 +531,17 @@ public: layout::PRenderFrameParent* aRenderFrame, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, - nsresult* aResult, - bool* aWindowIsNew, - InfallibleTArray<FrameScriptInfo>* aFrameScripts, - nsCString* aURLToLoad, - layers::TextureFactoryIdentifier* aTextureFactoryIdentifier, - uint64_t* aLayersId, - mozilla::layers::CompositorOptions* aCompositorOptions, - uint32_t* aMaxTouchPoints, - DimensionInfo* aDimensions) override; + CreateWindowResolver&& aResolve) override; virtual mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess( PBrowserParent* aThisTab, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const URIParams& aURIToLoad,
--- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -17,16 +17,18 @@ using struct mozilla::SerializedStructur using LayoutDeviceIntRect from "Units.h"; using DesktopIntRect from "Units.h"; using DesktopToLayoutDeviceScale from "Units.h"; using CSSToLayoutDeviceScale from "Units.h"; using CSSRect from "Units.h"; using CSSSize from "Units.h"; using mozilla::LayoutDeviceIntPoint from "Units.h"; using mozilla::dom::ScreenOrientationInternal from "mozilla/dom/ScreenOrientation.h"; +using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h"; +using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h"; namespace mozilla { namespace dom { struct MessagePortIdentifier { nsID uuid; nsID destinationUuid; @@ -91,10 +93,32 @@ struct DimensionInfo { CSSRect rect; CSSSize size; ScreenOrientationInternal orientation; LayoutDeviceIntPoint clientOffset; LayoutDeviceIntPoint chromeDisp; }; +struct FrameScriptInfo +{ + nsString url; + bool runInGlobalScope; +}; + +/** + * The information required to complete a window creation request. + */ +struct CreatedWindowInfo +{ + nsresult rv; + bool windowOpened; + FrameScriptInfo[] frameScripts; + nsCString urlToLoad; + TextureFactoryIdentifier textureFactoryIdentifier; + uint64_t layersId; + CompositorOptions compositorOptions; + uint32_t maxTouchPoints; + DimensionInfo dimensions; +}; + } // namespace dom } // namespace mozilla
--- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -454,23 +454,19 @@ parent: * process), then calls BrowserFrameOpenWindow on it. * * The parent process gets a chance to accept or reject the window.open * call, and windowOpened is set to true if we ended up going through with * the window.open. * * @param opener the PBrowser whose content called window.open. */ - sync BrowserFrameOpenWindow(PBrowser opener, PRenderFrame renderFrame, - nsString aURL, nsString aName, nsString aFeatures) - returns (bool windowOpened, - TextureFactoryIdentifier textureFactoryIdentifier, - uint64_t layersId, - CompositorOptions compositorOptions, - uint32_t maxTouchPoints); + async BrowserFrameOpenWindow(PBrowser opener, PRenderFrame renderFrame, + nsString aURL, nsString aName, nsString aFeatures) + returns (CreatedWindowInfo window); /** * Tells the containing widget whether the given input block results in a * swipe. Should be called in response to a WidgetWheelEvent that has * mFlags.mCanTriggerSwipe set on it. */ async RespondStartSwipeEvent(uint64_t aInputBlockId, bool aStartSwipe);
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -171,24 +171,16 @@ struct DomainPolicyClone { bool active; URIParams[] blacklist; URIParams[] whitelist; URIParams[] superBlacklist; URIParams[] superWhitelist; }; - - -struct FrameScriptInfo -{ - nsString url; - bool runInGlobalScope; -}; - struct AndroidSystemInfo { nsString device; nsString manufacturer; nsString release_version; nsString hardware; uint32_t sdk_version; bool isTablet; @@ -982,35 +974,27 @@ parent: async ShutdownProfile(nsCString aProfile); /** * Request graphics initialization information from the parent. */ sync GetGraphicsDeviceInitData() returns (ContentDeviceData aData); - sync CreateWindow(nullable PBrowser aThisTab, - PBrowser aNewTab, - PRenderFrame aRenderFrame, - uint32_t aChromeFlags, - bool aCalledFromJS, - bool aPositionSpecified, - bool aSizeSpecified, - nsCString aFeatures, - nsCString aBaseURI, - float aFullZoom) - returns (nsresult rv, - bool windowOpened, - FrameScriptInfo[] frameScripts, - nsCString urlToLoad, - TextureFactoryIdentifier textureFactoryIdentifier, - uint64_t layersId, - CompositorOptions compositorOptions, - uint32_t maxTouchPoints, - DimensionInfo dimensions); + async CreateWindow(nullable PBrowser aThisTab, + PBrowser aNewTab, + PRenderFrame aRenderFrame, + uint32_t aChromeFlags, + bool aCalledFromJS, + bool aPositionSpecified, + bool aSizeSpecified, + nsCString aFeatures, + nsCString aBaseURI, + float aFullZoom) + returns (CreatedWindowInfo window); async CreateWindowInDifferentProcess( PBrowser aThisTab, uint32_t aChromeFlags, bool aCalledFromJS, bool aPositionSpecified, bool aSizeSpecified, URIParams aURIToLoad,
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2578,31 +2578,41 @@ TabParent::ApzAwareEventRoutingToChild(S } mozilla::ipc::IPCResult TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, PRenderFrameParent* aRenderFrame, const nsString& aURL, const nsString& aName, const nsString& aFeatures, - bool* aOutWindowOpened, - TextureFactoryIdentifier* aTextureFactoryIdentifier, - uint64_t* aLayersId, - CompositorOptions* aCompositorOptions, - uint32_t* aMaxTouchPoints) + BrowserFrameOpenWindowResolver&& aResolve) { + CreatedWindowInfo cwi; + cwi.rv() = NS_OK; + cwi.layersId() = 0; + cwi.maxTouchPoints() = 0; + BrowserElementParent::OpenWindowResult opened = BrowserElementParent::OpenWindowOOP(TabParent::GetFrom(aOpener), this, aRenderFrame, aURL, aName, aFeatures, - aTextureFactoryIdentifier, aLayersId); - *aCompositorOptions = static_cast<RenderFrameParent*>(aRenderFrame)->GetCompositorOptions(); - *aOutWindowOpened = (opened == BrowserElementParent::OPEN_WINDOW_ADDED); + &cwi.textureFactoryIdentifier(), + &cwi.layersId()); + cwi.compositorOptions() = + static_cast<RenderFrameParent*>(aRenderFrame)->GetCompositorOptions(); + cwi.windowOpened() = (opened == BrowserElementParent::OPEN_WINDOW_ADDED); nsCOMPtr<nsIWidget> widget = GetWidget(); - *aMaxTouchPoints = widget ? widget->GetMaxTouchPoints() : 0; - if (!*aOutWindowOpened) { + if (widget) { + cwi.maxTouchPoints() = widget->GetMaxTouchPoints(); + cwi.dimensions() = GetDimensionInfo(); + } + + // Resolve the request with the information we collected. + aResolve(cwi); + + if (!cwi.windowOpened()) { Destroy(); } return IPC_OK(); } mozilla::ipc::IPCResult TabParent::RecvRespondStartSwipeEvent(const uint64_t& aInputBlockId, const bool& aStartSwipe)
--- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -160,26 +160,23 @@ public: virtual mozilla::ipc::IPCResult RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent) override; virtual mozilla::ipc::IPCResult RecvAccessKeyNotHandled(const WidgetKeyboardEvent& aEvent) override; virtual mozilla::ipc::IPCResult RecvSetHasBeforeUnload(const bool& aHasBeforeUnload) override; - virtual mozilla::ipc::IPCResult RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, - PRenderFrameParent* aRenderFrame, - const nsString& aURL, - const nsString& aName, - const nsString& aFeatures, - bool* aOutWindowOpened, - TextureFactoryIdentifier* aTextureFactoryIdentifier, - uint64_t* aLayersId, - CompositorOptions* aCompositorOptions, - uint32_t* aMaxTouchPoints) override; + virtual mozilla::ipc::IPCResult + RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, + PRenderFrameParent* aRenderFrame, + const nsString& aURL, + const nsString& aName, + const nsString& aFeatures, + BrowserFrameOpenWindowResolver&& aResolve) override; virtual mozilla::ipc::IPCResult RecvSyncMessage(const nsString& aMessage, const ClonedMessageData& aData, InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal, nsTArray<ipc::StructuredCloneData>* aRetVal) override;
--- a/ipc/ipdl/sync-messages.ini +++ b/ipc/ipdl/sync-messages.ini @@ -834,18 +834,16 @@ description = [PBrowser::IsParentWindowMainWidgetVisible] description = [PBrowser::GetDPI] description = [PBrowser::GetDefaultScale] description = [PBrowser::GetWidgetRounding] description = -[PBrowser::BrowserFrameOpenWindow] -description = [PBrowser::RequestNativeKeyBindings] description = [PBrowser::GetTabCount] description = [PBrowser::DispatchWheelEvent] description = [PBrowser::DispatchMouseEvent] description = @@ -904,18 +902,16 @@ description = [PContent::EndDriverCrashGuard] description = [PContent::KeygenProcessValue] description = [PContent::KeygenProvideContent] description = [PContent::GetGraphicsDeviceInitData] description = -[PContent::CreateWindow] -description = [PContent::GetAndroidSystemInfo] description = [PContent::UngrabPointer] description = [PContent::RemovePermission] description = [PContent::GetA11yContentId] description =