зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1279086) for causing painting issues a=backout
Backed out changeset b1c893387fdd (bug 1279086) Backed out changeset 277c54118c8a (bug 1279086)
This commit is contained in:
Родитель
730c59fce4
Коммит
b38dbd1378
|
@ -3309,7 +3309,6 @@ var PrintPreviewListener = {
|
|||
this._simplifyPageTab = null;
|
||||
}
|
||||
gBrowser.removeTab(this._printPreviewTab);
|
||||
gBrowser.deactivatePrintPreviewBrowsers();
|
||||
this._printPreviewTab = null;
|
||||
},
|
||||
_toggleAffectedChrome: function () {
|
||||
|
@ -3365,11 +3364,7 @@ var PrintPreviewListener = {
|
|||
|
||||
if (this._chromeState.sidebarOpen)
|
||||
SidebarUI.show(this._sidebarCommand);
|
||||
},
|
||||
|
||||
activateBrowser(browser) {
|
||||
gBrowser.activateBrowserForPrintPreview(browser);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function getMarkupDocumentViewer()
|
||||
|
|
|
@ -1632,7 +1632,8 @@
|
|||
// As frameLoaders start out with an active docShell we have to
|
||||
// deactivate it if this is not the selected tab's browser or the
|
||||
// browser window is minimized.
|
||||
aBrowser.docShellIsActive = this.shouldActivateDocShell(aBrowser);
|
||||
aBrowser.docShellIsActive = (aBrowser == this.selectedBrowser &&
|
||||
window.windowState != window.STATE_MINIMIZED);
|
||||
|
||||
// Create a new tab progress listener for the new browser we just injected,
|
||||
// since tab progress listeners have logic for handling the initial about:blank
|
||||
|
@ -2733,11 +2734,8 @@
|
|||
remoteBrowser._outerWindowIDBrowserMap.delete(aOtherBrowser.outerWindowID);
|
||||
}
|
||||
|
||||
// If switcher is active, it will intercept swap events and
|
||||
// react as needed.
|
||||
if (!this._switcher) {
|
||||
aOtherBrowser.docShellIsActive = this.shouldActivateDocShell(ourBrowser);
|
||||
}
|
||||
aOtherBrowser.docShellIsActive = (ourBrowser == this.selectedBrowser &&
|
||||
window.windowState != window.STATE_MINIMIZED);
|
||||
|
||||
// Swap the docshells
|
||||
ourBrowser.swapDocShells(aOtherBrowser);
|
||||
|
@ -3242,56 +3240,6 @@
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
List of browsers whose docshells must be active in order for print preview
|
||||
to work.
|
||||
-->
|
||||
<field name="_printPreviewBrowsers">
|
||||
new Set()
|
||||
</field>
|
||||
|
||||
<method name="activateBrowserForPrintPreview">
|
||||
<parameter name="aBrowser"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._printPreviewBrowsers.add(aBrowser);
|
||||
if (this._switcher) {
|
||||
this._switcher.activateBrowserForPrintPreview(aBrowser);
|
||||
}
|
||||
aBrowser.docShellIsActive = true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="deactivatePrintPreviewBrowsers">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let browsers = this._printPreviewBrowsers;
|
||||
this._printPreviewBrowsers = new Set();
|
||||
for (let browser of browsers) {
|
||||
browser.docShellIsActive = this.shouldActivateDocShell(browser);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Returns true if a given browser's docshell should be active.
|
||||
-->
|
||||
<method name="shouldActivateDocShell">
|
||||
<parameter name="aBrowser"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._switcher) {
|
||||
return this._switcher.shouldActivateDocShell(aBrowser);
|
||||
}
|
||||
return (aBrowser == this.selectedBrowser &&
|
||||
window.windowState != window.STATE_MINIMIZED) ||
|
||||
this._printPreviewBrowsers.has(aBrowser);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
The tab switcher is responsible for asynchronously switching
|
||||
tabs in e10s. It waits until the new tab is ready (i.e., the
|
||||
|
@ -3323,12 +3271,35 @@
|
|||
It's important that we always show either the spinner or a tab
|
||||
whose layers are available. Otherwise the compositor will draw
|
||||
an entirely black frame, which is very jarring. To ensure this
|
||||
never happens when switching away from a tab, we assume the
|
||||
old tab might still be drawn until a MozAfterPaint event
|
||||
occurs. Because layout and compositing happen asynchronously,
|
||||
we don't have any other way of knowing when the switch
|
||||
actually takes place. Therefore, we don't unload the old tab
|
||||
until the next MozAfterPaint event.
|
||||
never happens, we do the following:
|
||||
|
||||
1. When switching away from a tab, we assume the old tab might
|
||||
still be drawn until a MozAfterPaint event occurs. Because
|
||||
layout and compositing happen asynchronously, we don't have
|
||||
any other way of knowing when the switch actually takes
|
||||
place. Therefore, we don't unload the old tab until the next
|
||||
MozAfterPaint event.
|
||||
|
||||
2. Suppose that the user switches from tab A to B and then
|
||||
back to A. Suppose that we ask for tab A's layers to be
|
||||
unloaded via message M1 after the first switch and then
|
||||
request them again via message M2 once the second switch
|
||||
happens. Both loading and unloading of layers happens
|
||||
asynchronously, and this can cause problems. It's possible
|
||||
that the content process publishes one last layer tree before
|
||||
M1 is received. The parent process doesn't know that this
|
||||
layer tree was published before M1 and not after M2, so it
|
||||
will display the tab. However, once M1 arrives, the content
|
||||
process will destroy the layer tree for A and now we will
|
||||
display black for it.
|
||||
|
||||
To counter this problem, we keep tab A in a separate
|
||||
"unloading" state until the layer tree is actually dropped in
|
||||
the compositor thread. While the tab is in the "unloading"
|
||||
state, we're not allowed to request layers for it. Once the
|
||||
layers are dropped in the compositor, an event will fire and
|
||||
we will transition the tab to the "unloaded" state. Then we
|
||||
are free to request the tab's layers again.
|
||||
-->
|
||||
<field name="_switcher">null</field>
|
||||
<method name="_getSwitcher">
|
||||
|
@ -3375,6 +3346,11 @@
|
|||
// True if we're in the midst of switching tabs.
|
||||
switchInProgress: false,
|
||||
|
||||
// Keep an exact list of content processes (tabParent) in which
|
||||
// we're actively suppressing the display port. This gives a robust
|
||||
// way to make sure we don't forget to un-suppress.
|
||||
activeSuppressDisplayport: new Set(),
|
||||
|
||||
// Set of tabs that might be visible right now. We maintain
|
||||
// this set because we can't be sure when a tab is actually
|
||||
// drawn. A tab is added to this set when we ask to make it
|
||||
|
@ -3416,37 +3392,26 @@
|
|||
return state;
|
||||
},
|
||||
|
||||
setTabStateNoAction(tab, state) {
|
||||
setTabState: function(tab, state) {
|
||||
if (state == this.STATE_UNLOADED) {
|
||||
this.tabState.delete(tab);
|
||||
} else {
|
||||
this.tabState.set(tab, state);
|
||||
}
|
||||
},
|
||||
|
||||
setTabState: function(tab, state) {
|
||||
this.setTabStateNoAction(tab, state);
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
let {tabParent} = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
||||
let fl = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
||||
if (state == this.STATE_LOADING) {
|
||||
this.assert(!this.minimized);
|
||||
// Ask for a MozLayerTreeReady event.
|
||||
fl.requestNotifyLayerTreeReady();
|
||||
browser.docShellIsActive = true;
|
||||
if (!tabParent) {
|
||||
this.onLayersReady(browser);
|
||||
}
|
||||
} else if (state == this.STATE_UNLOADING) {
|
||||
// Ask for MozLayerTreeCleared event.
|
||||
fl.requestNotifyLayerTreeCleared();
|
||||
browser.docShellIsActive = false;
|
||||
if (!tabParent) {
|
||||
this.onLayersCleared(browser);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get minimized() {
|
||||
return window.windowState == window.STATE_MINIMIZED;
|
||||
},
|
||||
|
||||
init: function() {
|
||||
this.log("START");
|
||||
|
||||
|
@ -3454,12 +3419,7 @@
|
|||
window.addEventListener("MozLayerTreeReady", this);
|
||||
window.addEventListener("MozLayerTreeCleared", this);
|
||||
window.addEventListener("TabRemotenessChange", this);
|
||||
window.addEventListener("sizemodechange", this);
|
||||
window.addEventListener("SwapDocShells", this, true);
|
||||
window.addEventListener("EndSwapDocShells", this, true);
|
||||
if (!this.minimized) {
|
||||
this.setTabState(this.requestedTab, this.STATE_LOADED);
|
||||
}
|
||||
this.setTabState(this.requestedTab, this.STATE_LOADED);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
|
@ -3476,11 +3436,13 @@
|
|||
window.removeEventListener("MozLayerTreeReady", this);
|
||||
window.removeEventListener("MozLayerTreeCleared", this);
|
||||
window.removeEventListener("TabRemotenessChange", this);
|
||||
window.removeEventListener("sizemodechange", this);
|
||||
window.removeEventListener("SwapDocShells", this, true);
|
||||
window.removeEventListener("EndSwapDocShells", this, true);
|
||||
|
||||
this.tabbrowser._switcher = null;
|
||||
|
||||
this.activeSuppressDisplayport.forEach(function(tabParent) {
|
||||
tabParent.suppressDisplayport(false);
|
||||
});
|
||||
this.activeSuppressDisplayport.clear();
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
|
@ -3492,7 +3454,7 @@
|
|||
this.assert(!this.loadTimer);
|
||||
this.assert(!this.loadingTab);
|
||||
this.assert(this.lastVisibleTab === this.requestedTab);
|
||||
this.assert(this.minimized || this.getTabState(this.requestedTab) == this.STATE_LOADED);
|
||||
this.assert(this.getTabState(this.requestedTab) == this.STATE_LOADED);
|
||||
|
||||
this.destroy();
|
||||
|
||||
|
@ -3532,7 +3494,7 @@
|
|||
}
|
||||
|
||||
// Show or hide the spinner as needed.
|
||||
let needSpinner = this.getTabState(showTab) != this.STATE_LOADED && !this.minimized;
|
||||
let needSpinner = this.getTabState(showTab) != this.STATE_LOADED;
|
||||
if (!needSpinner && this.spinnerTab) {
|
||||
this.spinnerHidden();
|
||||
this.tabbrowser.removeAttribute("pendingpaint");
|
||||
|
@ -3587,15 +3549,14 @@
|
|||
// We've decided to try to load requestedTab.
|
||||
loadRequestedTab: function() {
|
||||
this.assert(!this.loadTimer);
|
||||
this.assert(!this.minimized);
|
||||
|
||||
// loadingTab can be non-null here if we timed out loading the current tab.
|
||||
// In that case we just overwrite it with a different tab; it's had its chance.
|
||||
this.loadingTab = this.requestedTab;
|
||||
this.log("Loading tab " + this.tinfo(this.loadingTab));
|
||||
|
||||
this.loadTimer = this.setTimer(() => this.onLoadTimeout(), this.TAB_SWITCH_TIMEOUT);
|
||||
this.setTabState(this.requestedTab, this.STATE_LOADING);
|
||||
this.loadTimer = this.setTimer(() => this.onLoadTimeout(), this.TAB_SWITCH_TIMEOUT);
|
||||
},
|
||||
|
||||
// This function runs before every event. It fixes up the state
|
||||
|
@ -3640,21 +3601,13 @@
|
|||
this.assert(!this.loadingTab || this.loadTimer);
|
||||
|
||||
// If we're not loading anything, try loading the requested tab.
|
||||
let requestedState = this.getTabState(this.requestedTab);
|
||||
if (!this.loadTimer && !this.minimized &&
|
||||
(requestedState == this.STATE_UNLOADED ||
|
||||
requestedState == this.STATE_UNLOADING)) {
|
||||
if (!this.loadTimer && this.getTabState(this.requestedTab) == this.STATE_UNLOADED) {
|
||||
this.loadRequestedTab();
|
||||
}
|
||||
|
||||
// See how many tabs still have work to do.
|
||||
let numPending = 0;
|
||||
for (let [tab, state] of this.tabState) {
|
||||
// Skip print preview browsers since they shouldn't affect tab switching.
|
||||
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state == this.STATE_LOADED && tab !== this.requestedTab) {
|
||||
numPending++;
|
||||
}
|
||||
|
@ -3689,10 +3642,6 @@
|
|||
|
||||
// Unload any tabs that can be unloaded.
|
||||
for (let [tab, state] of this.tabState) {
|
||||
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state == this.STATE_LOADED &&
|
||||
!this.maybeVisibleTabs.has(tab) &&
|
||||
tab !== this.lastVisibleTab &&
|
||||
|
@ -3726,15 +3675,9 @@
|
|||
|
||||
// Fires when the layers become available for a tab.
|
||||
onLayersReady: function(browser) {
|
||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||
if (!tab) {
|
||||
// Devtools sometimes makes its own remote browsers.
|
||||
return;
|
||||
}
|
||||
this.logState(`onLayersReady(${tab._tPos})`);
|
||||
this.logState("onLayersReady");
|
||||
|
||||
this.assert(this.getTabState(tab) == this.STATE_LOADING ||
|
||||
this.getTabState(tab) == this.STATE_LOADED);
|
||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||
this.setTabState(tab, this.STATE_LOADED);
|
||||
|
||||
this.maybeFinishTabSwitch();
|
||||
|
@ -3756,11 +3699,10 @@
|
|||
|
||||
// Called when we're done clearing the layers for a tab.
|
||||
onLayersCleared: function(browser) {
|
||||
this.logState("onLayersCleared");
|
||||
|
||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||
if (tab) {
|
||||
this.logState(`onLayersCleared(${tab._tPos})`);
|
||||
this.assert(this.getTabState(tab) == this.STATE_UNLOADING ||
|
||||
this.getTabState(tab) == this.STATE_UNLOADED);
|
||||
this.setTabState(tab, this.STATE_UNLOADED);
|
||||
}
|
||||
},
|
||||
|
@ -3769,7 +3711,7 @@
|
|||
// a MozLayerTreeReady notification that we requested may never fire,
|
||||
// so we need to simulate it.
|
||||
onRemotenessChange: function(tab) {
|
||||
this.logState(`onRemotenessChange(${tab._tPos}, ${tab.linkedBrowser.isRemoteBrowser})`);
|
||||
this.logState("onRemotenessChange");
|
||||
if (!tab.linkedBrowser.isRemoteBrowser) {
|
||||
if (this.getTabState(tab) == this.STATE_LOADING) {
|
||||
this.onLayersReady(tab.linkedBrowser);
|
||||
|
@ -3792,98 +3734,34 @@
|
|||
}
|
||||
},
|
||||
|
||||
onSizeModeChange() {
|
||||
if (this.minimized) {
|
||||
for (let [tab, state] of this.tabState) {
|
||||
// Skip print preview browsers since they shouldn't affect tab switching.
|
||||
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state == this.STATE_LOADING || state == this.STATE_LOADED) {
|
||||
this.setTabState(tab, this.STATE_UNLOADING);
|
||||
}
|
||||
if (this.loadTimer) {
|
||||
this.clearTimer(this.loadTimer);
|
||||
this.loadTimer = null;
|
||||
}
|
||||
this.loadingTab = null;
|
||||
}
|
||||
} else {
|
||||
// Do nothing. We'll automatically start loading the requested tab in
|
||||
// postActions.
|
||||
}
|
||||
},
|
||||
|
||||
onSwapDocShells(ourBrowser, otherBrowser) {
|
||||
// This event fires before the swap. ourBrowser is from
|
||||
// our window. We save the state of otherBrowser since ourBrowser
|
||||
// needs to take on that state at the end of the swap.
|
||||
|
||||
let otherTabbrowser = otherBrowser.ownerDocument.defaultView.gBrowser;
|
||||
let otherState;
|
||||
if (otherTabbrowser && otherTabbrowser._switcher) {
|
||||
let otherTab = otherTabbrowser.getTabForBrowser(otherBrowser);
|
||||
otherState = otherTabbrowser._switcher.getTabState(otherTab);
|
||||
} else {
|
||||
otherState = (otherBrowser.docShellIsActive
|
||||
? this.STATE_LOADED
|
||||
: this.STATE_UNLOADED);
|
||||
}
|
||||
|
||||
if (!this.swapMap) {
|
||||
this.swapMap = new WeakMap();
|
||||
}
|
||||
this.swapMap.set(otherBrowser, otherState);
|
||||
},
|
||||
|
||||
onEndSwapDocShells(ourBrowser, otherBrowser) {
|
||||
// The swap has happened. We reset the loadingTab in
|
||||
// case it has been swapped. We also set ourBrowser's state
|
||||
// to whatever otherBrowser's state was before the swap.
|
||||
|
||||
if (this.loadTimer) {
|
||||
// Clearing the load timer means that we will
|
||||
// immediately display a spinner if ourBrowser isn't
|
||||
// ready yet. Typically it will already be ready
|
||||
// though. If it's not, we're probably in a new window,
|
||||
// in which case we have no other tabs to display anyway.
|
||||
this.clearTimer(this.loadTimer);
|
||||
this.loadTimer = null;
|
||||
}
|
||||
this.loadingTab = null;
|
||||
|
||||
let otherState = this.swapMap.get(otherBrowser);
|
||||
this.swapMap.delete(otherBrowser);
|
||||
|
||||
let ourTab = this.tabbrowser.getTabForBrowser(ourBrowser);
|
||||
if (ourTab) {
|
||||
this.setTabStateNoAction(ourTab, otherState);
|
||||
}
|
||||
},
|
||||
|
||||
shouldActivateDocShell(browser) {
|
||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||
let state = this.getTabState(tab);
|
||||
return state == this.STATE_LOADING || state == this.STATE_LOADED;
|
||||
},
|
||||
|
||||
activateBrowserForPrintPreview(browser) {
|
||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||
this.setTabState(tab, this.STATE_LOADING);
|
||||
},
|
||||
|
||||
// Called when the user asks to switch to a given tab.
|
||||
requestTab: function(tab) {
|
||||
if (tab === this.requestedTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Instrumentation to figure out bug 1166351 - if the binding
|
||||
// on the browser we're switching to has gone away, try to find out
|
||||
// why. We should remove this and the checkBrowserBindingAlive
|
||||
// method once bug 1166351 has been closed.
|
||||
if (this.tabbrowser.AppConstants.E10S_TESTING_ONLY &&
|
||||
!this.checkBrowserBindingAlive(tab)) {
|
||||
Cu.reportError("Please report the above errors in bug 1166351.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.logState("requestTab " + this.tinfo(tab));
|
||||
this.startTabSwitch();
|
||||
|
||||
this.requestedTab = tab;
|
||||
|
||||
let browser = this.requestedTab.linkedBrowser;
|
||||
let fl = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
||||
if (fl && fl.tabParent && !this.activeSuppressDisplayport.has(fl.tabParent)) {
|
||||
fl.tabParent.suppressDisplayport(true);
|
||||
this.activeSuppressDisplayport.add(fl.tabParent);
|
||||
}
|
||||
|
||||
this.preActions();
|
||||
|
||||
if (this.unloadTimer) {
|
||||
|
@ -3915,12 +3793,6 @@
|
|||
this.onLayersCleared(event.originalTarget);
|
||||
} else if (event.type == "TabRemotenessChange") {
|
||||
this.onRemotenessChange(event.target);
|
||||
} else if (event.type == "sizemodechange") {
|
||||
this.onSizeModeChange();
|
||||
} else if (event.type == "SwapDocShells") {
|
||||
this.onSwapDocShells(event.originalTarget, event.detail);
|
||||
} else if (event.type == "EndSwapDocShells") {
|
||||
this.onEndSwapDocShells(event.originalTarget, event.detail);
|
||||
}
|
||||
|
||||
this.postActions();
|
||||
|
@ -4004,6 +3876,42 @@
|
|||
return this._shouldLog;
|
||||
},
|
||||
|
||||
// Instrumentation for bug 1166351
|
||||
checkBrowserBindingAlive: function(tab) {
|
||||
let err = Cu.reportError;
|
||||
|
||||
if (!tab.linkedBrowser) {
|
||||
err("Attempting to switch to tab that has no linkedBrowser.");
|
||||
return false;
|
||||
}
|
||||
|
||||
let b = tab.linkedBrowser;
|
||||
|
||||
if (!b._alive) {
|
||||
// The browser binding has been removed. Dump a bunch of
|
||||
// diagnostic information to the browser console.
|
||||
let utils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
let results = utils.getBindingURLs(b);
|
||||
let urls = [];
|
||||
|
||||
for (let i = 0; i < results.length; ++i) {
|
||||
urls.push(results.queryElementAt(i, Ci.nsIURI).spec);
|
||||
}
|
||||
err("The browser has the following bindings:");
|
||||
err(urls);
|
||||
err("MozBinding is currently: " +
|
||||
window.getComputedStyle(b).MozBinding);
|
||||
if (!b.parentNode) {
|
||||
err("Browser was removed from the DOM.");
|
||||
} else {
|
||||
err("Parent is: " + b.parentNode.outerHTML);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
tinfo: function(tab) {
|
||||
if (tab) {
|
||||
return tab._tPos + "(" + tab.linkedBrowser.currentURI.spec + ")";
|
||||
|
@ -4372,7 +4280,7 @@
|
|||
case "sizemodechange":
|
||||
if (aEvent.target == window) {
|
||||
this.mCurrentBrowser.setDocShellIsActiveAndForeground(
|
||||
this.shouldActivateDocShell(this.mCurrentBrowser));
|
||||
window.windowState != window.STATE_MINIMIZED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1021,6 +1021,8 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
|
|||
return rv;
|
||||
}
|
||||
|
||||
mRemoteBrowser->SwapLayerTreeObservers(aOther->mRemoteBrowser);
|
||||
|
||||
nsCOMPtr<nsIBrowserDOMWindow> otherBrowserDOMWindow =
|
||||
aOther->mRemoteBrowser->GetBrowserDOMWindow();
|
||||
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWindow =
|
||||
|
@ -3201,6 +3203,46 @@ nsFrameLoader::RequestNotifyAfterRemotePaint()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::RequestNotifyLayerTreeReady()
|
||||
{
|
||||
if (mRemoteBrowser) {
|
||||
return mRemoteBrowser->RequestNotifyLayerTreeReady() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!mOwnerContent) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
RefPtr<AsyncEventDispatcher> event =
|
||||
new AsyncEventDispatcher(mOwnerContent,
|
||||
NS_LITERAL_STRING("MozLayerTreeReady"),
|
||||
true, false);
|
||||
event->PostDOMEvent();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::RequestNotifyLayerTreeCleared()
|
||||
{
|
||||
if (mRemoteBrowser) {
|
||||
return mRemoteBrowser->RequestNotifyLayerTreeCleared() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!mOwnerContent) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
RefPtr<AsyncEventDispatcher> event =
|
||||
new AsyncEventDispatcher(mOwnerContent,
|
||||
NS_LITERAL_STRING("MozLayerTreeCleared"),
|
||||
true, false);
|
||||
event->PostDOMEvent();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::Print(uint64_t aOuterWindowID,
|
||||
nsIPrintSettings* aPrintSettings,
|
||||
|
|
|
@ -11121,14 +11121,14 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
|
||||
|
||||
// Null out the operation callback while we're re-entering JS here.
|
||||
bool old = JS_DisableInterruptCallback(cx);
|
||||
JSInterruptCallback old = JS_SetInterruptCallback(cx, nullptr);
|
||||
|
||||
// Open the dialog.
|
||||
rv = prompt->ConfirmEx(title, msg, buttonFlags, waitButton, stopButton,
|
||||
debugButton, neverShowDlg, &neverShowDlgChk,
|
||||
&buttonPressed);
|
||||
|
||||
JS_ResetInterruptCallback(cx, old);
|
||||
JS_SetInterruptCallback(cx, old);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && (buttonPressed == 0)) {
|
||||
return neverShowDlgChk ? AlwaysContinueSlowScript : ContinueSlowScript;
|
||||
|
|
|
@ -138,6 +138,14 @@ interface nsIFrameLoader : nsISupports
|
|||
*/
|
||||
void requestNotifyAfterRemotePaint();
|
||||
|
||||
/**
|
||||
* Request an event when the layer tree from the remote tab becomes
|
||||
* available or unavailable. When this happens, a mozLayerTreeReady
|
||||
* or mozLayerTreeCleared event is fired.
|
||||
*/
|
||||
void requestNotifyLayerTreeReady();
|
||||
void requestNotifyLayerTreeCleared();
|
||||
|
||||
/**
|
||||
* Print the current document.
|
||||
*
|
||||
|
|
|
@ -5501,12 +5501,3 @@ ContentParent::SendGetFilesResponseAndForget(const nsID& aUUID,
|
|||
Unused << SendGetFilesResponse(aUUID, aResult);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::ForceTabPaint(TabParent* aTabParent, uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
if (!mHangMonitorActor) {
|
||||
return;
|
||||
}
|
||||
ProcessHangMonitor::ForcePaint(mHangMonitorActor, aTabParent, aLayerObserverEpoch);
|
||||
}
|
||||
|
|
|
@ -563,9 +563,6 @@ public:
|
|||
|
||||
virtual int32_t Pid() const override;
|
||||
|
||||
// Use the PHangMonitor channel to ask the child to repaint a tab.
|
||||
void ForceTabPaint(TabParent* aTabParent, uint64_t aLayerObserverEpoch);
|
||||
|
||||
protected:
|
||||
void OnChannelConnected(int32_t pid) override;
|
||||
|
||||
|
|
|
@ -550,11 +550,6 @@ parent:
|
|||
*/
|
||||
async RemotePaintIsReady();
|
||||
|
||||
/**
|
||||
* Child informs the parent that the layer tree is already available.
|
||||
*/
|
||||
async ForcePaintNoOp(uint64_t aLayerObserverEpoch);
|
||||
|
||||
/**
|
||||
* Sent by the child to the parent to inform it that an update to the
|
||||
* dimensions has been requested, likely through win.moveTo or resizeTo
|
||||
|
@ -726,7 +721,7 @@ child:
|
|||
/**
|
||||
* Update the child side docShell active (resource use) state.
|
||||
*/
|
||||
async SetDocShellIsActive(bool aIsActive, bool aIsHidden, uint64_t aLayerObserverEpoch);
|
||||
async SetDocShellIsActive(bool aIsActive, bool aIsHidden);
|
||||
|
||||
/**
|
||||
* Notify the child that it shouldn't paint the offscreen displayport.
|
||||
|
|
|
@ -40,8 +40,6 @@ child:
|
|||
|
||||
async BeginStartingDebugger();
|
||||
async EndStartingDebugger();
|
||||
|
||||
async ForcePaint(TabId tabId, uint64_t aLayerObserverEpoch);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,13 +7,9 @@
|
|||
#include "mozilla/ProcessHangMonitor.h"
|
||||
#include "mozilla/ProcessHangMonitorIPC.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/GCAPI.h"
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
|
@ -100,11 +96,8 @@ class HangMonitorChild
|
|||
virtual bool RecvBeginStartingDebugger() override;
|
||||
virtual bool RecvEndStartingDebugger() override;
|
||||
|
||||
virtual bool RecvForcePaint(const TabId& aTabId, const uint64_t& aLayerObserverEpoch) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
void InterruptCallback();
|
||||
void Shutdown();
|
||||
|
||||
static HangMonitorChild* Get() { return sInstance; }
|
||||
|
@ -126,10 +119,6 @@ class HangMonitorChild
|
|||
bool mTerminateScript;
|
||||
bool mStartDebugger;
|
||||
bool mFinishedStartingDebugger;
|
||||
bool mForcePaint;
|
||||
TabId mForcePaintTab;
|
||||
uint64_t mForcePaintEpoch;
|
||||
JSContext* mContext;
|
||||
bool mShutdownDone;
|
||||
|
||||
// This field is only accessed on the hang thread.
|
||||
|
@ -219,8 +208,6 @@ public:
|
|||
|
||||
void Shutdown();
|
||||
|
||||
void ForcePaint(dom::TabParent* aTabParent, uint64_t aLayerObserverEpoch);
|
||||
|
||||
void TerminateScript();
|
||||
void BeginStartingDebugger();
|
||||
void EndStartingDebugger();
|
||||
|
@ -237,9 +224,6 @@ public:
|
|||
|
||||
private:
|
||||
bool TakeBrowserMinidump(const PluginHangData& aPhd, nsString& aCrashId);
|
||||
|
||||
void ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch);
|
||||
|
||||
void ShutdownOnThread();
|
||||
|
||||
const RefPtr<ProcessHangMonitor> mHangMonitor;
|
||||
|
@ -271,12 +255,10 @@ HangMonitorChild::HangMonitorChild(ProcessHangMonitor* aMonitor)
|
|||
mTerminateScript(false),
|
||||
mStartDebugger(false),
|
||||
mFinishedStartingDebugger(false),
|
||||
mForcePaint(false),
|
||||
mShutdownDone(false),
|
||||
mIPCOpen(true)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
mContext = danger::GetJSContext();
|
||||
}
|
||||
|
||||
HangMonitorChild::~HangMonitorChild()
|
||||
|
@ -286,33 +268,6 @@ HangMonitorChild::~HangMonitorChild()
|
|||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorChild::InterruptCallback()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
bool forcePaint;
|
||||
TabId forcePaintTab;
|
||||
uint64_t forcePaintEpoch;
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
forcePaint = mForcePaint;
|
||||
forcePaintTab = mForcePaintTab;
|
||||
forcePaintEpoch = mForcePaintEpoch;
|
||||
|
||||
mForcePaint = false;
|
||||
}
|
||||
|
||||
if (forcePaint) {
|
||||
RefPtr<TabChild> tabChild = TabChild::FindTabChild(forcePaintTab);
|
||||
if (tabChild) {
|
||||
JS::AutoAssertOnGC aaogc(mContext);
|
||||
tabChild->ForcePaint(forcePaintEpoch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorChild::Shutdown()
|
||||
{
|
||||
|
@ -376,23 +331,6 @@ HangMonitorChild::RecvEndStartingDebugger()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HangMonitorChild::RecvForcePaint(const TabId& aTabId, const uint64_t& aLayerObserverEpoch)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mForcePaint = true;
|
||||
mForcePaintTab = aTabId;
|
||||
mForcePaintEpoch = aLayerObserverEpoch;
|
||||
}
|
||||
|
||||
JS_RequestInterruptCallback(mContext);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorChild::Open(Transport* aTransport, ProcessId aPid,
|
||||
MessageLoop* aIOLoop)
|
||||
|
@ -586,25 +524,6 @@ HangMonitorParent::ShutdownOnThread()
|
|||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorParent::ForcePaint(dom::TabParent* aTab, uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
TabId id = aTab->GetTabId();
|
||||
MonitorLoop()->PostTask(NewNonOwningRunnableMethod<TabId, uint64_t>(
|
||||
this, &HangMonitorParent::ForcePaintOnThread, id, aLayerObserverEpoch));
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorParent::ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << SendForcePaint(aTabId, aLayerObserverEpoch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
|
@ -1040,16 +959,6 @@ HangMonitoredProcess::UserCanceled()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
InterruptCallback(JSContext* cx)
|
||||
{
|
||||
if (HangMonitorChild* child = HangMonitorChild::Get()) {
|
||||
child->InterruptCallback();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ProcessHangMonitor* ProcessHangMonitor::sInstance;
|
||||
|
||||
ProcessHangMonitor::ProcessHangMonitor()
|
||||
|
@ -1185,9 +1094,6 @@ mozilla::CreateHangMonitorChild(mozilla::ipc::Transport* aTransport,
|
|||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
JSContext* cx = danger::GetJSContext();
|
||||
JS_AddInterruptCallback(cx, InterruptCallback);
|
||||
|
||||
ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
|
||||
HangMonitorChild* child = new HangMonitorChild(monitor);
|
||||
|
||||
|
@ -1236,13 +1142,3 @@ ProcessHangMonitor::ClearHang()
|
|||
child->ClearHang();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ProcessHangMonitor::ForcePaint(PProcessHangMonitorParent* aParent,
|
||||
dom::TabParent* aTabParent,
|
||||
uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
auto parent = static_cast<HangMonitorParent*>(aParent);
|
||||
parent->ForcePaint(aTabParent, aLayerObserverEpoch);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace mozilla {
|
|||
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
class TabParent;
|
||||
} // namespace dom
|
||||
|
||||
class PProcessHangMonitorParent;
|
||||
|
@ -46,10 +45,6 @@ class ProcessHangMonitor final
|
|||
|
||||
static void ClearHang();
|
||||
|
||||
static void ForcePaint(PProcessHangMonitorParent* aParent,
|
||||
dom::TabParent* aTab,
|
||||
uint64_t aLayerObserverEpoch);
|
||||
|
||||
enum SlowScriptAction {
|
||||
Continue,
|
||||
Terminate,
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsWindowWatcher.h"
|
||||
#include "PermissionMessageUtils.h"
|
||||
|
@ -545,7 +544,6 @@ TabChild::TabChild(nsIContentChild* aManager,
|
|||
, mDidSetRealShowInfo(false)
|
||||
, mDidLoadURLInit(false)
|
||||
, mAPZChild(nullptr)
|
||||
, mLayerObserverEpoch(0)
|
||||
{
|
||||
// In the general case having the TabParent tell us if APZ is enabled or not
|
||||
// doesn't really work because the TabParent itself may not have a reference
|
||||
|
@ -2585,75 +2583,19 @@ TabChild::RecvSetUpdateHitRegion(const bool& aEnabled)
|
|||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvSetDocShellIsActive(const bool& aIsActive, const bool& aIsHidden, const uint64_t& aLayerObserverEpoch)
|
||||
TabChild::RecvSetDocShellIsActive(const bool& aIsActive, const bool& aIsHidden)
|
||||
{
|
||||
// Since SetDocShellIsActive requests come in from both the hang monitor
|
||||
// channel and the PContent channel, we have an ordering problem. This code
|
||||
// ensures that we respect the order in which the requests were made and
|
||||
// ignore stale requests.
|
||||
if (mLayerObserverEpoch > aLayerObserverEpoch) {
|
||||
return true;
|
||||
}
|
||||
mLayerObserverEpoch = aLayerObserverEpoch;
|
||||
|
||||
if (aIsActive && WebWidget()->IsVisible()) {
|
||||
// This request is a no-op. In this case, we still want a MozLayerTreeReady
|
||||
// notification to fire in the parent (so that it knows that the child has
|
||||
// updated its epoch). ForcePaintNoOp does that.
|
||||
if (IPCOpen()) {
|
||||
Unused << SendForcePaintNoOp(aLayerObserverEpoch);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPuppetWidget);
|
||||
MOZ_ASSERT(mPuppetWidget->GetLayerManager());
|
||||
MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() ==
|
||||
LayersBackend::LAYERS_CLIENT);
|
||||
|
||||
// We send the current layer observer epoch to the compositor so that
|
||||
// TabParent knows whether a layer update notification corresponds to the
|
||||
// latest SetDocShellIsActive request that was made.
|
||||
ClientLayerManager *manager = mPuppetWidget->GetLayerManager()->AsClientLayerManager();
|
||||
manager->SetLayerObserverEpoch(aLayerObserverEpoch);
|
||||
|
||||
// docshell is consider prerendered only if not active yet
|
||||
mIsPrerendered &= !aIsActive;
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||
if (docShell) {
|
||||
if (aIsHidden) {
|
||||
docShell->SetIsActive(aIsActive);
|
||||
} else {
|
||||
docShell->SetIsActiveAndForeground(aIsActive);
|
||||
}
|
||||
}
|
||||
|
||||
if (aIsActive) {
|
||||
// We don't use GetPresShell() here because that would create a content viewer
|
||||
// if one doesn't exist yet. Creating a content viewer can cause JS to run,
|
||||
// which we want to avoid. nsIDocShell::GetPresShell returns null if no
|
||||
// content viewer exists yet.
|
||||
if (nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell()) {
|
||||
// If we need to repaint, let's do that right away. No sense waiting until
|
||||
// we get back to the event loop again. We suppress the display port so that
|
||||
// we only paint what's visible. This ensures that the tab we're switching
|
||||
// to paints as quickly as possible.
|
||||
APZCCallbackHelper::SuppressDisplayport(true, presShell);
|
||||
if (nsContentUtils::IsSafeToRunScript()) {
|
||||
WebWidget()->PaintNowIfNeeded();
|
||||
// docshell is consider prerendered only if not active yet
|
||||
mIsPrerendered &= !aIsActive;
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||
if (docShell) {
|
||||
if (aIsHidden) {
|
||||
docShell->SetIsActive(aIsActive);
|
||||
} else {
|
||||
RefPtr<nsViewManager> vm = presShell->GetViewManager();
|
||||
if (nsView* view = vm->GetRootView()) {
|
||||
presShell->Paint(view, view->GetBounds(),
|
||||
nsIPresShell::PAINT_LAYERS |
|
||||
nsIPresShell::PAINT_SYNC_DECODE_IMAGES);
|
||||
}
|
||||
docShell->SetIsActiveAndForeground(aIsActive);
|
||||
}
|
||||
APZCCallbackHelper::SuppressDisplayport(false, presShell);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2874,10 +2816,6 @@ TabChild::NotifyPainted()
|
|||
void
|
||||
TabChild::MakeVisible()
|
||||
{
|
||||
if (mPuppetWidget && mPuppetWidget->IsVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPuppetWidget) {
|
||||
mPuppetWidget->Show(true);
|
||||
}
|
||||
|
@ -2886,10 +2824,6 @@ TabChild::MakeVisible()
|
|||
void
|
||||
TabChild::MakeHidden()
|
||||
{
|
||||
if (mPuppetWidget && !mPuppetWidget->IsVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
|
||||
|
||||
// Clear cached resources directly. This avoids one extra IPC
|
||||
|
@ -3248,13 +3182,6 @@ TabChild::GetOuterRect()
|
|||
return ViewAs<ScreenPixel>(outerRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::ForcePaint(uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
RecvSetDocShellIsActive(true, false, aLayerObserverEpoch);
|
||||
}
|
||||
|
||||
TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
|
||||
: mTabChild(aTabChild)
|
||||
{
|
||||
|
|
|
@ -646,9 +646,6 @@ public:
|
|||
mAPZChild = aAPZChild;
|
||||
}
|
||||
|
||||
// Request that the docshell be marked as active.
|
||||
void ForcePaint(uint64_t aLayerObserverEpoch);
|
||||
|
||||
protected:
|
||||
virtual ~TabChild();
|
||||
|
||||
|
@ -661,8 +658,7 @@ protected:
|
|||
virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) override;
|
||||
|
||||
virtual bool RecvSetDocShellIsActive(const bool& aIsActive,
|
||||
const bool& aIsHidden,
|
||||
const uint64_t& aLayerObserverEpoch) override;
|
||||
const bool& aIsHidden) override;
|
||||
|
||||
virtual bool RecvNavigateByKey(const bool& aForward,
|
||||
const bool& aForDocumentNavigation) override;
|
||||
|
@ -782,9 +778,6 @@ private:
|
|||
// dangling pointer.
|
||||
layers::APZChild* mAPZChild;
|
||||
|
||||
// The most recently seen layer observer epoch in RecvSetDocShellIsActive.
|
||||
uint64_t mLayerObserverEpoch;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||
};
|
||||
|
||||
|
|
|
@ -292,13 +292,13 @@ TabParent::TabParent(nsIContentParent* aManager,
|
|||
, mInitedByParent(false)
|
||||
, mTabId(aTabId)
|
||||
, mCreatingWindow(false)
|
||||
, mNeedLayerTreeReadyNotification(false)
|
||||
, mCursor(nsCursor(-1))
|
||||
, mTabSetsCursor(false)
|
||||
, mHasContentOpener(false)
|
||||
#ifdef DEBUG
|
||||
, mActiveSupressDisplayportCount(0)
|
||||
#endif
|
||||
, mLayerTreeEpoch(0)
|
||||
{
|
||||
MOZ_ASSERT(aManager);
|
||||
}
|
||||
|
@ -493,6 +493,13 @@ TabParent::DestroyInternal()
|
|||
if (RenderFrameParent* frame = GetRenderFrame()) {
|
||||
RemoveTabParentFromTable(frame->GetLayersId());
|
||||
frame->Destroy();
|
||||
|
||||
// Notify our layer tree update observer that we're going away. It's
|
||||
// possible that we race with a notification and there can be an
|
||||
// LayerTreeUpdateRunnable on the main thread's event queue with a pointer
|
||||
// to us. However, our actual destruction won't be until yet another event
|
||||
// *after* that one is processed, so this should be safe.
|
||||
mLayerUpdateObserver->TabParentDestroyed();
|
||||
}
|
||||
|
||||
// Let all PluginWidgets know we are tearing down. Prevents
|
||||
|
@ -2273,10 +2280,12 @@ TabParent::GetTabIdFrom(nsIDocShell *docShell)
|
|||
RenderFrameParent*
|
||||
TabParent::GetRenderFrame()
|
||||
{
|
||||
PRenderFrameParent* p = LoneManagedOrNullAsserts(ManagedPRenderFrameParent());
|
||||
RenderFrameParent* frame = static_cast<RenderFrameParent*>(p);
|
||||
if (!mLayerUpdateObserver) {
|
||||
mLayerUpdateObserver = new LayerTreeUpdateObserver(this);
|
||||
}
|
||||
|
||||
return frame;
|
||||
PRenderFrameParent* p = LoneManagedOrNullAsserts(ManagedPRenderFrameParent());
|
||||
return static_cast<RenderFrameParent*>(p);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2627,6 +2636,11 @@ TabParent::SetRenderFrame(PRenderFrameParent* aRFParent)
|
|||
uint64_t layersId = renderFrame->GetLayersId();
|
||||
AddTabParentToTable(layersId, this);
|
||||
|
||||
if (mNeedLayerTreeReadyNotification) {
|
||||
RequestNotifyLayerTreeReady();
|
||||
mNeedLayerTreeReadyNotification = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2871,22 +2885,10 @@ TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
|
|||
NS_IMETHODIMP
|
||||
TabParent::SetDocShellIsActive(bool isActive)
|
||||
{
|
||||
// Increment the epoch so that layer tree updates from previous
|
||||
// SetDocShellIsActive requests are ignored.
|
||||
mLayerTreeEpoch++;
|
||||
|
||||
// docshell is consider prerendered only if not active yet
|
||||
mIsPrerendered &= !isActive;
|
||||
mDocShellIsActive = isActive;
|
||||
Unused << SendSetDocShellIsActive(isActive, true, mLayerTreeEpoch);
|
||||
|
||||
// Ask the child to repaint using the PHangMonitor channel/thread (which may
|
||||
// be less congested).
|
||||
if (isActive) {
|
||||
ContentParent* cp = Manager()->AsContentParent();
|
||||
cp->ForceTabPaint(this, mLayerTreeEpoch);
|
||||
}
|
||||
|
||||
Unused << SendSetDocShellIsActive(isActive, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2910,7 +2912,7 @@ TabParent::SetDocShellIsActiveAndForeground(bool isActive)
|
|||
// docshell is consider prerendered only if not active yet
|
||||
mIsPrerendered &= !isActive;
|
||||
mDocShellIsActive = isActive;
|
||||
Unused << SendSetDocShellIsActive(isActive, false, mLayerTreeEpoch);
|
||||
Unused << SendSetDocShellIsActive(isActive, false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2971,13 +2973,12 @@ TabParent::NavigateByKey(bool aForward, bool aForDocumentNavigation)
|
|||
class LayerTreeUpdateRunnable final
|
||||
: public mozilla::Runnable
|
||||
{
|
||||
uint64_t mLayersId;
|
||||
uint64_t mEpoch;
|
||||
RefPtr<LayerTreeUpdateObserver> mUpdateObserver;
|
||||
bool mActive;
|
||||
|
||||
public:
|
||||
explicit LayerTreeUpdateRunnable(uint64_t aLayersId, uint64_t aEpoch, bool aActive)
|
||||
: mLayersId(aLayersId), mEpoch(aEpoch), mActive(aActive)
|
||||
explicit LayerTreeUpdateRunnable(LayerTreeUpdateObserver* aObs, bool aActive)
|
||||
: mUpdateObserver(aObs), mActive(aActive)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
}
|
||||
|
@ -2985,37 +2986,59 @@ public:
|
|||
private:
|
||||
NS_IMETHOD Run() override {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (RefPtr<TabParent> tabParent = TabParent::GetTabParentFromLayersId(mLayersId)) {
|
||||
tabParent->LayerTreeUpdate(mEpoch, mActive);
|
||||
if (RefPtr<TabParent> tabParent = mUpdateObserver->GetTabParent()) {
|
||||
tabParent->LayerTreeUpdate(mActive);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
TabParent::ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive)
|
||||
void
|
||||
LayerTreeUpdateObserver::ObserveUpdate(uint64_t aLayersId, bool aActive)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
RefPtr<LayerTreeUpdateRunnable> runnable =
|
||||
new LayerTreeUpdateRunnable(aLayersId, aEpoch, aActive);
|
||||
new LayerTreeUpdateRunnable(this, aActive);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::LayerTreeUpdate(uint64_t aEpoch, bool aActive)
|
||||
|
||||
bool
|
||||
TabParent::RequestNotifyLayerTreeReady()
|
||||
{
|
||||
// Ignore updates from old epochs. They might tell us that layers are
|
||||
// available when we've already sent a message to clear them. We can't trust
|
||||
// the update in that case since layers could disappear anytime after that.
|
||||
if (aEpoch != mLayerTreeEpoch || mIsDestroyed) {
|
||||
return;
|
||||
RenderFrameParent* frame = GetRenderFrame();
|
||||
if (!frame || !frame->IsInitted()) {
|
||||
mNeedLayerTreeReadyNotification = true;
|
||||
} else {
|
||||
GPUProcessManager::Get()->RequestNotifyLayerTreeReady(
|
||||
frame->GetLayersId(),
|
||||
mLayerUpdateObserver);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RequestNotifyLayerTreeCleared()
|
||||
{
|
||||
RenderFrameParent* frame = GetRenderFrame();
|
||||
if (!frame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GPUProcessManager::Get()->RequestNotifyLayerTreeCleared(
|
||||
frame->GetLayersId(),
|
||||
mLayerUpdateObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::LayerTreeUpdate(bool aActive)
|
||||
{
|
||||
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
|
||||
if (!target) {
|
||||
NS_WARNING("Could not locate target for layer tree message.");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
|
||||
|
@ -3028,16 +3051,33 @@ TabParent::LayerTreeUpdate(uint64_t aEpoch, bool aActive)
|
|||
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
|
||||
bool dummy;
|
||||
mFrameElement->DispatchEvent(event, &dummy);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvForcePaintNoOp(const uint64_t& aLayerObserverEpoch)
|
||||
void
|
||||
TabParent::SwapLayerTreeObservers(TabParent* aOther)
|
||||
{
|
||||
// We sent a ForcePaint message when layers were already visible. In this
|
||||
// case, we should act as if an update occurred even though we already have
|
||||
// the layers.
|
||||
LayerTreeUpdate(aLayerObserverEpoch, true);
|
||||
return true;
|
||||
if (IsDestroyed() || aOther->IsDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderFrameParent* rfp = GetRenderFrame();
|
||||
RenderFrameParent* otherRfp = aOther->GetRenderFrame();
|
||||
if (!rfp || !otherRfp) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The swap that happens for the observers in GPUProcessManager has to
|
||||
// happen in a lock so that an update being processed on the compositor thread
|
||||
// can't grab the layer update observer for the wrong tab parent.
|
||||
GPUProcessManager::Get()->SwapLayerTreeObservers(
|
||||
rfp->GetLayersId(),
|
||||
otherRfp->GetLayersId());
|
||||
|
||||
// No need for a lock, destruction can only happen on the main thread and we
|
||||
// only read mLayerUpdateObserver::mTabParent on the main thread.
|
||||
Swap(mLayerUpdateObserver, aOther->mLayerUpdateObserver);
|
||||
mLayerUpdateObserver->SwapTabParent(aOther->mLayerUpdateObserver);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -80,6 +80,39 @@ namespace ipc {
|
|||
class StructuredCloneData;
|
||||
} // ipc namespace
|
||||
|
||||
// This observer runs on the compositor thread, so we dispatch a runnable to the
|
||||
// main thread to actually dispatch the event.
|
||||
class LayerTreeUpdateObserver : public layers::CompositorUpdateObserver
|
||||
{
|
||||
public:
|
||||
explicit LayerTreeUpdateObserver(TabParent* aTabParent)
|
||||
: mTabParent(aTabParent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
virtual void ObserveUpdate(uint64_t aLayersId, bool aActive) override;
|
||||
|
||||
virtual void SwapTabParent(LayerTreeUpdateObserver* aOther) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
Swap(mTabParent, aOther->mTabParent);
|
||||
}
|
||||
|
||||
void TabParentDestroyed() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mTabParent = nullptr;
|
||||
}
|
||||
|
||||
TabParent* GetTabParent() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mTabParent;
|
||||
}
|
||||
|
||||
private:
|
||||
// NB: Should never be touched off the main thread!
|
||||
TabParent* mTabParent;
|
||||
};
|
||||
|
||||
class TabParent final : public PBrowserParent
|
||||
, public nsIDOMEventListener
|
||||
, public nsITabParent
|
||||
|
@ -554,8 +587,14 @@ public:
|
|||
bool SendLoadRemoteScript(const nsString& aURL,
|
||||
const bool& aRunInGlobalScope);
|
||||
|
||||
static void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive);
|
||||
void LayerTreeUpdate(uint64_t aEpoch, bool aActive);
|
||||
// See nsIFrameLoader requestNotifyLayerTreeReady.
|
||||
bool RequestNotifyLayerTreeReady();
|
||||
|
||||
bool RequestNotifyLayerTreeCleared();
|
||||
|
||||
bool LayerTreeUpdate(bool aActive);
|
||||
|
||||
void SwapLayerTreeObservers(TabParent* aOther);
|
||||
|
||||
virtual bool
|
||||
RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
|
||||
|
@ -605,8 +644,6 @@ protected:
|
|||
|
||||
virtual bool RecvRemotePaintIsReady() override;
|
||||
|
||||
virtual bool RecvForcePaintNoOp(const uint64_t& aLayerObserverEpoch) override;
|
||||
|
||||
virtual bool RecvSetDimensions(const uint32_t& aFlags,
|
||||
const int32_t& aX, const int32_t& aY,
|
||||
const int32_t& aCx, const int32_t& aCy) override;
|
||||
|
@ -724,6 +761,11 @@ private:
|
|||
// CreateWindow response. Then TabChild loads them immediately.
|
||||
nsTArray<FrameScriptInfo> mDelayedFrameScripts;
|
||||
|
||||
// If the user called RequestNotifyLayerTreeReady and the RenderFrameParent
|
||||
// wasn't ready yet, we set this flag and call RequestNotifyLayerTreeReady
|
||||
// again once the RenderFrameParent arrives.
|
||||
bool mNeedLayerTreeReadyNotification;
|
||||
|
||||
// Cached cursor setting from TabChild. When the cursor is over the tab,
|
||||
// it should take this appearance.
|
||||
nsCursor mCursor;
|
||||
|
@ -754,7 +796,7 @@ private:
|
|||
|
||||
static void RemoveTabParentFromTable(uint64_t aLayersId);
|
||||
|
||||
uint64_t mLayerTreeEpoch;
|
||||
RefPtr<LayerTreeUpdateObserver> mLayerUpdateObserver;
|
||||
|
||||
public:
|
||||
static TabParent* GetTabParentFromLayersId(uint64_t aLayersId);
|
||||
|
|
|
@ -813,7 +813,7 @@ InitJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSContext* aWorkerCx)
|
|||
return false;
|
||||
}
|
||||
|
||||
JS_AddInterruptCallback(aWorkerCx, InterruptCallback);
|
||||
JS_SetInterruptCallback(aWorkerCx, InterruptCallback);
|
||||
|
||||
js::SetCTypesActivityCallback(aWorkerCx, CTypesActivityCallback);
|
||||
|
||||
|
|
|
@ -522,6 +522,24 @@ GPUProcessManager::DeallocateLayerTreeId(uint64_t aLayersId)
|
|||
CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessManager::RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver)
|
||||
{
|
||||
CompositorBridgeParent::RequestNotifyLayerTreeReady(aLayersId, aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessManager::RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver)
|
||||
{
|
||||
CompositorBridgeParent::RequestNotifyLayerTreeCleared(aLayersId, aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessManager::SwapLayerTreeObservers(uint64_t aLayer, uint64_t aOtherLayer)
|
||||
{
|
||||
CompositorBridgeParent::SwapLayerTreeObservers(aLayer, aOtherLayer);
|
||||
}
|
||||
|
||||
bool
|
||||
GPUProcessManager::UpdateRemoteContentController(uint64_t aLayersId,
|
||||
dom::ContentParent* aContentParent,
|
||||
|
|
|
@ -104,6 +104,10 @@ public:
|
|||
// Must run on the content main thread.
|
||||
void DeallocateLayerTreeId(uint64_t aLayersId);
|
||||
|
||||
void RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
|
||||
void RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
|
||||
void SwapLayerTreeObservers(uint64_t aLayer, uint64_t aOtherLayer);
|
||||
|
||||
// Creates a new RemoteContentController for aTabId. Should only be called on
|
||||
// the main thread.
|
||||
//
|
||||
|
|
|
@ -835,12 +835,6 @@ ClientLayerManager::SetNextPaintSyncId(int32_t aSyncId)
|
|||
mForwarder->SetPaintSyncId(aSyncId);
|
||||
}
|
||||
|
||||
void
|
||||
ClientLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
mForwarder->SetLayerObserverEpoch(aLayerObserverEpoch);
|
||||
}
|
||||
|
||||
void
|
||||
ClientLayerManager::AddDidCompositeObserver(DidCompositeObserver* aObserver)
|
||||
{
|
||||
|
|
|
@ -238,8 +238,6 @@ public:
|
|||
|
||||
void SetNextPaintSyncId(int32_t aSyncId);
|
||||
|
||||
void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch);
|
||||
|
||||
class DidCompositeObserver {
|
||||
public:
|
||||
virtual void DidComposite() = 0;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
|
||||
#include "mozilla/DebugOnly.h" // for DebugOnly
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/gfx/2D.h" // for DrawTarget
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/gfx/Rect.h" // for IntSize
|
||||
|
@ -1820,6 +1819,19 @@ CompositorBridgeParent::DeallocateLayerTreeId(uint64_t aId)
|
|||
CompositorLoop()->PostTask(NewRunnableFunction(&EraseLayerState, aId));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CompositorBridgeParent::SwapLayerTreeObservers(uint64_t aLayerId, uint64_t aOtherLayerId)
|
||||
{
|
||||
EnsureLayerTreeMapReady();
|
||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||
NS_ASSERTION(sIndirectLayerTrees.find(aLayerId) != sIndirectLayerTrees.end(),
|
||||
"SwapLayerTrees missing layer 1");
|
||||
NS_ASSERTION(sIndirectLayerTrees.find(aOtherLayerId) != sIndirectLayerTrees.end(),
|
||||
"SwapLayerTrees missing layer 2");
|
||||
std::swap(sIndirectLayerTrees[aLayerId].mLayerTreeReadyObserver,
|
||||
sIndirectLayerTrees[aOtherLayerId].mLayerTreeReadyObserver);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateControllerForLayersId(uint64_t aLayersId,
|
||||
GeckoContentController* aController)
|
||||
|
@ -1896,6 +1908,22 @@ CompositorBridgeParent::PostInsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
|
|||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CompositorBridgeParent::RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver)
|
||||
{
|
||||
EnsureLayerTreeMapReady();
|
||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||
sIndirectLayerTrees[aLayersId].mLayerTreeReadyObserver = aObserver;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CompositorBridgeParent::RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver)
|
||||
{
|
||||
EnsureLayerTreeMapReady();
|
||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||
sIndirectLayerTrees[aLayersId].mLayerTreeClearedObserver = aObserver;
|
||||
}
|
||||
|
||||
widget::PCompositorWidgetParent*
|
||||
CompositorBridgeParent::AllocPCompositorWidgetParent(const CompositorWidgetInitData& aInitData)
|
||||
{
|
||||
|
@ -2500,8 +2528,10 @@ CrossProcessCompositorBridgeParent::ShadowLayersUpdated(
|
|||
mNotifyAfterRemotePaint = false;
|
||||
}
|
||||
|
||||
if (aLayerTree->ShouldParentObserveEpoch()) {
|
||||
dom::TabParent::ObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true);
|
||||
if (state->mLayerTreeReadyObserver) {
|
||||
RefPtr<CompositorUpdateObserver> observer = state->mLayerTreeReadyObserver;
|
||||
state->mLayerTreeReadyObserver = nullptr;
|
||||
observer->ObserveUpdate(id, true);
|
||||
}
|
||||
|
||||
aLayerTree->SetPendingTransactionId(aTransactionId);
|
||||
|
@ -2730,7 +2760,15 @@ CrossProcessCompositorBridgeParent::NotifyClearCachedResources(LayerTransactionP
|
|||
uint64_t id = aLayerTree->GetId();
|
||||
MOZ_ASSERT(id != 0);
|
||||
|
||||
dom::TabParent::ObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), false);
|
||||
RefPtr<CompositorUpdateObserver> observer;
|
||||
{ // scope lock
|
||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||
observer = sIndirectLayerTrees[id].mLayerTreeClearedObserver;
|
||||
sIndirectLayerTrees[id].mLayerTreeClearedObserver = nullptr;
|
||||
}
|
||||
if (observer) {
|
||||
observer->ObserveUpdate(id, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -191,6 +191,17 @@ private:
|
|||
#endif
|
||||
};
|
||||
|
||||
class CompositorUpdateObserver
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorUpdateObserver);
|
||||
|
||||
virtual void ObserveUpdate(uint64_t aLayersId, bool aActive) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~CompositorUpdateObserver() {}
|
||||
};
|
||||
|
||||
class CompositorBridgeParent final : public PCompositorBridgeParent,
|
||||
public ShadowLayersManager,
|
||||
public CompositorBridgeParentIPCAllocator,
|
||||
|
@ -429,6 +440,8 @@ public:
|
|||
LayerTransactionParent* mLayerTree;
|
||||
nsTArray<PluginWindowData> mPluginData;
|
||||
bool mUpdatedPluginDataAvailable;
|
||||
RefPtr<CompositorUpdateObserver> mLayerTreeReadyObserver;
|
||||
RefPtr<CompositorUpdateObserver> mLayerTreeClearedObserver;
|
||||
|
||||
// Number of times the compositor has been reset without having been
|
||||
// acknowledged by the child.
|
||||
|
@ -502,6 +515,10 @@ private:
|
|||
*/
|
||||
static void DeallocateLayerTreeId(uint64_t aId);
|
||||
|
||||
static void RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
|
||||
static void RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
|
||||
static void SwapLayerTreeObservers(uint64_t aLayer, uint64_t aOtherLayer);
|
||||
|
||||
/**
|
||||
* Creates a new RemoteContentController for aTabId. Should only be called on
|
||||
* the main thread.
|
||||
|
|
|
@ -149,8 +149,6 @@ LayerTransactionParent::LayerTransactionParent(LayerManagerComposite* aManager,
|
|||
: mLayerManager(aManager)
|
||||
, mShadowLayersManager(aLayersManager)
|
||||
, mId(aId)
|
||||
, mChildEpoch(0)
|
||||
, mParentEpoch(0)
|
||||
, mPendingTransaction(0)
|
||||
, mPendingCompositorUpdates(0)
|
||||
, mDestroyed(false)
|
||||
|
@ -713,24 +711,6 @@ LayerTransactionParent::RecvUpdate(InfallibleTArray<Edit>&& cset,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LayerTransactionParent::RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch)
|
||||
{
|
||||
mChildEpoch = aLayerObserverEpoch;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LayerTransactionParent::ShouldParentObserveEpoch()
|
||||
{
|
||||
if (mParentEpoch == mChildEpoch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mParentEpoch = mChildEpoch;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LayerTransactionParent::RecvSetTestSampleTime(const TimeStamp& aTime)
|
||||
{
|
||||
|
|
|
@ -60,9 +60,6 @@ public:
|
|||
uint64_t GetId() const { return mId; }
|
||||
Layer* GetRoot() const { return mRoot; }
|
||||
|
||||
uint64_t GetChildEpoch() const { return mChildEpoch; }
|
||||
bool ShouldParentObserveEpoch();
|
||||
|
||||
virtual ShmemAllocator* AsShmemAllocator() override { return this; }
|
||||
|
||||
virtual bool AllocShmem(size_t aSize,
|
||||
|
@ -142,8 +139,6 @@ protected:
|
|||
const mozilla::TimeStamp& aTransactionStart,
|
||||
const int32_t& aPaintSyncId) override;
|
||||
|
||||
virtual bool RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
|
||||
|
||||
virtual bool RecvClearCachedResources() override;
|
||||
virtual bool RecvForceComposite() override;
|
||||
virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) override;
|
||||
|
@ -201,13 +196,6 @@ private:
|
|||
// because the "real tree" is owned by the compositor.
|
||||
uint64_t mId;
|
||||
|
||||
// These fields keep track of the latest epoch values in the child and the
|
||||
// parent. mChildEpoch is the latest epoch value received from the child.
|
||||
// mParentEpoch is the latest epoch value that we have told TabParent about
|
||||
// (via ObserveLayerUpdate).
|
||||
uint64_t mChildEpoch;
|
||||
uint64_t mParentEpoch;
|
||||
|
||||
uint64_t mPendingTransaction;
|
||||
|
||||
// Number of compositor updates we're waiting for the child to
|
||||
|
|
|
@ -70,8 +70,6 @@ parent:
|
|||
bool isRepeatTransaction, TimeStamp transactionStart,
|
||||
int32_t paintSyncId);
|
||||
|
||||
async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
|
||||
|
||||
// Testing APIs
|
||||
|
||||
// Enter test mode, set the sample time to sampleTime, and resample
|
||||
|
|
|
@ -797,15 +797,6 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ShadowLayerForwarder::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
if (!HasShadowManager() || !mShadowManager->IPCOpen()) {
|
||||
return;
|
||||
}
|
||||
Unused << mShadowManager->SendSetLayerObserverEpoch(aLayerObserverEpoch);
|
||||
}
|
||||
|
||||
bool
|
||||
ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize,
|
||||
ipc::SharedMemory::SharedMemoryType aShmType,
|
||||
|
|
|
@ -376,8 +376,6 @@ public:
|
|||
|
||||
void SetPaintSyncId(int32_t aSyncId) { mPaintSyncId = aSyncId; }
|
||||
|
||||
void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch);
|
||||
|
||||
static void PlatformSyncBeforeUpdate();
|
||||
|
||||
virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize,
|
||||
|
|
|
@ -24,7 +24,7 @@ RequestInterruptCallback(JSContext* cx, unsigned argc, jsval* vp)
|
|||
|
||||
BEGIN_TEST(testSlowScript)
|
||||
{
|
||||
JS_AddInterruptCallback(cx, InterruptCallback);
|
||||
JS_SetInterruptCallback(cx, InterruptCallback);
|
||||
JS_DefineFunction(cx, global, "requestInterruptCallback", RequestInterruptCallback, 0, 0);
|
||||
|
||||
test("while (true)"
|
||||
|
|
|
@ -4640,24 +4640,18 @@ JS_CheckForInterrupt(JSContext* cx)
|
|||
return js::CheckForInterrupt(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback)
|
||||
JS_PUBLIC_API(JSInterruptCallback)
|
||||
JS_SetInterruptCallback(JSContext* cx, JSInterruptCallback callback)
|
||||
{
|
||||
return cx->interruptCallbacks.append(callback);
|
||||
JSInterruptCallback old = cx->interruptCallback;
|
||||
cx->interruptCallback = callback;
|
||||
return old;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DisableInterruptCallback(JSContext* cx)
|
||||
JS_PUBLIC_API(JSInterruptCallback)
|
||||
JS_GetInterruptCallback(JSContext* cx)
|
||||
{
|
||||
bool result = cx->interruptCallbackDisabled;
|
||||
cx->interruptCallbackDisabled = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ResetInterruptCallback(JSContext* cx, bool enable)
|
||||
{
|
||||
cx->interruptCallbackDisabled = enable;
|
||||
return cx->interruptCallback;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
@ -4320,14 +4320,11 @@ JS_CheckForInterrupt(JSContext* cx);
|
|||
* if it re-enters the JS engine. The embedding must ensure that the callback
|
||||
* is disconnected before attempting such re-entry.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback);
|
||||
extern JS_PUBLIC_API(JSInterruptCallback)
|
||||
JS_SetInterruptCallback(JSContext* cx, JSInterruptCallback callback);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DisableInterruptCallback(JSContext* cx);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ResetInterruptCallback(JSContext* cx, bool enable);
|
||||
extern JS_PUBLIC_API(JSInterruptCallback)
|
||||
JS_GetInterruptCallback(JSContext* cx);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_RequestInterruptCallback(JSContext* cx);
|
||||
|
|
|
@ -7563,7 +7563,7 @@ main(int argc, char** argv, char** envp)
|
|||
JS_SetSecurityCallbacks(cx, &ShellPrincipals::securityCallbacks);
|
||||
JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
|
||||
|
||||
JS_AddInterruptCallback(cx, ShellInterruptCallback);
|
||||
JS_SetInterruptCallback(cx, ShellInterruptCallback);
|
||||
JS::SetBuildIdOp(cx, ShellBuildId);
|
||||
JS::SetAsmJSCacheOps(cx, &asmJSCacheOps);
|
||||
|
||||
|
|
|
@ -360,9 +360,6 @@ js::RunScript(JSContext* cx, RunState& state)
|
|||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
// Since any script can conceivably GC, make sure it's safe to do so.
|
||||
JS::AutoAssertOnGC::VerifyIsSafeToGC(cx->runtime());
|
||||
|
||||
if (!Debugger::checkNoExecute(cx, state.script()))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
|||
telemetryCallback(nullptr),
|
||||
handlingSegFault(false),
|
||||
handlingJitInterrupt_(false),
|
||||
interruptCallbackDisabled(false),
|
||||
interruptCallback(nullptr),
|
||||
getIncumbentGlobalCallback(nullptr),
|
||||
enqueuePromiseJobCallback(nullptr),
|
||||
enqueuePromiseJobCallbackData(nullptr),
|
||||
|
@ -532,16 +532,11 @@ InvokeInterruptCallback(JSContext* cx)
|
|||
// Important: Additional callbacks can occur inside the callback handler
|
||||
// if it re-enters the JS engine. The embedding must ensure that the
|
||||
// callback is disconnected before attempting such re-entry.
|
||||
if (cx->runtime()->interruptCallbackDisabled)
|
||||
JSInterruptCallback cb = cx->runtime()->interruptCallback;
|
||||
if (!cb)
|
||||
return true;
|
||||
|
||||
bool stop = false;
|
||||
for (JSInterruptCallback cb : cx->runtime()->interruptCallbacks) {
|
||||
if (!cb(cx))
|
||||
stop = true;
|
||||
}
|
||||
|
||||
if (!stop) {
|
||||
if (cb(cx)) {
|
||||
// Debugger treats invoking the interrupt callback as a "step", so
|
||||
// invoke the onStep handler.
|
||||
if (cx->compartment()->isDebuggee()) {
|
||||
|
|
|
@ -631,9 +631,7 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||
return handlingJitInterrupt_;
|
||||
}
|
||||
|
||||
using InterruptCallbackVector = js::Vector<JSInterruptCallback, 2, js::SystemAllocPolicy>;
|
||||
InterruptCallbackVector interruptCallbacks;
|
||||
bool interruptCallbackDisabled;
|
||||
JSInterruptCallback interruptCallback;
|
||||
|
||||
JSGetIncumbentGlobalCallback getIncumbentGlobalCallback;
|
||||
JSEnqueuePromiseJobCallback enqueuePromiseJobCallback;
|
||||
|
|
|
@ -3529,7 +3529,7 @@ XPCJSRuntime::Initialize()
|
|||
#endif
|
||||
JS_SetAccumulateTelemetryCallback(cx, AccumulateTelemetryCallback);
|
||||
js::SetActivityCallback(cx, ActivityCallback, this);
|
||||
JS_AddInterruptCallback(cx, InterruptCallback);
|
||||
JS_SetInterruptCallback(cx, InterruptCallback);
|
||||
js::SetWindowProxyClass(cx, &OuterWindowProxyClass);
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
js::AutoEnterOOMUnsafeRegion::setAnnotateOOMAllocationSizeCallback(
|
||||
|
|
|
@ -1421,7 +1421,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp,
|
|||
sScriptedInterruptCallback = new PersistentRootedValue;
|
||||
sScriptedInterruptCallback->init(cx, UndefinedValue());
|
||||
|
||||
JS_AddInterruptCallback(cx, XPCShellInterruptCallback);
|
||||
JS_SetInterruptCallback(cx, XPCShellInterruptCallback);
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
|
|
@ -572,11 +572,7 @@ var PrintUtils = {
|
|||
|
||||
// Set the original window as an active window so any mozPrintCallbacks can
|
||||
// run without delayed setTimeouts.
|
||||
if (this._listener.activateBrowser) {
|
||||
this._listener.activateBrowser(this._sourceBrowser);
|
||||
} else {
|
||||
this._sourceBrowser.docShellIsActive = true;
|
||||
}
|
||||
this._sourceBrowser.docShellIsActive = true;
|
||||
|
||||
// show the toolbar after we go into print preview mode so
|
||||
// that we can initialize the toolbar with total num pages
|
||||
|
|
|
@ -747,10 +747,6 @@ var PrintPreviewListener = {
|
|||
gBrowser.collapsed = false;
|
||||
document.getElementById("viewSource-toolbox").hidden = false;
|
||||
},
|
||||
|
||||
activateBrowser(browser) {
|
||||
browser.docShellIsActive = true;
|
||||
},
|
||||
};
|
||||
|
||||
// viewZoomOverlay.js uses this
|
||||
|
|
|
@ -1278,11 +1278,6 @@
|
|||
if (aOtherBrowser._remoteFinder)
|
||||
aOtherBrowser._remoteFinder.swapBrowser(aOtherBrowser);
|
||||
}
|
||||
|
||||
event = new CustomEvent("EndSwapDocShells", {"detail": aOtherBrowser});
|
||||
this.dispatchEvent(event);
|
||||
event = new CustomEvent("EndSwapDocShells", {"detail": this});
|
||||
aOtherBrowser.dispatchEvent(event);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -1328,6 +1323,9 @@
|
|||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- This will go away if the binding has been removed for some reason. -->
|
||||
<field name="_alive">true</field>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
|
|
|
@ -1106,14 +1106,6 @@ PuppetWidget::PaintTask::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PuppetWidget::PaintNowIfNeeded()
|
||||
{
|
||||
if (IsVisible() && mPaintTask.IsPending()) {
|
||||
Paint();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(PuppetWidget::MemoryPressureObserver, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -200,9 +200,6 @@ public:
|
|||
|
||||
virtual bool NeedsPaint() override;
|
||||
|
||||
// Paint the widget immediately if any paints are queued up.
|
||||
void PaintNowIfNeeded();
|
||||
|
||||
virtual TabChild* GetOwningTabChild() override { return mTabChild; }
|
||||
|
||||
void UpdateBackingScaleCache(float aDpi, double aScale)
|
||||
|
|
Загрузка…
Ссылка в новой задаче