From 52529cb9a9509eb0b4c86dddc77749fc5680b0ea Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Thu, 17 Nov 2016 15:48:53 +0000 Subject: [PATCH] Bug 1147911 Part 8: Create separate content process for file:// URIs. r=gabor, r=gijs, r=smaug --- browser/modules/E10SUtils.jsm | 14 ++- .../browser_webconsole_bug_595223_file_uri.js | 2 +- dom/ipc/ContentParent.cpp | 88 +++++++++---------- dom/ipc/ContentParent.h | 7 +- modules/libpref/init/all.js | 11 +++ 5 files changed, 72 insertions(+), 50 deletions(-) diff --git a/browser/modules/E10SUtils.jsm b/browser/modules/E10SUtils.jsm index 5ac50471f587..f01b8c0bc1d5 100644 --- a/browser/modules/E10SUtils.jsm +++ b/browser/modules/E10SUtils.jsm @@ -26,13 +26,20 @@ function getAboutModule(aURL) { const NOT_REMOTE = null; const WEB_REMOTE_TYPE = "web"; +const FILE_REMOTE_TYPE = "file"; // This must match the one in ContentParent.h. const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE; +function validatedWebRemoteType(aPreferredRemoteType) { + return aPreferredRemoteType && aPreferredRemoteType.startsWith(WEB_REMOTE_TYPE) + ? aPreferredRemoteType : WEB_REMOTE_TYPE; +} + this.E10SUtils = { DEFAULT_REMOTE_TYPE, NOT_REMOTE, WEB_REMOTE_TYPE, + FILE_REMOTE_TYPE, canLoadURIInProcess: function(aURL, aProcess) { let remoteType = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT @@ -55,6 +62,11 @@ this.E10SUtils = { return aPreferredRemoteType; } + if (aURL.startsWith("file:")) { + return Services.prefs.getBoolPref("browser.tabs.remote.separateFileUriProcess") + ? FILE_REMOTE_TYPE : DEFAULT_REMOTE_TYPE; + } + if (aURL.startsWith("about:")) { // We need to special case about:blank because it needs to load in any. if (aURL == "about:blank") { @@ -115,7 +127,7 @@ this.E10SUtils = { aMultiProcess, aPreferredRemoteType); } - return WEB_REMOTE_TYPE; + return validatedWebRemoteType(aPreferredRemoteType); }, shouldLoadURIInThisProcess: function(aURI) { diff --git a/devtools/client/webconsole/test/browser_webconsole_bug_595223_file_uri.js b/devtools/client/webconsole/test/browser_webconsole_bug_595223_file_uri.js index 20aafba730c1..1ce2e13a53e2 100644 --- a/devtools/client/webconsole/test/browser_webconsole_bug_595223_file_uri.js +++ b/devtools/client/webconsole/test/browser_webconsole_bug_595223_file_uri.js @@ -23,7 +23,7 @@ add_task(function* () { // We need a file remote type to make sure we don't switch processes when we // load the file:// URI. - let { browser } = yield loadTab("about:blank", "file"); + let { browser } = yield loadTab("about:blank", E10SUtils.FILE_REMOTE_TYPE); hud = yield openConsole(); hud.jsterm.clearOutput(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index ff43258e6ae8..7709d0d55955 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -494,8 +494,7 @@ ContentParentsMemoryReporter::CollectReports( return NS_OK; } -nsTArray* ContentParent::sBrowserContentParents; -nsTArray* ContentParent::sLargeAllocationContentParents; +nsClassHashtable>* ContentParent::sBrowserContentParents; nsTArray* ContentParent::sPrivateContent; StaticAutoPtr > ContentParent::sContentParents; #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX) @@ -648,24 +647,22 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType, ContentParent* aOpener, bool aLargeAllocationProcess) { - nsTArray* contentParents; - int32_t maxContentParents; + if (!sBrowserContentParents) { + sBrowserContentParents = + new nsClassHashtable>; + } // Decide which pool of content parents we are going to be pulling from based - // on the aLargeAllocationProcess flag. - if (aLargeAllocationProcess) { - if (!sLargeAllocationContentParents) { - sLargeAllocationContentParents = new nsTArray(); - } - contentParents = sLargeAllocationContentParents; - - maxContentParents = Preferences::GetInt("dom.ipc.dedicatedProcessCount", 2); - } else { - if (!sBrowserContentParents) { - sBrowserContentParents = new nsTArray(); - } - contentParents = sBrowserContentParents; + // on the aRemoteType and aLargeAllocationProcess flag. + nsAutoString contentProcessType(aLargeAllocationProcess + ? LARGE_ALLOCATION_REMOTE_TYPE : aRemoteType); + nsTArray* contentParents = + sBrowserContentParents->LookupOrAdd(contentProcessType); + int32_t maxContentParents; + nsAutoCString processCountPref("dom.ipc.processCount."); + processCountPref.Append(NS_ConvertUTF16toUTF8(contentProcessType)); + if (NS_FAILED(Preferences::GetInt(processCountPref.get(), &maxContentParents))) { maxContentParents = Preferences::GetInt("dom.ipc.processCount", 1); } @@ -688,7 +685,7 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType, } while (currIdx != startIdx); } - RefPtr p = new ContentParent(aOpener, aRemoteType); + RefPtr p = new ContentParent(aOpener, contentProcessType); if (!p->LaunchSubprocess(aPriority)) { return nullptr; @@ -696,8 +693,6 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType, p->Init(); - p->mLargeAllocationProcess = aLargeAllocationProcess; - p->ForwardKnownInfo(); contentParents->AppendElement(p); @@ -1308,18 +1303,17 @@ void ContentParent::MarkAsDead() { if (sBrowserContentParents) { - sBrowserContentParents->RemoveElement(this); - if (!sBrowserContentParents->Length()) { - delete sBrowserContentParents; - sBrowserContentParents = nullptr; - } - } - - if (sLargeAllocationContentParents) { - sLargeAllocationContentParents->RemoveElement(this); - if (!sLargeAllocationContentParents->Length()) { - delete sLargeAllocationContentParents; - sLargeAllocationContentParents = nullptr; + nsTArray* contentParents = + sBrowserContentParents->Get(mRemoteType); + if (contentParents) { + contentParents->RemoveElement(this); + if (contentParents->IsEmpty()) { + sBrowserContentParents->Remove(mRemoteType); + if (sBrowserContentParents->IsEmpty()) { + delete sBrowserContentParents; + sBrowserContentParents = nullptr; + } + } } } @@ -1648,10 +1642,13 @@ ContentParent::NotifyTabDestroying(const TabId& aTabId, return; } - uint32_t numberOfParents = sBrowserContentParents ? sBrowserContentParents->Length() : 0; - int32_t processesToKeepAlive = Preferences::GetInt("dom.ipc.keepProcessesAlive", 0); - if (!cp->mLargeAllocationProcess && static_cast(numberOfParents) <= processesToKeepAlive) { - return; + if (sBrowserContentParents && cp->mRemoteType.Equals(DEFAULT_REMOTE_TYPE)) { + auto contentParents = sBrowserContentParents->Get(cp->mRemoteType); + int32_t numberOfParents = contentParents ? contentParents->Length() : 0; + int32_t processesToKeepAlive = Preferences::GetInt("dom.ipc.keepProcessesAlive", 0); + if (numberOfParents <= processesToKeepAlive) { + return; + } } // We're dying now, so prevent this content process from being @@ -1705,10 +1702,13 @@ ContentParent::NotifyTabDestroyed(const TabId& aTabId, // We might want to keep alive some content processes for testing, because of performance // reasons, but we don't want to alter behavior if the pref is not set. - uint32_t numberOfParents = sBrowserContentParents ? sBrowserContentParents->Length() : 0; - int32_t processesToKeepAlive = Preferences::GetInt("dom.ipc.keepProcessesAlive", 0); - bool shouldKeepAliveAny = !mLargeAllocationProcess && processesToKeepAlive > 0; - bool shouldKeepAliveThis = shouldKeepAliveAny && static_cast(numberOfParents) <= processesToKeepAlive; + bool shouldKeepAliveThis = false; + if (sBrowserContentParents && mRemoteType.Equals(DEFAULT_REMOTE_TYPE)) { + auto contentParents = sBrowserContentParents->Get(mRemoteType); + int32_t numberOfParents = contentParents ? contentParents->Length() : 0; + int32_t processesToKeepAlive = Preferences::GetInt("dom.ipc.keepProcessesAlive", 0); + shouldKeepAliveThis = numberOfParents <= processesToKeepAlive; + } if (tabIds.Length() == 1 && !shouldKeepAliveThis) { // In the case of normal shutdown, send a shutdown message to child to @@ -1800,7 +1800,6 @@ ContentParent::ContentParent(ContentParent* aOpener, , mOpener(aOpener) , mRemoteType(aRemoteType) , mIsForBrowser(!mRemoteType.IsEmpty()) - , mLargeAllocationProcess(false) { InitializeMembers(); // Perform common initialization. @@ -1838,10 +1837,9 @@ ContentParent::~ContentParent() // We should be removed from all these lists in ActorDestroy. MOZ_ASSERT(!sPrivateContent || !sPrivateContent->Contains(this)); - MOZ_ASSERT((!sBrowserContentParents || - !sBrowserContentParents->Contains(this)) && - (!sLargeAllocationContentParents || - !sLargeAllocationContentParents->Contains(this))); + MOZ_ASSERT(!sBrowserContentParents || + !sBrowserContentParents->Contains(mRemoteType) || + !sBrowserContentParents->Get(mRemoteType)->Contains(this)); } void diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 2d4a1cef947c..19ca4bc8ea65 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -87,6 +87,9 @@ class GetFilesHelper; // This must match the one in E10SUtils.jsm. static NS_NAMED_LITERAL_STRING(DEFAULT_REMOTE_TYPE, "web"); +// This must start with the DEFAULT_REMOTE_TYPE above. +static NS_NAMED_LITERAL_STRING(LARGE_ALLOCATION_REMOTE_TYPE, + "webLargeAllocation"); static NS_NAMED_LITERAL_STRING(NO_REMOTE_TYPE, ""); class ContentParent final : public PContentParent @@ -554,8 +557,7 @@ protected: void OnCompositorUnexpectedShutdown() override; private: - static nsTArray* sBrowserContentParents; - static nsTArray* sLargeAllocationContentParents; + static nsClassHashtable>* sBrowserContentParents; static nsTArray* sPrivateContent; static StaticAutoPtr > sContentParents; @@ -1152,7 +1154,6 @@ private: nsRefPtrHashtable mGetFilesPendingRequests; nsTArray mBlobURLs; - bool mLargeAllocationProcess; }; } // namespace dom diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 50ced2ebcb50..e64d97d2e7b1 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2866,6 +2866,17 @@ pref("dom.ipc.plugins.asyncdrawing.enabled", true); pref("dom.ipc.processCount", 1); +// Override default dom.ipc.processCount for some remote content process types. +pref("dom.ipc.processCount.webLargeAllocation", 2); + +// Pref to control whether we use separate content processes for top-level load +// of file:// URIs. +#if defined(NIGHTLY_BUILD) +pref("browser.tabs.remote.separateFileUriProcess", true); +#else +pref("browser.tabs.remote.separateFileUriProcess", false); +#endif + // Enable caching of Moz2D Path objects for SVG geometry elements pref("svg.path-caching.enabled", true);