Bug 1337064 - Remove sync protocol PContent::AllocateTabId. r=kanru
authorSamael Wang <freesamael@gmail.com>
Wed, 05 Apr 2017 18:42:00 +0800
changeset 354993 a69ca6edbe974f884a85364e6063dc94af623a88
parent 354992 e65a474321e63b3997e18aa06fbc354aaf8abd7b
child 354994 a5cb0de6bdb2ffe13eb41dc5a85f61d79d1606a9
push id31719
push userkwierso@gmail.com
push dateWed, 26 Apr 2017 22:37:51 +0000
treeherdermozilla-central@745f2d85212d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskanru
bugs1337064
milestone55.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 1337064 - Remove sync protocol PContent::AllocateTabId. r=kanru Remove sync protocol AllocateTabId. Instead we generate tabId in each process with nsContentUtils::GenerateTabId, and register RemoteFrameInfo in parent process. If the tab id was generated from a content process, it's sent parent through either PBrowserConstructor or PContent::CreateChildProcess. MozReview-Commit-ID: D3W2fK9eCNH
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/ContentProcessManager.cpp
dom/ipc/ContentProcessManager.h
dom/ipc/PContent.ipdl
dom/ipc/TabParent.cpp
dom/ipc/nsIContentParent.cpp
ipc/ipdl/sync-messages.ini
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -10268,9 +10268,34 @@ nsContentUtils::IsLocalRefURL(const nsSt
     if (*current > 0x20) {
       // if the first non-"C0 controls + space" character is '#', this is a
       // local-ref URL.
       return *current == '#';
     }
   }
 
   return false;
-}
\ No newline at end of file
+}
+
+// Tab ID is composed in a similar manner of Window ID.
+static uint64_t gNextTabId = 0;
+static const uint64_t kTabIdProcessBits = 32;
+static const uint64_t kTabIdTabBits = 64 - kTabIdProcessBits;
+
+/* static */ uint64_t
+nsContentUtils::GenerateTabId()
+{
+  uint64_t processId = 0;
+  if (XRE_IsContentProcess()) {
+    ContentChild* cc = ContentChild::GetSingleton();
+    processId = cc->GetID();
+  }
+
+  MOZ_RELEASE_ASSERT(processId < (uint64_t(1) << kTabIdProcessBits));
+  uint64_t processBits = processId & ((uint64_t(1) << kTabIdProcessBits) - 1);
+
+  uint64_t tabId = ++gNextTabId;
+  MOZ_RELEASE_ASSERT(tabId < (uint64_t(1) << kTabIdTabBits));
+  uint64_t tabBits = tabId & ((uint64_t(1) << kTabIdTabBits) - 1);
+
+  return (processBits << kTabIdTabBits) | tabBits;
+
+}
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2868,16 +2868,21 @@ public:
    * https://drafts.csswg.org/css-values/#local-urls
    */
   static bool
   IsLocalRefURL(const nsString& aString);
 
   static bool
   IsCustomElementsEnabled() { return sIsCustomElementsEnabled; }
 
+  /**
+   * Compose a tab id with process id and a serial number.
+   */
+  static uint64_t GenerateTabId();
+
 private:
   static bool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static bool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
                                 nsIPrincipal* aPrincipal);
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -769,21 +769,17 @@ ContentChild::ProvideWindowCommon(TabChi
   } else {
     // It's possible to not have a TabChild opener in the case
     // of ServiceWorker::OpenWindow.
     UnsafeIPCTabContext unsafeTabContext;
     ipcContext = new IPCTabContext(unsafeTabContext);
   }
 
   MOZ_ASSERT(ipcContext);
