Bug 1147911 Part 6: Send remote type down to child. r=gijs, r=smaug
☠☠ backed out by 8c10bb93818f ☠ ☠
authorBob Owen <bobowencode@gmail.com>
Wed, 23 Nov 2016 13:36:58 +0000
changeset 324085 360c780c0a95e2a85ae2d82065638b4a2ea62299
parent 324084 17ac392560a7de83e968e00278c3e0abb6595c75
child 324086 f8ff074e914525117bee0d236447521efcda3eb3
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersgijs, smaug
bugs1147911
milestone53.0a1
Bug 1147911 Part 6: Send remote type down to child. r=gijs, r=smaug
browser/modules/E10SUtils.jsm
dom/base/nsGkAtomList.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
toolkit/xre/nsAppRunner.cpp
xpcom/system/nsIXULRuntime.idl
--- a/browser/modules/E10SUtils.jsm
+++ b/browser/modules/E10SUtils.jsm
@@ -25,16 +25,17 @@ function getAboutModule(aURL) {
     // Either the about module isn't defined or it is broken. In either case
     // ignore it.
     return null;
   }
 }
 
 const NOT_REMOTE = null;
 const WEB_REMOTE_TYPE = "web";
+// This must match the one in ContentParent.h.
 const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE;
 
 this.E10SUtils = {
   DEFAULT_REMOTE_TYPE,
   NOT_REMOTE,
   WEB_REMOTE_TYPE,
 
   canLoadURIInProcess: function(aURL, aProcess) {
@@ -124,23 +125,28 @@ this.E10SUtils = {
     if (aURL.startsWith("view-source:")) {
       return this.getRemoteTypeForURI(aURL.substr("view-source:".length),
                                       aMultiProcess, aPreferredRemoteType);
     }
 
     return WEB_REMOTE_TYPE;
   },
 
+  shouldLoadURIInThisProcess: function(aURI) {
+    let remoteType = Services.appinfo.remoteType;
+    return remoteType == this.getRemoteTypeForURI(aURI.spec, true, remoteType);
+  },
+
   shouldLoadURI: function(aDocShell, aURI, aReferrer) {
     // Inner frames should always load in the current process
     if (aDocShell.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeParent)
       return true;
 
     // If the URI can be loaded in the current process then continue
-    return this.canLoadURIInProcess(aURI.spec, Services.appinfo.processType);
+    return this.shouldLoadURIInThisProcess(aURI);
   },
 
   redirectLoad: function(aDocShell, aURI, aReferrer, aFreshProcess) {
     // Retarget the load to the correct process
     let messageManager = aDocShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                   .getInterface(Ci.nsIContentFrameMessageManager);
     let sessionHistory = aDocShell.getInterface(Ci.nsIWebNavigation).sessionHistory;
 
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2209,16 +2209,17 @@ GK_ATOM(serif, "serif")
 GK_ATOM(sans_serif, "sans-serif")
 GK_ATOM(cursive, "cursive")
 GK_ATOM(fantasy, "fantasy")
 GK_ATOM(monospace, "monospace")
 
 // IPC stuff
 GK_ATOM(Remote, "remote")
 GK_ATOM(RemoteId, "_remote_id")
+GK_ATOM(RemoteType, "remoteType")
 GK_ATOM(DisplayPort, "_displayport")
 GK_ATOM(DisplayPortMargins, "_displayportmargins")
 GK_ATOM(DisplayPortBase, "_displayportbase")
 GK_ATOM(AsyncScrollLayerCreationFailed, "_asyncscrolllayercreationfailed")
 GK_ATOM(forcemessagemanager, "forcemessagemanager")
 
 // Names for system metrics
 GK_ATOM(color_picker_available, "color-picker-available")
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2372,16 +2372,31 @@ ContentChild::RecvAppInfo(const nsCStrin
   mAppInfo.UAName.Assign(UAName);
   mAppInfo.ID.Assign(ID);
   mAppInfo.vendor.Assign(vendor);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+ContentChild::RecvRemoteType(const nsString& aRemoteType)
+{
+  MOZ_ASSERT(DOMStringIsNull(mRemoteType));
+
+  mRemoteType.Assign(aRemoteType);
+  return IPC_OK();
+}
+
+const nsAString&
+ContentChild::GetRemoteType() const
+{
+  return mRemoteType;
+}
+
+mozilla::ipc::IPCResult
 ContentChild::RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig)
 {
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   MOZ_ASSERT(swm);
   swm->LoadRegistrations(aConfig.serviceWorkerRegistrations());
   return IPC_OK();
 }
 
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -419,16 +419,20 @@ public:
 
   virtual mozilla::ipc::IPCResult RecvGarbageCollect() override;
   virtual mozilla::ipc::IPCResult RecvCycleCollect() override;
 
   virtual mozilla::ipc::IPCResult RecvAppInfo(const nsCString& version, const nsCString& buildID,
                                               const nsCString& name, const nsCString& UAName,
                                               const nsCString& ID, const nsCString& vendor) override;
 
+  virtual mozilla::ipc::IPCResult RecvRemoteType(const nsString& aRemoteType) override;
+
+  const nsAString& GetRemoteType() const;
+
   virtual mozilla::ipc::IPCResult
   RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig) override;
 
   virtual mozilla::ipc::IPCResult
   RecvInitBlobURLs(nsTArray<BlobURLRegistrationData>&& aRegistations) override;
 
   virtual mozilla::ipc::IPCResult RecvLastPrivateDocShellDestroyed() override;
 
@@ -666,16 +670,17 @@ private:
    * generated by the chrome process.
    */
   uint32_t mMsaaID;
 #endif
 
   AppInfo mAppInfo;
 
   bool mIsForBrowser;
+  nsString mRemoteType = NullString();
   bool mCanOverrideProcessName;
   bool mIsAlive;
   nsString mProcessName;
 
   static ContentChild* sSingleton;
 
   nsCOMPtr<nsIDomainPolicy> mPolicy;
   nsCOMPtr<nsITimer> mForceKillTimer;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -637,17 +637,17 @@ ContentParent::JoinAllSubprocesses()
       lock.Wait();
     }
   }
 
   sCanLaunchSubprocesses = false;
 }
 
 /*static*/ already_AddRefed<ContentParent>
