mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset 1651dcb62397 (bug 835563) on a CLOSED TREE
This commit is contained in:
parent
d32c6a8452
commit
5d6a7991c8
@ -641,18 +641,8 @@ BrowserElementChild.prototype = {
|
||||
|
||||
_recvSetVisible: function(data) {
|
||||
debug("Received setVisible message: (" + data.json.visible + ")");
|
||||
if (this._forcedVisible == data.json.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
_recvVisible: function(data) {
|
||||
|
@ -127,32 +127,22 @@ IsBackgroundPriority(ProcessPriority aPriority)
|
||||
}
|
||||
|
||||
/**
|
||||
* This class listens to various Gecko events and asks the hal back-end to
|
||||
* change this process's priority when it transitions between various states of
|
||||
* "importance".
|
||||
* This class listens to window creation and visibilitychange events and
|
||||
* informs the hal back-end when this process transitions between having no
|
||||
* visible top-level windows, and when it has at least one visible top-level
|
||||
* window.
|
||||
*
|
||||
* The process's priority determines its CPU priority and also how likely it is
|
||||
* to be killed when the system is running out of memory.
|
||||
*
|
||||
* The most basic dichotomy in the ProcessPriorityManager is between
|
||||
* "foreground" processes, which usually have at least one active docshell, and
|
||||
* "background" processes.
|
||||
* An important heuristic here is that we don't mark a process as background
|
||||
* until it's had no visible top-level windows for some amount of time.
|
||||
*
|
||||
* An important heuristic here is that we don't always mark a process as having
|
||||
* "background" priority until it's met the requisite criteria for some amount
|
||||
* of time.
|
||||
* We do this because the notion of visibility is tied to inner windows
|
||||
* (actually, to documents). When we navigate a page with outer window W, we
|
||||
* first destroy W's inner window and document, then insert a new inner window
|
||||
* and document into W. If not for our grace period, this transition could
|
||||
* cause us to inform hal that this process quickly transitioned from
|
||||
* foreground to background to foreground again.
|
||||
*
|
||||
* We do this because otherwise there are cases where we'd thrash a process
|
||||
* between foreground and background priorities; for example, Gaia sometimes
|
||||
* releases and re-acquires CPU wake locks in quick succession.
|
||||
*
|
||||
* On the other hand, when the embedder of an <iframe mozbrowser> calls
|
||||
* setVisible(false) on an iframe, we immediately send the relevant process to
|
||||
* the background, if it has no other foreground docshells. This is necessary
|
||||
* to ensure that when we load an app, the embedder first has a chance to send
|
||||
* the previous app into the background. This ensures that there's only one
|
||||
* foreground app at a time, thus ensuring that we kill the right process if we
|
||||
* come under memory pressure.
|
||||
*/
|
||||
class ProcessPriorityManager MOZ_FINAL
|
||||
: public nsIObserver
|
||||
@ -259,16 +249,10 @@ ProcessPriorityManager::Init()
|
||||
|
||||
// We can't do this in the constructor because we need to hold a strong ref
|
||||
// to |this| before calling these methods.
|
||||
//
|
||||
// Notice that we track /window/ creation and destruction even though our
|
||||
// notion of "is-foreground" is tied to /docshell/ activity. We do this
|
||||
// because docshells don't fire an event when their visibility changes, but
|
||||
// windows do.
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
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);
|
||||
os->AddObserver(this, "process-priority:reset-now", /* ownsWeak = */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -282,9 +266,6 @@ ProcessPriorityManager::Observe(
|
||||
} else if (!strcmp(aTopic, "inner-window-destroyed") ||
|
||||
!strcmp(aTopic, "audio-channel-agent-changed")) {
|
||||
ResetPriority();
|
||||
} else if (!strcmp(aTopic, "process-priority:reset-now")) {
|
||||
LOG("Got process-priority:reset-now notification.");
|
||||
ResetPriorityNow();
|
||||
} else {
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
@ -366,43 +347,40 @@ ProcessPriorityManager::ResetPriorityNow()
|
||||
bool
|
||||
ProcessPriorityManager::ComputeIsInForeground()
|
||||
{
|
||||
// We could try to be clever and keep a running count of the number of active
|
||||
// docshells, instead of iterating over mWindows every time one window's
|
||||
// visibility state changes. But experience suggests that iterating over the
|
||||
// windows is prone to fewer errors (and one mistake doesn't mess you up for
|
||||
// the entire session). Moreover, mWindows should be a very short list,
|
||||
// since it contains only top-level content windows.
|
||||
// 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.
|
||||
// But experience suggests that iterating over the windows is prone to fewer
|
||||
// errors (and one mistake doesn't mess you up for the entire session).
|
||||
// Moreover, mWindows should be a very short list, since it contains only
|
||||
// top-level content windows.
|
||||
|
||||
bool allHidden = true;
|
||||
for (uint32_t i = 0; i < mWindows.Length(); i++) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindows[i]);
|
||||
nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mWindows[i]);
|
||||
if (!window) {
|
||||
mWindows.RemoveElementAt(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(window);
|
||||
if (!docshell) {
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
window->GetDocument(getter_AddRefs(doc));
|
||||
if (!doc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isActive = false;
|
||||
docshell->GetIsActive(&isActive);
|
||||
|
||||
bool hidden = false;
|
||||
doc->GetHidden(&hidden);
|
||||
#ifdef DEBUG
|
||||
nsAutoCString spec;
|
||||
nsCOMPtr<nsIURI> uri = window->GetDocumentURI();
|
||||
if (uri) {
|
||||
uri->GetSpec(spec);
|
||||
}
|
||||
LOG("Docshell at %s has visibility %d.", spec.get(), isActive);
|
||||
nsAutoString spec;
|
||||
doc->GetDocumentURI(spec);
|
||||
LOG("Document at %s has visibility %d.", NS_ConvertUTF16toUTF8(spec).get(), !hidden);
|
||||
#endif
|
||||
|
||||
allHidden = allHidden && !isActive;
|
||||
allHidden = allHidden && hidden;
|
||||
|
||||
// We could break out early from this loop if
|
||||
// isActive && mProcessPriority == BACKGROUND,
|
||||
// !hidden && mProcessPriority == BACKGROUND,
|
||||
// but then we might not clean up all the weak refs.
|
||||
}
|
||||
|
||||
@ -489,8 +467,7 @@ ProcessPriorityManager::TemporarilySetIsForeground()
|
||||
SetIsForeground();
|
||||
|
||||
// Each call to TemporarilySetIsForeground guarantees us temporaryPriorityMS
|
||||
// in the foreground (unless we receive a process-priority:reset-now
|
||||
// notification). So cancel our timer if it's running (which is due to a
|
||||
// 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();
|
||||
|
Loading…
Reference in New Issue
Block a user