-  TabId tabId;
-  SendAllocateTabId(openerTabId,
-                    *ipcContext,
-                    GetID(),
-                    &tabId);
+  TabId tabId(nsContentUtils::GenerateTabId());
 
   // We need to assign a TabGroup to the PBrowser actor before we send it to the
   // parent. Otherwise, the parent could send messages to us before we have a
   // proper TabGroup for that actor.
   RefPtr<TabGroup> tabGroup;
   if (aTabOpener && !aForceNoOpener) {
     // The new actor will use the same tab group as the opener.
     tabGroup = aTabOpener->TabGroup();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -904,19 +904,19 @@ ContentParent::SendAsyncUpdate(nsIWidget
   }
 }
 #endif // defined(XP_WIN)
 
 mozilla::ipc::IPCResult
 ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
                                       const hal::ProcessPriority& aPriority,
                                       const TabId& aOpenerTabId,
+                                      const TabId& aTabId,
                                       ContentParentId* aCpId,
-                                      bool* aIsForBrowser,
-                                      TabId* aTabId)
+                                      bool* aIsForBrowser)
 {
 #if 0
   if (!CanOpenBrowser(aContext)) {
       return false;
   }
 #endif
   RefPtr<ContentParent> cp;
   MaybeInvalidTabContext tc(aContext);
@@ -937,22 +937,18 @@ ContentParent::RecvCreateChildProcess(co
   }
 
   *aCpId = cp->ChildID();
   *aIsForBrowser = cp->IsForBrowser();
 
   ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
   cpm->AddContentProcess(cp, this->ChildID());
 
-  if (cpm->AddGrandchildProcess(this->ChildID(), cp->ChildID())) {
-    // Pre-allocate a TabId here to save one time IPC call at app startup.
-    *aTabId = AllocateTabId(aOpenerTabId, aContext, cp->ChildID());
-    if (*aTabId == 0) {
-      return IPC_FAIL_NO_REASON(this);
-    }
+  if (cpm->AddGrandchildProcess(this->ChildID(), cp->ChildID()) &&
+      cpm->RegisterRemoteFrame(aTabId, aOpenerTabId, aContext, cp->ChildID())) {
     return IPC_OK();
   }
 
   return IPC_FAIL_NO_REASON(this);
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvBridgeToChildProcess(const ContentParentId& aCpId,
@@ -1174,17 +1170,17 @@ ContentParent::CreateBrowser(const TabCo
                  "Shouldn't have an owner elemnt before");
       parent->SetOwnerElement(aFrameElement);
       return parent;
     }
   }
 
   ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
   bool isInContentProcess = !XRE_IsParentProcess();
-  TabId tabId;
+  TabId tabId(nsContentUtils::GenerateTabId());
 
   nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
   TabId openerTabId;
   if (docShell) {
     openerTabId = TabParent::GetTabIdFrom(docShell);
   }
 
   nsAutoString remoteType;
@@ -1192,30 +1188,32 @@ ContentParent::CreateBrowser(const TabCo
                               remoteType)) {
     remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
   }
 
   RefPtr<nsIContentParent> constructorSender;
   if (isInContentProcess) {
     MOZ_ASSERT(aContext.IsMozBrowserElement());
     constructorSender = CreateContentBridgeParent(aContext, initialPriority,
-                                                  openerTabId, &tabId);
+                                                  openerTabId, tabId);
   } else {
     if (aOpenerContentParent) {
       constructorSender = aOpenerContentParent;
     } else {
       constructorSender =
         GetNewOrUsedBrowserProcess(remoteType, initialPriority, nullptr);
       if (!constructorSender) {
         return nullptr;
       }
     }
-    tabId = AllocateTabId(openerTabId,
-                          aContext.AsIPCTabContext(),
-                          constructorSender->ChildID());
+    ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+    cpm->RegisterRemoteFrame(tabId,
+                             openerTabId,
+                             aContext.AsIPCTabContext(),
+                             constructorSender->ChildID());
   }
   if (constructorSender) {
     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
     docShell->GetTreeOwner(getter_AddRefs(treeOwner));
     if (!treeOwner) {
       return nullptr;
     }
 
@@ -1265,29 +1263,29 @@ ContentParent::CreateBrowser(const TabCo
   }
   return nullptr;
 }
 
 /*static*/ ContentBridgeParent*
 ContentParent::CreateContentBridgeParent(const TabContext& aContext,
                                          const hal::ProcessPriority& aPriority,
                                          const TabId& aOpenerTabId,
-                                         /*out*/ TabId* aTabId)
+                                         const TabId& aTabId)
 {
   MOZ_ASSERT(aTabId);
 
   ContentChild* child = ContentChild::GetSingleton();
   ContentParentId cpId;
   bool isForBrowser;
   if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(),
                                      aPriority,
                                      aOpenerTabId,
+                                     aTabId,
                                      &cpId,
-                                     &isForBrowser,
-                                     aTabId)) {
+                                     &isForBrowser)) {
     return nullptr;
   }
   if (cpId == 0) {
     return nullptr;
   }
   Endpoint<PContentBridgeParent> endpoint;
   if (!child->SendBridgeToChildProcess(cpId, &endpoint)) {
     return nullptr;
@@ -4211,72 +4209,40 @@ ContentParent::NotifyUpdatedDictionaries
   InfallibleTArray<nsString> dictionaries;
   spellChecker->GetDictionaryList(&dictionaries);
 
   for (auto* cp : AllProcesses(eLive)) {
     Unused << cp->SendUpdateDictionaryList(dictionaries);
   }
 }
 
