зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1376895 - Make preloaded browser use pre-existing content process. r=mconley
We want to avoid to have several cached content processes, one for each preloaded browser (one per window) and one for the preallocated process. For that we force the preloaded browser to choose an existing process and during the first navigation in that tab, that leaves about:newtab, we re-run the process selecting algorithm
This commit is contained in:
Родитель
5acd81eb72
Коммит
722233fed1
|
@ -1088,6 +1088,14 @@ function _loadURIWithFlags(browser, uri, params) {
|
|||
}
|
||||
|
||||
let mustChangeProcess = requiredRemoteType != currentRemoteType;
|
||||
let newFrameloader = false;
|
||||
if (browser.getAttribute("isPreloadBrowser") == "true" && uri != "about:newtab") {
|
||||
// Leaving about:newtab from a used to be preloaded browser should run the process
|
||||
// selecting algorithm again.
|
||||
mustChangeProcess = true;
|
||||
newFrameloader = true;
|
||||
browser.removeAttribute("isPreloadBrowser");
|
||||
}
|
||||
|
||||
// !requiredRemoteType means we're loading in the parent/this process.
|
||||
if (!requiredRemoteType) {
|
||||
|
@ -1122,7 +1130,8 @@ function _loadURIWithFlags(browser, uri, params) {
|
|||
referrer: referrer ? referrer.spec : null,
|
||||
referrerPolicy,
|
||||
remoteType: requiredRemoteType,
|
||||
postData
|
||||
postData,
|
||||
newFrameloader,
|
||||
}
|
||||
|
||||
if (params.userContextId) {
|
||||
|
@ -1167,6 +1176,11 @@ function LoadInOtherProcess(browser, loadOptions, historyIndex = -1) {
|
|||
// Called when a docshell has attempted to load a page in an incorrect process.
|
||||
// This function is responsible for loading the page in the correct process.
|
||||
function RedirectLoad({ target: browser, data }) {
|
||||
if (browser.getAttribute("isPreloadBrowser") == "true") {
|
||||
browser.removeAttribute("isPreloadBrowser");
|
||||
data.loadOptions.newFrameloader = true;
|
||||
}
|
||||
|
||||
if (data.loadOptions.reloadInFreshProcess) {
|
||||
// Convert the fresh process load option into a large allocation remote type
|
||||
// to use common processing from this point.
|
||||
|
|
|
@ -2118,6 +2118,10 @@
|
|||
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
|
||||
}
|
||||
|
||||
if (aParams.isPreloadBrowser) {
|
||||
b.setAttribute("isPreloadBrowser", "true");
|
||||
}
|
||||
|
||||
if (this.hasAttribute("selectmenulist"))
|
||||
b.setAttribute("selectmenulist", this.getAttribute("selectmenulist"));
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
add_task(async function() {
|
||||
let input = "i-definitely-dont-exist.example.com";
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", false);
|
||||
// NB: CPOW usage because new tab pages can be preloaded, in which case no
|
||||
// load events fire.
|
||||
await BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
|
||||
|
@ -29,7 +29,7 @@ add_task(async function() {
|
|||
add_task(async function() {
|
||||
let input = "To be or not to be-that is the question";
|
||||
await SpecialPowers.pushPrefEnv({set: [["keyword.enabled", false]]});
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", false);
|
||||
// NB: CPOW usage because new tab pages can be preloaded, in which case no
|
||||
// load events fire.
|
||||
await BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
|
||||
|
|
|
@ -243,6 +243,14 @@ this.E10SUtils = {
|
|||
this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI);
|
||||
}
|
||||
|
||||
if (sessionHistory.count == 1 && webNav.currentURI.spec == "about:newtab") {
|
||||
// This is possibly a preloaded browser and we're about to navigate away for
|
||||
// the first time. On the child side there is no way to tell for sure if that
|
||||
// is the case, so let's redirect this request to the parent to decide if a new
|
||||
// process is needed.
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the URI can be loaded in the current process then continue
|
||||
return this.shouldLoadURIInThisProcess(aURI);
|
||||
},
|
||||
|
|
|
@ -2231,6 +2231,7 @@ GK_ATOM(DisplayPortMargins, "_displayportmargins")
|
|||
GK_ATOM(DisplayPortBase, "_displayportbase")
|
||||
GK_ATOM(AsyncScrollLayerCreationFailed, "_asyncscrolllayercreationfailed")
|
||||
GK_ATOM(forcemessagemanager, "forcemessagemanager")
|
||||
GK_ATOM(isPreloadBrowser, "isPreloadBrowser")
|
||||
|
||||
// Names for system metrics
|
||||
GK_ATOM(color_picker_available, "color-picker-available")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
audio.ogg
|
||||
dummy.html
|
||||
empty.html
|
||||
file_audioLoop.html
|
||||
file_audioLoopInIframe.html
|
||||
|
@ -35,6 +36,8 @@ tags = mcb
|
|||
[browser_force_process_selector.js]
|
||||
skip-if = !e10s # this only makes sense with e10s-multi
|
||||
[browser_messagemanager_loadprocessscript.js]
|
||||
[browser_aboutnewtab_process_selection.js]
|
||||
skip-if = os == 'linux' # Linux x64 JSDCov failure
|
||||
[browser_messagemanager_targetframeloader.js]
|
||||
[browser_messagemanager_unload.js]
|
||||
[browser_pagehide_on_tab_close.js]
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
const TEST_URL = "http://www.example.com/browser/dom/base/test/dummy.html";
|
||||
|
||||
var ppmm = Services.ppmm;
|
||||
|
||||
add_task(async function(){
|
||||
// We want to count processes in this test, so let's disable the pre-allocated process manager.
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.ipc.processPrelaunch.enabled", false],
|
||||
["dom.ipc.processCount", 10],
|
||||
["dom.ipc.keepProcessesAlive.web", 10],
|
||||
]});
|
||||
});
|
||||
|
||||
// Ensure that the preloaded browser exists, and it's finished loading.
|
||||
async function ensurePreloaded(gBrowser) {
|
||||
gBrowser._createPreloadBrowser();
|
||||
// We cannot use the regular BrowserTestUtils helper for waiting here, since that
|
||||
// would try to insert the preloaded browser, which would only break things.
|
||||
await BrowserTestUtils.waitForCondition( () => {
|
||||
return gBrowser._preloadedBrowser.contentDocument.readyState == "complete";
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function(){
|
||||
// This test is only relevant in e10s.
|
||||
if (!gMultiProcessBrowser)
|
||||
return;
|
||||
|
||||
ppmm.releaseCachedProcesses();
|
||||
|
||||
// Wait for the preloaded browser to load.
|
||||
await ensurePreloaded(gBrowser);
|
||||
|
||||
// Store the number of processes (note: +1 for the parent process).
|
||||
const { childCount: originalChildCount } = ppmm;
|
||||
|
||||
// Use the preloaded browser and create another one.
|
||||
BrowserOpenTab();
|
||||
let tab1 = gBrowser.selectedTab;
|
||||
await ensurePreloaded(gBrowser);
|
||||
|
||||
// Check that the process count did not change.
|
||||
is(ppmm.childCount, originalChildCount, "Preloaded browser should not create a new content process.")
|
||||
|
||||
// Let's do another round.
|
||||
BrowserOpenTab();
|
||||
let tab2 = gBrowser.selectedTab;
|
||||
await ensurePreloaded(gBrowser);
|
||||
|
||||
// Check that the process count did not change.
|
||||
is(ppmm.childCount, originalChildCount, "Preloaded browser should (still) not create a new content process.")
|
||||
|
||||
// Navigate to a content page from the parent side.
|
||||
tab2.linkedBrowser.loadURI(TEST_URL);
|
||||
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, TEST_URL);
|
||||
is(ppmm.childCount, originalChildCount + 1,
|
||||
"Navigating away from the preloaded browser (parent side) should create a new content process.")
|
||||
|
||||
// Navigate to a content page from the child side.
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab1);
|
||||
await ContentTask.spawn(tab1.linkedBrowser, null, async function() {
|
||||
const TEST_URL = "http://www.example.com/browser/dom/base/test/dummy.html";
|
||||
content.location.href = TEST_URL;
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab1.linkedBrowser, false, TEST_URL);
|
||||
is(ppmm.childCount, originalChildCount + 2,
|
||||
"Navigating away from the preloaded browser (child side) should create a new content process.")
|
||||
|
||||
await BrowserTestUtils.removeTab(tab1);
|
||||
await BrowserTestUtils.removeTab(tab2);
|
||||
|
||||
// Since we kept alive all the processes, we can shut down the ones that do
|
||||
// not host any tabs reliably.
|
||||
ppmm.releaseCachedProcesses();
|
||||
is(ppmm.childCount, originalChildCount, "We're back to the original process count.");
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Dummy test page</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
|
||||
</head>
|
||||
<body>
|
||||
<p>Dummy test page</p>
|
||||
</body>
|
||||
</html>
|
|
@ -762,11 +762,11 @@ ContentParent::MinTabSelect(const nsTArray<ContentParent*>& aContentParents,
|
|||
/*static*/ already_AddRefed<ContentParent>
|
||||
ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
|
||||
ProcessPriority aPriority,
|
||||
ContentParent* aOpener)
|
||||
ContentParent* aOpener,
|
||||
bool aPreferUsed)
|
||||
{
|
||||
nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
|
||||
uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
|
||||
|
||||
if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
|
||||
// We never want to re-use Large-Allocation processes.
|
||||
if (contentParents.Length() >= maxContentParents) {
|
||||
|
@ -775,11 +775,18 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
|
|||
aOpener);
|
||||
}
|
||||
} else {
|
||||
nsTArray<nsIContentProcessInfo*> infos(contentParents.Length());
|
||||
uint32_t numberOfParents = contentParents.Length();
|
||||
nsTArray<nsIContentProcessInfo*> infos(numberOfParents);
|
||||
for (auto* cp : contentParents) {
|
||||
infos.AppendElement(cp->mScriptableHelper);
|
||||
}
|
||||
|
||||
if (aPreferUsed && numberOfParents) {
|
||||
// For the preloaded browser we don't want to create a new process but reuse an
|
||||
// existing one.
|
||||
maxContentParents = numberOfParents;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentProcessProvider> cpp =
|
||||
do_GetService("@mozilla.org/ipc/processselector;1");
|
||||
nsIContentProcessInfo* openerInfo = aOpener ? aOpener->mScriptableHelper.get() : nullptr;
|
||||
|
@ -1131,6 +1138,13 @@ ContentParent::CreateBrowser(const TabContext& aContext,
|
|||
remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
|
||||
}
|
||||
|
||||
bool isPreloadBrowser = false;
|
||||
nsAutoString isPreloadBrowserStr;
|
||||
if (aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::isPreloadBrowser,
|
||||
isPreloadBrowserStr)) {
|
||||
isPreloadBrowser = isPreloadBrowserStr.EqualsLiteral("true");
|
||||
}
|
||||
|
||||
RefPtr<nsIContentParent> constructorSender;
|
||||
if (isInContentProcess) {
|
||||
MOZ_ASSERT(aContext.IsMozBrowserElement() || aContext.IsJSPlugin());
|
||||
|
@ -1146,7 +1160,8 @@ ContentParent::CreateBrowser(const TabContext& aContext,
|
|||
initialPriority);
|
||||
} else {
|
||||
constructorSender =
|
||||
GetNewOrUsedBrowserProcess(remoteType, initialPriority, nullptr);
|
||||
GetNewOrUsedBrowserProcess(remoteType, initialPriority,
|
||||
nullptr, isPreloadBrowser);
|
||||
}
|
||||
if (!constructorSender) {
|
||||
return nullptr;
|
||||
|
|
|
@ -172,7 +172,8 @@ public:
|
|||
GetNewOrUsedBrowserProcess(const nsAString& aRemoteType = NS_LITERAL_STRING(NO_REMOTE_TYPE),
|
||||
hal::ProcessPriority aPriority =
|
||||
hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
|
||||
ContentParent* aOpener = nullptr);
|
||||
ContentParent* aOpener = nullptr,
|
||||
bool aPreferUsed = false);
|
||||
|
||||
/**
|
||||
* Get or create a content process for a JS plugin. aPluginID is the id of the JS plugin
|
||||
|
|
|
@ -15,17 +15,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=841850
|
|||
var blankTarget = document.getElementById("blankTarget");
|
||||
blankTarget.click();
|
||||
|
||||
var os = SpecialPowers.Cc["@mozilla.org/observer-service;1"].
|
||||
getService(SpecialPowers.Components.interfaces.nsIObserverService);
|
||||
var observer = {
|
||||
observe: function(subject, topic, data) {
|
||||
if(topic == "content-document-global-created" && data =="http://example.com") {
|
||||
parent.parent.postMessage({"test": "blankTarget", "msg": "opened an http link with target=_blank from a secure page"}, "http://mochi.test:8888");
|
||||
os.removeObserver(observer, "content-document-global-created");
|
||||
SpecialPowers.removeAsyncObserver(observer, "content-document-global-created");
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, "content-document-global-created");
|
||||
SpecialPowers.addAsyncObserver(observer, "content-document-global-created");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
Загрузка…
Ссылка в новой задаче