Backed out 4 changesets (bug 1343728) for failures in test_group_mouseevents.html a=backout
authorWes Kocher <wkocher@mozilla.com>
Wed, 21 Jun 2017 17:13:49 -0700
changeset 414148 14f84d3b3233a87af51f5ad8302ee24cc2371a01
parent 414147 79c8da654a9301f57f4c9216eeb2ca1c76d58603
child 414149 e9c2da54cfed9b3b7af85dd4a938f0d2ad3f3d16
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1343728
milestone56.0a1
backs out2029cb6bce8660c14d9a98b74ab0e36c9adab4b6
0169e09f60304d074424804812ebe83c5372e2f5
831e95b29f6640714312f35dc4c933857e087257
d5630ef01b17b62aa3a9e870035e4b3bce724bf4
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
Backed out 4 changesets (bug 1343728) for failures in test_group_mouseevents.html a=backout Backed out changeset 2029cb6bce86 (bug 1343728) Backed out changeset 0169e09f6030 (bug 1343728) Backed out changeset 831e95b29f66 (bug 1343728) Backed out changeset d5630ef01b17 (bug 1343728) MozReview-Commit-ID: 2RRBTmp5FGj
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/DOMTypes.ipdlh
dom/ipc/PBrowser.ipdl
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
gfx/layers/CompositorTypes.h
ipc/ipdl/sync-messages.ini
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -319,17 +319,16 @@ uint32_t nsContentUtils::sHandlingInputT
 
 uint32_t nsContentUtils::sCookiesLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
 uint32_t nsContentUtils::sCookiesBehavior = nsICookieService::BEHAVIOR_ACCEPT;
 
 nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
 nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
 nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
 bool nsContentUtils::sFragmentParsingActive = false;
-nsISerialEventTarget* nsContentUtils::sStableStateEventTarget = nullptr;
 
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
 bool nsContentUtils::sDOMWindowDumpEnabled;
 #endif
 
 bool nsContentUtils::sDoNotTrackEnabled = false;
 
 mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
@@ -533,62 +532,16 @@ public:
   {
     return mCharset;
   }
 
 private:
   nsCString mCharset;
 };
 
-class StableStateEventTarget final : public nsISerialEventTarget
-{
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIEVENTTARGET_FULL
-private:
-  ~StableStateEventTarget() {}
-};
-
-NS_IMPL_ISUPPORTS(StableStateEventTarget, nsISerialEventTarget);
-
-bool
-StableStateEventTarget::IsOnCurrentThreadInfallible()
-{
-  return true;
-}
-
-NS_IMETHODIMP
-StableStateEventTarget::IsOnCurrentThread(bool* aResult)
-{
-  *aResult = true;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-StableStateEventTarget::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
-{
-  if (NS_WARN_IF(!CycleCollectedJSContext::Get())) {
-    return NS_ERROR_UNEXPECTED;
-  }
-  nsContentUtils::RunInStableState(Move(aEvent));
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-StableStateEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
-{
-  return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
-}
-
-NS_IMETHODIMP
-StableStateEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aDelay)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 } // namespace
 
 /**
  * This class is used to determine whether or not the user is currently
  * interacting with the browser. It listens to observer events to toggle the
  * value of the sUserActive static.
  *
  * This class is an internal implementation detail.
@@ -784,19 +737,16 @@ nsContentUtils::Init()
 
   nsDependentCString buildID(mozilla::PlatformBuildID());
   sJSBytecodeMimeType = new nsCString(NS_LITERAL_CSTRING("javascript/moz-bytecode-") + buildID);
 
   Element::InitCCCallbacks();
 
   Unused << nsRFPService::GetOrCreate();
 
-  RefPtr<StableStateEventTarget> stableStateEventTarget = new StableStateEventTarget();
-  stableStateEventTarget.forget(&sStableStateEventTarget);
-
   nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
     do_GetService("@mozilla.org/uuid-generator;1", &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   uuidGenerator.forget(&sUUIDGenerator);
 
   RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
@@ -2213,18 +2163,16 @@ nsContentUtils::Shutdown()
   delete sModifierSeparator;
   sModifierSeparator = nullptr;
 
   delete sJSBytecodeMimeType;
   sJSBytecodeMimeType = nullptr;
 
   NS_IF_RELEASE(sSameOriginChecker);
 
-  NS_IF_RELEASE(sStableStateEventTarget);
-
   if (sUserInteractionObserver) {
     sUserInteractionObserver->Shutdown();
     NS_RELEASE(sUserInteractionObserver);
   }
 
   HTMLInputElement::Shutdown();
   nsMappedAttributes::Shutdown();
 }
@@ -5713,23 +5661,16 @@ nsContentUtils::RunInStableState(already
 /* static */
 void
 nsContentUtils::RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable)
 {
   MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
   CycleCollectedJSContext::Get()->RunInMetastableState(Move(aRunnable));
 }
 
