Bug 1324359 - Rename and simplify the DocShell ProcessLock concept, r=smaug

MozReview-Commit-ID: JTp8Q2mWqpN
This commit is contained in:
Michael Layzell 2016-12-29 17:28:17 -05:00
parent d8db8fb565
commit f24af1792b
5 changed files with 44 additions and 87 deletions

View File

@ -14739,44 +14739,31 @@ nsDocShell::GetCommandManager()
}
NS_IMETHODIMP
nsDocShell::GetIsProcessLocked(bool* aIsLocked)
nsDocShell::GetIsOnlyToplevelInTabGroup(bool* aResult)
{
MOZ_ASSERT(aIsLocked);
*aIsLocked = GetProcessLockReason() != PROCESS_LOCK_NONE;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetProcessLockReason(uint32_t* aReason)
{
MOZ_ASSERT(aReason);
MOZ_ASSERT(aResult);
nsPIDOMWindowOuter* outer = GetWindow();
MOZ_ASSERT(outer);
// Check if we are a toplevel window
// If we are not toplevel then we are not the only toplevel window in the tab
// group.
if (outer->GetScriptableParentOrNull()) {
*aReason = PROCESS_LOCK_IFRAME;
*aResult = false;
return NS_OK;
}
// If we have any other toplevel windows in our tab group, then we cannot
// perform the navigation.
// If we have any other toplevel windows in our tab group, then we are not the
// only toplevel window in the tab group.
nsTArray<nsPIDOMWindowOuter*> toplevelWindows =
outer->TabGroup()->GetTopLevelWindows();
if (toplevelWindows.Length() > 1) {
*aReason = PROCESS_LOCK_RELATED_CONTEXTS;
*aResult = false;
return NS_OK;
}
MOZ_ASSERT(toplevelWindows.Length() == 1);
MOZ_ASSERT(toplevelWindows[0] == outer);
// If we aren't in a content process, we cannot perform a cross-process load.
if (!XRE_IsContentProcess()) {
*aReason = PROCESS_LOCK_NON_CONTENT;
return NS_OK;
}
*aReason = PROCESS_LOCK_NONE;
*aResult = true;
return NS_OK;
}

View File

@ -1112,38 +1112,16 @@ interface nsIDocShell : nsIDocShellTreeItem
const unsigned long TOUCHEVENTS_OVERRIDE_NONE = 2;
/**
* A DocShell is locked to the current process if it would be
* content-observable for a process switch to occur before performing a
* navigation load. It is important to ensure that a DocShell is not process
* locked before performing process changing loads.
*/
[infallible] readonly attribute boolean isProcessLocked;
/**
* Return PROCESS_LOCK_NONE if docShell is not locked to current process,
* otherwise return the reason why process is locked.
*/
[infallible] readonly attribute unsigned long processLockReason;
/**
* The DocShell is not locked to the current process, and a navigation may
* proceed in a new process.
*/
const unsigned long PROCESS_LOCK_NONE = 0;
/**
* The DocShell is locked to the current process because it is not a
* toplevel browsing context.
*/
const unsigned long PROCESS_LOCK_IFRAME = 1;
/**
* The DocShell is locked to the current process because there exist other
* related browsing contexts which may be holding a reference.
*/
const unsigned long PROCESS_LOCK_RELATED_CONTEXTS = 2;
/**
* The DocShell is locked to the current process because the current
* process is not a content process.
* This value is `true` if its corresponding unit of related browsing contexts
* (TabGroup) contains only 1 toplevel window, and that window is the outer
* window corresponding to this docshell.
*
* NOTE: Some loads may not consider this a hard process lock, and may wish to
* ignore this reason.
* The value is `false` otherwise. This is the case if the docshell is an
* iframe, has window.opener set, or another window with window.opener
* referring to this window exists.
*
* If this value is `false`, it would be web content visible for a load
* occuring in this docshell to be performed within a different docshell.
*/
const unsigned long PROCESS_LOCK_NON_CONTENT = 3;
[infallible] readonly attribute boolean isOnlyToplevelInTabGroup;
};

View File

@ -9702,39 +9702,28 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
return false;
}
nsIDocShell* docShell = outer->GetDocShell();
nsIDocument* doc = outer->GetExtantDoc();
// If the docshell is not allowed to change process, report an error based on
// the reason
const char* errorName = nullptr;
switch (docShell->GetProcessLockReason()) {
case nsIDocShell::PROCESS_LOCK_NON_CONTENT:
errorName = "LargeAllocationNonE10S";
break;
case nsIDocShell::PROCESS_LOCK_IFRAME:
errorName = "LargeAllocationIFrame";
break;
case nsIDocShell::PROCESS_LOCK_RELATED_CONTEXTS:
errorName = "LargeAllocationRelatedBrowsingContexts";
break;
case nsIDocShell::PROCESS_LOCK_NONE:
// Don't print a warning, we're allowed to change processes!
break;
default:
MOZ_ASSERT(false, "Should be unreachable!");
return false;
}
if (errorName) {
if (!XRE_IsContentProcess()) {
if (doc) {
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("DOM"),
doc,
nsContentUtils::eDOM_PROPERTIES,
errorName);
"LargeAllocationNonE10S");
}
return false;
}
nsIDocShell* docShell = outer->GetDocShell();
if (!docShell->GetIsOnlyToplevelInTabGroup()) {
if (doc) {
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("DOM"),
doc,
nsContentUtils::eDOM_PROPERTIES,
"LargeAllocationRelatedBrowsingContexts");
}
return false;
}

View File

@ -2964,11 +2964,16 @@ nsIDocument::PrerenderHref(nsIURI* aHref)
return false;
}
// Adopting an out-of-process prerendered document is conceptually similar to
// switching dochshell's process, since it's the same browsing context from
// other browsing contexts' perspective. If we're locked in current process,
// we can not prerender out-of-process.
if (docShell->GetIsProcessLocked()) {
// We currently do not support prerendering in documents loaded within the
// chrome process.
if (!XRE_IsContentProcess()) {
return false;
}
// Adopting an prerendered document is similar to performing a load within a
// different docshell, as the prerendering must have occurred in a different
// docshell.
if (!docShell->GetIsOnlyToplevelInTabGroup()) {
return false;
}

View File

@ -314,9 +314,7 @@ GenericFileName=file
LargeAllocationSuccess=This page was loaded in a new process due to a Large-Allocation header.
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name. Do not translate GET.
LargeAllocationNonGetRequest=A Large-Allocation header was ignored due to the load being triggered by a non-GET request.
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name
LargeAllocationRelatedBrowsingContexts=A Large-Allocation header was ignored due to the presence of windows which have a reference to this browsing context.
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name
LargeAllocationInIFrame=A Large-Allocation header was ignored due to the load occuring within an iframe.
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name. Do not translate `window.opener`.
LargeAllocationRelatedBrowsingContexts=A Large-Allocation header was ignored due to the presence of windows which have a reference to this browsing context through the frame hierarchy or window.opener.
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name
LargeAllocationNonE10S=A Large-Allocation header was ignored due to the document not being loaded out of process.