-ContentParent::GetNewOrUsedBrowserProcess(bool aForBrowserElement,
+ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
                                           ProcessPriority aPriority,
                                           ContentParent* aOpener,
                                           bool aLargeAllocationProcess)
 {
   nsTArray<ContentParent*>* contentParents;
   int32_t maxContentParents;
 
   // Decide which pool of content parents we are going to be pulling from based
@@ -682,18 +682,17 @@ ContentParent::GetNewOrUsedBrowserProces
       NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sBrowserContentParents?");
       if (p->mOpener == aOpener) {
         return p.forget();
       }
       currIdx = (currIdx + 1) % maxSelectable;
     } while (currIdx != startIdx);
   }
 
-  RefPtr<ContentParent> p = new ContentParent(aOpener,
-                                              aForBrowserElement);
+  RefPtr<ContentParent> p = new ContentParent(aOpener, aRemoteType);
 
   if (!p->LaunchSubprocess(aPriority)) {
     return nullptr;
   }
 
   p->Init();
 
   p->mLargeAllocationProcess = aLargeAllocationProcess;
@@ -765,18 +764,17 @@ ContentParent::RecvCreateChildProcess(co
   MaybeInvalidTabContext tc(aContext);
   if (!tc.IsValid()) {
     NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
                              "the child process. (%s)",
                              tc.GetInvalidReason()).get());
     return IPC_FAIL_NO_REASON(this);
   }
 
-  cp = GetNewOrUsedBrowserProcess(/* isBrowserElement = */ true,
-                                  aPriority, this);
+  cp = GetNewOrUsedBrowserProcess(DEFAULT_REMOTE_TYPE, aPriority, this);
 
   if (!cp) {
     *aCpId = 0;
     *aIsForBrowser = false;
     return IPC_OK();
   }
 
   *aCpId = cp->ChildID();