-/* static */
-nsISerialEventTarget*
-nsContentUtils::GetStableStateEventTarget()
-{
-  return sStableStateEventTarget;
-}
-
 void
 nsContentUtils::EnterMicroTask()
 {
   MOZ_ASSERT(NS_IsMainThread());
   ++sMicroTaskLevel;
 }
 
 void
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1874,26 +1874,16 @@ public:
    * microtask has finished.  This is not specced at this time.
    * In practice this runs aRunnable once the currently executing task or
    * microtask finishes.  If called multiple times per microtask, all the
    * runnables will be executed, in the order in which RunInMetastableState()
    * was called
    */
   static void RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable);
 
-  /**
-   * Returns a nsISerialEventTarget which will run any event dispatched to it
-   * once the event loop has reached a "stable state". Runnables dispatched to
-   * this event target must not cause any queued events to be processed (i.e.
-   * must not spin the event loop).
-   *
-   * See RunInStableState for more information about stable states
-   */
-  static nsISerialEventTarget* GetStableStateEventTarget();
-
   // Call EnterMicroTask when you're entering JS execution.
   // Usually the best way to do this is to use nsAutoMicroTask.
   static void EnterMicroTask();
   static void LeaveMicroTask();
 
   static bool IsInMicroTask();
   static uint32_t MicroTaskLevel();
   static void SetMicroTaskLevel(uint32_t aLevel);
@@ -3217,18 +3207,16 @@ private:
   static nsIParser* sXMLFragmentParser;
   static nsIFragmentContentSink* sXMLFragmentSink;
 
   /**
    * True if there's a fragment parser activation on the stack.
    */
   static bool sFragmentParsingActive;
 
-  static nsISerialEventTarget* sStableStateEventTarget;
-
   static nsString* sShiftText;
   static nsString* sControlText;
   static nsString* sMetaText;
   static nsString* sOSText;
   static nsString* sAltText;
   static nsString* sModifierSeparator;
 
   // Alternate data mime type, used by the ScriptLoader to register and read the
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -852,144 +852,64 @@ 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);
     }
 
-    // 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));
+    newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame, NS_ConvertUTF8toUTF16(url),
+                                         name, NS_ConvertUTF8toUTF16(features),
+                                         aWindowIsNew, &textureFactoryIdentifier,
+                                         &layersId, &compositorOptions, &maxTouchPoints);
   } else {
     nsAutoCString baseURIString;
     float fullZoom;
     rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    windowCreated =
-      SendCreateWindow(aTabOpener, newChild, renderFrame,
-                       aChromeFlags, aCalledFromJS, aPositionSpecified,
-                       aSizeSpecified,
-                       features,
-                       baseURIString,
-                       fullZoom);
+    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;
+    }
+
+    if (NS_FAILED(rv)) {
+      PRenderFrameChild::Send__delete__(renderFrame);
+      return rv;
+    }
   }
