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

--HG--
extra : rebase_source : 1913f8f586537be1c82a70a19cc8c6351671d0df
This commit is contained in:
Samael Wang 2017-04-05 18:42:00 +08:00
parent e7a1ec743f
commit d5dd0ed263
11 changed files with 120 additions and 129 deletions

View File

@ -10273,4 +10273,29 @@ nsContentUtils::IsLocalRefURL(const nsString& aString)
}
return false;
}
}
// 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;
}

View File

@ -2873,6 +2873,11 @@ public:
static bool
IsCustomElementsEnabled() { return sIsCustomElementsEnabled; }
/**
* Compose a tab id with process id and a serial number.
*/
static uint64_t GenerateTabId();
private:
static bool InitializeEventTable();

View File

@ -774,11 +774,7 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
}
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

View File

@ -909,9 +909,9 @@ 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)) {
@ -942,12 +942,8 @@ ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
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();
}
@ -1179,7 +1175,7 @@ ContentParent::CreateBrowser(const TabContext& aContext,
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
bool isInContentProcess = !XRE_IsParentProcess();
TabId tabId;
TabId tabId(nsContentUtils::GenerateTabId());
nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
TabId openerTabId;
@ -1197,7 +1193,7 @@ ContentParent::CreateBrowser(const TabContext& aContext,
if (isInContentProcess) {
MOZ_ASSERT(aContext.IsMozBrowserElement());
constructorSender = CreateContentBridgeParent(aContext, initialPriority,
openerTabId, &tabId);
openerTabId, tabId);
} else {
if (aOpenerContentParent) {
constructorSender = aOpenerContentParent;
@ -1208,9 +1204,11 @@ ContentParent::CreateBrowser(const TabContext& aContext,
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;
@ -1270,7 +1268,7 @@ ContentParent::CreateBrowser(const TabContext& aContext,
ContentParent::CreateContentBridgeParent(const TabContext& aContext,
const hal::ProcessPriority& aPriority,
const TabId& aOpenerTabId,
/*out*/ TabId* aTabId)
const TabId& aTabId)
{
MOZ_ASSERT(aTabId);
@ -1280,9 +1278,9 @@ ContentParent::CreateContentBridgeParent(const TabContext& aContext,
if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(),
aPriority,
aOpenerTabId,
aTabId,
&cpId,
&isForBrowser,
aTabId)) {
&isForBrowser)) {
return nullptr;
}
if (cpId == 0) {
@ -4216,27 +4214,8 @@ ContentParent::NotifyUpdatedDictionaries()
}
}
/*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)
{
@ -4246,32 +4225,19 @@ ContentParent::DeallocateTabId(const TabId& aTabId,
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();
}

View File

@ -279,9 +279,9 @@ public:
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;
@ -350,15 +350,10 @@ public:
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();
@ -489,14 +484,9 @@ public:
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;
@ -694,7 +684,7 @@ private:
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.

View File

@ -24,8 +24,6 @@
namespace mozilla {
namespace dom {
static uint64_t gTabId = 0;
/* static */
StaticAutoPtr<ContentProcessManager>
ContentProcessManager::sSingleton;
@ -135,17 +133,18 @@ ContentProcessManager::GetAllChildProcessById(const ContentParentId& aParentCpId
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;
@ -156,20 +155,10 @@ ContentProcessManager::AllocateTabId(const TabId& aOpenerTabId,
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 {
@ -178,21 +167,19 @@ ContentProcessManager::AllocateTabId(const TabId& aOpenerTabId,
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());

View File

@ -72,21 +72,23 @@ public:
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.
@ -151,7 +153,6 @@ public:
private:
static StaticAutoPtr<ContentProcessManager> sSingleton;
TabId mUniqueId;
std::map<ContentParentId, ContentProcessInfo> mContentParentMap;
ContentProcessManager() {MOZ_COUNT_CTOR(ContentProcessManager);};

View File

@ -623,8 +623,9 @@ parent:
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);
@ -914,15 +915,10 @@ parent:
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)

View File

@ -413,15 +413,15 @@ 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();

View File

@ -10,6 +10,7 @@
#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"
@ -138,12 +139,15 @@ nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
}
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();
@ -158,6 +162,29 @@ nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
}
}
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;

View File

@ -917,8 +917,6 @@ description =
description =
[PContent::KeygenProvideContent]
description =
[PContent::AllocateTabId]
description =
[PContent::GetGraphicsDeviceInitData]
description =
[PContent::CreateWindow]