Backed out changeset f1ff6d4dca5f (bug 1311149)
This commit is contained in:
@@ -613,6 +613,9 @@ pref("hal.processPriorityManager.gonk.MASTER.OomScoreAdjust", 0);
|
|||||||
pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096);
|
pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096);
|
||||||
pref("hal.processPriorityManager.gonk.MASTER.cgroup", "");
|
pref("hal.processPriorityManager.gonk.MASTER.cgroup", "");
|
||||||
|
|
||||||
|
pref("hal.processPriorityManager.gonk.PREALLOC.OomScoreAdjust", 67);
|
||||||
|
pref("hal.processPriorityManager.gonk.PREALLOC.cgroup", "apps/bg_non_interactive");
|
||||||
|
|
||||||
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67);
|
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67);
|
||||||
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120);
|
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120);
|
||||||
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.cgroup", "apps/critical");
|
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.cgroup", "apps/critical");
|
||||||
@@ -690,6 +693,12 @@ pref("gonk.notifySoftLowMemUnderKB", 43008);
|
|||||||
// blocked on a poll(), and this pref has no effect.)
|
// blocked on a poll(), and this pref has no effect.)
|
||||||
pref("gonk.systemMemoryPressureRecoveryPollMS", 5000);
|
pref("gonk.systemMemoryPressureRecoveryPollMS", 5000);
|
||||||
|
|
||||||
|
// Enable pre-launching content processes for improved startup time
|
||||||
|
// (hiding latency).
|
||||||
|
pref("dom.ipc.processPrelaunch.enabled", true);
|
||||||
|
// Wait this long before pre-launching a new subprocess.
|
||||||
|
pref("dom.ipc.processPrelaunch.delayMs", 5000);
|
||||||
|
|
||||||
pref("dom.ipc.reuse_parent_app", false);
|
pref("dom.ipc.reuse_parent_app", false);
|
||||||
|
|
||||||
// When a process receives a system message, we hold a CPU wake lock on its
|
// When a process receives a system message, we hold a CPU wake lock on its
|
||||||
|
|||||||
@@ -13,5 +13,7 @@ support-files =
|
|||||||
|
|
||||||
[test_Simple.html]
|
[test_Simple.html]
|
||||||
[test_HighPriority.html]
|
[test_HighPriority.html]
|
||||||
|
[test_Preallocated.html]
|
||||||
|
disabled = bug 968604, bug 987164
|
||||||
[test_WebGLContextLost.html]
|
[test_WebGLContextLost.html]
|
||||||
disabled = bug 865844
|
disabled = bug 865844
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Test that the preallocated process starts up with priority BACKGROUND.
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="../browserElementTestHelpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
browserElementTestHelpers.setEnabledPref(true);
|
||||||
|
browserElementTestHelpers.addPermission();
|
||||||
|
browserElementTestHelpers.enableProcessPriorityManager();
|
||||||
|
|
||||||
|
var preallocationEnabledPref = null;
|
||||||
|
try {
|
||||||
|
preallocationEnabledPref = SpecialPowers.getBoolPref('dom.ipc.processPrelaunch.enabled');
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
preallocationEnabledPref = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var childID = null;
|
||||||
|
|
||||||
|
var cleanedUp = false;
|
||||||
|
function cleanUp()
|
||||||
|
{
|
||||||
|
if (cleanedUp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanedUp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even if this test times out, we still want to run cleanUp so as to set the
|
||||||
|
// pref back.
|
||||||
|
addEventListener('unload', cleanUp);
|
||||||
|
|
||||||
|
function runTest()
|
||||||
|
{
|
||||||
|
if (preallocationEnabledPref) {
|
||||||
|
ok(false, "dom.ipc.processPrelaunch.enabled must be " +
|
||||||
|
"false for this test to work.");
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the preallocated process initially gets BACKGROUND priority.
|
||||||
|
// That's it.
|
||||||
|
expectProcessCreated('PREALLOC').then(function() {
|
||||||
|
// We need to set the pref asynchoronously or the preallocated process won't
|
||||||
|
// be shut down.
|
||||||
|
SimpleTest.executeSoon(function(){
|
||||||
|
cleanUp();
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Setting this pref to true should cause us to prelaunch a process.
|
||||||
|
addEventListener('testready', function() {
|
||||||
|
SpecialPowers.pushPrefEnv({'set':[["dom.ipc.processPrelaunch.enabled",true]]},runTest);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -593,6 +593,7 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SendGetProcessAttributes(&mID, &mIsForBrowser);
|
SendGetProcessAttributes(&mID, &mIsForBrowser);
|
||||||
|
InitProcessAttributes();
|
||||||
|
|
||||||
#ifdef NS_PRINTING
|
#ifdef NS_PRINTING
|
||||||
// Force the creation of the nsPrintingProxy so that it's IPC counterpart,
|
// Force the creation of the nsPrintingProxy so that it's IPC counterpart,
|
||||||
@@ -600,11 +601,23 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
|||||||
RefPtr<nsPrintingProxy> printingProxy = nsPrintingProxy::GetInstance();
|
RefPtr<nsPrintingProxy> printingProxy = nsPrintingProxy::GetInstance();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SetProcessName(NS_LITERAL_STRING("Web Content"), true);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ContentChild::InitProcessAttributes()
|
||||||
|
{
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
if (mIsForBrowser) {
|
||||||
|
SetProcessName(NS_LITERAL_STRING("Browser"), false);
|
||||||
|
} else {
|
||||||
|
SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
SetProcessName(NS_LITERAL_STRING("Web Content"), true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
|
ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
|
||||||
{
|
{
|
||||||
@@ -1479,6 +1492,14 @@ ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CancelableRunnable* sFirstIdleTask;
|
||||||
|
|
||||||
|
static void FirstIdle(void)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(sFirstIdleTask);
|
||||||
|
sFirstIdleTask = nullptr;
|
||||||
|
ContentChild::GetSingleton()->SendFirstIdle();
|
||||||
|
}
|
||||||
|
|
||||||
mozilla::jsipc::PJavaScriptChild *
|
mozilla::jsipc::PJavaScriptChild *
|
||||||
ContentChild::AllocPJavaScriptChild()
|
ContentChild::AllocPJavaScriptChild()
|
||||||
@@ -1542,6 +1563,22 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
|||||||
os->NotifyObservers(tc, "tab-child-created", nullptr);
|
os->NotifyObservers(tc, "tab-child-created", nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hasRunOnce = false;
|
||||||
|
if (!hasRunOnce) {
|
||||||
|
hasRunOnce = true;
|
||||||
|
|
||||||
|
MOZ_ASSERT(!sFirstIdleTask);
|
||||||
|
RefPtr<CancelableRunnable> firstIdleTask = NewCancelableRunnableFunction(FirstIdle);
|
||||||
|
sFirstIdleTask = firstIdleTask;
|
||||||
|
MessageLoop::current()->PostIdleTask(firstIdleTask.forget());
|
||||||
|
|
||||||
|
// Redo InitProcessAttributes() when the app or browser is really
|
||||||
|
// launching so the attributes will be correct.
|
||||||
|
mID = aCpID;
|
||||||
|
mIsForBrowser = aIsForBrowser;
|
||||||
|
InitProcessAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2051,6 +2088,9 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
|
|||||||
// keep persistent state.
|
// keep persistent state.
|
||||||
ProcessChild::QuickExit();
|
ProcessChild::QuickExit();
|
||||||
#else
|
#else
|
||||||
|
if (sFirstIdleTask) {
|
||||||
|
sFirstIdleTask->Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
nsHostObjectProtocolHandler::RemoveDataEntries();
|
nsHostObjectProtocolHandler::RemoveDataEntries();
|
||||||
|
|
||||||
@@ -2354,6 +2394,19 @@ ContentChild::RecvCycleCollect()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PreloadSlowThings()
|
||||||
|
{
|
||||||
|
// This fetches and creates all the built-in stylesheets.
|
||||||
|
//
|
||||||
|
// XXXheycam In the future we might want to preload the Servo-flavoured
|
||||||
|
// UA sheets too, but for now that will be a waste of time.
|
||||||
|
nsLayoutStylesheetCache::For(StyleBackendType::Gecko)->UserContentSheet();
|
||||||
|
|
||||||
|
TabChild::PreloadSlowThings();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
|
ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
|
||||||
const nsCString& name, const nsCString& UAName,
|
const nsCString& name, const nsCString& UAName,
|
||||||
@@ -2369,6 +2422,25 @@ ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContentChild::RecvAppInit()
|
||||||
|
{
|
||||||
|
if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're part of the mozbrowser machinery, go ahead and start
|
||||||
|
// preloading things. We can only do this for mozbrowser because
|
||||||
|
// PreloadSlowThings() may set the docshell of the first TabChild
|
||||||
|
// inactive, and we can only safely restore it to active from
|
||||||
|
// BrowserElementChild.js.
|
||||||
|
if (mIsForBrowser) {
|
||||||
|
PreloadSlowThings();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentChild::RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig)
|
ContentChild::RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ public:
|
|||||||
base::ProcessId aParentPid,
|
base::ProcessId aParentPid,
|
||||||
IPC::Channel* aChannel);
|
IPC::Channel* aChannel);
|
||||||
|
|
||||||
|
void InitProcessAttributes();
|
||||||
|
|
||||||
void InitXPCOM();
|
void InitXPCOM();
|
||||||
|
|
||||||
void InitGraphicsDeviceData();
|
void InitGraphicsDeviceData();
|
||||||
@@ -424,6 +426,8 @@ public:
|
|||||||
const nsCString& name, const nsCString& UAName,
|
const nsCString& name, const nsCString& UAName,
|
||||||
const nsCString& ID, const nsCString& vendor) override;
|
const nsCString& ID, const nsCString& vendor) override;
|
||||||
|
|
||||||
|
virtual bool RecvAppInit() override;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig) override;
|
RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig) override;
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsToolkitCompsCID.h"
|
#include "nsToolkitCompsCID.h"
|
||||||
#include "nsWidgetsCID.h"
|
#include "nsWidgetsCID.h"
|
||||||
|
#include "PreallocatedProcessManager.h"
|
||||||
#include "ProcessPriorityManager.h"
|
#include "ProcessPriorityManager.h"
|
||||||
#include "SandboxHal.h"
|
#include "SandboxHal.h"
|
||||||
#include "ScreenManagerParent.h"
|
#include "ScreenManagerParent.h"
|
||||||
@@ -552,6 +553,25 @@ static const char* sObserverTopics[] = {
|
|||||||
"cacheservice:empty-cache",
|
"cacheservice:empty-cache",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PreallocateAppProcess is called by the PreallocatedProcessManager.
|
||||||
|
// ContentParent then takes this process back within
|
||||||
|
// GetNewOrPreallocatedAppProcess.
|
||||||
|
/*static*/ already_AddRefed<ContentParent>
|
||||||
|
ContentParent::PreallocateAppProcess()
|
||||||
|
{
|
||||||
|
RefPtr<ContentParent> process =
|
||||||
|
new ContentParent(/* aOpener = */ nullptr,
|
||||||
|
/* isForBrowserElement = */ false,
|
||||||
|
/* isForPreallocated = */ true);
|
||||||
|
|
||||||
|
if (!process->LaunchSubprocess(PROCESS_PRIORITY_PREALLOC)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
process->Init();
|
||||||
|
return process.forget();
|
||||||
|
}
|
||||||
|
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
ContentParent::StartUp()
|
ContentParent::StartUp()
|
||||||
{
|
{
|
||||||
@@ -585,6 +605,9 @@ ContentParent::StartUp()
|
|||||||
|
|
||||||
BackgroundChild::Startup();
|
BackgroundChild::Startup();
|
||||||
|
|
||||||
|
// Try to preallocate a process that we can transform into an app later.
|
||||||
|
PreallocatedProcessManager::AllocateAfterDelay();
|
||||||
|
|
||||||
sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
|
sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
|
||||||
|
|
||||||
#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
|
#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
|
||||||
@@ -697,15 +720,23 @@ ContentParent::GetNewOrUsedBrowserProcess(bool aForBrowserElement,
|
|||||||
} while (currIdx != startIdx);
|
} while (currIdx != startIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<ContentParent> p = new ContentParent(aOpener,
|
// Try to take and transform the preallocated process into browser.
|
||||||
aForBrowserElement);
|
RefPtr<ContentParent> p = PreallocatedProcessManager::Take();
|
||||||
|
if (p) {
|
||||||
|
p->TransformPreallocatedIntoBrowser(aOpener);
|
||||||
|
} else {
|
||||||
|
// Failed in using the preallocated process: fork from the chrome process.
|
||||||
|
p = new ContentParent(aOpener,
|
||||||
|
aForBrowserElement,
|
||||||
|
/* isForPreallocated = */ false);
|
||||||
|
|
||||||
if (!p->LaunchSubprocess(aPriority)) {
|
if (!p->LaunchSubprocess(aPriority)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
p->Init();
|
|
||||||
|
|
||||||
p->mLargeAllocationProcess = aLargeAllocationProcess;
|
p->mLargeAllocationProcess = aLargeAllocationProcess;
|
||||||
|
|
||||||
p->ForwardKnownInfo();
|
p->ForwardKnownInfo();
|
||||||
@@ -760,6 +791,12 @@ ContentParent::SendAsyncUpdate(nsIWidget* aWidget)
|
|||||||
}
|
}
|
||||||
#endif // defined(XP_WIN)
|
#endif // defined(XP_WIN)
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContentParent::PreallocatedProcessReady()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
|
ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
|
||||||
const hal::ProcessPriority& aPriority,
|
const hal::ProcessPriority& aPriority,
|
||||||
@@ -1208,6 +1245,15 @@ ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ContentParent::TransformPreallocatedIntoBrowser(ContentParent* aOpener)
|
||||||
|
{
|
||||||
|
// Reset mIsForBrowser and mOSPrivileges for browser.
|
||||||
|
mMetamorphosed = true;
|
||||||
|
mOpener = aOpener;
|
||||||
|
mIsForBrowser = true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ContentParent::ShutDownProcess(ShutDownMethod aMethod)
|
ContentParent::ShutDownProcess(ShutDownMethod aMethod)
|
||||||
{
|
{
|
||||||
@@ -1776,14 +1822,20 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContentParent::ContentParent(ContentParent* aOpener,
|
ContentParent::ContentParent(ContentParent* aOpener,
|
||||||
bool aIsForBrowser)
|
bool aIsForBrowser,
|
||||||
|
bool aIsForPreallocated)
|
||||||
: nsIContentParent()
|
: nsIContentParent()
|
||||||
, mOpener(aOpener)
|
, mOpener(aOpener)
|
||||||
, mIsForBrowser(aIsForBrowser)
|
, mIsForBrowser(aIsForBrowser)
|
||||||
|
, mIsPreallocated(aIsForPreallocated)
|
||||||
, mLargeAllocationProcess(false)
|
, mLargeAllocationProcess(false)
|
||||||
{
|
{
|
||||||
InitializeMembers(); // Perform common initialization.
|
InitializeMembers(); // Perform common initialization.
|
||||||
|
|
||||||
|
// No more than one of aIsForBrowser and aIsForPreallocated should be
|
||||||
|
// true.
|
||||||
|
MOZ_ASSERT(aIsForBrowser + aIsForPreallocated <= 1);
|
||||||
|
|
||||||
mMetamorphosed = true;
|
mMetamorphosed = true;
|
||||||
|
|
||||||
// Insert ourselves into the global linked list of ContentParent objects.
|
// Insert ourselves into the global linked list of ContentParent objects.
|
||||||
@@ -1896,6 +1948,11 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gAppData) {
|
||||||
|
// Sending all information to content process.
|
||||||
|
Unused << SendAppInit();
|
||||||
|
}
|
||||||
|
|
||||||
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
||||||
if (sheetService) {
|
if (sheetService) {
|
||||||
// This looks like a lot of work, but in a normal browser session we just
|
// This looks like a lot of work, but in a normal browser session we just
|
||||||
@@ -2255,6 +2312,17 @@ ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContentParent::RecvFirstIdle()
|
||||||
|
{
|
||||||
|
// When the ContentChild goes idle, it sends us a FirstIdle message
|
||||||
|
// which we use as a good time to prelaunch another process. If we
|
||||||
|
// prelaunch any sooner than this, then we'll be competing with the
|
||||||
|
// child process and slowing it down.
|
||||||
|
PreallocatedProcessManager::AllocateAfterDelay();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
|
ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
|
||||||
const bool& aHidden)
|
const bool& aHidden)
|
||||||
@@ -2751,11 +2819,19 @@ ContentParent::KillHard(const char* aReason)
|
|||||||
otherProcessHandle, /*force=*/true));
|
otherProcessHandle, /*force=*/true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContentParent::IsPreallocated() const
|
||||||
|
{
|
||||||
|
return mIsPreallocated;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ContentParent::FriendlyName(nsAString& aName, bool aAnonymize)
|
ContentParent::FriendlyName(nsAString& aName, bool aAnonymize)
|
||||||
{
|
{
|
||||||
aName.Truncate();
|
aName.Truncate();
|
||||||
if (mIsForBrowser) {
|
if (IsPreallocated()) {
|
||||||
|
aName.AssignLiteral("(Preallocated)");
|
||||||
|
} else if (mIsForBrowser) {
|
||||||
aName.AssignLiteral("Browser");
|
aName.AssignLiteral("Browser");
|
||||||
} else if (aAnonymize) {
|
} else if (aAnonymize) {
|
||||||
aName.AssignLiteral("<anonymized-name>");
|
aName.AssignLiteral("<anonymized-name>");
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
static void JoinAllSubprocesses();
|
static void JoinAllSubprocesses();
|
||||||
|
|
||||||
|
static bool PreallocatedProcessReady();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or create a content process for:
|
* Get or create a content process for:
|
||||||
* 1. browser iframe
|
* 1. browser iframe
|
||||||
@@ -135,6 +137,11 @@ public:
|
|||||||
ContentParent* aOpener = nullptr,
|
ContentParent* aOpener = nullptr,
|
||||||
bool aLargeAllocationProcess = false);
|
bool aLargeAllocationProcess = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a subprocess suitable for use as a preallocated app process.
|
||||||
|
*/
|
||||||
|
static already_AddRefed<ContentParent> PreallocateAppProcess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or create a content process for the given TabContext. aFrameElement
|
* Get or create a content process for the given TabContext. aFrameElement
|
||||||
* should be the frame/iframe element with which this process will
|
* should be the frame/iframe element with which this process will
|
||||||
@@ -352,6 +359,8 @@ public:
|
|||||||
|
|
||||||
ContentParentId ChildID() const override { return mChildID; }
|
ContentParentId ChildID() const override { return mChildID; }
|
||||||
|
|
||||||
|
bool IsPreallocated() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a user-friendly name for this ContentParent. We make no guarantees
|
* Get a user-friendly name for this ContentParent. We make no guarantees
|
||||||
* about this name: It might not be unique, apps can spoof special names,
|
* about this name: It might not be unique, apps can spoof special names,
|
||||||
@@ -574,8 +583,11 @@ private:
|
|||||||
|
|
||||||
FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
|
FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
|
||||||
|
|
||||||
|
// No more than one of aIsForBrowser, and aIsForPreallocated may be
|
||||||
|
// true.
|
||||||
ContentParent(ContentParent* aOpener,
|
ContentParent(ContentParent* aOpener,
|
||||||
bool aIsForBrowser);
|
bool aIsForBrowser,
|
||||||
|
bool aIsForPreallocated);
|
||||||
|
|
||||||
// The common initialization for the constructors.
|
// The common initialization for the constructors.
|
||||||
void InitializeMembers();
|
void InitializeMembers();
|
||||||
@@ -604,6 +616,10 @@ private:
|
|||||||
// unlikely that the process will be killed after this point.
|
// unlikely that the process will be killed after this point.
|
||||||
bool SetPriorityAndCheckIsAlive(hal::ProcessPriority aPriority);
|
bool SetPriorityAndCheckIsAlive(hal::ProcessPriority aPriority);
|
||||||
|
|
||||||
|
// Transform a pre-allocated app process into a browser process. If this
|
||||||
|
// returns false, the child process has died.
|
||||||
|
void TransformPreallocatedIntoBrowser(ContentParent* aOpener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark this ContentParent as dead for the purposes of Get*().
|
* Mark this ContentParent as dead for the purposes of Get*().
|
||||||
* This method is idempotent.
|
* This method is idempotent.
|
||||||
@@ -913,6 +929,8 @@ private:
|
|||||||
|
|
||||||
virtual bool RecvPrivateDocShellsExist(const bool& aExist) override;
|
virtual bool RecvPrivateDocShellsExist(const bool& aExist) override;
|
||||||
|
|
||||||
|
virtual bool RecvFirstIdle() override;
|
||||||
|
|
||||||
virtual bool RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
|
virtual bool RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
|
||||||
const bool& aHidden) override;
|
const bool& aHidden) override;
|
||||||
|
|
||||||
@@ -1084,6 +1102,7 @@ private:
|
|||||||
|
|
||||||
bool mSendPermissionUpdates;
|
bool mSendPermissionUpdates;
|
||||||
bool mIsForBrowser;
|
bool mIsForBrowser;
|
||||||
|
bool mIsPreallocated;
|
||||||
|
|
||||||
// These variables track whether we've called Close() and KillHard() on our
|
// These variables track whether we've called Close() and KillHard() on our
|
||||||
// channel.
|
// channel.
|
||||||
|
|||||||
@@ -531,6 +531,7 @@ child:
|
|||||||
|
|
||||||
async AppInfo(nsCString version, nsCString buildID, nsCString name, nsCString UAName,
|
async AppInfo(nsCString version, nsCString buildID, nsCString name, nsCString UAName,
|
||||||
nsCString ID, nsCString vendor);
|
nsCString ID, nsCString vendor);
|
||||||
|
async AppInit();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send ServiceWorkerRegistrationData to child process.
|
* Send ServiceWorkerRegistrationData to child process.
|
||||||
@@ -915,6 +916,9 @@ parent:
|
|||||||
// Notify the parent of the presence or absence of private docshells
|
// Notify the parent of the presence or absence of private docshells
|
||||||
async PrivateDocShellsExist(bool aExist);
|
async PrivateDocShellsExist(bool aExist);
|
||||||
|
|
||||||
|
// Tell the parent that the child has gone idle for the first time
|
||||||
|
async FirstIdle();
|
||||||
|
|
||||||
async AudioChannelServiceStatus(bool aActiveTelephonyChannel,
|
async AudioChannelServiceStatus(bool aActiveTelephonyChannel,
|
||||||
bool aContentOrNormalChannel,
|
bool aContentOrNormalChannel,
|
||||||
bool aAnyActiveChannel);
|
bool aAnyActiveChannel);
|
||||||
|
|||||||
252
dom/ipc/PreallocatedProcessManager.cpp
Normal file
252
dom/ipc/PreallocatedProcessManager.cpp
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/PreallocatedProcessManager.h"
|
||||||
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/Unused.h"
|
||||||
|
#include "mozilla/dom/ContentParent.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
|
#include "nsIPropertyBag2.h"
|
||||||
|
#include "ProcessPriorityManager.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
|
||||||
|
// This number is fairly arbitrary ... the intention is to put off
|
||||||
|
// launching another app process until the last one has finished
|
||||||
|
// loading its content, to reduce CPU/memory/IO contention.
|
||||||
|
#define DEFAULT_ALLOCATE_DELAY 1000
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::hal;
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This singleton class implements the static methods on
|
||||||
|
* PreallocatedProcessManager.
|
||||||
|
*/
|
||||||
|
class PreallocatedProcessManagerImpl final
|
||||||
|
: public nsIObserver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static PreallocatedProcessManagerImpl* Singleton();
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
|
// See comments on PreallocatedProcessManager for these methods.
|
||||||
|
void AllocateAfterDelay();
|
||||||
|
void AllocateOnIdle();
|
||||||
|
void AllocateNow();
|
||||||
|
already_AddRefed<ContentParent> Take();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
|
||||||
|
|
||||||
|
PreallocatedProcessManagerImpl();
|
||||||
|
~PreallocatedProcessManagerImpl() {}
|
||||||
|
DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManagerImpl);
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void RereadPrefs();
|
||||||
|
void Enable();
|
||||||
|
void Disable();
|
||||||
|
|
||||||
|
void ObserveProcessShutdown(nsISupports* aSubject);
|
||||||
|
|
||||||
|
bool mEnabled;
|
||||||
|
bool mShutdown;
|
||||||
|
RefPtr<ContentParent> mPreallocatedAppProcess;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* static */ StaticRefPtr<PreallocatedProcessManagerImpl>
|
||||||
|
PreallocatedProcessManagerImpl::sSingleton;
|
||||||
|
|
||||||
|
/* static */ PreallocatedProcessManagerImpl*
|
||||||
|
PreallocatedProcessManagerImpl::Singleton()
|
||||||
|
{
|
||||||
|
if (!sSingleton) {
|
||||||
|
sSingleton = new PreallocatedProcessManagerImpl();
|
||||||
|
sSingleton->Init();
|
||||||
|
ClearOnShutdown(&sSingleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sSingleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PreallocatedProcessManagerImpl, nsIObserver)
|
||||||
|
|
||||||
|
PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
|
||||||
|
:
|
||||||
|
mEnabled(false)
|
||||||
|
, mShutdown(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::Init()
|
||||||
|
{
|
||||||
|
Preferences::AddStrongObserver(this, "dom.ipc.processPrelaunch.enabled");
|
||||||
|
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||||
|
if (os) {
|
||||||
|
os->AddObserver(this, "ipc:content-shutdown",
|
||||||
|
/* weakRef = */ false);
|
||||||
|
os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||||
|
/* weakRef = */ false);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RereadPrefs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
|
||||||
|
const char* aTopic,
|
||||||
|
const char16_t* aData)
|
||||||
|
{
|
||||||
|
if (!strcmp("ipc:content-shutdown", aTopic)) {
|
||||||
|
ObserveProcessShutdown(aSubject);
|
||||||
|
} else if (!strcmp("nsPref:changed", aTopic)) {
|
||||||
|
// The only other observer we registered was for our prefs.
|
||||||
|
RereadPrefs();
|
||||||
|
} else if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
|
||||||
|
mShutdown = true;
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::RereadPrefs()
|
||||||
|
{
|
||||||
|
if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled")) {
|
||||||
|
Enable();
|
||||||
|
} else {
|
||||||
|
Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<ContentParent>
|
||||||
|
PreallocatedProcessManagerImpl::Take()
|
||||||
|
{
|
||||||
|
return mPreallocatedAppProcess.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::Enable()
|
||||||
|
{
|
||||||
|
if (mEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mEnabled = true;
|
||||||
|
AllocateAfterDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::AllocateAfterDelay()
|
||||||
|
{
|
||||||
|
if (!mEnabled || mPreallocatedAppProcess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageLoop::current()->PostDelayedTask(
|
||||||
|
NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateOnIdle),
|
||||||
|
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
|
||||||
|
DEFAULT_ALLOCATE_DELAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::AllocateOnIdle()
|
||||||
|
{
|
||||||
|
if (!mEnabled || mPreallocatedAppProcess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageLoop::current()->PostIdleTask(NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateNow));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::AllocateNow()
|
||||||
|
{
|
||||||
|
if (!mEnabled || mPreallocatedAppProcess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPreallocatedAppProcess = ContentParent::PreallocateAppProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::Disable()
|
||||||
|
{
|
||||||
|
if (!mEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mEnabled = false;
|
||||||
|
|
||||||
|
if (mPreallocatedAppProcess) {
|
||||||
|
mPreallocatedAppProcess->Close();
|
||||||
|
mPreallocatedAppProcess = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::ObserveProcessShutdown(nsISupports* aSubject)
|
||||||
|
{
|
||||||
|
if (!mPreallocatedAppProcess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
|
||||||
|
NS_ENSURE_TRUE_VOID(props);
|
||||||
|
|
||||||
|
uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
|
||||||
|
props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
|
||||||
|
NS_ENSURE_TRUE_VOID(childID != CONTENT_PROCESS_ID_UNKNOWN);
|
||||||
|
|
||||||
|
if (childID == mPreallocatedAppProcess->ChildID()) {
|
||||||
|
mPreallocatedAppProcess = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PreallocatedProcessManagerImpl* GetPPMImpl()
|
||||||
|
{
|
||||||
|
return PreallocatedProcessManagerImpl::Singleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
PreallocatedProcessManager::AllocateAfterDelay()
|
||||||
|
{
|
||||||
|
GetPPMImpl()->AllocateAfterDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
PreallocatedProcessManager::AllocateOnIdle()
|
||||||
|
{
|
||||||
|
GetPPMImpl()->AllocateOnIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
PreallocatedProcessManager::AllocateNow()
|
||||||
|
{
|
||||||
|
GetPPMImpl()->AllocateNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ already_AddRefed<ContentParent>
|
||||||
|
PreallocatedProcessManager::Take()
|
||||||
|
{
|
||||||
|
return GetPPMImpl()->Take();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
88
dom/ipc/PreallocatedProcessManager.h
Normal file
88
dom/ipc/PreallocatedProcessManager.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_PreallocatedProcessManager_h
|
||||||
|
#define mozilla_PreallocatedProcessManager_h
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIObserver.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
class ContentParent;
|
||||||
|
} // namespace dom
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class manages a ContentParent that it starts up ahead of any particular
|
||||||
|
* need. You can then call Take() to get this process and use it. Since we
|
||||||
|
* already started it up, it should be ready for use faster than if you'd
|
||||||
|
* created the process when you needed it.
|
||||||
|
*
|
||||||
|
* This class watches the dom.ipc.processPrelaunch.enabled pref. If it changes
|
||||||
|
* from false to true, it preallocates a process. If it changes from true to
|
||||||
|
* false, it kills the preallocated process, if any.
|
||||||
|
*
|
||||||
|
* We don't expect this pref to flip between true and false in production, but
|
||||||
|
* flipping the pref is important for tests.
|
||||||
|
*
|
||||||
|
* The static methods here are implemented by forwarding calls on to a
|
||||||
|
* PreallocatedProcessManagerImpl singleton class, so if you add a new static
|
||||||
|
* method here, you'll need to write a corresponding public method on the
|
||||||
|
* singleton.
|
||||||
|
*/
|
||||||
|
class PreallocatedProcessManager final
|
||||||
|
{
|
||||||
|
typedef mozilla::dom::ContentParent ContentParent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a process after a delay. We wait for a period of time (specified
|
||||||
|
* by the dom.ipc.processPrelaunch.delayMs pref), then wait for this process
|
||||||
|
* to go idle, then allocate the new process.
|
||||||
|
*
|
||||||
|
* If the dom.ipc.processPrelaunch.enabled pref is false, or if we already
|
||||||
|
* have a preallocated process, this function does nothing.
|
||||||
|
*/
|
||||||
|
static void AllocateAfterDelay();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a process once this process goes idle.
|
||||||
|
*
|
||||||
|
* If the dom.ipc.processPrelaunch.enabled pref is false, or if we already
|
||||||
|
* have a preallocated process, this function does nothing.
|
||||||
|
*/
|
||||||
|
static void AllocateOnIdle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a process right now.
|
||||||
|
*
|
||||||
|
* If the dom.ipc.processPrelaunch.enabled pref is false, or if we already
|
||||||
|
* have a preallocated process, this function does nothing.
|
||||||
|
*/
|
||||||
|
static void AllocateNow();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take the preallocated process, if we have one. If we don't have one, this
|
||||||
|
* returns null.
|
||||||
|
*
|
||||||
|
* If you call Take() twice in a row, the second call is guaranteed to return
|
||||||
|
* null.
|
||||||
|
*
|
||||||
|
* After you Take() the preallocated process, you need to call one of the
|
||||||
|
* Allocate* functions (or change the dom.ipc.processPrelaunch pref from
|
||||||
|
* false to true) before we'll create a new process.
|
||||||
|
*/
|
||||||
|
static already_AddRefed<ContentParent> Take();
|
||||||
|
|
||||||
|
private:
|
||||||
|
PreallocatedProcessManager();
|
||||||
|
DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // defined mozilla_PreallocatedProcessManager_h
|
||||||
@@ -301,6 +301,7 @@ public:
|
|||||||
|
|
||||||
int32_t Pid() const;
|
int32_t Pid() const;
|
||||||
uint64_t ChildID() const;
|
uint64_t ChildID() const;
|
||||||
|
bool IsPreallocated() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used in logging, this method returns the ContentParent's name followed by
|
* Used in logging, this method returns the ContentParent's name followed by
|
||||||
@@ -617,12 +618,15 @@ ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
|
|||||||
ProcessPriority aOldPriority)
|
ProcessPriority aOldPriority)
|
||||||
{
|
{
|
||||||
ProcessPriority newPriority = aParticularManager->CurrentPriority();
|
ProcessPriority newPriority = aParticularManager->CurrentPriority();
|
||||||
|
bool isPreallocated = aParticularManager->IsPreallocated();
|
||||||
|
|
||||||
if (newPriority == PROCESS_PRIORITY_BACKGROUND &&
|
if (newPriority == PROCESS_PRIORITY_BACKGROUND &&
|
||||||
aOldPriority != PROCESS_PRIORITY_BACKGROUND) {
|
aOldPriority != PROCESS_PRIORITY_BACKGROUND &&
|
||||||
|
!isPreallocated) {
|
||||||
mBackgroundLRUPool.Add(aParticularManager);
|
mBackgroundLRUPool.Add(aParticularManager);
|
||||||
} else if (newPriority != PROCESS_PRIORITY_BACKGROUND &&
|
} else if (newPriority != PROCESS_PRIORITY_BACKGROUND &&
|
||||||
aOldPriority == PROCESS_PRIORITY_BACKGROUND) {
|
aOldPriority == PROCESS_PRIORITY_BACKGROUND &&
|
||||||
|
!isPreallocated) {
|
||||||
mBackgroundLRUPool.Remove(aParticularManager);
|
mBackgroundLRUPool.Remove(aParticularManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,6 +809,12 @@ ParticularProcessPriorityManager::Pid() const
|
|||||||
return mContentParent ? mContentParent->Pid() : -1;
|
return mContentParent ? mContentParent->Pid() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ParticularProcessPriorityManager::IsPreallocated() const
|
||||||
|
{
|
||||||
|
return mContentParent ? mContentParent->IsPreallocated() : false;
|
||||||
|
}
|
||||||
|
|
||||||
const nsAutoCString&
|
const nsAutoCString&
|
||||||
ParticularProcessPriorityManager::NameWithComma()
|
ParticularProcessPriorityManager::NameWithComma()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -326,6 +326,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
StaticRefPtr<TabChild> sPreallocatedTab;
|
||||||
|
|
||||||
std::map<TabId, RefPtr<TabChild>>&
|
std::map<TabId, RefPtr<TabChild>>&
|
||||||
NestedTabChildMap()
|
NestedTabChildMap()
|
||||||
{
|
{
|
||||||
@@ -346,12 +348,89 @@ TabChild::FindTabChild(const TabId& aTabId)
|
|||||||
return tabChild.forget();
|
return tabChild.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PreloadSlowThingsPostFork(void* aUnused)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIObserverService> observerService =
|
||||||
|
mozilla::services::GetObserverService();
|
||||||
|
observerService->NotifyObservers(nullptr, "preload-postfork", nullptr);
|
||||||
|
|
||||||
|
MOZ_ASSERT(sPreallocatedTab);
|
||||||
|
// Initialize initial reflow of the PresShell has to happen after fork
|
||||||
|
// because about:blank content viewer is created in the above observer
|
||||||
|
// notification.
|
||||||
|
nsCOMPtr<nsIDocShell> docShell =
|
||||||
|
do_GetInterface(sPreallocatedTab->WebNavigation());
|
||||||
|
if (nsIPresShell* presShell = docShell->GetPresShell()) {
|
||||||
|
// Initialize and do an initial reflow of the about:blank
|
||||||
|
// PresShell to let it preload some things for us.
|
||||||
|
presShell->Initialize(0, 0);
|
||||||
|
nsIDocument* doc = presShell->GetDocument();
|
||||||
|
doc->FlushPendingNotifications(Flush_Layout);
|
||||||
|
// ... but after it's done, make sure it doesn't do any more
|
||||||
|
// work.
|
||||||
|
presShell->MakeZombie();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sPreloaded = false;
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
TabChild::PreloadSlowThings()
|
||||||
|
{
|
||||||
|
if (sPreloaded) {
|
||||||
|
// If we are alredy initialized in Nuwa, don't redo preloading.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sPreloaded = true;
|
||||||
|
|
||||||
|
// Pass nullptr to aManager since at this point the TabChild is
|
||||||
|
// not connected to any manager. Any attempt to use the TabChild
|
||||||
|
// in IPC will crash.
|
||||||
|
RefPtr<TabChild> tab(new TabChild(nullptr,
|
||||||
|
TabId(0),
|
||||||
|
TabContext(), /* chromeFlags */ 0));
|
||||||
|
if (!NS_SUCCEEDED(tab->Init()) ||
|
||||||
|
!tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just load and compile these scripts, but don't run them.
|
||||||
|
tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
|
||||||
|
// Load, compile, and run these scripts.
|
||||||
|
tab->RecvLoadRemoteScript(
|
||||||
|
NS_LITERAL_STRING("chrome://global/content/preload.js"),
|
||||||
|
true);
|
||||||
|
|
||||||
|
sPreallocatedTab = tab;
|
||||||
|
ClearOnShutdown(&sPreallocatedTab);
|
||||||
|
|
||||||
|
PreloadSlowThingsPostFork(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
/*static*/ already_AddRefed<TabChild>
|
/*static*/ already_AddRefed<TabChild>
|
||||||
TabChild::Create(nsIContentChild* aManager,
|
TabChild::Create(nsIContentChild* aManager,
|
||||||
const TabId& aTabId,
|
const TabId& aTabId,
|
||||||
const TabContext &aContext,
|
const TabContext &aContext,
|
||||||
uint32_t aChromeFlags)
|
uint32_t aChromeFlags)
|
||||||
{
|
{
|
||||||
|
if (sPreallocatedTab &&
|
||||||
|
sPreallocatedTab->mChromeFlags == aChromeFlags &&
|
||||||
|
aContext.IsMozBrowser()) {
|
||||||
|
|
||||||
|
RefPtr<TabChild> child = sPreallocatedTab.get();
|
||||||
|
sPreallocatedTab = nullptr;
|
||||||
|
|
||||||
|
MOZ_ASSERT(!child->mTriedBrowserInit);
|
||||||
|
|
||||||
|
child->mManager = aManager;
|
||||||
|
child->SetTabId(aTabId);
|
||||||
|
child->SetTabContext(aContext);
|
||||||
|
child->NotifyTabContextUpdated(true);
|
||||||
|
return child.forget();
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<TabChild> iframe = new TabChild(aManager, aTabId,
|
RefPtr<TabChild> iframe = new TabChild(aManager, aTabId,
|
||||||
aContext, aChromeFlags);
|
aContext, aChromeFlags);
|
||||||
return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
|
return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
|
||||||
@@ -542,6 +621,13 @@ TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
|
|||||||
const ViewID& aViewId,
|
const ViewID& aViewId,
|
||||||
const Maybe<ZoomConstraints>& aConstraints)
|
const Maybe<ZoomConstraints>& aConstraints)
|
||||||
{
|
{
|
||||||
|
if (sPreallocatedTab == this) {
|
||||||
|
// If we're the preallocated tab, bail out because doing IPC will crash.
|
||||||
|
// Once we get used for something we'll get another zoom constraints update
|
||||||
|
// and all will be well.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!mApzcTreeManager) {
|
if (!mApzcTreeManager) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2416,7 +2502,7 @@ TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TabChild::InitTabChildGlobal()
|
TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
|
||||||
{
|
{
|
||||||
if (!mGlobal && !mTabChildGlobal) {
|
if (!mGlobal && !mTabChildGlobal) {
|
||||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
|
nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
|
||||||
@@ -2440,7 +2526,7 @@ TabChild::InitTabChildGlobal()
|
|||||||
root->SetParentTarget(scope);
|
root->SetParentTarget(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mTriedBrowserInit) {
|
if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {
|
||||||
mTriedBrowserInit = true;
|
mTriedBrowserInit = true;
|
||||||
// Initialize the child side of the browser element machinery,
|
// Initialize the child side of the browser element machinery,
|
||||||
// if appropriate.
|
// if appropriate.
|
||||||
|
|||||||
@@ -280,6 +280,13 @@ public:
|
|||||||
|
|
||||||
nsresult Init();
|
nsresult Init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is expected to be called off the critical path to content
|
||||||
|
* startup. This is an opportunity to load things that are slow
|
||||||
|
* on the critical path.
|
||||||
|
*/
|
||||||
|
static void PreloadSlowThings();
|
||||||
|
|
||||||
/** Return a TabChild with the given attributes. */
|
/** Return a TabChild with the given attributes. */
|
||||||
static already_AddRefed<TabChild>
|
static already_AddRefed<TabChild>
|
||||||
Create(nsIContentChild* aManager, const TabId& aTabId,
|
Create(nsIContentChild* aManager, const TabId& aTabId,
|
||||||
@@ -717,7 +724,9 @@ private:
|
|||||||
|
|
||||||
void ActorDestroy(ActorDestroyReason why) override;
|
void ActorDestroy(ActorDestroyReason why) override;
|
||||||
|
|
||||||
bool InitTabChildGlobal();
|
enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS };
|
||||||
|
|
||||||
|
bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS);
|
||||||
|
|
||||||
void InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
void InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
||||||
const uint64_t& aLayersId,
|
const uint64_t& aLayersId,
|
||||||
|
|||||||
@@ -10,3 +10,4 @@ toolkit.jar:
|
|||||||
content/global/BrowserElementCopyPaste.js (../browser-element/BrowserElementCopyPaste.js)
|
content/global/BrowserElementCopyPaste.js (../browser-element/BrowserElementCopyPaste.js)
|
||||||
content/global/extensions.js (extensions.js)
|
content/global/extensions.js (extensions.js)
|
||||||
content/global/manifestMessages.js (manifestMessages.js)
|
content/global/manifestMessages.js (manifestMessages.js)
|
||||||
|
content/global/preload.js (preload.js)
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ EXPORTS.mozilla.dom += [
|
|||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
'AppProcessChecker.h',
|
'AppProcessChecker.h',
|
||||||
|
'PreallocatedProcessManager.h',
|
||||||
'ProcessHangMonitor.h',
|
'ProcessHangMonitor.h',
|
||||||
'ProcessHangMonitorIPC.h',
|
'ProcessHangMonitorIPC.h',
|
||||||
'ProcessPriorityManager.h',
|
'ProcessPriorityManager.h',
|
||||||
@@ -59,6 +60,7 @@ UNIFIED_SOURCES += [
|
|||||||
'nsIContentChild.cpp',
|
'nsIContentChild.cpp',
|
||||||
'nsIContentParent.cpp',
|
'nsIContentParent.cpp',
|
||||||
'PermissionMessageUtils.cpp',
|
'PermissionMessageUtils.cpp',
|
||||||
|
'PreallocatedProcessManager.cpp',
|
||||||
'ProcessPriorityManager.cpp',
|
'ProcessPriorityManager.cpp',
|
||||||
'ScreenManagerParent.cpp',
|
'ScreenManagerParent.cpp',
|
||||||
'StructuredCloneData.cpp',
|
'StructuredCloneData.cpp',
|
||||||
|
|||||||
130
dom/ipc/preload.js
Normal file
130
dom/ipc/preload.js
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// Preload some things, in an attempt to make app startup faster.
|
||||||
|
//
|
||||||
|
// This script is run when the preallocated process starts. It is injected as
|
||||||
|
// a frame script.
|
||||||
|
|
||||||
|
var BrowserElementIsPreloaded = true;
|
||||||
|
|
||||||
|
var DoPreloadPostfork = function(aCallback) {
|
||||||
|
Services.obs.addObserver({
|
||||||
|
_callback: aCallback,
|
||||||
|
|
||||||
|
observe: function() {
|
||||||
|
this._callback();
|
||||||
|
Services.obs.removeObserver(this, "preload-postfork");
|
||||||
|
}
|
||||||
|
}, "preload-postfork", false);
|
||||||
|
};
|
||||||
|
|
||||||
|
(function (global) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let Cu = Components.utils;
|
||||||
|
let Cc = Components.classes;
|
||||||
|
let Ci = Components.interfaces;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||||
|
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
||||||
|
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Geometry.jsm");
|
||||||
|
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||||
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource://gre/modules/SettingsDB.jsm");
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
Cc["@mozilla.org/appshell/appShellService;1"].getService(Ci["nsIAppShellService"]);
|
||||||
|
Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci["nsIWindowMediator"]);
|
||||||
|
Cc["@mozilla.org/base/telemetry;1"].getService(Ci["nsITelemetry"]);
|
||||||
|
Cc["@mozilla.org/categorymanager;1"].getService(Ci["nsICategoryManager"]);
|
||||||
|
Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci["nsIMessageSender"]);
|
||||||
|
Cc["@mozilla.org/consoleservice;1"].getService(Ci["nsIConsoleService"]);
|
||||||
|
Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci["nsIURIFixup"]);
|
||||||
|
Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci["nsIDOMRequestService"]);
|
||||||
|
Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci["nsIPromptService"]);
|
||||||
|
Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci["nsIWindowWatcher"]);
|
||||||
|
Cc["@mozilla.org/eventlistenerservice;1"].getService(Ci["nsIEventListenerService"]);
|
||||||
|
Cc["@mozilla.org/focus-manager;1"].getService(Ci["nsIFocusManager"]);
|
||||||
|
Cc["@mozilla.org/intl/nslocaleservice;1"].getService(Ci["nsILocaleService"]);
|
||||||
|
Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci["nsIStringBundleService"]);
|
||||||
|
Cc["@mozilla.org/layout/content-policy;1"].getService(Ci["nsIContentPolicy"]);
|
||||||
|
Cc["@mozilla.org/message-loop;1"].getService(Ci["nsIMessageLoop"]);
|
||||||
|
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci["mozIJSSubScriptLoader"]);
|
||||||
|
Cc["@mozilla.org/network/application-cache-service;1"].getService(Ci["nsIApplicationCacheService"]);
|
||||||
|
Cc["@mozilla.org/network/dns-service;1"].getService(Ci["nsIDNSService"]);
|
||||||
|
Cc["@mozilla.org/network/effective-tld-service;1"].getService(Ci["nsIEffectiveTLDService"]);
|
||||||
|
Cc["@mozilla.org/network/idn-service;1"].getService(Ci["nsIIDNService"]);
|
||||||
|
Cc["@mozilla.org/network/io-service;1"].getService(Ci["nsIIOService2"]);
|
||||||
|
Cc["@mozilla.org/network/mime-hdrparam;1"].getService(Ci["nsIMIMEHeaderParam"]);
|
||||||
|
Cc["@mozilla.org/network/socket-transport-service;1"].getService(Ci["nsISocketTransportService"]);
|
||||||
|
Cc["@mozilla.org/network/stream-transport-service;1"].getService(Ci["nsIStreamTransportService"]);
|
||||||
|
Cc["@mozilla.org/network/url-parser;1?auth=maybe"].getService(Ci["nsIURLParser"]);
|
||||||
|
Cc["@mozilla.org/network/url-parser;1?auth=no"].getService(Ci["nsIURLParser"]);
|
||||||
|
Cc["@mozilla.org/network/url-parser;1?auth=yes"].getService(Ci["nsIURLParser"]);
|
||||||
|
Cc["@mozilla.org/observer-service;1"].getService(Ci["nsIObserverService"]);
|
||||||
|
Cc["@mozilla.org/preferences-service;1"].getService(Ci["nsIPrefBranch"]);
|
||||||
|
Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci["nsIScriptSecurityManager"]);
|
||||||
|
Cc["@mozilla.org/storage/service;1"].getService(Ci["mozIStorageService"]);
|
||||||
|
Cc["@mozilla.org/system-info;1"].getService(Ci["nsIPropertyBag2"]);
|
||||||
|
Cc["@mozilla.org/thread-manager;1"].getService(Ci["nsIThreadManager"]);
|
||||||
|
Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci["nsIAppStartup"]);
|
||||||
|
Cc["@mozilla.org/uriloader;1"].getService(Ci["nsIURILoader"]);
|
||||||
|
Cc["@mozilla.org/cspcontext;1"].createInstance(Ci["nsIContentSecurityPolicy"]);
|
||||||
|
Cc["@mozilla.org/settingsManager;1"].createInstance(Ci["nsISupports"]);
|
||||||
|
|
||||||
|
/* Applications Specific Helper */
|
||||||
|
try {
|
||||||
|
if (Services.prefs.getBoolPref("dom.sysmsg.enabled")) {
|
||||||
|
Cc["@mozilla.org/system-message-manager;1"].getService(Ci["nsIDOMNavigatorSystemMessages"]);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) {
|
||||||
|
Services.scriptloader.loadSubScript("chrome://global/content/forms.js", global);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js", global);
|
||||||
|
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js", global);
|
||||||
|
|
||||||
|
Services.io.getProtocolHandler("app");
|
||||||
|
Services.io.getProtocolHandler("default");
|
||||||
|
|
||||||
|
// Register an observer for topic "preload_postfork" after we fork a content
|
||||||
|
// process.
|
||||||
|
DoPreloadPostfork(function () {
|
||||||
|
// Load AppsServiceChild.jsm after fork since it sends an async message to
|
||||||
|
// the chrome process in its init() function.
|
||||||
|
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
|
||||||
|
|
||||||
|
// Load nsIAppsService after fork since its implementation loads
|
||||||
|
// AppsServiceChild.jsm
|
||||||
|
Cc["@mozilla.org/AppsService;1"].getService(Ci["nsIAppsService"]);
|
||||||
|
|
||||||
|
// Load nsICookieService after fork since it sends an IPC constructor
|
||||||
|
// message to the chrome process.
|
||||||
|
Cc["@mozilla.org/cookieService;1"].getService(Ci["nsICookieService"]);
|
||||||
|
|
||||||
|
// Load nsIPermissionManager after fork since it sends a message to the
|
||||||
|
// chrome process to read permissions.
|
||||||
|
Cc["@mozilla.org/permissionmanager;1"].getService(Ci["nsIPermissionManager"]);
|
||||||
|
|
||||||
|
// Load nsIProtocolProxyService after fork since it asynchronously accesses
|
||||||
|
// the "Proxy Resolution" thread after it's frozen.
|
||||||
|
Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(Ci["nsIProtocolProxyService"]);
|
||||||
|
|
||||||
|
// Call docShell.createAboutBlankContentViewer() after fork since it has IPC
|
||||||
|
// activity in the PCompositor protocol.
|
||||||
|
docShell.createAboutBlankContentViewer(null);
|
||||||
|
docShell.isActive = false;
|
||||||
|
});
|
||||||
|
})(this);
|
||||||
|
|
||||||
@@ -1574,6 +1574,12 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
|
|||||||
ContentParent::GetAll(cplist);
|
ContentParent::GetAll(cplist);
|
||||||
for (uint32_t i = 0; i < cplist.Length(); ++i) {
|
for (uint32_t i = 0; i < cplist.Length(); ++i) {
|
||||||
ContentParent* cp = cplist[i];
|
ContentParent* cp = cplist[i];
|
||||||
|
// On platforms where we use a preallocated template process we don't
|
||||||
|
// want to notify this process about session specific permissions so
|
||||||
|
// new tabs or apps created on it won't inherit the session permissions.
|
||||||
|
if (cp->IsPreallocated() &&
|
||||||
|
aExpireType == nsIPermissionManager::EXPIRE_SESSION)
|
||||||
|
continue;
|
||||||
if (cp->NeedsPermissionsUpdate())
|
if (cp->NeedsPermissionsUpdate())
|
||||||
Unused << cp->SendAddPermission(permission);
|
Unused << cp->SendAddPermission(permission);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -915,6 +915,8 @@ ProcessPriorityToString(ProcessPriority aPriority)
|
|||||||
switch (aPriority) {
|
switch (aPriority) {
|
||||||
case PROCESS_PRIORITY_MASTER:
|
case PROCESS_PRIORITY_MASTER:
|
||||||
return "MASTER";
|
return "MASTER";
|
||||||
|
case PROCESS_PRIORITY_PREALLOC:
|
||||||
|
return "PREALLOC";
|
||||||
case PROCESS_PRIORITY_FOREGROUND_HIGH:
|
case PROCESS_PRIORITY_FOREGROUND_HIGH:
|
||||||
return "FOREGROUND_HIGH";
|
return "FOREGROUND_HIGH";
|
||||||
case PROCESS_PRIORITY_FOREGROUND:
|
case PROCESS_PRIORITY_FOREGROUND:
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ enum ProcessPriority {
|
|||||||
PROCESS_PRIORITY_BACKGROUND,
|
PROCESS_PRIORITY_BACKGROUND,
|
||||||
PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE,
|
PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE,
|
||||||
PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
|
PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
|
||||||
|
// The special class for the preallocated process, high memory priority but
|
||||||
|
// low CPU priority.
|
||||||
|
PROCESS_PRIORITY_PREALLOC,
|
||||||
// Any priority greater than or equal to FOREGROUND is considered
|
// Any priority greater than or equal to FOREGROUND is considered
|
||||||
// "foreground" for the purposes of priority testing, for example
|
// "foreground" for the purposes of priority testing, for example
|
||||||
// CurrentProcessIsForeground().
|
// CurrentProcessIsForeground().
|
||||||
|
|||||||
@@ -205,6 +205,18 @@ public:
|
|||||||
|
|
||||||
bool IsDestroying() { return mIsDestroying; }
|
bool IsDestroying() { return mIsDestroying; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a one-way transition into a "zombie" state. In this state,
|
||||||
|
* no reflow is done, no painting is done, and no refresh driver
|
||||||
|
* ticks are processed. This is a dangerous state: it can leave
|
||||||
|
* areas of the composition target unpainted if callers aren't
|
||||||
|
* careful. (Don't let your zombie presshell out of the shed.)
|
||||||
|
*
|
||||||
|
* This is used in cases where a presshell is created for reasons
|
||||||
|
* other than reflow/painting.
|
||||||
|
*/
|
||||||
|
virtual void MakeZombie() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All frames owned by the shell are allocated from an arena. They
|
* All frames owned by the shell are allocated from an arena. They
|
||||||
* are also recycled using free lists. Separate free lists are
|
* are also recycled using free lists. Separate free lists are
|
||||||
@@ -1798,6 +1810,7 @@ protected:
|
|||||||
bool mStylesHaveChanged : 1;
|
bool mStylesHaveChanged : 1;
|
||||||
bool mDidInitialize : 1;
|
bool mDidInitialize : 1;
|
||||||
bool mIsDestroying : 1;
|
bool mIsDestroying : 1;
|
||||||
|
bool mIsZombie : 1;
|
||||||
bool mIsReflowing : 1;
|
bool mIsReflowing : 1;
|
||||||
|
|
||||||
// For all documents we initially lock down painting.
|
// For all documents we initially lock down painting.
|
||||||
|
|||||||
@@ -1358,6 +1358,13 @@ PresShell::Destroy()
|
|||||||
mTouchManager.Destroy();
|
mTouchManager.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PresShell::MakeZombie()
|
||||||
|
{
|
||||||
|
mIsZombie = true;
|
||||||
|
CancelAllPendingReflows();
|
||||||
|
}
|
||||||
|
|
||||||
nsRefreshDriver*
|
nsRefreshDriver*
|
||||||
nsIPresShell::GetRefreshDriver() const
|
nsIPresShell::GetRefreshDriver() const
|
||||||
{
|
{
|
||||||
@@ -4019,6 +4026,10 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
|
|||||||
void
|
void
|
||||||
PresShell::FlushPendingNotifications(mozilla::ChangesToFlush aFlush)
|
PresShell::FlushPendingNotifications(mozilla::ChangesToFlush aFlush)
|
||||||
{
|
{
|
||||||
|
if (mIsZombie) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VERY IMPORTANT: If you add some sort of new flushing to this
|
* VERY IMPORTANT: If you add some sort of new flushing to this
|
||||||
* method, make sure to add the relevant SetNeedLayoutFlush or
|
* method, make sure to add the relevant SetNeedLayoutFlush or
|
||||||
@@ -6263,7 +6274,7 @@ PresShell::Paint(nsView* aViewToPaint,
|
|||||||
|
|
||||||
MOZ_ASSERT(!mApproximateFrameVisibilityVisited, "Should have been cleared");
|
MOZ_ASSERT(!mApproximateFrameVisibilityVisited, "Should have been cleared");
|
||||||
|
|
||||||
if (!mIsActive) {
|
if (!mIsActive || mIsZombie) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9218,6 +9229,10 @@ PresShell::ScheduleReflowOffTimer()
|
|||||||
bool
|
bool
|
||||||
PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
||||||
{
|
{
|
||||||
|
if (mIsZombie) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
gfxTextPerfMetrics* tp = mPresContext->GetTextPerfMetrics();
|
gfxTextPerfMetrics* tp = mPresContext->GetTextPerfMetrics();
|
||||||
TimeStamp timeStart;
|
TimeStamp timeStart;
|
||||||
if (tp) {
|
if (tp) {
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ public:
|
|||||||
void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
|
void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
|
||||||
nsViewManager* aViewManager, mozilla::StyleSetHandle aStyleSet);
|
nsViewManager* aViewManager, mozilla::StyleSetHandle aStyleSet);
|
||||||
virtual void Destroy() override;
|
virtual void Destroy() override;
|
||||||
|
virtual void MakeZombie() override;
|
||||||
|
|
||||||
virtual void UpdatePreferenceStyles() override;
|
virtual void UpdatePreferenceStyles() override;
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ function run_test() {
|
|||||||
// We finish in clean_up()
|
// We finish in clean_up()
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (pb.getCharPref('dom.ipc.processPrelaunch.enabled')) {
|
||||||
|
dump('WARNING: Content process may already have launched, so this test may not be meaningful.');
|
||||||
|
}
|
||||||
|
} catch(e) { }
|
||||||
|
|
||||||
initialValue = pb.getCharPref(kPrefName);
|
initialValue = pb.getCharPref(kPrefName);
|
||||||
|
|
||||||
test_user_setting();
|
test_user_setting();
|
||||||
@@ -67,4 +73,4 @@ function clean_up() {
|
|||||||
check_child_pref_info_eq(function () {
|
check_child_pref_info_eq(function () {
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user