-
-  // 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();
-    }
-  });
-
-  // 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,88 +4625,83 @@ 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,
-                                CreateWindowResolver&& aResolve)
-{
-  nsresult rv = NS_OK;
-  CreatedWindowInfo cwi;
-
+                                nsresult* aResult,
+                                bool* aWindowIsNew,
+                                InfallibleTArray<FrameScriptInfo>* aFrameScripts,
+                                nsCString* aURLToLoad,
+                                TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                uint64_t* aLayersId,
+                                CompositorOptions* aCompositorOptions,
+                                uint32_t* aMaxTouchPoints,
+                                DimensionInfo* aDimensions)
+{
   // We always expect to open a new window here. If we don't, it's an error.
-  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);
-  });
+  *aWindowIsNew = true;
+  *aResult = NS_OK;
 
   TabParent* newTab = TabParent::GetFrom(aNewTab);
   MOZ_ASSERT(newTab);
 
   auto destroyNewTabOnError = MakeScopeExit([&] {
-    // We always expect to open a new window here. If we don't, it's an error.
-    if (!cwi.windowOpened() || NS_FAILED(rv)) {
+    if (!*aWindowIsNew || NS_FAILED(*aResult)) {
       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, &cwi.urlToLoad());
+  TabParent::AutoUseNewTab aunt(newTab, aURLToLoad);
   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(), rv,
-                       newRemoteTab, &cwi.windowOpened());
+                       nextTabParentId, NullString(), *aResult,
+                       newRemoteTab, aWindowIsNew);
   if (!ipcResult) {
     return ipcResult;
   }
 
-  if (NS_WARN_IF(NS_FAILED(rv))) {
+  if (NS_WARN_IF(NS_FAILED(*aResult))) {
     return IPC_OK();
   }
 
   if (sNextTabParents.GetAndRemove(nextTabParentId).valueOr(nullptr)) {
-    cwi.windowOpened() = false;
+    *aWindowIsNew = false;
   }
   MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab);
 
-  newTab->SwapFrameScriptsFrom(cwi.frameScripts());
+  newTab->SwapFrameScriptsFrom(*aFrameScripts);
 
   RenderFrameParent* rfp = static_cast<RenderFrameParent*>(aRenderFrame);
   if (!newTab->SetRenderFrame(rfp) ||
-      !newTab->GetRenderFrameInfo(&cwi.textureFactoryIdentifier(), &cwi.layersId())) {
-    rv = NS_ERROR_FAILURE;
-  }
-  cwi.compositorOptions() = rfp->GetCompositorOptions();
+      !newTab->GetRenderFrameInfo(aTextureFactoryIdentifier, aLayersId)) {
+    *aResult = NS_ERROR_FAILURE;
+  }
+  *aCompositorOptions = rfp->GetCompositorOptions();
 
   nsCOMPtr<nsIWidget> widget = newTab->GetWidget();
-  if (widget) {
-    cwi.maxTouchPoints() = widget->GetMaxTouchPoints();
-    cwi.dimensions() = newTab->GetDimensionInfo();
-  }
+  *aMaxTouchPoints = widget ? widget->GetMaxTouchPoints() : 0;
+
+  // NOTE: widget must be set for this to return a meaningful value.
+  *aDimensions = widget ? newTab->GetDimensionInfo() : DimensionInfo();
 
   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,17 +531,25 @@ 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,
-                   CreateWindowResolver&& aResolve) override;
+                   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;
 
   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,18 +17,16 @@ 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;
@@ -93,32 +91,10 @@ 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,19 +454,23 @@ 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.
      */
-    async BrowserFrameOpenWindow(PBrowser opener, PRenderFrame renderFrame,
-                                 nsString aURL, nsString aName, nsString aFeatures)
-        returns (CreatedWindowInfo window);
+    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);
 
     /**
      * 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,16 +171,24 @@ 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;
@@ -974,27 +982,35 @@ parent:
     async ShutdownProfile(nsCString aProfile);
 
     /**
      * Request graphics initialization information from the parent.
      */
     sync GetGraphicsDeviceInitData()
         returns (ContentDeviceData aData);
 
