Bug 1147911 Part 6: Send remote type down to child. r=gijs, r=smaug
authorBob Owen <bobowencode@gmail.com>
Thu, 24 Nov 2016 15:08:31 +0000
changeset 324222 a5c21c2ae2c8e1b0bf4806924c1ab4ef4f5068cc
parent 324221 19e9ac4bb5ca12a3a60a7109e311c4eca3b94739
child 324223 fee9d778b2baee8eb1cfb744176008a9e394b3de
push id30993
push usercbook@mozilla.com
push dateFri, 25 Nov 2016 14:40:38 +0000
treeherdermozilla-central@b982373cb0e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgijs, smaug
bugs1147911
milestone53.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
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,17 +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,
+  cp = GetNewOrUsedBrowserProcess(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
                                   aPriority, this);
 
   if (!cp) {
     *aCpId = 0;
     *aIsForBrowser = false;
     return IPC_OK();
   }
 
@@ -958,19 +957,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.AssignLiteral(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 +1093,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 +1769,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
@@ -27,16 +27,21 @@
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIDOMGeoPositionErrorCallback.h"
 #include "nsRefPtrHashtable.h"
 #include "PermissionMessageUtils.h"
 #include "DriverCrashGuard.h"
 
 #define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown")
 
+#define NO_REMOTE_TYPE ""
+
+// This must match the one in E10SUtils.jsm.
+#define DEFAULT_REMOTE_TYPE "web"
+
 class nsConsoleService;
 class nsICycleCollectorLogSink;
 class nsIDumpGCAndCCLogsCallback;
 class nsITimer;
 class ParentIdleListener;
 class nsIWidget;
 
 namespace mozilla {
@@ -124,17 +129,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 = NS_LITERAL_STRING(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 +582,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 +1054,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