Bug 558184 - Part 7 - Keep track of the content parent that opened a tab so that ContentProcessManager::GetTopLevelTabParent can walk up to the top level tab parent for a JS plugin tab child. r=kanru.
authorPeter Van der Beken <peterv@propagandism.org>
Mon, 16 Jan 2017 21:15:11 +0100
changeset 409916 e69bf3dbf73c58fb3e85ab95d8cb18a70aad6914
parent 409915 0aa594d8fb39d096c685a04ca69e1b68e081952d
child 409917 b31942dbee848f90041776eb0da2867b8ae9f59e
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskanru
bugs558184
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 558184 - Part 7 - Keep track of the content parent that opened a tab so that ContentProcessManager::GetTopLevelTabParent can walk up to the top level tab parent for a JS plugin tab child. r=kanru.
dom/ipc/ContentParent.cpp
dom/ipc/ContentProcessManager.cpp
dom/ipc/ContentProcessManager.h
dom/ipc/nsIContentParent.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -951,17 +951,17 @@ 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()) &&
-      cpm->RegisterRemoteFrame(aTabId, aOpenerTabId, aContext, cp->ChildID())) {
+      cpm->RegisterRemoteFrame(aTabId, ChildID(), aOpenerTabId, aContext, cp->ChildID())) {
     return IPC_OK();
   }
 
   return IPC_FAIL_NO_REASON(this);
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvBridgeToChildProcess(const ContentParentId& aCpId,
@@ -1183,16 +1183,17 @@ ContentParent::CreateBrowser(const TabCo
       constructorSender =
         GetNewOrUsedBrowserProcess(remoteType, initialPriority, nullptr);
       if (!constructorSender) {
         return nullptr;
       }
     }
     ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
     cpm->RegisterRemoteFrame(tabId,
+                             ContentParentId(0),
                              openerTabId,
                              aContext.AsIPCTabContext(),
                              constructorSender->ChildID());
   }
   if (constructorSender) {
     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
     docShell->GetTreeOwner(getter_AddRefs(treeOwner));
     if (!treeOwner) {
@@ -1586,27 +1587,27 @@ ContentParent::AllocateLayerTreeId(Conte
 mozilla::ipc::IPCResult
 ContentParent::RecvAllocateLayerTreeId(const ContentParentId& aCpId,
                                        const TabId& aTabId, uint64_t* aId)
 {
   // Protect against spoofing by a compromised child. aCpId must either
   // correspond to the process that this ContentParent represents or be a
   // child of it.
   ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+  RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId);
   if (ChildID() != aCpId) {
     ContentParentId parent;
-    if (!cpm->GetParentProcessId(aCpId, &parent) ||
+    if (!cpm->GetParentProcessId(contentParent->ChildID(), &parent) ||
         ChildID() != parent) {
       return IPC_FAIL_NO_REASON(this);
     }
   }
 
   // GetTopLevelTabParentByProcessAndTabId will make sure that aTabId
   // lives in the process for aCpId.
-  RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId);
   RefPtr<TabParent> browserParent =
     cpm->GetTopLevelTabParentByProcessAndTabId(aCpId, aTabId);
   MOZ_ASSERT(contentParent && browserParent);
 
   if (!AllocateLayerTreeId(contentParent, browserParent, aTabId, aId)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
--- a/dom/ipc/ContentProcessManager.cpp
+++ b/dom/ipc/ContentProcessManager.cpp
@@ -42,20 +42,24 @@ ContentProcessManager::GetSingleton()
 
 void
 ContentProcessManager::AddContentProcess(ContentParent* aChildCp,
                                          const ContentParentId& aParentCpId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aChildCp);
 
-  ContentProcessInfo info;
-  info.mCp = aChildCp;
+  ContentProcessInfo& info = mContentParentMap[aChildCp->ChildID()];
+  if (!info.mCp) {
+    info.mCp = aChildCp;
+  } else {
+    MOZ_ASSERT(info.mCp == aChildCp);
+    MOZ_ASSERT_IF(!!info.mParentCpId, info.mParentCpId == aParentCpId);
+  }
   info.mParentCpId = aParentCpId;
-  mContentParentMap[aChildCp->ChildID()] = info;
 }
 
 void
 ContentProcessManager::RemoveContentProcess(const ContentParentId& aChildCpId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mContentParentMap.find(aChildCpId) != mContentParentMap.end());
 
@@ -130,16 +134,17 @@ ContentProcessManager::GetAllChildProces
     cpIdArray.AppendElement(*cpIter);
   }
 
   return Move(cpIdArray);
 }
 
 bool
 ContentProcessManager::RegisterRemoteFrame(const TabId& aTabId,
+                                           const ContentParentId& aOpenerCpId,
                                            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())) {
@@ -153,27 +158,29 @@ ContentProcessManager::RegisterRemoteFra
   // 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 false;
     }
 