-    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);
+    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 CreateWindowInDifferentProcess(
       PBrowser aThisTab,
       uint32_t aChromeFlags,
       bool aCalledFromJS,
       bool aPositionSpecified,
       bool aSizeSpecified,
       URIParams aURIToLoad,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -402,20 +402,16 @@ TabChild::TabChild(nsIContentChild* aMan
   , mSkipKeyPress(false)
   , mLayerObserverEpoch(0)
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   , mNativeWindowHandle(0)
 #endif
 #if defined(ACCESSIBILITY)
   , mTopLevelDocAccessibleChild(nullptr)
 #endif
-  , mPendingDocShellIsActive(false)
-  , mPendingDocShellPreserveLayers(false)
-  , mPendingDocShellReceivedMessage(false)
-  , mPendingDocShellBlockers(0)
 {
   nsWeakPtr weakPtrThis(do_GetWeakReference(static_cast<nsITabChild*>(this)));  // for capture by the lambda
   mSetAllowedTouchBehaviorCallback = [weakPtrThis](uint64_t aInputBlockId,
                                                    const nsTArray<TouchBehaviorFlags>& aFlags)
   {
     if (nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(weakPtrThis)) {
       static_cast<TabChild*>(tabChild.get())->SetAllowedTouchBehavior(aInputBlockId, aFlags);
     }
@@ -2362,36 +2358,30 @@ TabChild::RecvDestroy()
   // Bounce through the event loop once to allow any delayed teardown runnables
   // that were just generated to have a chance to run.
   nsCOMPtr<nsIRunnable> deleteRunnable = new DelayedDeleteRunnable(this);
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(deleteRunnable));
 
   return IPC_OK();
 }
 
-void
-TabChild::AddPendingDocShellBlocker()
-{
-  mPendingDocShellBlockers++;
-}
-
-void
-TabChild::RemovePendingDocShellBlocker()
+mozilla::ipc::IPCResult
+TabChild::RecvSetDocShellIsActive(const bool& aIsActive,
+                                  const bool& aPreserveLayers,
+                                  const uint64_t& aLayerObserverEpoch)
 {
-  mPendingDocShellBlockers--;
-  if (!mPendingDocShellBlockers && mPendingDocShellReceivedMessage) {
-    mPendingDocShellReceivedMessage = false;
-    InternalSetDocShellIsActive(mPendingDocShellIsActive,
-                                mPendingDocShellPreserveLayers);
+  // Since SetDocShellIsActive requests come in from both the hang monitor
+  // channel and the PContent channel, we have an ordering problem. This code
+  // ensures that we respect the order in which the requests were made and
+  // ignore stale requests.
+  if (mLayerObserverEpoch >= aLayerObserverEpoch) {
+    return IPC_OK();
   }
-}
-
-void
-TabChild::InternalSetDocShellIsActive(bool aIsActive, bool aPreserveLayers)
-{
+  mLayerObserverEpoch = aLayerObserverEpoch;
+
   auto clearForcePaint = MakeScopeExit([&] {
     // We might force a paint, or we might already have painted and this is a
     // no-op. In either case, once we exit this scope, we need to alert the
     // ProcessHangMonitor that we've finished responding to what might have
     // been a request to force paint. This is so that the BackgroundHangMonitor
     // for force painting can be made to wait again.
     if (aIsActive) {
       ProcessHangMonitor::ClearForcePaint();
@@ -2407,32 +2397,32 @@ TabChild::InternalSetDocShellIsActive(bo
     MOZ_ASSERT(mPuppetWidget->GetLayerManager());
     MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
             || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR
             || (gfxPlatform::IsHeadless() && mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC));
 
     // We send the current layer observer epoch to the compositor so that
     // TabParent knows whether a layer update notification corresponds to the
     // latest SetDocShellIsActive request that was made.
-    mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(mLayerObserverEpoch);
+    mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(aLayerObserverEpoch);
   }
 
   // docshell is consider prerendered only if not active yet
   mIsPrerendered &= !aIsActive;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   if (docShell) {
     bool wasActive;
     docShell->GetIsActive(&wasActive);
     if (aIsActive && wasActive) {
       // This request is a no-op. In this case, we still want a MozLayerTreeReady
       // notification to fire in the parent (so that it knows that the child has
       // updated its epoch). ForcePaintNoOp does that.
       if (IPCOpen()) {
-        Unused << SendForcePaintNoOp(mLayerObserverEpoch);
-        return;
+        Unused << SendForcePaintNoOp(aLayerObserverEpoch);
+        return IPC_OK();
       }
     }
 
     docShell->SetIsActive(aIsActive);
   }
 
   if (aIsActive) {
     MakeVisible();
@@ -2463,43 +2453,17 @@ TabChild::InternalSetDocShellIsActive(bo
                            nsIPresShell::PAINT_LAYERS);
         }
       }
       APZCCallbackHelper::SuppressDisplayport(false, presShell);
     }
   } else if (!aPreserveLayers) {
     MakeHidden();
   }
-}
-
-mozilla::ipc::IPCResult
-TabChild::RecvSetDocShellIsActive(const bool& aIsActive,
-                                  const bool& aPreserveLayers,
-                                  const uint64_t& aLayerObserverEpoch)
-{
-  // Since requests to change the active docshell come in from both the hang
-  // monitor channel and the PContent channel, we have an ordering problem. This
-  // code ensures that we respect the order in which the requests were made and
-  // ignore stale requests.
-  if (mLayerObserverEpoch >= aLayerObserverEpoch) {
-    return IPC_OK();
-  }
-  mLayerObserverEpoch = aLayerObserverEpoch;
-
-  // If we're currently waiting for window opening to complete, we need to hold
-  // off on setting the docshell active. We queue up the values we're receiving
-  // in the mWindowOpenDocShellActiveStatus.
-  if (mPendingDocShellBlockers > 0) {
-    mPendingDocShellReceivedMessage = true;
-    mPendingDocShellIsActive = aIsActive;
-    mPendingDocShellPreserveLayers = aPreserveLayers;
-    return IPC_OK();
-  }
-
-  InternalSetDocShellIsActive(aIsActive, aPreserveLayers);
+
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNavigation)
 {
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm) {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -689,19 +689,16 @@ public:
   }
 
   PDocAccessibleChild* GetTopLevelDocAccessibleChild()
   {
     return mTopLevelDocAccessibleChild;
   }
 #endif
 
-  void AddPendingDocShellBlocker();
-  void RemovePendingDocShellBlocker();
-
 protected:
   virtual ~TabChild();
 
   virtual PRenderFrameChild* AllocPRenderFrameChild() override;
 
   virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) override;
 
   virtual mozilla::ipc::IPCResult RecvDestroy() override;
@@ -788,19 +785,16 @@ private:
                                bool* aIsNextWheelEvent);
 
   void MaybeDispatchCoalescedWheelEvent();
 
   void DispatchWheelEvent(const WidgetWheelEvent& aEvent,
                           const ScrollableLayerGuid& aGuid,
                           const uint64_t& aInputBlockId);
 
