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; const IPCTabContextUnion& contextUnion = aContext.contextUnion(); // 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 (contextUnion.type() == IPCTabContextUnion::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 = contextUnion.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; }
bool nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext) { // (PopupIPCTabContext lets the child process prove that it has access to // the app it's trying to open.) // On e10s we also allow UnsafeTabContext to allow service workers to open // windows. This is enforced in MaybeInvalidTabContext. if (aContext.type() != IPCTabContext::TPopupIPCTabContext && aContext.type() != IPCTabContext::TUnsafeIPCTabContext) { ASSERT_UNLESS_FUZZING("Unexpected IPCTabContext type. Aborting AllocPBrowserParent."); return false; } if (aContext.type() == IPCTabContext::TPopupIPCTabContext) { const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext(); if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) { ASSERT_UNLESS_FUZZING("Unexpected PopupIPCTabContext type. Aborting AllocPBrowserParent."); return false; } auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent()); if (!opener) { ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent."); return false; } // Popup windows of isMozBrowserElement frames must be isMozBrowserElement if // the parent isMozBrowserElement. Allocating a !isMozBrowserElement frame with // same app ID would allow the content to access data it's not supposed to. if (!popupContext.isMozBrowserElement() && opener->IsMozBrowserElement()) { ASSERT_UNLESS_FUZZING("Child trying to escalate privileges! Aborting AllocPBrowserParent."); return false; } } MaybeInvalidTabContext tc(aContext); if (!tc.IsValid()) { NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) " "Aborting AllocPBrowserParent.", tc.GetInvalidReason()).get()); return false; } return true; }
bool nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext) { const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext(); // We don't trust the IPCTabContext we receive from the child, so we'll bail // if we receive an IPCTabContext that's not a PopupIPCTabContext. // (PopupIPCTabContext lets the child process prove that it has access to // the app it's trying to open.) if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) { ASSERT_UNLESS_FUZZING("Unexpected IPCTabContext type. Aborting AllocPBrowserParent."); return false; } const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext(); if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) { ASSERT_UNLESS_FUZZING("Unexpected PopupIPCTabContext type. Aborting AllocPBrowserParent."); return false; } auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent()); if (!opener) { ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent."); return false; } // Popup windows of isBrowser frames must be isBrowser if the parent // isBrowser. Allocating a !isBrowser frame with same app ID would allow // the content to access data it's not supposed to. if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) { ASSERT_UNLESS_FUZZING("Child trying to escalate privileges! Aborting AllocPBrowserParent."); return false; } MaybeInvalidTabContext tc(aContext); if (!tc.IsValid()) { NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) " "Aborting AllocPBrowserParent.", tc.GetInvalidReason()).get()); return false; } 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; }
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; }
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; }
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; }
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); } }
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); }
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); }
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::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 InfallibleTArray<PBrowserParent*>& browsers = iter->second.mCp->ManagedPBrowserParent(); for (uint32_t i = 0; i < browsers.Length(); i++) { nsRefPtr<TabParent> tab = TabParent::GetFrom(browsers[i]); if (tab->GetTabId() == aChildTabId) { return tab.forget(); } } return nullptr; }