mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1114507 - Part 2: Add/release the appId's refcnt in oop case. r=kanru
This commit is contained in:
parent
3c2040e20d
commit
13015804f5
@ -1468,7 +1468,9 @@ ContentParent::Init()
|
||||
}
|
||||
Preferences::AddStrongObserver(this, "");
|
||||
if (obs) {
|
||||
obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", nullptr);
|
||||
nsAutoString cpId;
|
||||
cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
|
||||
obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", cpId.get());
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
@ -2057,7 +2059,9 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
|
||||
nsAutoString cpId;
|
||||
cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
|
||||
obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", cpId.get());
|
||||
}
|
||||
|
||||
// Remove any and all idle listeners.
|
||||
@ -2085,10 +2089,35 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
// least until after the current task finishes running.
|
||||
NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
|
||||
|
||||
// Destroy any processes created by this ContentParent
|
||||
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
|
||||
// Release the appId's reference count of any processes
|
||||
// created by this ContentParent and the frame opened by this ContentParent
|
||||
// if this ContentParent crashes.
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
nsTArray<ContentParentId> childIDArray =
|
||||
cpm->GetAllChildProcessById(this->ChildID());
|
||||
if (why == AbnormalShutdown) {
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||
if(permMgr) {
|
||||
// Release the appId's reference count of its child-processes
|
||||
for (uint32_t i = 0; i < childIDArray.Length(); i++) {
|
||||
nsTArray<TabContext> tabCtxs = cpm->GetTabContextByContentProcess(childIDArray[i]);
|
||||
for (uint32_t j = 0 ; j < tabCtxs.Length() ; j++) {
|
||||
if (tabCtxs[j].OwnOrContainingAppId() != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
permMgr->ReleaseAppId(tabCtxs[j].OwnOrContainingAppId());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Release the appId's reference count belong to itself
|
||||
nsTArray<TabContext> tabCtxs = cpm->GetTabContextByContentProcess(mChildID);
|
||||
for (uint32_t i = 0; i < tabCtxs.Length() ; i++) {
|
||||
if (tabCtxs[i].OwnOrContainingAppId()!= nsIScriptSecurityManager::NO_APP_ID) {
|
||||
permMgr->ReleaseAppId(tabCtxs[i].OwnOrContainingAppId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy any processes created by this ContentParent
|
||||
for(uint32_t i = 0; i < childIDArray.Length(); i++) {
|
||||
ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
|
||||
MessageLoop::current()->PostTask(
|
||||
@ -2104,23 +2133,33 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::NotifyTabDestroying(PBrowserParent* aTab)
|
||||
ContentParent::NotifyTabDestroying(const TabId& aTabId,
|
||||
const ContentParentId& aCpId)
|
||||
{
|
||||
if (XRE_IsParentProcess()) {
|
||||
// There can be more than one PBrowser for a given app process
|
||||
// because of popup windows. PBrowsers can also destroy
|
||||
// concurrently. When all the PBrowsers are destroying, kick off
|
||||
// another task to ensure the child process *really* shuts down,
|
||||
// even if the PBrowsers themselves never finish destroying.
|
||||
int32_t numLiveTabs = ManagedPBrowserParent().Length();
|
||||
++mNumDestroyingTabs;
|
||||
if (mNumDestroyingTabs != numLiveTabs) {
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
ContentParent* cp = cpm->GetContentProcessById(aCpId);
|
||||
if (!cp) {
|
||||
return;
|
||||
}
|
||||
++cp->mNumDestroyingTabs;
|
||||
nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(aCpId);
|
||||
if (static_cast<size_t>(cp->mNumDestroyingTabs) != tabIds.Length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We're dying now, so prevent this content process from being
|
||||
// recycled during its shutdown procedure.
|
||||
MarkAsDead();
|
||||
StartForceKillTimer();
|
||||
cp->MarkAsDead();
|
||||
cp->StartForceKillTimer();
|
||||
} else {
|
||||
ContentChild::GetSingleton()->SendNotifyTabDestroying(aTabId, aCpId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -2142,16 +2181,15 @@ ContentParent::StartForceKillTimer()
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::NotifyTabDestroyed(PBrowserParent* aTab,
|
||||
ContentParent::NotifyTabDestroyed(const TabId& aTabId,
|
||||
bool aNotifiedDestroying)
|
||||
{
|
||||
if (aNotifiedDestroying) {
|
||||
--mNumDestroyingTabs;
|
||||
}
|
||||
|
||||
TabId id = static_cast<TabParent*>(aTab)->GetTabId();
|
||||
nsTArray<PContentPermissionRequestParent*> parentArray =
|
||||
nsContentPermissionUtils::GetContentPermissionRequestParentById(id);
|
||||
nsContentPermissionUtils::GetContentPermissionRequestParentById(aTabId);
|
||||
|
||||
// Need to close undeleted ContentPermissionRequestParents before tab is closed.
|
||||
for (auto& permissionRequestParent : parentArray) {
|
||||
@ -2164,7 +2202,9 @@ ContentParent::NotifyTabDestroyed(PBrowserParent* aTab,
|
||||
// There can be more than one PBrowser for a given app process
|
||||
// because of popup windows. When the last one closes, shut
|
||||
// us down.
|
||||
if (ManagedPBrowserParent().Length() == 1) {
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(this->ChildID());
|
||||
if (tabIds.Length() == 1) {
|
||||
// In the case of normal shutdown, send a shutdown message to child to
|
||||
// allow it to perform shutdown tasks.
|
||||
MessageLoop::current()->PostTask(
|
||||
@ -4899,8 +4939,12 @@ ContentParent::AllocateTabId(const TabId& aOpenerTabId,
|
||||
{
|
||||
TabId tabId;
|
||||
if (XRE_IsParentProcess()) {
|
||||
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
tabId = cpm->AllocateTabId(aOpenerTabId, aContext, aCpId);
|
||||
// Add appId's reference count in oop case
|
||||
if (tabId) {
|
||||
PermissionManagerAddref(aCpId, tabId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ContentChild::GetSingleton()->SendAllocateTabId(aOpenerTabId,
|
||||
@ -4913,14 +4957,27 @@ ContentParent::AllocateTabId(const TabId& aOpenerTabId,
|
||||
|
||||
/*static*/ void
|
||||
ContentParent::DeallocateTabId(const TabId& aTabId,
|
||||
const ContentParentId& aCpId)
|
||||
const ContentParentId& aCpId,
|
||||
bool aMarkedDestroying)
|
||||
{
|
||||
if (XRE_IsParentProcess()) {
|
||||
// Release appId's reference count in oop case
|
||||
if (aTabId) {
|
||||
PermissionManagerRelease(aCpId, aTabId);
|
||||
}
|
||||
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
ContentParent* cp = cpm->GetContentProcessById(aCpId);
|
||||
|
||||
cp->NotifyTabDestroyed(aTabId, aMarkedDestroying);
|
||||
|
||||
ContentProcessManager::GetSingleton()->DeallocateTabId(aCpId,
|
||||
aTabId);
|
||||
}
|
||||
else {
|
||||
ContentChild::GetSingleton()->SendDeallocateTabId(aTabId);
|
||||
ContentChild::GetSingleton()->SendDeallocateTabId(aTabId,
|
||||
aCpId,
|
||||
aMarkedDestroying);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4938,9 +4995,19 @@ ContentParent::RecvAllocateTabId(const TabId& aOpenerTabId,
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvDeallocateTabId(const TabId& aTabId)
|
||||
ContentParent::RecvDeallocateTabId(const TabId& aTabId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aMarkedDestroying)
|
||||
{
|
||||
DeallocateTabId(aTabId, this->ChildID());
|
||||
DeallocateTabId(aTabId, aCpId, aMarkedDestroying);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvNotifyTabDestroying(const TabId& aTabId,
|
||||
const ContentParentId& aCpId)
|
||||
{
|
||||
NotifyTabDestroying(aTabId, aCpId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5111,6 +5178,38 @@ ContentParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestP
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ContentParent::PermissionManagerAddref(const ContentParentId& aCpId,
|
||||
const TabId& aTabId)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Call PermissionManagerAddref in content process!");
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
uint32_t appId = cpm->GetAppIdByProcessAndTabId(aCpId, aTabId);
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||
if (appId != nsIScriptSecurityManager::NO_APP_ID && permMgr) {
|
||||
permMgr->AddrefAppId(appId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ContentParent::PermissionManagerRelease(const ContentParentId& aCpId,
|
||||
const TabId& aTabId)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Call PermissionManagerRelease in content process!");
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
uint32_t appId = cpm->GetAppIdByProcessAndTabId(aCpId, aTabId);
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||
if (appId != nsIScriptSecurityManager::NO_APP_ID && permMgr) {
|
||||
permMgr->ReleaseAppId(appId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetBrowserConfiguration(const nsCString& aURI, BrowserConfiguration* aConfig)
|
||||
{
|
||||
|
@ -212,9 +212,10 @@ public:
|
||||
virtual bool KillChild() override;
|
||||
|
||||
/** Notify that a tab is beginning its destruction sequence. */
|
||||
void NotifyTabDestroying(PBrowserParent* aTab);
|
||||
static void NotifyTabDestroying(const TabId& aTabId,
|
||||
const ContentParentId& aCpId);
|
||||
/** Notify that a tab was destroyed during normal operation. */
|
||||
void NotifyTabDestroyed(PBrowserParent* aTab,
|
||||
void NotifyTabDestroyed(const TabId& aTabId,
|
||||
bool aNotifiedDestroying);
|
||||
|
||||
TestShellParent* CreateTestShell();
|
||||
@ -227,7 +228,21 @@ public:
|
||||
const IPCTabContext& aContext,
|
||||
const ContentParentId& aCpId);
|
||||
static void
|
||||
DeallocateTabId(const TabId& aTabId, const ContentParentId& aCpId);
|
||||
DeallocateTabId(const TabId& aTabId,
|
||||
const ContentParentId& aCpId,
|
||||
bool aMarkedDestroying);
|
||||
|
||||
/*
|
||||
* Add the appId's reference count by the given ContentParentId and TabId
|
||||
*/
|
||||
static bool
|
||||
PermissionManagerAddref(const ContentParentId& aCpId, const TabId& aTabId);
|
||||
|
||||
/*
|
||||
* Release the appId's reference count by the given ContentParentId and TabId
|
||||
*/
|
||||
static bool
|
||||
PermissionManagerRelease(const ContentParentId& aCpId, const TabId& aTabId);
|
||||
|
||||
static bool
|
||||
GetBrowserConfiguration(const nsCString& aURI, BrowserConfiguration& aConfig);
|
||||
@ -356,7 +371,12 @@ public:
|
||||
const ContentParentId& aCpId,
|
||||
TabId* aTabId) override;
|
||||
|
||||
virtual bool RecvDeallocateTabId(const TabId& aTabId) override;
|
||||
virtual bool RecvDeallocateTabId(const TabId& aTabId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aMarkedDestroying) override;
|
||||
|
||||
virtual bool RecvNotifyTabDestroying(const TabId& aTabId,
|
||||
const ContentParentId& aCpId) override;
|
||||
|
||||
nsTArray<TabContext> GetManagedTabContext();
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#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
|
||||
@ -334,5 +335,40 @@ ContentProcessManager::GetTopLevelTabParentByProcessAndTabId(const ContentParent
|
||||
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
|
||||
|
@ -110,6 +110,13 @@ public:
|
||||
const TabId& aChildTabId,
|
||||
/*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);
|
||||
|
||||
/**
|
||||
* Get the TabParent by the given content process and tab id.
|
||||
* Return nullptr when TabParent couldn't be found via aChildCpId
|
||||
@ -135,6 +142,15 @@ public:
|
||||
GetTopLevelTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
|
||||
const TabId& aChildTabId);
|
||||
|
||||
/**
|
||||
* Return appId by given TabId and ContentParentId.
|
||||
* It will return nsIScriptSecurityManager::NO_APP_ID
|
||||
* if the given tab is not an app.
|
||||
*/
|
||||
uint32_t
|
||||
GetAppIdByProcessAndTabId(const ContentParentId& aChildCpId,
|
||||
const TabId& aChildTabId);
|
||||
|
||||
private:
|
||||
static StaticAutoPtr<ContentProcessManager> sSingleton;
|
||||
TabId mUniqueId;
|
||||
|
@ -991,8 +991,15 @@ parent:
|
||||
*/
|
||||
sync AllocateTabId(TabId openerTabId, IPCTabContext context, ContentParentId cpId)
|
||||
returns (TabId tabId);
|
||||
async DeallocateTabId(TabId tabId);
|
||||
async DeallocateTabId(TabId tabId,
|
||||
ContentParentId cpId,
|
||||
bool aMarkedDestroying);
|
||||
|
||||
/**
|
||||
* Tell the chrome process there is a destruction of PBrowser(Tab)
|
||||
*/
|
||||
async NotifyTabDestroying(TabId tabId,
|
||||
ContentParentId cpId);
|
||||
/**
|
||||
* Starts an offline application cache update.
|
||||
* @param manifestURI
|
||||
|
@ -436,12 +436,8 @@ TabParent::IsVisible()
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::Destroy()
|
||||
TabParent::DestroyInternal()
|
||||
{
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
IMEStateManager::OnTabParentDestroying(this);
|
||||
|
||||
RemoveWindowListeners();
|
||||
@ -455,11 +451,6 @@ TabParent::Destroy()
|
||||
RemoveTabParentFromTable(frame->GetLayersId());
|
||||
frame->Destroy();
|
||||
}
|
||||
mIsDestroyed = true;
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
Manager()->AsContentParent()->NotifyTabDestroying(this);
|
||||
}
|
||||
|
||||
// Let all PluginWidgets know we are tearing down. Prevents
|
||||
// these objects from sending async events after the child side
|
||||
@ -468,6 +459,24 @@ TabParent::Destroy()
|
||||
for (uint32_t idx = 0; idx < kids.Length(); ++idx) {
|
||||
static_cast<mozilla::plugins::PluginWidgetParent*>(kids[idx])->ParentDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::Destroy()
|
||||
{
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
DestroyInternal();
|
||||
|
||||
mIsDestroyed = true;
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
ContentParent::NotifyTabDestroying(this->GetTabId(), Manager()->AsContentParent()->ChildID());
|
||||
} else {
|
||||
ContentParent::NotifyTabDestroying(this->GetTabId(), Manager()->ChildID());
|
||||
}
|
||||
|
||||
mMarkedDestroying = true;
|
||||
}
|
||||
@ -476,12 +485,15 @@ bool
|
||||
TabParent::Recv__delete__()
|
||||
{
|
||||
if (XRE_IsParentProcess()) {
|
||||
Manager()->AsContentParent()->NotifyTabDestroyed(this, mMarkedDestroying);
|
||||
ContentParent::DeallocateTabId(mTabId,
|
||||
Manager()->AsContentParent()->ChildID());
|
||||
Manager()->AsContentParent()->ChildID(),
|
||||
mMarkedDestroying);
|
||||
}
|
||||
else {
|
||||
ContentParent::DeallocateTabId(mTabId, ContentParentId(0));
|
||||
Manager()->AsContentBridgeParent()->NotifyTabDestroyed();
|
||||
ContentParent::DeallocateTabId(mTabId,
|
||||
Manager()->ChildID(),
|
||||
mMarkedDestroying);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -494,6 +506,22 @@ TabParent::ActorDestroy(ActorDestroyReason why)
|
||||
// case of a crash.
|
||||
IMEStateManager::OnTabParentDestroying(this);
|
||||
|
||||
// Prevent executing ContentParent::NotifyTabDestroying in
|
||||
// TabParent::Destroy() called by frameLoader->DestroyComplete() below
|
||||
// when tab crashes in contentprocess because ContentParent::ActorDestroy()
|
||||
// in main process will be triggered before this function
|
||||
// and remove the process information that
|
||||
// ContentParent::NotifyTabDestroying need from mContentParentMap.
|
||||
|
||||
// When tab crashes in content process,
|
||||
// there is no need to call ContentParent::NotifyTabDestroying
|
||||
// because the jobs in ContentParent::NotifyTabDestroying
|
||||
// will be done by ContentParent::ActorDestroy.
|
||||
if (XRE_IsContentProcess() && why == AbnormalShutdown && !mIsDestroyed) {
|
||||
DestroyInternal();
|
||||
mIsDestroyed = true;
|
||||
}
|
||||
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true);
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (frameLoader) {
|
||||
|
@ -491,6 +491,7 @@ protected:
|
||||
LayoutDeviceIntPoint mChromeOffset;
|
||||
|
||||
private:
|
||||
void DestroyInternal();
|
||||
already_AddRefed<nsFrameLoader> GetFrameLoader(bool aUseCachedFrameLoaderAfterDestroy = false) const;
|
||||
nsRefPtr<nsIContentParent> mManager;
|
||||
void TryCacheDPIAndScale();
|
||||
|
Loading…
Reference in New Issue
Block a user