-/*static*/ TabId
-ContentParent::AllocateTabId(const TabId& aOpenerTabId,
-                             const IPCTabContext& aContext,
-                             const ContentParentId& aCpId)
-{
-  TabId tabId;
-  if (XRE_IsParentProcess()) {
-    ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
-    tabId = cpm->AllocateTabId(aOpenerTabId, aContext, aCpId);
-  }
-  else {
-    ContentChild::GetSingleton()->SendAllocateTabId(aOpenerTabId,
-                                                      aContext,
-                                                      aCpId,
-                                                      &tabId);
-  }
-  return tabId;
-}
-
 /*static*/ void
-ContentParent::DeallocateTabId(const TabId& aTabId,
+ContentParent::UnregisterRemoteFrame(const TabId& aTabId,
                                const ContentParentId& aCpId,
                                bool aMarkedDestroying)
 {
   if (XRE_IsParentProcess()) {
     ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
     ContentParent* cp = cpm->GetContentProcessById(aCpId);
 
     cp->NotifyTabDestroyed(aTabId, aMarkedDestroying);
 
-    ContentProcessManager::GetSingleton()->DeallocateTabId(aCpId, aTabId);
+    ContentProcessManager::GetSingleton()->UnregisterRemoteFrame(aCpId, aTabId);
   } else {
-    ContentChild::GetSingleton()->SendDeallocateTabId(aTabId, aCpId,
+    ContentChild::GetSingleton()->SendUnregisterRemoteFrame(aTabId, aCpId,
                                                       aMarkedDestroying);
   }
 }
 
 mozilla::ipc::IPCResult
-ContentParent::RecvAllocateTabId(const TabId& aOpenerTabId,
-                                 const IPCTabContext& aContext,
-                                 const ContentParentId& aCpId,
-                                 TabId* aTabId)
-{
-  *aTabId = AllocateTabId(aOpenerTabId, aContext, aCpId);
-  if (!(*aTabId)) {
-    return IPC_FAIL_NO_REASON(this);
-  }
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-ContentParent::RecvDeallocateTabId(const TabId& aTabId,
+ContentParent::RecvUnregisterRemoteFrame(const TabId& aTabId,
                                    const ContentParentId& aCpId,
                                    const bool& aMarkedDestroying)
 {
-  DeallocateTabId(aTabId, aCpId, aMarkedDestroying);
+  UnregisterRemoteFrame(aTabId, aCpId, aMarkedDestroying);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvNotifyTabDestroying(const TabId& aTabId,
                                        const ContentParentId& aCpId)
 {
   NotifyTabDestroying(aTabId, aCpId);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -274,19 +274,19 @@ public:
 #endif
 
   // Let managees query if it is safe to send messages.
   bool IsDestroyed() const { return !mIPCOpen; }
 
   virtual mozilla::ipc::IPCResult RecvCreateChildProcess(const IPCTabContext& aContext,
                                                          const hal::ProcessPriority& aPriority,
                                                          const TabId& aOpenerTabId,
+                                                         const TabId& aTabId,
                                                          ContentParentId* aCpId,
-                                                         bool* aIsForBrowser,
-                                                         TabId* aTabId) override;
+                                                         bool* aIsForBrowser) override;
 
   virtual mozilla::ipc::IPCResult RecvBridgeToChildProcess(const ContentParentId& aCpId,
                                                            Endpoint<PContentBridgeParent>* aEndpoint) override;
 
   virtual mozilla::ipc::IPCResult RecvCreateGMPService() override;
 
   virtual mozilla::ipc::IPCResult RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv,
                                                  uint32_t* aRunID,
@@ -345,25 +345,20 @@ public:
   TestShellParent* CreateTestShell();
 
   bool DestroyTestShell(TestShellParent* aTestShell);
 
   TestShellParent* GetTestShellSingleton();
 
   jsipc::CPOWManager* GetCPOWManager() override;
 
-  static TabId
-  AllocateTabId(const TabId& aOpenerTabId,
-                const IPCTabContext& aContext,
-                const ContentParentId& aCpId);
-
   static void
-  DeallocateTabId(const TabId& aTabId,
-                  const ContentParentId& aCpId,
-                  bool aMarkedDestroying);
+  UnregisterRemoteFrame(const TabId& aTabId,
+                        const ContentParentId& aCpId,
+                        bool aMarkedDestroying);
 
   void ReportChildAlreadyBlocked();
 
   bool RequestRunToCompletion();
 
   bool IsAvailable() const
   {
     return mIsAvailable;
@@ -484,24 +479,19 @@ public:
   bool CycleCollectWithLogs(bool aDumpAllTraces,
                             nsICycleCollectorLogSink* aSink,
                             nsIDumpGCAndCCLogsCallback* aCallback);
 
   virtual PBlobParent*
   SendPBlobConstructor(PBlobParent* aActor,
                        const BlobConstructorParams& aParams) override;
 
-  virtual mozilla::ipc::IPCResult RecvAllocateTabId(const TabId& aOpenerTabId,
-                                                    const IPCTabContext& aContext,
-                                                    const ContentParentId& aCpId,
-                                                    TabId* aTabId) override;
-
-  virtual mozilla::ipc::IPCResult RecvDeallocateTabId(const TabId& aTabId,
-                                                      const ContentParentId& aCpId,
-                                                      const bool& aMarkedDestroying) override;
+  virtual mozilla::ipc::IPCResult RecvUnregisterRemoteFrame(const TabId& aTabId,
+                                                            const ContentParentId& aCpId,
+                                                            const bool& aMarkedDestroying) override;
 
   virtual mozilla::ipc::IPCResult RecvNotifyTabDestroying(const TabId& aTabId,
                                                           const ContentParentId& aCpId) override;
 
   virtual mozilla::ipc::IPCResult RecvTabChildNotReady(const TabId& aTabId) override;
 
   nsTArray<TabContext> GetManagedTabContext();
 
@@ -689,17 +679,17 @@ private:
   static void JoinProcessesIOThread(const nsTArray<ContentParent*>* aProcesses,
                                     Monitor* aMonitor, bool* aDone);
 
   static hal::ProcessPriority GetInitialProcessPriority(Element* aFrameElement);
 
   static ContentBridgeParent* CreateContentBridgeParent(const TabContext& aContext,
                                                         const hal::ProcessPriority& aPriority,
                                                         const TabId& aOpenerTabId,
-                                                        /*out*/ TabId* aTabId);
+                                                        const TabId& aTabId);
 
   // Hide the raw constructor methods since we don't want client code
   // using them.
   virtual PBrowserParent* SendPBrowserConstructor(
       PBrowserParent* actor,
       const TabId& aTabId,
       const TabId& aSameTabGroupsAs,
       const IPCTabContext& context,
--- a/dom/ipc/ContentProcessManager.cpp
+++ b/dom/ipc/ContentProcessManager.cpp
@@ -19,18 +19,16 @@
 #define ASSERT_UNLESS_FUZZING(...) do { } while (0)
 #else
 #define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
 #endif
 
 namespace mozilla {
 namespace dom {
 
-static uint64_t gTabId = 0;
-
 /* static */
 StaticAutoPtr<ContentProcessManager>
 ContentProcessManager::sSingleton;
 
 /* static */ ContentProcessManager*
 ContentProcessManager::GetSingleton()
 {
   MOZ_ASSERT(XRE_IsParentProcess());
@@ -130,74 +128,63 @@ ContentProcessManager::GetAllChildProces
        cpIter != iter->second.mChildrenCpId.end();
        ++cpIter) {
     cpIdArray.AppendElement(*cpIter);
   }
 
   return Move(cpIdArray);
 }
 
-TabId
-ContentProcessManager::AllocateTabId(const TabId& aOpenerTabId,
-                                     const IPCTabContext& aContext,
-                                     const ContentParentId& aChildCpId)
+bool
+ContentProcessManager::RegisterRemoteFrame(const TabId& aTabId,
+                                           const TabId& aOpenerTabId,
+                                           const IPCTabContext& aContext,
+                                           const ContentParentId& aChildCpId)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   auto iter = mContentParentMap.find(aChildCpId);
   if (NS_WARN_IF(iter == mContentParentMap.end())) {
     ASSERT_UNLESS_FUZZING();
-    return TabId(0);
+    return false;
   }
 
   struct RemoteFrameInfo info;
 
   // If it's a PopupIPCTabContext, it's the case that a TabChild want to
   // open a new tab. aOpenerTabId has to be it's parent frame's opener id.
   if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
     auto remoteFrameIter = iter->second.mRemoteFrames.find(aOpenerTabId);
     if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
       ASSERT_UNLESS_FUZZING("Failed to find parent frame's opener id.");
-      return TabId(0);
+      return false;
     }
 
     info.mOpenerTabId = remoteFrameIter->second.mOpenerTabId;
-
-    const PopupIPCTabContext &ipcContext = aContext.get_PopupIPCTabContext();
-    MOZ_ASSERT(ipcContext.opener().type() == PBrowserOrId::TTabId);
-
-    remoteFrameIter = iter->second.mRemoteFrames.find(ipcContext.opener().get_TabId());
-    if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
-      ASSERT_UNLESS_FUZZING("Failed to find tab id.");
-      return TabId(0);
-    }
-
     info.mContext = remoteFrameIter->second.mContext;
   }
   else {
     MaybeInvalidTabContext tc(aContext);
     if (!tc.IsValid()) {
       NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
                                "the child process. (%s)",
                                tc.GetInvalidReason()).get());
-      return TabId(0);
+      return false;
     }
     info.mOpenerTabId = aOpenerTabId;
     info.mContext = tc.GetTabContext();
   }
 
-  mUniqueId = ++gTabId;
-  iter->second.mRemoteFrames[mUniqueId] = info;
-
-  return mUniqueId;
+  iter->second.mRemoteFrames[aTabId] = info;
+  return true;
 }
 
 void
-ContentProcessManager::DeallocateTabId(const ContentParentId& aChildCpId,
-                                       const TabId& aChildTabId)
+ContentProcessManager::UnregisterRemoteFrame(const ContentParentId& aChildCpId,
+                                             const TabId& aChildTabId)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   auto iter = mContentParentMap.find(aChildCpId);
   if (NS_WARN_IF(iter == mContentParentMap.end())) {
     ASSERT_UNLESS_FUZZING();
     return;
   }
--- a/dom/ipc/ContentProcessManager.h
+++ b/dom/ipc/ContentProcessManager.h
@@ -67,31 +67,33 @@ public:
 
   /**
    * Return a list of all child process's id.
    */
   nsTArray<ContentParentId>
   GetAllChildProcessById(const ContentParentId& aParentCpId);
 
   /**
-   * Allocate a tab id for the given content process's id.
+   * Register RemoteFrameInfo with given tab id.
    * Used when a content process wants to create a new tab. aOpenerTabId and
    * aContext are saved in RemoteFrameInfo, which is a part of
    * ContentProcessInfo.  We can use the tab id and process id to locate the
    * TabContext for future use.
    */
-  TabId AllocateTabId(const TabId& aOpenerTabId,
-                      const IPCTabContext& aContext,
-                      const ContentParentId& aChildCpId);
+  bool RegisterRemoteFrame(const TabId& aTabId,
+                           const TabId& aOpenerTabId,
+                           const IPCTabContext& aContext,
+                           const ContentParentId& aChildCpId);
+
 
   /**
    * Remove the RemoteFrameInfo by the given process and tab id.
    */
-  void DeallocateTabId(const ContentParentId& aChildCpId,
-                       const TabId& aChildTabId);
+  void UnregisterRemoteFrame(const ContentParentId& aChildCpId,
+                             const TabId& aChildTabId);
 
   /**
    * Get the TabContext by the given content process and tab id.
    */
   bool
   GetTabContextByProcessAndTabId(const ContentParentId& aChildCpId,
                                  const TabId& aChildTabId,
                                  /*out*/ TabContext* aTabContext);
@@ -146,17 +148,16 @@ public:
    *  is belong to the chrome process.
    */
   already_AddRefed<TabParent>
   GetTopLevelTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
                                         const TabId& aChildTabId);
 
 private:
   static StaticAutoPtr<ContentProcessManager> sSingleton;
