Bug 844323 - Part 2 (The Main Event): Move ProcesPriorityManager to the main process. r=bent,khuey

This commit is contained in:
Justin Lebar 2013-04-30 13:44:05 -04:00
Родитель c60e290a2a
Коммит 69298c893a
21 изменённых файлов: 1138 добавлений и 605 удалений

Просмотреть файл

@ -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();