123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "ContentProcessManager.h"
- #include "ContentParent.h"
- #include "mozilla/dom/TabParent.h"
- #include "mozilla/StaticPtr.h"
- #include "mozilla/ClearOnShutdown.h"
- #include "nsPrintfCString.h"
- #include "nsIScriptSecurityManager.h"
- // XXX need another bug to move this to a common header.
- #ifdef DISABLE_ASSERTS_FOR_FUZZING
- #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());
- if (!sSingleton) {
- sSingleton = new ContentProcessManager();
- ClearOnShutdown(&sSingleton);
- }
- return sSingleton;
- }
- void
- ContentProcessManager::AddContentProcess(ContentParent* aChildCp,
- const ContentParentId& aParentCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aChildCp);
- ContentProcessInfo info;
- info.mCp = aChildCp;
- info.mParentCpId = aParentCpId;
- mContentParentMap[aChildCp->ChildID()] = info;
- }
- void
- ContentProcessManager::RemoveContentProcess(const ContentParentId& aChildCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mContentParentMap.find(aChildCpId) != mContentParentMap.end());
- mContentParentMap.erase(aChildCpId);
- for (auto iter = mContentParentMap.begin();
- iter != mContentParentMap.end();
- ++iter) {
- if (!iter->second.mChildrenCpId.empty()) {
- iter->second.mChildrenCpId.erase(aChildCpId);
- }
- }
- }
- bool
- ContentProcessManager::AddGrandchildProcess(const ContentParentId& aParentCpId,
- const ContentParentId& aChildCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- auto iter = mContentParentMap.find(aParentCpId);
- if (NS_WARN_IF(iter == mContentParentMap.end())) {
- ASSERT_UNLESS_FUZZING("Parent process should be already in map!");
- return false;
- }
- iter->second.mChildrenCpId.insert(aChildCpId);
- return true;
- }
- bool
- ContentProcessManager::GetParentProcessId(const ContentParentId& aChildCpId,
- /*out*/ ContentParentId* aParentCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- auto iter = mContentParentMap.find(aChildCpId);
- if (NS_WARN_IF(iter == mContentParentMap.end())) {
- ASSERT_UNLESS_FUZZING();
- return false;
- }
- *aParentCpId = iter->second.mParentCpId;
- return true;
- }
- ContentParent*
- ContentProcessManager::GetContentProcessById(const ContentParentId& aChildCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- auto iter = mContentParentMap.find(aChildCpId);
- if (NS_WARN_IF(iter == mContentParentMap.end())) {
- ASSERT_UNLESS_FUZZING();
- return nullptr;
- }
- return iter->second.mCp;
- }
- nsTArray<ContentParentId>
- ContentProcessManager::GetAllChildProcessById(const ContentParentId& aParentCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsTArray<ContentParentId> cpIdArray;
- auto iter = mContentParentMap.find(aParentCpId);
- if (NS_WARN_IF(iter == mContentParentMap.end())) {
- ASSERT_UNLESS_FUZZING();
- return Move(cpIdArray);
- }
- for (auto cpIter = iter->second.mChildrenCpId.begin();
- cpIter != iter->second.mChildrenCpId.end();
- ++cpIter) {
- cpIdArray.AppendElement(*cpIter);
- }
- return Move(cpIdArray);
- }
- TabId
- ContentProcessManager::AllocateTabId(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);
- }
- 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);
- }
- 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);
- }
- info.mOpenerTabId = aOpenerTabId;
- info.mContext = tc.GetTabContext();
- }
- mUniqueId = ++gTabId;
- iter->second.mRemoteFrames[mUniqueId] = info;
- return mUniqueId;
- }
- void
- ContentProcessManager::DeallocateTabId(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;
- }
- auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
- if (remoteFrameIter != iter->second.mRemoteFrames.end()) {
- iter->second.mRemoteFrames.erase(aChildTabId);
- }
- }
- bool
- ContentProcessManager::GetTabContextByProcessAndTabId(const ContentParentId& aChildCpId,
- const TabId& aChildTabId,
- /*out*/ TabContext* aTabContext)
- {
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aTabContext);
- 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;
- }
- *aTabContext = remoteFrameIter->second.mContext;
- return true;
- }
- nsTArray<TabContext>
- ContentProcessManager::GetTabContextByContentProcess(const ContentParentId& aChildCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsTArray<TabContext> tabContextArray;
- auto iter = mContentParentMap.find(aChildCpId);
- if (NS_WARN_IF(iter == mContentParentMap.end())) {
- ASSERT_UNLESS_FUZZING();
- return Move(tabContextArray);
- }
- for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
- remoteFrameIter != iter->second.mRemoteFrames.end();
- ++remoteFrameIter) {
- tabContextArray.AppendElement(remoteFrameIter->second.mContext);
- }
- return Move(tabContextArray);
- }
- bool
- ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
- const TabId& aChildTabId,
- /*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;
- }
- *aOpenerTabId = remoteFrameIter->second.mOpenerTabId;
- return true;
- }
- already_AddRefed<TabParent>
- ContentProcessManager::GetTabParentByProcessAndTabId(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 nullptr;
- }
- const ManagedContainer<PBrowserParent>& browsers = iter->second.mCp->ManagedPBrowserParent();
- for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
- RefPtr<TabParent> tab = TabParent::GetFrom(iter.Get()->GetKey());
- if (tab->GetTabId() == aChildTabId) {
- return tab.forget();
- }
- }
- return nullptr;
- }
- already_AddRefed<TabParent>
- ContentProcessManager::GetTopLevelTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
- const TabId& aChildTabId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- // Used to keep the current ContentParentId and the current TabId
- // in the iteration(do-while loop below)
- ContentParentId currentCpId;
- TabId currentTabId;
- // To get the ContentParentId and the TabParentId on upper level
- ContentParentId parentCpId = aChildCpId;
- TabId openerTabId = aChildTabId;
- // 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)) {
- return nullptr;
- }
- } while (parentCpId);
- // Get the top level TabParent by the current ContentParentId and TabId
- return GetTabParentByProcessAndTabId(currentCpId, currentTabId);
- }
- nsTArray<TabId>
- ContentProcessManager::GetTabParentsByProcessId(const ContentParentId& aChildCpId)
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsTArray<TabId> tabIdList;
- auto iter = mContentParentMap.find(aChildCpId);
- if (NS_WARN_IF(iter == mContentParentMap.end())) {
- ASSERT_UNLESS_FUZZING();
- return Move(tabIdList);
- }
- for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
- remoteFrameIter != iter->second.mRemoteFrames.end();
- ++remoteFrameIter) {
- tabIdList.AppendElement(remoteFrameIter->first);
- }
- return Move(tabIdList);
- }
- uint32_t
- ContentProcessManager::GetAppIdByProcessAndTabId(const ContentParentId& aChildCpId,
- const TabId& aChildTabId)
- {
- uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
- if (aChildCpId && aChildTabId) {
- TabContext tabContext;
- if (GetTabContextByProcessAndTabId(aChildCpId, aChildTabId, &tabContext)) {
- appId = tabContext.OwnOrContainingAppId();
- }
- }
- return appId;
- }
- } // namespace dom
- } // namespace mozilla
|