gecko-dev/dom/ipc/ContentProcessManager.cpp
Ehsan Akhgari eac76d9772 Bug 1310845 - Remove support for mozapp iframes; r=fabrice,jryans,baku,mcmanus
This patch removes support for mozapp iframes, leaving support for
mozbrowser iframes intact.  Some of the code has been rewritten in order
to phrase things in terms of mozbrowser only, as opposed to mozbrowser
or app.  In some places, code that was only useful with apps has been
completely removed, so that the APIs consumed can also be removed.  In
some places where the notion of appId was bleeding out of this API, now
we use NO_APP_ID.  Other notions of appId which were restricted to this
API have been removed.
2016-11-16 09:13:38 -05:00

359 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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);
}
} // namespace dom
} // namespace mozilla