-  TabId mUniqueId;
   std::map<ContentParentId, ContentProcessInfo> mContentParentMap;
 
   ContentProcessManager() {MOZ_COUNT_CTOR(ContentProcessManager);};
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -618,18 +618,19 @@ child:
 
     async PIPCBlobInputStream(nsID aID, uint64_t aSize);
 
 parent:
     async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
 
     sync CreateChildProcess(IPCTabContext context,
                             ProcessPriority priority,
-                            TabId openerTabId)
-        returns (ContentParentId cpId, bool isForBrowser, TabId tabId);
+                            TabId openerTabId,
+                            TabId tabId)
+        returns (ContentParentId cpId, bool isForBrowser);
     sync BridgeToChildProcess(ContentParentId cpId)
         returns (Endpoint<PContentBridgeParent> endpoint);
 
     async CreateGMPService();
 
     /**
      * This call connects the content process to a plugin process. This call
      * returns an endpoint for a new PluginModuleParent. The corresponding
@@ -909,25 +910,20 @@ parent:
         returns (nsString newValue);
 
     /**
      * Called to provide the options for <keygen> elements.
      */
     sync KeygenProvideContent()
         returns (nsString aAttribute, nsString[] aContent);
 
-    /**
-     * Tell the chrome process there is an creation of PBrowser.
-     * return a system-wise unique Id.
-     */
-    sync AllocateTabId(TabId openerTabId, IPCTabContext context, ContentParentId cpId)
-        returns (TabId tabId);
-    async DeallocateTabId(TabId tabId,
-                          ContentParentId cpId,
-                          bool aMarkedDestroying);
+    /** Clear RemoteFrameInfo of the given tab id. */
+    async UnregisterRemoteFrame(TabId tabId,
+                                ContentParentId cpId,
+                                bool aMarkedDestroying);
 
     /**
      * Tell the chrome process there is a destruction of PBrowser(Tab)
      */
     async NotifyTabDestroying(TabId tabId,
                               ContentParentId cpId);
 
     async TabChildNotReady(TabId tabId);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -408,25 +408,25 @@ TabParent::RecvEnsureLayersConnected(Com
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabParent::Recv__delete__()
 {
   if (XRE_IsParentProcess()) {
-    ContentParent::DeallocateTabId(mTabId,
-                                   Manager()->AsContentParent()->ChildID(),
-                                   mMarkedDestroying);
+    ContentParent::UnregisterRemoteFrame(mTabId,
+                                         Manager()->AsContentParent()->ChildID(),
+                                         mMarkedDestroying);
   }
   else {
     Manager()->AsContentBridgeParent()->NotifyTabDestroyed();
-    ContentParent::DeallocateTabId(mTabId,
-                                   Manager()->ChildID(),
-                                   mMarkedDestroying);
+    ContentParent::UnregisterRemoteFrame(mTabId,
+                                         Manager()->ChildID(),
+                                         mMarkedDestroying);
   }
 
   return IPC_OK();
 }
 
 void
 TabParent::ActorDestroy(ActorDestroyReason why)
 {
--- a/dom/ipc/nsIContentParent.cpp
+++ b/dom/ipc/nsIContentParent.cpp
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIContentParent.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentBridgeParent.h"
+#include "mozilla/dom/ContentProcessManager.h"
 #include "mozilla/dom/PTabContext.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
 #include "mozilla/dom/ipc/MemoryStreamParent.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
@@ -133,36 +134,62 @@ nsIContentParent::AllocPBrowserParent(co
   Unused << aCpId;
   Unused << aIsForBrowser;
 
   if (!CanOpenBrowser(aContext)) {
     return nullptr;
   }
 
   uint32_t chromeFlags = aChromeFlags;
+  TabId openerTabId(0);
   if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
     // CanOpenBrowser has ensured that the IPCTabContext is of
     // type PopupIPCTabContext, and that the opener TabParent is
     // reachable.
     const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
     auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
+    openerTabId = opener->GetTabId();
+
     // We must ensure that the private browsing and remoteness flags
     // match those of the opener.
     nsCOMPtr<nsILoadContext> loadContext = opener->GetLoadContext();
     if (!loadContext) {
       return nullptr;
     }
 
     bool isPrivate;
     loadContext->GetUsePrivateBrowsing(&isPrivate);
     if (isPrivate) {
       chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
     }
   }
 
+  if (openerTabId > 0 ||
+      aContext.type() == IPCTabContext::TUnsafeIPCTabContext) {
+    // Creation of PBrowser triggered from grandchild process is currently
+    // broken and not supported (i.e. this code path doesn't work in
+    // ContentBridgeParent).
+    //
+    // If you're working on fixing the code path for ContentBridgeParent,
+    // remember to handle the remote frame registration below carefully as it
+    // has to be registered in parent process.
+    MOZ_ASSERT(XRE_IsParentProcess());
+    if (!XRE_IsParentProcess()) {
+      return nullptr;
+    }
+
+    // The creation of PBrowser was triggered from content process through
+    // either window.open() or service worker's openWindow().
+    // We need to register remote frame with the child generated tab id.
+    ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+    if (!cpm->RegisterRemoteFrame(aTabId, openerTabId, aContext, aCpId)) {
+      return nullptr;
+    }
+  }
+
   // And because we're allocating a remote browser, of course the
   // window is remote.
   chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
 
   MaybeInvalidTabContext tc(aContext);
   MOZ_ASSERT(tc.IsValid());
   TabParent* parent = new TabParent(this, aTabId, tc.GetTabContext(), chromeFlags);
 
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -912,18 +912,16 @@ description =
 [PContent::BeginDriverCrashGuard]
 description =
 [PContent::EndDriverCrashGuard]
 description =
 [PContent::KeygenProcessValue]
 description =
 [PContent::KeygenProvideContent]
 description =
-[PContent::AllocateTabId]
-description =
 [PContent::GetGraphicsDeviceInitData]
 description =
 [PContent::CreateWindow]
 description =
 [PContent::GetAndroidSystemInfo]
 description =
 [PContent::UngrabPointer]
 description =