@@ -958,19 +956,25 @@ ContentParent::CreateBrowser(const TabCo
   if (isInContentProcess) {
     MOZ_ASSERT(aContext.IsMozBrowserElement());
     constructorSender = CreateContentBridgeParent(aContext, initialPriority,
                                                   openerTabId, &tabId);
   } else {
     if (aOpenerContentParent) {
       constructorSender = aOpenerContentParent;
     } else {
+      nsAutoString remoteType;
+      if (!aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
+                                  remoteType)) {
+        remoteType.Assign(DEFAULT_REMOTE_TYPE);
+      }
+
       constructorSender =
-        GetNewOrUsedBrowserProcess(aContext.IsMozBrowserElement(),
-                                   initialPriority, nullptr, aFreshProcess);
+        GetNewOrUsedBrowserProcess(remoteType, initialPriority, nullptr,
+                                   aFreshProcess);
       if (!constructorSender) {
         return nullptr;
       }
     }
     tabId = AllocateTabId(openerTabId,
                           aContext.AsIPCTabContext(),
                           constructorSender->ChildID());
   }
@@ -1088,16 +1092,18 @@ ContentParent::Init()
   }
   Preferences::AddStrongObserver(this, "");
   if (obs) {
     nsAutoString cpId;
     cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
     obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", cpId.get());
   }
 
+  Unused << SendRemoteType(mRemoteType);
+
 #ifdef ACCESSIBILITY
   // If accessibility is running in chrome process then start it in content
   // process.
   if (nsIPresShell::IsAccessibilityActive()) {
 #if defined(XP_WIN)
     if (IsVistaOrLater()) {
       Unused <<
         SendActivateA11y(a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
@@ -1762,20 +1768,21 @@ ContentParent::LaunchSubprocess(ProcessP
 
   // Set a reply timeout for CPOWs.
   SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 0));
 
   return true;
 }
 
 ContentParent::ContentParent(ContentParent* aOpener,
-                             bool aIsForBrowser)
+                             const nsAString& aRemoteType)
   : nsIContentParent()
   , mOpener(aOpener)