-  void InternalSetDocShellIsActive(bool aIsActive,
-                                   bool aPreserveLayers);
-
   class DelayedDeleteRunnable;
 
   TextureFactoryIdentifier mTextureFactoryIdentifier;
   nsCOMPtr<nsIWebNavigation> mWebNav;
   RefPtr<mozilla::dom::TabGroup> mTabGroup;
   RefPtr<PuppetWidget> mPuppetWidget;
   nsCOMPtr<nsIURI> mLastURI;
   RenderFrameChild* mRemoteFrame;
@@ -871,20 +865,15 @@ private:
   // The handle associated with the native window that contains this tab
   uintptr_t mNativeWindowHandle;
 #endif // defined(XP_WIN)
 
 #if defined(ACCESSIBILITY)
   PDocAccessibleChild* mTopLevelDocAccessibleChild;
 #endif
 
-  bool mPendingDocShellIsActive;
-  bool mPendingDocShellPreserveLayers;
-  bool mPendingDocShellReceivedMessage;
-  uint32_t mPendingDocShellBlockers;
-
   DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TabChild_h
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2578,41 +2578,31 @@ TabParent::ApzAwareEventRoutingToChild(S
 }
 
 mozilla::ipc::IPCResult
 TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
                                       PRenderFrameParent* aRenderFrame,
                                       const nsString& aURL,
                                       const nsString& aName,
                                       const nsString& aFeatures,