+    info.mOpenerCpId = remoteFrameIter->second.mOpenerCpId;
     info.mOpenerTabId = remoteFrameIter->second.mOpenerTabId;
     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 false;
     }
+    info.mOpenerCpId = aOpenerCpId;
     info.mOpenerTabId = aOpenerTabId;
     info.mContext = tc.GetTabContext();
   }
 
   iter->second.mRemoteFrames[aTabId] = info;
   return true;
 }
 
@@ -239,31 +246,33 @@ ContentProcessManager::GetTabContextByCo
   }
 
   return Move(tabContextArray);
 }
 
 bool
 ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
                                                  const TabId& aChildTabId,
+                                                 /*out*/ContentParentId* aOpenerCpId,
                                                  /*out*/TabId* aOpenerTabId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   auto iter = mContentParentMap.find(aChildCpId);
   if (NS_WARN_IF(iter == mContentParentMap.end())) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
   auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
   if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
+  *aOpenerCpId = remoteFrameIter->second.mOpenerCpId;
   *aOpenerTabId = remoteFrameIter->second.mOpenerTabId;
 
   return true;
 }
 
 already_AddRefed<TabParent>
 ContentProcessManager::GetTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
                                                      const TabId& aChildTabId)
@@ -305,18 +314,17 @@ ContentProcessManager::GetTopLevelTabPar
   // Stop this loop when the upper ContentParentId of
   // the current ContentParentId is chrome(ContentParentId = 0).
   do {
     // Update the current ContentParentId and TabId in iteration
     currentCpId = parentCpId;
     currentTabId = openerTabId;
 
     // Get the ContentParentId and TabId on upper level
-    if (!GetParentProcessId(currentCpId, &parentCpId) ||
-        !GetRemoteFrameOpenerTabId(currentCpId, currentTabId, &openerTabId)) {
+    if (!GetRemoteFrameOpenerTabId(currentCpId, currentTabId, &parentCpId, &openerTabId)) {
       return nullptr;
     }
   } while (parentCpId);
 
   // Get the top level TabParent by the current ContentParentId and TabId
   return GetTabParentByProcessAndTabId(currentCpId, currentTabId);
 }
 
--- a/dom/ipc/ContentProcessManager.h
+++ b/dom/ipc/ContentProcessManager.h
@@ -15,16 +15,17 @@
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 class ContentParent;
 
 struct RemoteFrameInfo
 {
+  ContentParentId mOpenerCpId;
   TabId mOpenerTabId;
   TabContext mContext;
 };
 
 struct ContentProcessInfo
 {
   ContentParent* mCp;
   ContentParentId mParentCpId;
@@ -74,16 +75,17 @@ public:
   /**
    * 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.
    */
   bool RegisterRemoteFrame(const TabId& aTabId,
+                           const ContentParentId& aOpenerCpId,
                            const TabId& aOpenerTabId,
                            const IPCTabContext& aContext,
                            const ContentParentId& aChildCpId);
 
 
   /**
    * Remove the RemoteFrameInfo by the given process and tab id.
    */
@@ -105,16 +107,17 @@ public:
   GetTabContextByContentProcess(const ContentParentId& aChildCpId);
 
   /**
    * Query a tab's opener id by the given process and tab id.
    * XXX Currently not used. Plan to be used for bug 1020179.
    */
   bool GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
                                  const TabId& aChildTabId,
+                                 /*out*/ContentParentId* aOpenerCpId,
                                  /*out*/ TabId* aOpenerTabId);
 
   /**
    * Get all TabParents' Ids managed by the givent content process.
    * Return empty array when TabParent couldn't be found via aChildCpId
    */
   nsTArray<TabId>
   GetTabParentsByProcessId(const ContentParentId& aChildCpId);
--- a/dom/ipc/nsIContentParent.cpp
+++ b/dom/ipc/nsIContentParent.cpp
@@ -133,23 +133,25 @@ nsIContentParent::AllocPBrowserParent(co
   Unused << aIsForBrowser;
 
   if (!CanOpenBrowser(aContext)) {
     return nullptr;
   }
 
   uint32_t chromeFlags = aChromeFlags;
   TabId openerTabId(0);
+  ContentParentId openerCpId(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();
+    openerCpId = opener->Manager()->ChildID();
 
     // We must ensure that the private browsing and remoteness flags
     // match those of the opener.
     nsCOMPtr<nsILoadContext> loadContext = opener->GetLoadContext();
     if (!loadContext) {
       return nullptr;
     }
 
@@ -173,17 +175,17 @@ nsIContentParent::AllocPBrowserParent(co
     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)) {
+    if (!cpm->RegisterRemoteFrame(aTabId, openerCpId, openerTabId, aContext, aCpId)) {
       return nullptr;
     }
   }
 
   // And because we're allocating a remote browser, of course the
   // window is remote.
   chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;