-  , mIsForBrowser(aIsForBrowser)
+  , mRemoteType(aRemoteType)
+  , mIsForBrowser(!mRemoteType.IsEmpty())
   , mLargeAllocationProcess(false)
 {
   InitializeMembers();  // Perform common initialization.
 
   // Insert ourselves into the global linked list of ContentParent objects.
   if (!sContentParents) {
     sContentParents = new LinkedList<ContentParent>();
   }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -79,16 +79,20 @@ class Element;
 class TabParent;
 class PStorageParent;
 class ClonedMessageData;
 class MemoryReport;
 class TabContext;
 class ContentBridgeParent;
 class GetFilesHelper;
 
+// This must match the one in E10SUtils.jsm.
+static NS_NAMED_LITERAL_STRING(DEFAULT_REMOTE_TYPE, "web");
+static NS_NAMED_LITERAL_STRING(NO_REMOTE_TYPE, "");
+
 class ContentParent final : public PContentParent
                           , public nsIContentParent
                           , public nsIObserver
                           , public nsIDOMGeoPositionCallback
                           , public nsIDOMGeoPositionErrorCallback
                           , public gfx::gfxVarReceiver
                           , public mozilla::LinkedListElement<ContentParent>
                           , public gfx::GPUProcessListener
@@ -124,17 +128,17 @@ public:
 
   /**
    * Get or create a content process for:
    * 1. browser iframe
    * 2. remote xul <browser>
    * 3. normal iframe
    */
   static already_AddRefed<ContentParent>
-  GetNewOrUsedBrowserProcess(bool aForBrowserElement = false,
+  GetNewOrUsedBrowserProcess(const nsAString& aRemoteType = NO_REMOTE_TYPE,
                              hal::ProcessPriority aPriority =
                              hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
                              ContentParent* aOpener = nullptr,
                              bool aLargeAllocationProcess = false);
 
   /**
    * Get or create a content process for the given TabContext.  aFrameElement
    * should be the frame/iframe element with which this process will
@@ -577,17 +581,17 @@ private:
       const uint32_t& chromeFlags,
       const ContentParentId& aCpId,
       const bool& aIsForBrowser) override;
   using PContentParent::SendPTestShellConstructor;
 
   FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
 
   ContentParent(ContentParent* aOpener,
-                bool aIsForBrowser);
+                const nsAString& aRemoteType);
 
   // The common initialization for the constructors.
   void InitializeMembers();
 
   // Launch the subprocess and associated initialization.
   // Returns false if the process fails to start.
   bool LaunchSubprocess(hal::ProcessPriority aInitialPriority = hal::PROCESS_PRIORITY_FOREGROUND);
 
@@ -1049,16 +1053,18 @@ private:
 
   // If you add strong pointers to cycle collected objects here, be sure to
   // release these objects in ShutDownProcess.  See the comment there for more
   // details.
 
   GeckoChildProcessHost* mSubprocess;
   ContentParent* mOpener;
 
+  nsString mRemoteType;
+
   ContentParentId mChildID;
   int32_t mGeolocationWatchID;
 
   nsCString mKillHardAnnotation;
 
   // After we initiate shutdown, we also start a timer to ensure
   // that even content processes that are 100% blocked (say from
   // SIGSTOP), are still killed eventually.  This task enforces that
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -511,16 +511,21 @@ child:
      * Shutdown accessibility engine in content process (if not in use).
      */
     async ShutdownA11y();
 
     async AppInfo(nsCString version, nsCString buildID, nsCString name, nsCString UAName,
                   nsCString ID, nsCString vendor);
 
     /**
+     * Send the remote type associated with the content process.
+     */
+    async RemoteType(nsString aRemoteType);
+
+    /**
      * Send ServiceWorkerRegistrationData to child process.
      */
     async InitServiceWorkers(ServiceWorkerConfiguration aConfig);
 
     /**
      * Send BlobURLRegistrationData to child process.
      */
     async InitBlobURLs(BlobURLRegistrationData[] registrations);
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -883,16 +883,29 @@ nsXULAppInfo::GetUniqueProcessID(uint64_
     ContentChild* cc = ContentChild::GetSingleton();
     *aResult = cc->GetID();
   } else {
     *aResult = 0;
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXULAppInfo::GetRemoteType(nsAString& aRemoteType)
+{
+  if (XRE_IsContentProcess()) {
+    ContentChild* cc = ContentChild::GetSingleton();
+    aRemoteType.Assign(cc->GetRemoteType());
+  } else {
+    SetDOMStringToNull(aRemoteType);
+  }
+
+  return NS_OK;
+}
+
 static bool gBrowserTabsRemoteAutostart = false;
 static uint64_t gBrowserTabsRemoteStatus = 0;
 static bool gBrowserTabsRemoteAutostartInitialized = false;
 
 static bool gMultiprocessBlockPolicyInitialized = false;
 static uint32_t gMultiprocessBlockPolicy = 0;
 
 NS_IMETHODIMP
--- a/xpcom/system/nsIXULRuntime.idl
+++ b/xpcom/system/nsIXULRuntime.idl
@@ -87,16 +87,22 @@ interface nsIXULRuntime : nsISupports
   readonly attribute unsigned long processID;
 
   /**
    * A globally unique and non-recycled ID of the caller's process.
    */
   readonly attribute uint64_t uniqueProcessID;
 
   /**
+   * The type of remote content process we're running in.
+   * null if we're in the parent/chrome process.
+   */
+  readonly attribute DOMString remoteType;
+
+  /**
    * If true, browser tabs may be opened by default in a different process
    * from the main browser UI.
    */
   readonly attribute boolean browserTabsRemoteAutostart;
 
   /**
    * A numeric value indicating whether multiprocess might be blocked.
    * Possible values can be found at nsAppRunner.cpp. A value of 0