-                                      BrowserFrameOpenWindowResolver&& aResolve)
+                                      bool* aOutWindowOpened,
+                                      TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                      uint64_t* aLayersId,
+                                      CompositorOptions* aCompositorOptions,
+                                      uint32_t* aMaxTouchPoints)
 {
-  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,
-                                        &cwi.textureFactoryIdentifier(),
-                                        &cwi.layersId());
-  cwi.compositorOptions() =
-    static_cast<RenderFrameParent*>(aRenderFrame)->GetCompositorOptions();
-  cwi.windowOpened() = (opened == BrowserElementParent::OPEN_WINDOW_ADDED);
+                                        aTextureFactoryIdentifier, aLayersId);
+  *aCompositorOptions = static_cast<RenderFrameParent*>(aRenderFrame)->GetCompositorOptions();
+  *aOutWindowOpened = (opened == BrowserElementParent::OPEN_WINDOW_ADDED);
   nsCOMPtr<nsIWidget> widget = GetWidget();
-  if (widget) {
-    cwi.maxTouchPoints() = widget->GetMaxTouchPoints();
-    cwi.dimensions() = GetDimensionInfo();
-  }
-
-  // Resolve the request with the information we collected.
-  aResolve(cwi);
-
-  if (!cwi.windowOpened()) {
+  *aMaxTouchPoints = widget ? widget->GetMaxTouchPoints() : 0;
+  if (!*aOutWindowOpened) {
     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,23 +160,26 @@ 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,
-                             BrowserFrameOpenWindowResolver&& aResolve) 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
   RecvSyncMessage(const nsString& aMessage,
                   const ClonedMessageData& aData,
                   InfallibleTArray<CpowEntry>&& aCpows,
                   const IPC::Principal& aPrincipal,
                   nsTArray<ipc::StructuredCloneData>* aRetVal) override;
 
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -190,28 +190,16 @@ struct TextureFactoryIdentifier
     , mMaxTextureSize(aMaxTextureSize)
     , mCompositorUseANGLE(aCompositorUseANGLE)
     , mSupportsTextureBlitting(aSupportsTextureBlitting)
     , mSupportsPartialUploads(aSupportsPartialUploads)
     , mSupportsComponentAlpha(aSupportsComponentAlpha)
     , mSupportsBackdropCopyForComponentAlpha(true)
     , mSyncHandle(aSyncHandle)
   {}
-
-  bool operator==(const TextureFactoryIdentifier& aOther) const {
-    return
-      mParentBackend == aOther.mParentBackend &&
-      mParentProcessType == aOther.mParentProcessType &&
-      mMaxTextureSize == aOther.mMaxTextureSize &&
-      mCompositorUseANGLE == aOther.mCompositorUseANGLE &&
-      mSupportsTextureBlitting == aOther.mSupportsTextureBlitting &&
-      mSupportsPartialUploads == aOther.mSupportsPartialUploads &&
-      mSupportsComponentAlpha == aOther.mSupportsComponentAlpha &&
-      mSyncHandle == aOther.mSyncHandle;
-  }
 };
 
 /**
  * Information required by the compositor from the content-side for creating or
  * using compositables and textures.
  * XXX - TextureInfo is a bad name: this information is useful for the compositable,
  * not the Texture. And ith new Textures, only the compositable type is really
  * useful. This may (should) be removed in the near future.
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -838,16 +838,18 @@ 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 =
@@ -906,16 +908,18 @@ 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 =