зеркало из https://github.com/mozilla/gecko-dev.git
Bug 844323 - Part 2 (The Main Event): Move ProcesPriorityManager to the main process. r=bent,khuey
This commit is contained in:
Родитель
c60e290a2a
Коммит
69298c893a
|
@ -12,6 +12,7 @@ interface nsSubDocumentFrame;
|
|||
interface nsIMessageSender;
|
||||
interface nsIVariant;
|
||||
interface nsIDOMElement;
|
||||
interface nsITabParent;
|
||||
|
||||
typedef unsigned long long nsContentViewId;
|
||||
|
||||
|
@ -109,7 +110,7 @@ interface nsIContentViewManager : nsISupports
|
|||
readonly attribute nsIContentView rootContentView;
|
||||
};
|
||||
|
||||
[scriptable, uuid(a4db652e-e3b0-4345-8107-cf6a30486759)]
|
||||
[scriptable, builtinclass, uuid(e4333e51-f2fa-4fdd-becd-75d000703355)]
|
||||
interface nsIFrameLoader : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -117,6 +118,12 @@ interface nsIFrameLoader : nsISupports
|
|||
*/
|
||||
readonly attribute nsIDocShell docShell;
|
||||
|
||||
/**
|
||||
* Get this frame loader's TabParent, if it has a remote frame. Otherwise,
|
||||
* returns null.
|
||||
*/
|
||||
readonly attribute nsITabParent tabParent;
|
||||
|
||||
/**
|
||||
* Start loading the frame. This method figures out what to load
|
||||
* from the owner content in the frame loader.
|
||||
|
@ -248,6 +255,15 @@ interface nsIFrameLoader : nsISupports
|
|||
* returns the iframe element.
|
||||
*/
|
||||
readonly attribute nsIDOMElement ownerElement;
|
||||
|
||||
/**
|
||||
* Get or set this frame loader's visibility.
|
||||
*
|
||||
* The notion of "visibility" here is separate from the notion of a
|
||||
* window/docshell's visibility. This field is mostly here so that we can
|
||||
* have a notion of visibility in the parent process when frames are OOP.
|
||||
*/
|
||||
[infallible] attribute boolean visible;
|
||||
};
|
||||
|
||||
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
|
||||
|
|
|
@ -301,6 +301,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
|
|||
, mClampScrollPosition(true)
|
||||
, mRemoteBrowserInitialized(false)
|
||||
, mObservingOwnerContent(false)
|
||||
, mVisible(true)
|
||||
, mCurrentRemoteFrame(nullptr)
|
||||
, mRemoteBrowser(nullptr)
|
||||
, mRenderMode(RENDER_MODE_DEFAULT)
|
||||
|
@ -2583,3 +2584,29 @@ nsFrameLoader::ResetPermissionManagerStatus()
|
|||
}
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsFrameLoader::SetVisible(bool aVisible)
|
||||
{
|
||||
mVisible = aVisible;
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
|
||||
"frameloader-visible-changed", nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsFrameLoader::GetVisible(bool* aVisible)
|
||||
{
|
||||
*aVisible = mVisible;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::GetTabParent(nsITabParent** aTabParent)
|
||||
{
|
||||
nsCOMPtr<nsITabParent> tp = mRemoteBrowser;
|
||||
tp.forget(aTabParent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -428,6 +428,11 @@ private:
|
|||
bool mRemoteBrowserInitialized : 1;
|
||||
bool mObservingOwnerContent : 1;
|
||||
|
||||
// Backs nsIFrameLoader::{Get,Set}Visible. Visibility state here relates to
|
||||
// whether this frameloader's <iframe mozbrowser> is setVisible(true)'ed, and
|
||||
// doesn't necessarily correlate with docshell/document visibility.
|
||||
bool mVisible : 1;
|
||||
|
||||
// XXX leaking
|
||||
nsCOMPtr<nsIObserver> mChildHost;
|
||||
RenderFrameParent* mCurrentRemoteFrame;
|
||||
|
|
|
@ -52,7 +52,8 @@
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::ipc;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(WebGLMemoryPressureObserver, nsIObserver)
|
||||
|
@ -67,7 +68,8 @@ WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
|
|||
|
||||
bool wantToLoseContext = true;
|
||||
|
||||
if (!mContext->mCanLoseContextInForeground && CurrentProcessIsForeground())
|
||||
if (!mContext->mCanLoseContextInForeground &&
|
||||
ProcessPriorityManager::CurrentProcessIsForeground())
|
||||
wantToLoseContext = false;
|
||||
else if (!nsCRT::strcmp(aSomeData,
|
||||
NS_LITERAL_STRING("heap-minimize").get()))
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "base/basictypes.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsIAudioManager.h"
|
||||
|
@ -106,7 +107,7 @@ AudioChannelService::RegisterType(AudioChannelType aType, uint64_t aChildID)
|
|||
// In order to avoid race conditions, it's safer to notify any existing
|
||||
// agent any time a new one is registered.
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
SendAudioChannelChangedNotification();
|
||||
SendAudioChannelChangedNotification(aChildID);
|
||||
Notify();
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +144,7 @@ AudioChannelService::UnregisterType(AudioChannelType aType,
|
|||
!mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID))) {
|
||||
mActiveContentChildIDs.RemoveElement(aChildID);
|
||||
}
|
||||
SendAudioChannelChangedNotification();
|
||||
SendAudioChannelChangedNotification(aChildID);
|
||||
Notify();
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +165,6 @@ AudioChannelService::GetMuted(AudioChannelAgent* aAgent, bool aElementHidden)
|
|||
aElementHidden, oldElementHidden);
|
||||
data->mMuted = muted;
|
||||
|
||||
SendAudioChannelChangedNotification();
|
||||
return muted;
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,6 @@ AudioChannelService::GetMutedInternal(AudioChannelType aType, uint64_t aChildID,
|
|||
mActiveContentChildIDs.AppendElement(aChildID);
|
||||
}
|
||||
}
|
||||
|
||||
else if (newType == AUDIO_CHANNEL_INT_CONTENT_HIDDEN &&
|
||||
oldType == AUDIO_CHANNEL_INT_CONTENT &&
|
||||
!mActiveContentChildIDsFrozen) {
|
||||
|
@ -214,6 +213,8 @@ AudioChannelService::GetMutedInternal(AudioChannelType aType, uint64_t aChildID,
|
|||
Notify();
|
||||
}
|
||||
|
||||
SendAudioChannelChangedNotification(aChildID);
|
||||
|
||||
// Let play any visible audio channel.
|
||||
if (!aElementHidden) {
|
||||
return false;
|
||||
|
@ -244,13 +245,29 @@ AudioChannelService::ContentOrNormalChannelIsActive()
|
|||
!mChannelCounters[AUDIO_CHANNEL_INT_NORMAL].IsEmpty();
|
||||
}
|
||||
|
||||
bool
|
||||
AudioChannelService::ProcessContentOrNormalChannelIsActive(uint64_t aChildID)
|
||||
{
|
||||
return mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID) ||
|
||||
mChannelCounters[AUDIO_CHANNEL_INT_CONTENT_HIDDEN].Contains(aChildID) ||
|
||||
mChannelCounters[AUDIO_CHANNEL_INT_NORMAL].Contains(aChildID);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::SendAudioChannelChangedNotification()
|
||||
AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID)
|
||||
{
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
|
||||
props->Init();
|
||||
props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), aChildID);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(static_cast<nsIWritablePropertyBag*>(props),
|
||||
"audio-channel-process-changed", nullptr);
|
||||
|
||||
// Calculating the most important active channel.
|
||||
AudioChannelType higher = AUDIO_CHANNEL_LAST;
|
||||
|
||||
|
@ -327,7 +344,6 @@ AudioChannelService::SendAudioChannelChangedNotification()
|
|||
channelName.AssignLiteral("none");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(nullptr, "audio-channel-changed", channelName.get());
|
||||
}
|
||||
|
||||
|
@ -341,7 +357,6 @@ AudioChannelService::SendAudioChannelChangedNotification()
|
|||
channelName.AssignLiteral("none");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(nullptr, "visible-audio-channel-changed", channelName.get());
|
||||
}
|
||||
}
|
||||
|
@ -447,7 +462,7 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const PR
|
|||
// We don't have to remove the agents from the mAgents hashtable because if
|
||||
// that table contains only agents running on the same process.
|
||||
|
||||
SendAudioChannelChangedNotification();
|
||||
SendAudioChannelChangedNotification(childID);
|
||||
Notify();
|
||||
} else {
|
||||
NS_WARNING("ipc:content-shutdown message without childID property");
|
||||
|
|
|
@ -59,13 +59,20 @@ public:
|
|||
*/
|
||||
virtual bool ContentOrNormalChannelIsActive();
|
||||
|
||||
/**
|
||||
* Return true iff a normal or content channel is active for the given process
|
||||
* ID.
|
||||
*/
|
||||
virtual bool ProcessContentOrNormalChannelIsActive(uint64_t aChildID);
|
||||
|
||||
protected:
|
||||
void Notify();
|
||||
|
||||
/**
|
||||
* Send the audio-channel-changed notification if needed.
|
||||
* Send the audio-channel-changed notification for the given process ID if
|
||||
* needed.
|
||||
*/
|
||||
void SendAudioChannelChangedNotification();
|
||||
void SendAudioChannelChangedNotification(uint64_t aChildID);
|
||||
|
||||
/* Register/Unregister IPC types: */
|
||||
void RegisterType(AudioChannelType aType, uint64_t aChildID);
|
||||
|
|
|
@ -656,13 +656,7 @@ BrowserElementChild.prototype = {
|
|||
}
|
||||
|
||||
this._forcedVisible = data.json.visible;
|
||||
this._updateDocShellVisibility();
|
||||
|
||||
// Fire a notification to the ProcessPriorityManager to reset this
|
||||
// process's priority now (as opposed to after a brief delay).
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(/* subject */ null, 'process-priority:reset-now',
|
||||
/* data */ null);
|
||||
this._updateVisibility();
|
||||
},
|
||||
|
||||
_recvVisible: function(data) {
|
||||
|
@ -679,13 +673,14 @@ BrowserElementChild.prototype = {
|
|||
_recvOwnerVisibilityChange: function(data) {
|
||||
debug("Received ownerVisibilityChange: (" + data.json.visible + ")");
|
||||
this._ownerVisible = data.json.visible;
|
||||
this._updateDocShellVisibility();
|
||||
this._updateVisibility();
|
||||
},
|
||||
|
||||
_updateDocShellVisibility: function() {
|
||||
_updateVisibility: function() {
|
||||
var visible = this._forcedVisible && this._ownerVisible;
|
||||
if (docShell.isActive !== visible) {
|
||||
docShell.isActive = visible;
|
||||
sendAsyncMsg('visibility-change', {visibility: visible});
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -117,7 +117,8 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
|
|||
"fullscreen-origin-change": this._remoteFullscreenOriginChange,
|
||||
"rollback-fullscreen": this._remoteFrameFullscreenReverted,
|
||||
"exit-fullscreen": this._exitFullscreen,
|
||||
"got-visible": this._gotDOMRequestResult
|
||||
"got-visible": this._gotDOMRequestResult,
|
||||
"visibility-change": this._childVisibilityChange,
|
||||
}
|
||||
|
||||
this._mm.addMessageListener('browser-element-api:call', function(aMsg) {
|
||||
|
@ -446,6 +447,7 @@ BrowserElementParent.prototype = {
|
|||
|
||||
_setVisible: function(visible) {
|
||||
this._sendAsyncMsg('set-visible', {visible: visible});
|
||||
this._frameLoader.visible = visible;
|
||||
},
|
||||
|
||||
_sendMouseEvent: function(type, x, y, button, clickCount, modifiers) {
|
||||
|
@ -561,6 +563,19 @@ BrowserElementParent.prototype = {
|
|||
{visible: !this._window.document.mozHidden});
|
||||
},
|
||||
|
||||
/*
|
||||
* Called when the child notices that its visibility has changed.
|
||||
*
|
||||
* This is sometimes redundant; for example, the child's visibility may
|
||||
* change in response to a setVisible request that we made here! But it's
|
||||
* not always redundant; for example, the child's visibility may change in
|
||||
* response to its parent docshell being hidden.
|
||||
*/
|
||||
_childVisibilityChange: function(data) {
|
||||
debug("_childVisibilityChange(" + data.json.visible + ")");
|
||||
this._frameLoader.visible = data.json.visible;
|
||||
},
|
||||
|
||||
_exitFullscreen: function() {
|
||||
this._windowUtils.exitFullscreen();
|
||||
},
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "nsJSEnvironment.h"
|
||||
#include "SandboxHal.h"
|
||||
#include "nsDebugImpl.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsLayoutStylesheetCache.h"
|
||||
|
||||
#include "IHistory.h"
|
||||
|
@ -571,12 +572,6 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* actor,
|
|||
{
|
||||
// This runs after AllocPBrowser() returns and the IPC machinery for this
|
||||
// PBrowserChild has been set up.
|
||||
//
|
||||
// We have to NotifyObservers("tab-child-created") before we
|
||||
// TemporarilyLockProcessPriority because the NotifyObservers call may cause
|
||||
// us to initialize the ProcessPriorityManager, and
|
||||
// TemporarilyLockProcessPriority only works after the
|
||||
// ProcessPriorityManager has been initialized.
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
|
@ -592,13 +587,6 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* actor,
|
|||
MOZ_ASSERT(!sFirstIdleTask);
|
||||
sFirstIdleTask = NewRunnableFunction(FirstIdle);
|
||||
MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask);
|
||||
|
||||
// We are either a brand-new process loading its first PBrowser, or we
|
||||
// are the preallocated process transforming into a particular
|
||||
// app/browser. Either way, our parent has already set our process
|
||||
// priority, and we want to leave it there for a few seconds while we
|
||||
// start up.
|
||||
TemporarilyLockProcessPriority();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1274,5 +1262,57 @@ ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvNotifyProcessPriorityChanged(
|
||||
const hal::ProcessPriority& aPriority)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
NS_ENSURE_TRUE(os, true);
|
||||
|
||||
nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
|
||||
props->Init();
|
||||
props->SetPropertyAsInt32(NS_LITERAL_STRING("priority"),
|
||||
static_cast<int32_t>(aPriority));
|
||||
|
||||
os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
|
||||
"ipc:process-priority-changed", nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvMinimizeMemoryUsage()
|
||||
{
|
||||
nsCOMPtr<nsIMemoryReporterManager> mgr =
|
||||
do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
NS_ENSURE_TRUE(mgr, true);
|
||||
|
||||
nsCOMPtr<nsICancelableRunnable> runnable =
|
||||
do_QueryReferent(mMemoryMinimizerRunnable);
|
||||
|
||||
// Cancel the previous task if it's still pending.
|
||||
if (runnable) {
|
||||
runnable->Cancel();
|
||||
runnable = nullptr;
|
||||
}
|
||||
|
||||
mgr->MinimizeMemoryUsage(/* callback = */ nullptr,
|
||||
getter_AddRefs(runnable));
|
||||
mMemoryMinimizerRunnable = do_GetWeakReference(runnable);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvCancelMinimizeMemoryUsage()
|
||||
{
|
||||
nsCOMPtr<nsICancelableRunnable> runnable =
|
||||
do_QueryReferent(mMemoryMinimizerRunnable);
|
||||
if (runnable) {
|
||||
runnable->Cancel();
|
||||
mMemoryMinimizerRunnable = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -195,6 +195,10 @@ public:
|
|||
const int32_t& aState,
|
||||
const int32_t& aMountGeneration);
|
||||
|
||||
virtual bool RecvNotifyProcessPriorityChanged(const hal::ProcessPriority& aPriority);
|
||||
virtual bool RecvMinimizeMemoryUsage();
|
||||
virtual bool RecvCancelMinimizeMemoryUsage();
|
||||
|
||||
#ifdef ANDROID
|
||||
gfxIntSize GetScreenSize() { return mScreenSize; }
|
||||
#endif
|
||||
|
@ -249,6 +253,7 @@ private:
|
|||
bool mIsForApp;
|
||||
bool mIsForBrowser;
|
||||
nsString mProcessName;
|
||||
nsWeakPtr mMemoryMinimizerRunnable;
|
||||
|
||||
static ContentChild* sSingleton;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "nsFrameMessageManager.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIAlertsService.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
|
@ -200,8 +201,9 @@ static uint64_t gContentChildID = 1;
|
|||
ContentParent::PreallocateAppProcess()
|
||||
{
|
||||
nsRefPtr<ContentParent> process =
|
||||
new ContentParent(MAGIC_PREALLOCATED_APP_MANIFEST_URL,
|
||||
/*isBrowserElement=*/false,
|
||||
new ContentParent(/* app = */ nullptr,
|
||||
/* isForBrowserElement = */ false,
|
||||
/* isForPreallocated = */ true,
|
||||
// Final privileges are set when we
|
||||
// transform into our app.
|
||||
base::PRIVILEGES_INHERIT,
|
||||
|
@ -318,8 +320,9 @@ ContentParent::GetNewOrUsed(bool aForBrowserElement)
|
|||
}
|
||||
|
||||
nsRefPtr<ContentParent> p =
|
||||
new ContentParent(/* appManifestURL = */ EmptyString(),
|
||||
new ContentParent(/* app = */ nullptr,
|
||||
aForBrowserElement,
|
||||
/* isForPreallocated = */ false,
|
||||
base::PRIVILEGES_DEFAULT,
|
||||
PROCESS_PRIORITY_FOREGROUND);
|
||||
p->Init();
|
||||
|
@ -440,8 +443,11 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
initialPriority);
|
||||
if (!p) {
|
||||
NS_WARNING("Unable to use pre-allocated app process");
|
||||
p = new ContentParent(manifestURL, /* isBrowserElement = */ false,
|
||||
privs, initialPriority);
|
||||
p = new ContentParent(ownApp,
|
||||
/* isForBrowserElement = */ false,
|
||||
/* isForPreallocated = */ false,
|
||||
privs,
|
||||
initialPriority);
|
||||
p->Init();
|
||||
}
|
||||
sAppContentParents->Put(manifestURL, p);
|
||||
|
@ -450,22 +456,10 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
nsRefPtr<TabParent> tp = new TabParent(aContext);
|
||||
tp->SetOwnerElement(aFrameElement);
|
||||
PBrowserParent* browser = p->SendPBrowserConstructor(
|
||||
tp.forget().get(), // DeallocPBrowserParent() releases this ref.
|
||||
nsRefPtr<TabParent>(tp).forget().get(), // DeallocPBrowserParent() releases this ref.
|
||||
aContext.AsIPCTabContext(),
|
||||
/* chromeFlags */ 0);
|
||||
|
||||
// Send the frame element's mozapptype down to the child process. This ends
|
||||
// up in TabChild::GetAppType(). We have to do this /before/ we acquire the
|
||||
// CPU wake lock for this process, because if the child sees that it has a
|
||||
// CPU wake lock but its TabChild doesn't have the right mozapptype, it
|
||||
// might downgrade its process priority.
|
||||
nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
|
||||
if (frameElement) {
|
||||
nsAutoString appType;
|
||||
frameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapptype, appType);
|
||||
unused << browser->SendSetAppType(appType);
|
||||
}
|
||||
|
||||
p->MaybeTakeCPUWakeLock(aFrameElement);
|
||||
|
||||
return static_cast<TabParent*>(browser);
|
||||
|
@ -608,17 +602,6 @@ NS_IMPL_ISUPPORTS1(SystemMessageHandledListener,
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
ContentParent::SetProcessPriority(ProcessPriority aPriority)
|
||||
{
|
||||
if (!Preferences::GetBool("dom.ipc.processPriorityManager.enabled")) {
|
||||
return;
|
||||
}
|
||||
|
||||
hal::SetProcessPriority(base::GetProcId(mSubprocess->GetChildProcessHandle()),
|
||||
aPriority);
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::MaybeTakeCPUWakeLock(nsIDOMElement* aFrameElement)
|
||||
{
|
||||
|
@ -646,7 +629,7 @@ ContentParent::MaybeTakeCPUWakeLock(nsIDOMElement* aFrameElement)
|
|||
bool
|
||||
ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority)
|
||||
{
|
||||
SetProcessPriority(aPriority);
|
||||
ProcessPriorityManager::SetProcessPriority(this, aPriority);
|
||||
|
||||
// Now that we've set this process's priority, check whether the process is
|
||||
// still alive. Hopefully we've set the priority to FOREGROUND*, so the
|
||||
|
@ -665,14 +648,38 @@ ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Helper for ContentParent::TransformPreallocatedIntoApp.
|
||||
static void
|
||||
TryGetNameFromManifestURL(const nsAString& aManifestURL,
|
||||
nsAString& aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
if (aManifestURL.IsEmpty() ||
|
||||
aManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE_VOID(appsService);
|
||||
|
||||
nsCOMPtr<mozIDOMApplication> domApp;
|
||||
appsService->GetAppByManifestURL(aManifestURL, getter_AddRefs(domApp));
|
||||
|
||||
nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
|
||||
if (!app) {
|
||||
return;
|
||||
}
|
||||
|
||||
app->GetName(aName);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::TransformPreallocatedIntoApp(const nsAString& aAppManifestURL,
|
||||
ChildPrivileges aPrivs)
|
||||
{
|
||||
MOZ_ASSERT(mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL);
|
||||
// Clients should think of mAppManifestURL as const ... we're
|
||||
// bending the rules here just for the preallocation hack.
|
||||
const_cast<nsString&>(mAppManifestURL) = aAppManifestURL;
|
||||
MOZ_ASSERT(IsPreallocated());
|
||||
mAppManifestURL = aAppManifestURL;
|
||||
TryGetNameFromManifestURL(aAppManifestURL, mAppName);
|
||||
|
||||
return SendSetProcessPrivileges(aPrivs);
|
||||
}
|
||||
|
@ -980,8 +987,9 @@ ContentParent::GetTestShellSingleton()
|
|||
return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
|
||||
}
|
||||
|
||||
ContentParent::ContentParent(const nsAString& aAppManifestURL,
|
||||
ContentParent::ContentParent(mozIApplication* aApp,
|
||||
bool aIsForBrowser,
|
||||
bool aIsForPreallocated,
|
||||
ChildOSPrivileges aOSPrivileges,
|
||||
ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */)
|
||||
: mSubprocess(nullptr)
|
||||
|
@ -990,7 +998,6 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL,
|
|||
, mGeolocationWatchID(-1)
|
||||
, mRunToCompletionDepth(0)
|
||||
, mShouldCallUnblockChild(false)
|
||||
, mAppManifestURL(aAppManifestURL)
|
||||
, mForceKillTask(nullptr)
|
||||
, mNumDestroyingTabs(0)
|
||||
, mIsAlive(true)
|
||||
|
@ -998,9 +1005,20 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL,
|
|||
, mSendPermissionUpdates(false)
|
||||
, mIsForBrowser(aIsForBrowser)
|
||||
{
|
||||
// No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated should
|
||||
// be true.
|
||||
MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated <= 1);
|
||||
|
||||
// Insert ourselves into the global linked list of ContentParent objects.
|
||||
sContentParents.insertBack(this);
|
||||
|
||||
if (aApp) {
|
||||
aApp->GetManifestURL(mAppManifestURL);
|
||||
aApp->GetName(mAppName);
|
||||
} else if (aIsForPreallocated) {
|
||||
mAppManifestURL = MAGIC_PREALLOCATED_APP_MANIFEST_URL;
|
||||
}
|
||||
|
||||
// From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
|
||||
// PID along with the warning.
|
||||
nsDebugImpl::SetMultiprocessMode("Parent");
|
||||
|
@ -1011,13 +1029,16 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL,
|
|||
|
||||
mSubprocess->LaunchAndWaitForProcessHandle();
|
||||
|
||||
// Set the subprocess's priority. We do this first because we're likely
|
||||
// /lowering/ its CPU and memory priority, which it has inherited from this
|
||||
// process.
|
||||
SetProcessPriority(aInitialPriority);
|
||||
|
||||
Open(mSubprocess->GetChannel(), mSubprocess->GetChildProcessHandle());
|
||||
|
||||
// Set the subprocess's priority. We do this early on because we're likely
|
||||
// /lowering/ the process's CPU and memory priority, which it has inherited
|
||||
// from this process.
|
||||
//
|
||||
// This call can cause us to send IPC messages to the child process, so it
|
||||
// must come after the Open() call above.
|
||||
ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
|
||||
|
||||
// NB: internally, this will send an IPC message to the child
|
||||
// process to get it to create the CompositorChild. This
|
||||
// message goes through the regular IPC queue for this
|
||||
|
@ -1348,7 +1369,7 @@ ContentParent::RecvAudioChannelChangedNotification()
|
|||
nsRefPtr<AudioChannelService> service =
|
||||
AudioChannelService::GetAudioChannelService();
|
||||
if (service) {
|
||||
service->SendAudioChannelChangedNotification();
|
||||
service->SendAudioChannelChangedNotification(ChildID());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1759,6 +1780,30 @@ ContentParent::KillHard()
|
|||
OtherProcess(), /*force=*/true));
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::IsPreallocated()
|
||||
{
|
||||
return mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL;
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::FriendlyName(nsAString& aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
if (IsPreallocated()) {
|
||||
aName.AssignLiteral("(Preallocated)");
|
||||
} else if (mIsForBrowser) {
|
||||
aName.AssignLiteral("Browser");
|
||||
} else if (!mAppName.IsEmpty()) {
|
||||
aName = mAppName;
|
||||
} else if (!mAppManifestURL.IsEmpty()) {
|
||||
aName.AssignLiteral("Unknown app: ");
|
||||
aName.Append(mAppManifestURL);
|
||||
} else {
|
||||
aName.AssignLiteral("???");
|
||||
}
|
||||
}
|
||||
|
||||
PCrashReporterParent*
|
||||
ContentParent::AllocPCrashReporter(const NativeThreadId& tid,
|
||||
const uint32_t& processType)
|
||||
|
|
|
@ -138,6 +138,10 @@ public:
|
|||
return mSubprocess;
|
||||
}
|
||||
|
||||
int32_t Pid() {
|
||||
return base::GetProcId(mSubprocess->GetChildProcessHandle());
|
||||
}
|
||||
|
||||
bool NeedsPermissionsUpdate() {
|
||||
return mSendPermissionUpdates;
|
||||
}
|
||||
|
@ -153,6 +157,15 @@ public:
|
|||
void KillHard();
|
||||
|
||||
uint64_t ChildID() { return mChildID; }
|
||||
bool IsPreallocated();
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* etc. So please don't use this name to make any decisions about the
|
||||
* ContentParent based on the value returned here.
|
||||
*/
|
||||
void FriendlyName(nsAString& aName);
|
||||
|
||||
protected:
|
||||
void OnChannelConnected(int32_t pid);
|
||||
|
@ -184,17 +197,18 @@ private:
|
|||
using PContentParent::SendPBrowserConstructor;
|
||||
using PContentParent::SendPTestShellConstructor;
|
||||
|
||||
ContentParent(const nsAString& aAppManifestURL, bool aIsForBrowser,
|
||||
// No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be
|
||||
// true.
|
||||
ContentParent(mozIApplication* aApp,
|
||||
bool aIsForBrowser,
|
||||
bool aIsForPreallocated,
|
||||
ChildOSPrivileges aOSPrivileges = base::PRIVILEGES_DEFAULT,
|
||||
hal::ProcessPriority aInitialPriority = hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
|
||||
virtual ~ContentParent();
|
||||
|
||||
void Init();
|
||||
|
||||
// Set the child process's priority. Once the child starts up, it will
|
||||
// manage its own priority via the ProcessPriorityManager.
|
||||
void SetProcessPriority(hal::ProcessPriority aInitialPriority);
|
||||
|
||||
// If the frame element indicates that the child process is "critical" and
|
||||
// has a pending system message, this function acquires the CPU wake lock on
|
||||
// behalf of the child. We'll release the lock when the system message is
|
||||
|
@ -400,7 +414,15 @@ private:
|
|||
// the nsIObserverService.
|
||||
nsCOMArray<nsIMemoryReporter> mMemoryReporters;
|
||||
|
||||
const nsString mAppManifestURL;
|
||||
nsString mAppManifestURL;
|
||||
|
||||
/**
|
||||
* We cache mAppName instead of looking it up using mAppManifestURL when we
|
||||
* need it because it turns out that getting an app from the apps service is
|
||||
* expensive.
|
||||
*/
|
||||
nsString mAppName;
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> mMessageManager;
|
||||
|
||||
// After we initiate shutdown, we also start a timer to ensure
|
||||
|
|
|
@ -380,20 +380,6 @@ child:
|
|||
uint32_t renderFlags, bool flushLayout,
|
||||
nsIntSize renderSize);
|
||||
|
||||
/**
|
||||
* Send the child its app type. The app type identifies the kind of app
|
||||
* shown in this PBrowser. Currently, the only recognized app type is
|
||||
* "homescreen".
|
||||
*
|
||||
* The value here corresponds to the "mozapptype" attribute on iframes. For
|
||||
* example, <iframe mozbrowser mozapp="..." mozapptype="homescreen">.
|
||||
*
|
||||
* Only app frames (i.e., frames with an app-id) should have a non-empty app
|
||||
* type. If you try to SetAppType() with a non-empty app type on a non-app
|
||||
* PBrowserChild, we may assert.
|
||||
*/
|
||||
SetAppType(nsString appType);
|
||||
|
||||
/**
|
||||
* Sent by the chrome process when it no longer wants this remote
|
||||
* <browser>. The child side cleans up in response, then
|
||||
|
|
|
@ -26,6 +26,7 @@ include URIParams;
|
|||
include "mozilla/chrome/RegistryMessageUtils.h";
|
||||
include "mozilla/dom/PermissionMessageUtils.h";
|
||||
include "mozilla/dom/TabMessageUtils.h";
|
||||
include "mozilla/HalTypes.h";
|
||||
include "mozilla/layout/RenderFrameUtils.h";
|
||||
include "mozilla/net/NeckoMessageUtils.h";
|
||||
include "nsGeoPositionIPCSerialiser.h";
|
||||
|
@ -43,6 +44,7 @@ using mozilla::null_t;
|
|||
using mozilla::void_t;
|
||||
using mozilla::dom::AudioChannelType;
|
||||
using mozilla::dom::NativeThreadId;
|
||||
using mozilla::hal::ProcessPriority;
|
||||
using mozilla::layout::ScrollingBehavior;
|
||||
using gfxIntSize;
|
||||
|
||||
|
@ -332,6 +334,10 @@ child:
|
|||
FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState,
|
||||
int32_t mountGeneration);
|
||||
|
||||
NotifyProcessPriorityChanged(ProcessPriority priority);
|
||||
MinimizeMemoryUsage();
|
||||
CancelMinimizeMemoryUsage();
|
||||
|
||||
parent:
|
||||
/**
|
||||
* Tell the content process some attributes of itself. This is
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,46 +7,75 @@
|
|||
#ifndef mozilla_ProcessPriorityManager_h_
|
||||
#define mozilla_ProcessPriorityManager_h_
|
||||
|
||||
#include "mozilla/HalTypes.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
class ContentParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the ProcessPriorityManager.
|
||||
* This class sets the priority of subprocesses in response to explicit
|
||||
* requests and events in the system.
|
||||
*
|
||||
* The ProcessPriorityManager informs the hal back-end whether this is the root
|
||||
* Gecko process, and, if we're not the root, informs hal when this process
|
||||
* transitions between having no visible top-level windows, and having at least
|
||||
* one visible top-level window.
|
||||
* A process's priority changes e.g. when it goes into the background via
|
||||
* mozbrowser's setVisible(false). Process priority affects CPU scheduling and
|
||||
* also which processes get killed when we run out of memory.
|
||||
*
|
||||
* Hal may adjust this process's operating system priority (e.g. niceness, on
|
||||
* *nix) according to these notificaitons.
|
||||
*
|
||||
* This function call does nothing if the pref for OOP tabs is not set.
|
||||
* After you call Initialize(), the only thing you probably have to do is call
|
||||
* SetProcessPriority on processes immediately after creating them in order to
|
||||
* set their initial priority. The ProcessPriorityManager takes care of the
|
||||
* rest.
|
||||
*/
|
||||
void InitProcessPriorityManager();
|
||||
class ProcessPriorityManager MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initialize the ProcessPriorityManager machinery, causing the
|
||||
* ProcessPriorityManager to actively manage the priorities of all
|
||||
* subprocesses. You should call this before creating any subprocesses.
|
||||
*
|
||||
* You should also call this function even if you're in a child process,
|
||||
* since it will initialize ProcessPriorityManagerChild.
|
||||
*/
|
||||
static void Init();
|
||||
|
||||
/**
|
||||
* True iff the current process has foreground or higher priority as
|
||||
* computed by DOM visibility. The returned answer may not match the
|
||||
* actual OS process priority, for short intervals.
|
||||
*/
|
||||
bool CurrentProcessIsForeground();
|
||||
/**
|
||||
* Set the process priority of a given ContentParent's process.
|
||||
*
|
||||
* Note that because this method takes a ContentParent*, you can only set the
|
||||
* priority of your subprocesses. In fact, because we don't support nested
|
||||
* content processes (bug 761935), you can only call this method from the
|
||||
* main process.
|
||||
*
|
||||
* It probably only makes sense to call this function immediately after a
|
||||
* process is created. At this point, the process priority manager doesn't
|
||||
* have enough context about the processs to know what its priority should
|
||||
* be.
|
||||
*
|
||||
* Eventually whatever priority you set here can and probably will be
|
||||
* overwritten by the process priority manager.
|
||||
*/
|
||||
static void SetProcessPriority(dom::ContentParent* aContentParent,
|
||||
hal::ProcessPriority aPriority);
|
||||
|
||||
/**
|
||||
* Calling this function prevents us from changing this process's priority
|
||||
* for a few seconds, if that change in priority would not have taken effect
|
||||
* immediately to begin with.
|
||||
*
|
||||
* In practice, this prevents foreground --> background transitions, but not
|
||||
* background --> foreground transitions. It also does not prevent
|
||||
* transitions from an unknown priority (as happens immediately after we're
|
||||
* constructed) to a foreground priority.
|
||||
*/
|
||||
void TemporarilyLockProcessPriority();
|
||||
/**
|
||||
* Returns true iff this process's priority is FOREGROUND*.
|
||||
*
|
||||
* Note that because process priorities are set in the main process, it's
|
||||
* possible for this method to return a stale value. So be careful about
|
||||
* what you use this for.
|
||||
*/
|
||||
static bool CurrentProcessIsForeground();
|
||||
|
||||
private:
|
||||
ProcessPriorityManager();
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ProcessPriorityManager);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1818,14 +1818,6 @@ TabChild::RecvDestroy()
|
|||
return Send__delete__(this);
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
TabChild::RecvSetAppType(const nsString& aAppType)
|
||||
{
|
||||
MOZ_ASSERT_IF(!aAppType.IsEmpty(), HasOwnApp());
|
||||
mAppType = aAppType;
|
||||
return true;
|
||||
}
|
||||
|
||||
PRenderFrameChild*
|
||||
TabChild::AllocPRenderFrame(ScrollingBehavior* aScrolling,
|
||||
LayersBackend* aBackend,
|
||||
|
|
|
@ -307,16 +307,6 @@ public:
|
|||
void MakeVisible();
|
||||
void MakeHidden();
|
||||
|
||||
virtual bool RecvSetAppType(const nsString& aAppType);
|
||||
|
||||
/**
|
||||
* Get this object's app type.
|
||||
*
|
||||
* A TabChild's app type corresponds to the value of its frame element's
|
||||
* "mozapptype" attribute.
|
||||
*/
|
||||
void GetAppType(nsAString& aAppType) const { aAppType = mAppType; }
|
||||
|
||||
protected:
|
||||
virtual PRenderFrameChild* AllocPRenderFrame(ScrollingBehavior* aScrolling,
|
||||
LayersBackend* aBackend,
|
||||
|
@ -437,7 +427,6 @@ private:
|
|||
bool mNotified;
|
||||
bool mContentDocumentIsDisplayed;
|
||||
bool mTriedBrowserInit;
|
||||
nsString mAppType;
|
||||
ScreenOrientation mOrientation;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||
|
|
|
@ -106,6 +106,31 @@ TabParent::SetOwnerElement(nsIDOMElement* aElement)
|
|||
TryCacheDPI();
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::GetAppType(nsAString& aOut)
|
||||
{
|
||||
aOut.Truncate();
|
||||
nsCOMPtr<Element> elem = do_QueryInterface(mFrameElement);
|
||||
if (!elem) {
|
||||
return;
|
||||
}
|
||||
|
||||
elem->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapptype, aOut);
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::IsVisible()
|
||||
{
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (!frameLoader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visible = false;
|
||||
frameLoader->GetVisible(&visible);
|
||||
return visible;
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::Destroy()
|
||||
{
|
||||
|
@ -152,18 +177,20 @@ TabParent::ActorDestroy(ActorDestroyReason why)
|
|||
mIMETabParent = nullptr;
|
||||
}
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (frameLoader) {
|
||||
ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr);
|
||||
frameLoader->DestroyChild();
|
||||
|
||||
if (why == AbnormalShutdown) {
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, frameLoader),
|
||||
"oop-frameloader-crashed", nullptr);
|
||||
}
|
||||
if (why == AbnormalShutdown && os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, frameLoader),
|
||||
"oop-frameloader-crashed", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsITabParent*, this), "ipc:browser-destroyed", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -61,6 +61,20 @@ public:
|
|||
virtual ~TabParent();
|
||||
nsIDOMElement* GetOwnerElement() { return mFrameElement; }
|
||||
void SetOwnerElement(nsIDOMElement* aElement);
|
||||
|
||||
/**
|
||||
* Get the mozapptype attribute from this TabParent's owner DOM element.
|
||||
*/
|
||||
void GetAppType(nsAString& aOut);
|
||||
|
||||
/**
|
||||
* Returns true iff this TabParent's nsIFrameLoader is visible.
|
||||
*
|
||||
* The frameloader's visibility can be independent of e.g. its docshell's
|
||||
* visibility.
|
||||
*/
|
||||
bool IsVisible();
|
||||
|
||||
nsIBrowserDOMWindow *GetBrowserDOMWindow() { return mBrowserDOMWindow; }
|
||||
void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
|
||||
mBrowserDOMWindow = aBrowserDOMWindow;
|
||||
|
|
|
@ -263,7 +263,7 @@ nsLayoutStatics::Initialize()
|
|||
|
||||
nsSVGUtils::Init();
|
||||
|
||||
InitProcessPriorityManager();
|
||||
ProcessPriorityManager::Init();
|
||||
|
||||
nsPermissionManager::AppClearDataObserverInit();
|
||||
nsCookieService::AppClearDataObserverInit();
|
||||
|
|
Загрузка…
Ссылка в новой задаче