Bug 1337064 - Remove sync protocol PContent::AllocateTabId. r?kanru draft
authorSamael Wang <freesamael@gmail.com>
Wed, 05 Apr 2017 18:42:00 +0800
changeset 568382 01ba4c689923deec847e87e1a2ebb4967309bd95
parent 567113 e17cbb839dd225a2da7e5d5bec43cf94e11749d8
child 625908 f0d8141f14beb3d577c096e48ed6a91cd7b3e08a
push id55851
push userbmo:sawang@mozilla.com
push dateWed, 26 Apr 2017 03:40:42 +0000
reviewerskanru
bugs1337064
milestone55.0a1
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
@@ -10269,9 +10269,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
@@ -767,21 +767,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
@@ -898,19 +898,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);
@@ -931,22 +931,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,
@@ -1162,17 +1158,17 @@ ContentParent::CreateBrowser(const TabCo
 
   if (TabParent* parent = TabParent::GetNextTabParent()) {
     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;
@@ -1180,30 +1176,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;
     }
 
@@ -1253,29 +1251,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;
@@ -4165,72 +4163,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
@@ -273,19 +273,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,
@@ -344,25 +344,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;
@@ -483,24 +478,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();
 
@@ -688,17 +678,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
@@ -609,18 +609,19 @@ child:
 
     async RefreshScreens(ScreenDetails[] aScreens);
 
 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
@@ -900,25 +901,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/MemoryStreamParent.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/ipc/FileDescriptorSetParent.h"
@@ -132,36 +133,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 =