зеркало из https://github.com/mozilla/gecko-dev.git
Bug 834059 - Send processses into the foreground when they first launch, so they don't get killed quite so quickly. r=cjones
This patch also sends the preallocated process into the background immediately after it's launched.
This commit is contained in:
Родитель
ea653f66d2
Коммит
0f0d04a754
|
@ -543,7 +543,8 @@ pref("ui.showHideScrollbars", 1);
|
|||
// documents a 1s grace period before they're eligible to be marked as
|
||||
// background.
|
||||
pref("dom.ipc.processPriorityManager.enabled", true);
|
||||
pref("dom.ipc.processPriorityManager.gracePeriodMS", 1000);
|
||||
pref("dom.ipc.processPriorityManager.backgroundGracePeriodMS", 1000);
|
||||
pref("dom.ipc.processPriorityManager.temporaryPriorityMS", 5000);
|
||||
|
||||
// Kernel parameters for how processes are killed on low-memory.
|
||||
pref("gonk.systemMemoryPressureRecoveryPollMS", 5000);
|
||||
|
|
|
@ -102,12 +102,14 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "AudioChannelService.h"
|
||||
#include "ProcessPriorityManager.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::docshell;
|
||||
using namespace mozilla::dom::bluetooth;
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
using namespace mozilla::dom::ipc;
|
||||
using namespace mozilla::dom::sms;
|
||||
using namespace mozilla::dom::indexedDB;
|
||||
using namespace mozilla::hal_sandbox;
|
||||
|
@ -289,13 +291,8 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
bool startBackground = true;
|
||||
SendGetProcessAttributes(&mID, &startBackground,
|
||||
&mIsForApp, &mIsForBrowser);
|
||||
hal::SetProcessPriority(
|
||||
GetCurrentProcId(),
|
||||
startBackground ? hal::PROCESS_PRIORITY_BACKGROUND:
|
||||
hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
|
||||
|
||||
if (mIsForApp && !mIsForBrowser) {
|
||||
SetProcessName(NS_LITERAL_STRING("(Preallocated app)"));
|
||||
} else {
|
||||
|
@ -529,12 +526,19 @@ PBrowserChild*
|
|||
ContentChild::AllocPBrowser(const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags)
|
||||
{
|
||||
static bool firstIdleTaskPosted = false;
|
||||
if (!firstIdleTaskPosted) {
|
||||
static bool hasRunOnce = false;
|
||||
if (!hasRunOnce) {
|
||||
hasRunOnce = true;
|
||||
|
||||
MOZ_ASSERT(!sFirstIdleTask);
|
||||
sFirstIdleTask = NewRunnableFunction(FirstIdle);
|
||||
MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask);
|
||||
firstIdleTaskPosted = true;
|
||||
|
||||
// If we are the preallocated process transforming into an app process,
|
||||
// we'll have background priority at this point. Give ourselves a
|
||||
// priority boost for a few seconds, so we don't get killed while we're
|
||||
// loading our first TabChild.
|
||||
TemporarilySetProcessPriorityToForeground();
|
||||
}
|
||||
|
||||
// We'll happily accept any kind of IPCTabContext here; we don't need to
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "mozilla/dom/bluetooth/PBluetoothParent.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
|
||||
#include "SmsParent.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/hal_sandbox/PHalParent.h"
|
||||
#include "mozilla/ipc/TestShellParent.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
|
@ -119,7 +120,7 @@ using namespace mozilla::dom::bluetooth;
|
|||
using namespace mozilla::dom::devicestorage;
|
||||
using namespace mozilla::dom::sms;
|
||||
using namespace mozilla::dom::indexedDB;
|
||||
using namespace mozilla::hal_sandbox;
|
||||
using namespace mozilla::hal;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::net;
|
||||
|
@ -870,14 +871,23 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL,
|
|||
mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content,
|
||||
aOSPrivileges);
|
||||
|
||||
bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
|
||||
if (useOffMainThreadCompositing) {
|
||||
// We need the subprocess's ProcessHandle to create the
|
||||
// PCompositor channel below. Block just until we have that.
|
||||
mSubprocess->LaunchAndWaitForProcessHandle();
|
||||
} else {
|
||||
mSubprocess->AsyncLaunch();
|
||||
mSubprocess->LaunchAndWaitForProcessHandle();
|
||||
|
||||
// Set the subprocess's priority (bg if we're a preallocated process, fg
|
||||
// otherwise). We do this first because we're likely /lowering/ its CPU and
|
||||
// memory priority, which it has inherited from this process.
|
||||
if (Preferences::GetBool("dom.ipc.processPriorityManager.enabled")) {
|
||||
ProcessPriority priority;
|
||||
if (aAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL) {
|
||||
priority = PROCESS_PRIORITY_BACKGROUND;
|
||||
} else {
|
||||
priority = PROCESS_PRIORITY_FOREGROUND;
|
||||
}
|
||||
|
||||
SetProcessPriority(base::GetProcId(mSubprocess->GetChildProcessHandle()),
|
||||
priority);
|
||||
}
|
||||
|
||||
Open(mSubprocess->GetChannel(), mSubprocess->GetChildProcessHandle());
|
||||
|
||||
// NB: internally, this will send an IPC message to the child
|
||||
|
@ -888,6 +898,7 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL,
|
|||
// PBrowsers are created, because they rely on the Compositor
|
||||
// already being around. (Creation is async, so can't happen
|
||||
// on demand.)
|
||||
bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
|
||||
if (useOffMainThreadCompositing) {
|
||||
DebugOnly<bool> opened = PCompositor::Open(this);
|
||||
MOZ_ASSERT(opened);
|
||||
|
@ -1359,12 +1370,10 @@ ContentParent::AllocPImageBridge(mozilla::ipc::Transport* aTransport,
|
|||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetProcessAttributes(uint64_t* aId, bool* aStartBackground,
|
||||
ContentParent::RecvGetProcessAttributes(uint64_t* aId,
|
||||
bool* aIsForApp, bool* aIsForBrowser)
|
||||
{
|
||||
*aId = mChildID = gContentChildID++;
|
||||
*aStartBackground =
|
||||
(mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL);
|
||||
*aIsForApp = IsForApp();
|
||||
*aIsForBrowser = mIsForBrowser;
|
||||
|
||||
|
@ -1650,14 +1659,14 @@ ContentParent::DeallocPCrashReporter(PCrashReporterParent* crashreporter)
|
|||
return true;
|
||||
}
|
||||
|
||||
PHalParent*
|
||||
hal_sandbox::PHalParent*
|
||||
ContentParent::AllocPHal()
|
||||
{
|
||||
return CreateHalParent();
|
||||
return hal_sandbox::CreateHalParent();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPHal(PHalParent* aHal)
|
||||
ContentParent::DeallocPHal(hal_sandbox::PHalParent* aHal)
|
||||
{
|
||||
delete aHal;
|
||||
return true;
|
||||
|
|
|
@ -203,7 +203,6 @@ private:
|
|||
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvGetProcessAttributes(uint64_t* aId,
|
||||
bool* aStartBackground,
|
||||
bool* aIsForApp,
|
||||
bool* aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
|
||||
|
|
|
@ -343,8 +343,7 @@ parent:
|
|||
* !isForBrowser|, we're probably loading <xul:browser remote>.
|
||||
*/
|
||||
sync GetProcessAttributes()
|
||||
returns (uint64_t id, bool startBackground,
|
||||
bool isForApp, bool isForBrowser);
|
||||
returns (uint64_t id, bool isForApp, bool isForBrowser);
|
||||
sync GetXPCOMProcessAttributes()
|
||||
returns (bool isOffline);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/TimeStamp.h"
|
||||
#include "AudioChannelService.h"
|
||||
#include "prlog.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
@ -139,43 +140,98 @@ IsBackgroundPriority(ProcessPriority aPriority)
|
|||
class ProcessPriorityManager MOZ_FINAL
|
||||
: public nsIObserver
|
||||
, public nsIDOMEventListener
|
||||
, public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
ProcessPriorityManager();
|
||||
void Init();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
ProcessPriority GetPriority() const { return mProcessPriority; }
|
||||
|
||||
private:
|
||||
void SetPriority(ProcessPriority aPriority);
|
||||
void OnAudioChannelAgentChanged();
|
||||
void OnContentDocumentGlobalCreated(nsISupports* aOuterWindow);
|
||||
void OnInnerWindowDestroyed();
|
||||
void OnGracePeriodTimerFired();
|
||||
void RecomputeNumVisibleWindows();
|
||||
/**
|
||||
* If this process is not already in the foreground, move it into the
|
||||
* foreground and set a timer to call ResetPriorityNow() in a few seconds.
|
||||
*/
|
||||
void TemporarilySetIsForeground();
|
||||
|
||||
// mProcessPriority tracks the priority we've given this process in hal,
|
||||
// except that, when the grace period timer is active, mProcessPriority ==
|
||||
// BACKGROUND or HOMESCREEN_BACKGROUND even though hal still thinks we're a
|
||||
// foreground process.
|
||||
/**
|
||||
* Recompute this process's priority and apply it, potentially after a brief
|
||||
* delay.
|
||||
*
|
||||
* If the new priority is FOREGROUND, it takes effect immediately.
|
||||
*
|
||||
* If the new priority is a BACKGROUND* priority and this process's priority
|
||||
* is currently a BACKGROUND* priority, the new priority takes effect
|
||||
* immediately.
|
||||
*
|
||||
* But if the new priority is a BACKGROUND* priority and this process is not
|
||||
* currently in the background, we schedule a timer and run
|
||||
* ResetPriorityNow() after a short period of time.
|
||||
*/
|
||||
void ResetPriority();
|
||||
|
||||
/**
|
||||
* Recompute this process's priority and apply it immediately.
|
||||
*/
|
||||
void ResetPriorityNow();
|
||||
|
||||
private:
|
||||
void OnContentDocumentGlobalCreated(nsISupports* aOuterWindow);
|
||||
|
||||
/**
|
||||
* Compute whether this process is in the foreground and return the result.
|
||||
*/
|
||||
bool ComputeIsInForeground();
|
||||
|
||||
/**
|
||||
* Set this process's priority to FOREGROUND immediately.
|
||||
*/
|
||||
void SetIsForeground();
|
||||
|
||||
/**
|
||||
* Set this process's priority to the appropriate BACKGROUND* priority
|
||||
* immediately.
|
||||
*/
|
||||
void SetIsBackgroundNow();
|
||||
|
||||
/**
|
||||
* If mResetPriorityTimer is null (i.e., not running), create a timer and set
|
||||
* it to invoke ResetPriorityNow() after
|
||||
* dom.ipc.processPriorityManager.aTimeoutPref ms.
|
||||
*/
|
||||
void
|
||||
ScheduleResetPriority(const char* aTimeoutPref);
|
||||
|
||||
// mProcessPriority tracks the priority we've given this process in hal.
|
||||
ProcessPriority mProcessPriority;
|
||||
|
||||
nsTArray<nsWeakPtr> mWindows;
|
||||
nsCOMPtr<nsITimer> mGracePeriodTimer;
|
||||
|
||||
// When this timer expires, we set mResetPriorityTimer to null and run
|
||||
// ResetPriorityNow().
|
||||
nsCOMPtr<nsITimer> mResetPriorityTimer;
|
||||
|
||||
nsWeakPtr mMemoryMinimizerRunnable;
|
||||
TimeStamp mStartupTime;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(ProcessPriorityManager, nsIObserver, nsIDOMEventListener)
|
||||
|
||||
ProcessPriorityManager::ProcessPriorityManager()
|
||||
: mProcessPriority(PROCESS_PRIORITY_FOREGROUND)
|
||||
, mStartupTime(TimeStamp::Now())
|
||||
: mProcessPriority(ProcessPriority(-1))
|
||||
{
|
||||
// When our parent process forked us, it set our priority either to
|
||||
// FOREGROUND (if our parent launched this process to meet an immediate need)
|
||||
// or one of the BACKGROUND priorities (if our parent launched this process
|
||||
// to meet a future need).
|
||||
//
|
||||
// We don't know which situation we're in, so we set mProcessPriority to -1
|
||||
// so that the next time ResetPriorityNow is run, we'll definitely call into
|
||||
// hal and set our priority.
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -189,8 +245,6 @@ ProcessPriorityManager::Init()
|
|||
os->AddObserver(this, "content-document-global-created", /* ownsWeak = */ false);
|
||||
os->AddObserver(this, "inner-window-destroyed", /* ownsWeak = */ false);
|
||||
os->AddObserver(this, "audio-channel-agent-changed", /* ownsWeak = */ false);
|
||||
|
||||
SetPriority(PROCESS_PRIORITY_FOREGROUND);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -201,12 +255,9 @@ ProcessPriorityManager::Observe(
|
|||
{
|
||||
if (!strcmp(aTopic, "content-document-global-created")) {
|
||||
OnContentDocumentGlobalCreated(aSubject);
|
||||
} else if (!strcmp(aTopic, "inner-window-destroyed")) {
|
||||
OnInnerWindowDestroyed();
|
||||
} else if (!strcmp(aTopic, "timer-callback")) {
|
||||
OnGracePeriodTimerFired();
|
||||
} else if (!strcmp(aTopic, "audio-channel-agent-changed")) {
|
||||
OnAudioChannelAgentChanged();
|
||||
} else if (!strcmp(aTopic, "inner-window-destroyed") ||
|
||||
!strcmp(aTopic, "audio-channel-agent-changed")) {
|
||||
ResetPriority();
|
||||
} else {
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
|
@ -218,22 +269,15 @@ ProcessPriorityManager::HandleEvent(
|
|||
nsIDOMEvent* aEvent)
|
||||
{
|
||||
LOG("Got visibilitychange.");
|
||||
RecomputeNumVisibleWindows();
|
||||
ResetPriority();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::OnAudioChannelAgentChanged()
|
||||
{
|
||||
if (IsBackgroundPriority(mProcessPriority)) {
|
||||
SetPriority(GetBackgroundPriority());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::OnContentDocumentGlobalCreated(
|
||||
nsISupports* aOuterWindow)
|
||||
{
|
||||
LOG("DocumentGlobalCreated");
|
||||
// Get the inner window (the topic of content-document-global-created is
|
||||
// the /outer/ window!).
|
||||
nsCOMPtr<nsPIDOMWindow> outerWindow = do_QueryInterface(aOuterWindow);
|
||||
|
@ -265,17 +309,35 @@ ProcessPriorityManager::OnContentDocumentGlobalCreated(
|
|||
/* wantsUntrusted = */ false);
|
||||
|
||||
mWindows.AppendElement(weakWin);
|
||||
RecomputeNumVisibleWindows();
|
||||
ResetPriority();
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::OnInnerWindowDestroyed()
|
||||
ProcessPriorityManager::ResetPriority()
|
||||
{
|
||||
RecomputeNumVisibleWindows();
|
||||
if (ComputeIsInForeground()) {
|
||||
SetIsForeground();
|
||||
} else if (IsBackgroundPriority(mProcessPriority)) {
|
||||
// If we're already in the background, recompute our background priority
|
||||
// and set it immediately.
|
||||
SetIsBackgroundNow();
|
||||
} else {
|
||||
ScheduleResetPriority("backgroundGracePeriodMS");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::RecomputeNumVisibleWindows()
|
||||
ProcessPriorityManager::ResetPriorityNow()
|
||||
{
|
||||
if (ComputeIsInForeground()) {
|
||||
SetIsForeground();
|
||||
} else {
|
||||
SetIsBackgroundNow();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessPriorityManager::ComputeIsInForeground()
|
||||
{
|
||||
// We could try to be clever and count the number of visible windows, instead
|
||||
// of iterating over mWindows every time one window's visibility state changes.
|
||||
|
@ -314,68 +376,38 @@ ProcessPriorityManager::RecomputeNumVisibleWindows()
|
|||
// but then we might not clean up all the weak refs.
|
||||
}
|
||||
|
||||
SetPriority(allHidden ?
|
||||
GetBackgroundPriority() :
|
||||
PROCESS_PRIORITY_FOREGROUND);
|
||||
return !allHidden;
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::SetPriority(ProcessPriority aPriority)
|
||||
ProcessPriorityManager::SetIsForeground()
|
||||
{
|
||||
if (aPriority == mProcessPriority) {
|
||||
if (mProcessPriority == PROCESS_PRIORITY_FOREGROUND) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsBackgroundPriority(aPriority)) {
|
||||
// If this is a foreground --> background transition, give ourselves a
|
||||
// grace period before informing hal.
|
||||
uint32_t gracePeriodMS = Preferences::GetUint("dom.ipc.processPriorityManager.gracePeriodMS", 1000);
|
||||
if (mGracePeriodTimer) {
|
||||
LOG("Grace period timer already active.");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("Initializing grace period timer.");
|
||||
mProcessPriority = aPriority;
|
||||
mGracePeriodTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
mGracePeriodTimer->Init(this, gracePeriodMS, nsITimer::TYPE_ONE_SHOT);
|
||||
|
||||
} else if (aPriority == PROCESS_PRIORITY_FOREGROUND) {
|
||||
// If this is a background --> foreground transition, do it immediately, and
|
||||
// cancel the outstanding grace period timer, if there is one.
|
||||
if (mGracePeriodTimer) {
|
||||
mGracePeriodTimer->Cancel();
|
||||
mGracePeriodTimer = nullptr;
|
||||
}
|
||||
|
||||
// Cancel the memory minimization procedure we might have started.
|
||||
nsCOMPtr<nsICancelableRunnable> runnable =
|
||||
do_QueryReferent(mMemoryMinimizerRunnable);
|
||||
if (runnable) {
|
||||
runnable->Cancel();
|
||||
}
|
||||
|
||||
LOG("Setting priority to %d.", aPriority);
|
||||
mProcessPriority = aPriority;
|
||||
hal::SetProcessPriority(getpid(), aPriority);
|
||||
|
||||
} else {
|
||||
MOZ_ASSERT(false);
|
||||
// Cancel the memory minimization procedure we might have started.
|
||||
nsCOMPtr<nsICancelableRunnable> runnable =
|
||||
do_QueryReferent(mMemoryMinimizerRunnable);
|
||||
if (runnable) {
|
||||
runnable->Cancel();
|
||||
}
|
||||
|
||||
LOG("Setting priority to FOREGROUND.");
|
||||
mProcessPriority = PROCESS_PRIORITY_FOREGROUND;
|
||||
hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_FOREGROUND);
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::OnGracePeriodTimerFired()
|
||||
ProcessPriorityManager::SetIsBackgroundNow()
|
||||
{
|
||||
LOG("Grace period timer fired; setting priority to %d.",
|
||||
mProcessPriority);
|
||||
ProcessPriority backgroundPriority = GetBackgroundPriority();
|
||||
if (mProcessPriority == backgroundPriority) {
|
||||
return;
|
||||
}
|
||||
|
||||
// mProcessPriority should already be one of the BACKGROUND values: We set it
|
||||
// in SetPriority(BACKGROUND), and we canceled this timer if there was an
|
||||
// intervening SetPriority(FOREGROUND) call.
|
||||
MOZ_ASSERT(IsBackgroundPriority(mProcessPriority));
|
||||
|
||||
mGracePeriodTimer = nullptr;
|
||||
mProcessPriority = backgroundPriority;
|
||||
LOG("Setting priority to BACKGROUND (type %d)", mProcessPriority);
|
||||
hal::SetProcessPriority(getpid(), mProcessPriority);
|
||||
|
||||
// We're in the background; dump as much memory as we can.
|
||||
|
@ -396,6 +428,46 @@ ProcessPriorityManager::OnGracePeriodTimerFired()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::ScheduleResetPriority(const char* aTimeoutPref)
|
||||
{
|
||||
if (mResetPriorityTimer) {
|
||||
// The timer is already running.
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t timeout = Preferences::GetUint(
|
||||
nsPrintfCString("dom.ipc.processPriorityManager.%s", aTimeoutPref).get());
|
||||
LOG("Scheduling reset timer to fire in %dms.", timeout);
|
||||
mResetPriorityTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
mResetPriorityTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ProcessPriorityManager::Notify(nsITimer* aTimer)
|
||||
{
|
||||
LOG("Reset priority timer callback; about to ResetPriorityNow.");
|
||||
ResetPriorityNow();
|
||||
mResetPriorityTimer = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManager::TemporarilySetIsForeground()
|
||||
{
|
||||
LOG("TemporarilySetIsForeground");
|
||||
SetIsForeground();
|
||||
|
||||
// Each call to TemporarilySetIsForeground guarantees us temporaryPriorityMS
|
||||
// in the foreground. So cancel our timer if it's running (which is due to a
|
||||
// previous call to either TemporarilySetIsForeground() or ResetPriority()).
|
||||
if (mResetPriorityTimer) {
|
||||
mResetPriorityTimer->Cancel();
|
||||
mResetPriorityTimer = nullptr;
|
||||
}
|
||||
ScheduleResetPriority("temporaryPriorityMS");
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
|
@ -408,6 +480,7 @@ InitProcessPriorityManager()
|
|||
// If IPC tabs aren't enabled at startup, don't bother with any of this.
|
||||
if (!Preferences::GetBool("dom.ipc.processPriorityManager.enabled") ||
|
||||
Preferences::GetBool("dom.ipc.tabs.disabled")) {
|
||||
LOG("InitProcessPriorityManager bailing due to prefs.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -439,6 +512,17 @@ CurrentProcessIsForeground()
|
|||
return sManager->GetPriority() >= PROCESS_PRIORITY_FOREGROUND;
|
||||
}
|
||||
|
||||
void
|
||||
TemporarilySetProcessPriorityToForeground()
|
||||
{
|
||||
if (sManager) {
|
||||
sManager->TemporarilySetIsForeground();
|
||||
} else {
|
||||
LOG("TemporarilySetProcessPriorityToForeground called before "
|
||||
"InitProcessPriorityManager. Bailing.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -33,6 +33,17 @@ void InitProcessPriorityManager();
|
|||
*/
|
||||
bool CurrentProcessIsForeground();
|
||||
|
||||
/**
|
||||
* If this process is in the background, temporarily boost its priority to the
|
||||
* foreground. This priority boost will expire after a few seconds
|
||||
* (dom.ipc.processPriorityManager.temporaryPriorityMS).
|
||||
*
|
||||
* You might want to call this function when a process starts loading some
|
||||
* things, but doesn't yet have a foreground window. The hope would be that by
|
||||
* once the timer here expires, the process will have a foreground window.
|
||||
*/
|
||||
void TemporarilySetProcessPriorityToForeground();
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
Загрузка…
Ссылка в новой задаче