mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 1279086 - Allow painting for tab switch when JS is running (r=dvander,mconley,mrbkap)
This commit is contained in:
parent
95c5d71549
commit
3799faa926
@ -3300,6 +3300,7 @@ var PrintPreviewListener = {
|
|||||||
this._simplifyPageTab = null;
|
this._simplifyPageTab = null;
|
||||||
}
|
}
|
||||||
gBrowser.removeTab(this._printPreviewTab);
|
gBrowser.removeTab(this._printPreviewTab);
|
||||||
|
gBrowser.deactivatePrintPreviewBrowsers();
|
||||||
this._printPreviewTab = null;
|
this._printPreviewTab = null;
|
||||||
},
|
},
|
||||||
_toggleAffectedChrome: function () {
|
_toggleAffectedChrome: function () {
|
||||||
@ -3355,7 +3356,11 @@ var PrintPreviewListener = {
|
|||||||
|
|
||||||
if (this._chromeState.sidebarOpen)
|
if (this._chromeState.sidebarOpen)
|
||||||
SidebarUI.show(this._sidebarCommand);
|
SidebarUI.show(this._sidebarCommand);
|
||||||
}
|
},
|
||||||
|
|
||||||
|
activateBrowser(browser) {
|
||||||
|
gBrowser.activateBrowserForPrintPreview(browser);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMarkupDocumentViewer()
|
function getMarkupDocumentViewer()
|
||||||
|
@ -1634,8 +1634,7 @@
|
|||||||
// As frameLoaders start out with an active docShell we have to
|
// As frameLoaders start out with an active docShell we have to
|
||||||
// deactivate it if this is not the selected tab's browser or the
|
// deactivate it if this is not the selected tab's browser or the
|
||||||
// browser window is minimized.
|
// browser window is minimized.
|
||||||
aBrowser.docShellIsActive = (aBrowser == this.selectedBrowser &&
|
aBrowser.docShellIsActive = this.shouldActivateDocShell(aBrowser);
|
||||||
window.windowState != window.STATE_MINIMIZED);
|
|
||||||
|
|
||||||
// Create a new tab progress listener for the new browser we just injected,
|
// 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
|
// since tab progress listeners have logic for handling the initial about:blank
|
||||||
@ -2804,8 +2803,11 @@
|
|||||||
remoteBrowser._outerWindowIDBrowserMap.delete(aOtherBrowser.outerWindowID);
|
remoteBrowser._outerWindowIDBrowserMap.delete(aOtherBrowser.outerWindowID);
|
||||||
}
|
}
|
||||||
|
|
||||||
aOtherBrowser.docShellIsActive = (ourBrowser == this.selectedBrowser &&
|
// If switcher is active, it will intercept swap events and
|
||||||
window.windowState != window.STATE_MINIMIZED);
|
// react as needed.
|
||||||
|
if (!this._switcher) {
|
||||||
|
aOtherBrowser.docShellIsActive = this.shouldActivateDocShell(ourBrowser);
|
||||||
|
}
|
||||||
|
|
||||||
// Swap the docshells
|
// Swap the docshells
|
||||||
ourBrowser.swapDocShells(aOtherBrowser);
|
ourBrowser.swapDocShells(aOtherBrowser);
|
||||||
@ -3310,6 +3312,56 @@
|
|||||||
</body>
|
</body>
|
||||||
</method>
|
</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
|
The tab switcher is responsible for asynchronously switching
|
||||||
tabs in e10s. It waits until the new tab is ready (i.e., the
|
tabs in e10s. It waits until the new tab is ready (i.e., the
|
||||||
@ -3341,35 +3393,12 @@
|
|||||||
It's important that we always show either the spinner or a tab
|
It's important that we always show either the spinner or a tab
|
||||||
whose layers are available. Otherwise the compositor will draw
|
whose layers are available. Otherwise the compositor will draw
|
||||||
an entirely black frame, which is very jarring. To ensure this
|
an entirely black frame, which is very jarring. To ensure this
|
||||||
never happens, we do the following:
|
never happens when switching away from a tab, we assume the
|
||||||
|
old tab might still be drawn until a MozAfterPaint event
|
||||||
1. When switching away from a tab, we assume the old tab might
|
occurs. Because layout and compositing happen asynchronously,
|
||||||
still be drawn until a MozAfterPaint event occurs. Because
|
we don't have any other way of knowing when the switch
|
||||||
layout and compositing happen asynchronously, we don't have
|
actually takes place. Therefore, we don't unload the old tab
|
||||||
any other way of knowing when the switch actually takes
|
until the next MozAfterPaint event.
|
||||||
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>
|
<field name="_switcher">null</field>
|
||||||
<method name="_getSwitcher">
|
<method name="_getSwitcher">
|
||||||
@ -3416,11 +3445,6 @@
|
|||||||
// True if we're in the midst of switching tabs.
|
// True if we're in the midst of switching tabs.
|
||||||
switchInProgress: false,
|
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
|
// Set of tabs that might be visible right now. We maintain
|
||||||
// this set because we can't be sure when a tab is actually
|
// 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
|
// drawn. A tab is added to this set when we ask to make it
|
||||||
@ -3462,26 +3486,37 @@
|
|||||||
return state;
|
return state;
|
||||||
},
|
},
|
||||||
|
|
||||||
setTabState: function(tab, state) {
|
setTabStateNoAction(tab, state) {
|
||||||
if (state == this.STATE_UNLOADED) {
|
if (state == this.STATE_UNLOADED) {
|
||||||
this.tabState.delete(tab);
|
this.tabState.delete(tab);
|
||||||
} else {
|
} else {
|
||||||
this.tabState.set(tab, state);
|
this.tabState.set(tab, state);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setTabState: function(tab, state) {
|
||||||
|
this.setTabStateNoAction(tab, state);
|
||||||
|
|
||||||
let browser = tab.linkedBrowser;
|
let browser = tab.linkedBrowser;
|
||||||
let fl = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
let {tabParent} = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
||||||
if (state == this.STATE_LOADING) {
|
if (state == this.STATE_LOADING) {
|
||||||
// Ask for a MozLayerTreeReady event.
|
this.assert(!this.minimized);
|
||||||
fl.requestNotifyLayerTreeReady();
|
|
||||||
browser.docShellIsActive = true;
|
browser.docShellIsActive = true;
|
||||||
|
if (!tabParent) {
|
||||||
|
this.onLayersReady(browser);
|
||||||
|
}
|
||||||
} else if (state == this.STATE_UNLOADING) {
|
} else if (state == this.STATE_UNLOADING) {
|
||||||
// Ask for MozLayerTreeCleared event.
|
|
||||||
fl.requestNotifyLayerTreeCleared();
|
|
||||||
browser.docShellIsActive = false;
|
browser.docShellIsActive = false;
|
||||||
|
if (!tabParent) {
|
||||||
|
this.onLayersCleared(browser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get minimized() {
|
||||||
|
return window.windowState == window.STATE_MINIMIZED;
|
||||||
|
},
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
this.log("START");
|
this.log("START");
|
||||||
|
|
||||||
@ -3489,7 +3524,12 @@
|
|||||||
window.addEventListener("MozLayerTreeReady", this);
|
window.addEventListener("MozLayerTreeReady", this);
|
||||||
window.addEventListener("MozLayerTreeCleared", this);
|
window.addEventListener("MozLayerTreeCleared", this);
|
||||||
window.addEventListener("TabRemotenessChange", this);
|
window.addEventListener("TabRemotenessChange", this);
|
||||||
this.setTabState(this.requestedTab, this.STATE_LOADED);
|
window.addEventListener("sizemodechange", this);
|
||||||
|
window.addEventListener("SwapDocShells", this, true);
|
||||||
|
window.addEventListener("EndSwapDocShells", this, true);
|
||||||
|
if (!this.minimized) {
|
||||||
|
this.setTabState(this.requestedTab, this.STATE_LOADED);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
@ -3506,13 +3546,11 @@
|
|||||||
window.removeEventListener("MozLayerTreeReady", this);
|
window.removeEventListener("MozLayerTreeReady", this);
|
||||||
window.removeEventListener("MozLayerTreeCleared", this);
|
window.removeEventListener("MozLayerTreeCleared", this);
|
||||||
window.removeEventListener("TabRemotenessChange", this);
|
window.removeEventListener("TabRemotenessChange", this);
|
||||||
|
window.removeEventListener("sizemodechange", this);
|
||||||
|
window.removeEventListener("SwapDocShells", this, true);
|
||||||
|
window.removeEventListener("EndSwapDocShells", this, true);
|
||||||
|
|
||||||
this.tabbrowser._switcher = null;
|
this.tabbrowser._switcher = null;
|
||||||
|
|
||||||
this.activeSuppressDisplayport.forEach(function(tabParent) {
|
|
||||||
tabParent.suppressDisplayport(false);
|
|
||||||
});
|
|
||||||
this.activeSuppressDisplayport.clear();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
finish: function() {
|
finish: function() {
|
||||||
@ -3524,7 +3562,7 @@
|
|||||||
this.assert(!this.loadTimer);
|
this.assert(!this.loadTimer);
|
||||||
this.assert(!this.loadingTab);
|
this.assert(!this.loadingTab);
|
||||||
this.assert(this.lastVisibleTab === this.requestedTab);
|
this.assert(this.lastVisibleTab === this.requestedTab);
|
||||||
this.assert(this.getTabState(this.requestedTab) == this.STATE_LOADED);
|
this.assert(this.minimized || this.getTabState(this.requestedTab) == this.STATE_LOADED);
|
||||||
|
|
||||||
this.destroy();
|
this.destroy();
|
||||||
|
|
||||||
@ -3564,7 +3602,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show or hide the spinner as needed.
|
// Show or hide the spinner as needed.
|
||||||
let needSpinner = this.getTabState(showTab) != this.STATE_LOADED;
|
let needSpinner = this.getTabState(showTab) != this.STATE_LOADED && !this.minimized;
|
||||||
if (!needSpinner && this.spinnerTab) {
|
if (!needSpinner && this.spinnerTab) {
|
||||||
this.spinnerHidden();
|
this.spinnerHidden();
|
||||||
this.tabbrowser.removeAttribute("pendingpaint");
|
this.tabbrowser.removeAttribute("pendingpaint");
|
||||||
@ -3619,14 +3657,15 @@
|
|||||||
// We've decided to try to load requestedTab.
|
// We've decided to try to load requestedTab.
|
||||||
loadRequestedTab: function() {
|
loadRequestedTab: function() {
|
||||||
this.assert(!this.loadTimer);
|
this.assert(!this.loadTimer);
|
||||||
|
this.assert(!this.minimized);
|
||||||
|
|
||||||
// loadingTab can be non-null here if we timed out loading the current tab.
|
// 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.
|
// In that case we just overwrite it with a different tab; it's had its chance.
|
||||||
this.loadingTab = this.requestedTab;
|
this.loadingTab = this.requestedTab;
|
||||||
this.log("Loading tab " + this.tinfo(this.loadingTab));
|
this.log("Loading tab " + this.tinfo(this.loadingTab));
|
||||||
|
|
||||||
this.setTabState(this.requestedTab, this.STATE_LOADING);
|
|
||||||
this.loadTimer = this.setTimer(() => this.onLoadTimeout(), this.TAB_SWITCH_TIMEOUT);
|
this.loadTimer = this.setTimer(() => this.onLoadTimeout(), this.TAB_SWITCH_TIMEOUT);
|
||||||
|
this.setTabState(this.requestedTab, this.STATE_LOADING);
|
||||||
},
|
},
|
||||||
|
|
||||||
// This function runs before every event. It fixes up the state
|
// This function runs before every event. It fixes up the state
|
||||||
@ -3671,13 +3710,21 @@
|
|||||||
this.assert(!this.loadingTab || this.loadTimer);
|
this.assert(!this.loadingTab || this.loadTimer);
|
||||||
|
|
||||||
// If we're not loading anything, try loading the requested tab.
|
// If we're not loading anything, try loading the requested tab.
|
||||||
if (!this.loadTimer && this.getTabState(this.requestedTab) == this.STATE_UNLOADED) {
|
let requestedState = this.getTabState(this.requestedTab);
|
||||||
|
if (!this.loadTimer && !this.minimized &&
|
||||||
|
(requestedState == this.STATE_UNLOADED ||
|
||||||
|
requestedState == this.STATE_UNLOADING)) {
|
||||||
this.loadRequestedTab();
|
this.loadRequestedTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
// See how many tabs still have work to do.
|
// See how many tabs still have work to do.
|
||||||
let numPending = 0;
|
let numPending = 0;
|
||||||
for (let [tab, state] of this.tabState) {
|
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) {
|
if (state == this.STATE_LOADED && tab !== this.requestedTab) {
|
||||||
numPending++;
|
numPending++;
|
||||||
}
|
}
|
||||||
@ -3712,6 +3759,10 @@
|
|||||||
|
|
||||||
// Unload any tabs that can be unloaded.
|
// Unload any tabs that can be unloaded.
|
||||||
for (let [tab, state] of this.tabState) {
|
for (let [tab, state] of this.tabState) {
|
||||||
|
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (state == this.STATE_LOADED &&
|
if (state == this.STATE_LOADED &&
|
||||||
!this.maybeVisibleTabs.has(tab) &&
|
!this.maybeVisibleTabs.has(tab) &&
|
||||||
tab !== this.lastVisibleTab &&
|
tab !== this.lastVisibleTab &&
|
||||||
@ -3745,9 +3796,11 @@
|
|||||||
|
|
||||||
// Fires when the layers become available for a tab.
|
// Fires when the layers become available for a tab.
|
||||||
onLayersReady: function(browser) {
|
onLayersReady: function(browser) {
|
||||||
this.logState("onLayersReady");
|
|
||||||
|
|
||||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||||
|
this.logState(`onLayersReady(${tab._tPos})`);
|
||||||
|
|
||||||
|
this.assert(this.getTabState(tab) == this.STATE_LOADING ||
|
||||||
|
this.getTabState(tab) == this.STATE_LOADED);
|
||||||
this.setTabState(tab, this.STATE_LOADED);
|
this.setTabState(tab, this.STATE_LOADED);
|
||||||
|
|
||||||
this.maybeFinishTabSwitch();
|
this.maybeFinishTabSwitch();
|
||||||
@ -3769,10 +3822,11 @@
|
|||||||
|
|
||||||
// Called when we're done clearing the layers for a tab.
|
// Called when we're done clearing the layers for a tab.
|
||||||
onLayersCleared: function(browser) {
|
onLayersCleared: function(browser) {
|
||||||
this.logState("onLayersCleared");
|
|
||||||
|
|
||||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||||
if (tab) {
|
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);
|
this.setTabState(tab, this.STATE_UNLOADED);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3781,7 +3835,7 @@
|
|||||||
// a MozLayerTreeReady notification that we requested may never fire,
|
// a MozLayerTreeReady notification that we requested may never fire,
|
||||||
// so we need to simulate it.
|
// so we need to simulate it.
|
||||||
onRemotenessChange: function(tab) {
|
onRemotenessChange: function(tab) {
|
||||||
this.logState("onRemotenessChange");
|
this.logState(`onRemotenessChange(${tab._tPos}, ${tab.linkedBrowser.isRemoteBrowser})`);
|
||||||
if (!tab.linkedBrowser.isRemoteBrowser) {
|
if (!tab.linkedBrowser.isRemoteBrowser) {
|
||||||
if (this.getTabState(tab) == this.STATE_LOADING) {
|
if (this.getTabState(tab) == this.STATE_LOADING) {
|
||||||
this.onLayersReady(tab.linkedBrowser);
|
this.onLayersReady(tab.linkedBrowser);
|
||||||
@ -3804,34 +3858,98 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
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.
|
// Called when the user asks to switch to a given tab.
|
||||||
requestTab: function(tab) {
|
requestTab: function(tab) {
|
||||||
if (tab === this.requestedTab) {
|
if (tab === this.requestedTab) {
|
||||||
return;
|
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.logState("requestTab " + this.tinfo(tab));
|
||||||
this.startTabSwitch();
|
this.startTabSwitch();
|
||||||
|
|
||||||
this.requestedTab = tab;
|
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();
|
this.preActions();
|
||||||
|
|
||||||
if (this.unloadTimer) {
|
if (this.unloadTimer) {
|
||||||
@ -3863,6 +3981,12 @@
|
|||||||
this.onLayersCleared(event.originalTarget);
|
this.onLayersCleared(event.originalTarget);
|
||||||
} else if (event.type == "TabRemotenessChange") {
|
} else if (event.type == "TabRemotenessChange") {
|
||||||
this.onRemotenessChange(event.target);
|
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();
|
this.postActions();
|
||||||
@ -3946,42 +4070,6 @@
|
|||||||
return this._shouldLog;
|
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) {
|
tinfo: function(tab) {
|
||||||
if (tab) {
|
if (tab) {
|
||||||
return tab._tPos + "(" + tab.linkedBrowser.currentURI.spec + ")";
|
return tab._tPos + "(" + tab.linkedBrowser.currentURI.spec + ")";
|
||||||
@ -4350,7 +4438,7 @@
|
|||||||
case "sizemodechange":
|
case "sizemodechange":
|
||||||
if (aEvent.target == window) {
|
if (aEvent.target == window) {
|
||||||
this.mCurrentBrowser.setDocShellIsActiveAndForeground(
|
this.mCurrentBrowser.setDocShellIsActiveAndForeground(
|
||||||
window.windowState != window.STATE_MINIMIZED);
|
this.shouldActivateDocShell(this.mCurrentBrowser));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1021,8 +1021,6 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRemoteBrowser->SwapLayerTreeObservers(aOther->mRemoteBrowser);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIBrowserDOMWindow> otherBrowserDOMWindow =
|
nsCOMPtr<nsIBrowserDOMWindow> otherBrowserDOMWindow =
|
||||||
aOther->mRemoteBrowser->GetBrowserDOMWindow();
|
aOther->mRemoteBrowser->GetBrowserDOMWindow();
|
||||||
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWindow =
|
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWindow =
|
||||||
@ -3203,46 +3201,6 @@ nsFrameLoader::RequestNotifyAfterRemotePaint()
|
|||||||
return NS_OK;
|
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
|
NS_IMETHODIMP
|
||||||
nsFrameLoader::Print(uint64_t aOuterWindowID,
|
nsFrameLoader::Print(uint64_t aOuterWindowID,
|
||||||
nsIPrintSettings* aPrintSettings,
|
nsIPrintSettings* aPrintSettings,
|
||||||
|
@ -138,14 +138,6 @@ interface nsIFrameLoader : nsISupports
|
|||||||
*/
|
*/
|
||||||
void requestNotifyAfterRemotePaint();
|
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.
|
* Print the current document.
|
||||||
*
|
*
|
||||||
|
@ -5501,3 +5501,12 @@ ContentParent::SendGetFilesResponseAndForget(const nsID& aUUID,
|
|||||||
Unused << SendGetFilesResponse(aUUID, aResult);
|
Unused << SendGetFilesResponse(aUUID, aResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ContentParent::ForceTabPaint(TabParent* aTabParent, uint64_t aLayerObserverEpoch)
|
||||||
|
{
|
||||||
|
if (!mHangMonitorActor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProcessHangMonitor::ForcePaint(mHangMonitorActor, aTabParent, aLayerObserverEpoch);
|
||||||
|
}
|
||||||
|
@ -563,6 +563,9 @@ public:
|
|||||||
|
|
||||||
virtual int32_t Pid() const override;
|
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:
|
protected:
|
||||||
void OnChannelConnected(int32_t pid) override;
|
void OnChannelConnected(int32_t pid) override;
|
||||||
|
|
||||||
|
@ -550,6 +550,11 @@ parent:
|
|||||||
*/
|
*/
|
||||||
async RemotePaintIsReady();
|
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
|
* 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
|
* dimensions has been requested, likely through win.moveTo or resizeTo
|
||||||
@ -721,7 +726,7 @@ child:
|
|||||||
/**
|
/**
|
||||||
* Update the child side docShell active (resource use) state.
|
* Update the child side docShell active (resource use) state.
|
||||||
*/
|
*/
|
||||||
async SetDocShellIsActive(bool aIsActive, bool aIsHidden);
|
async SetDocShellIsActive(bool aIsActive, bool aIsHidden, uint64_t aLayerObserverEpoch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the child that it shouldn't paint the offscreen displayport.
|
* Notify the child that it shouldn't paint the offscreen displayport.
|
||||||
|
@ -40,6 +40,8 @@ child:
|
|||||||
|
|
||||||
async BeginStartingDebugger();
|
async BeginStartingDebugger();
|
||||||
async EndStartingDebugger();
|
async EndStartingDebugger();
|
||||||
|
|
||||||
|
async ForcePaint(TabId tabId, uint64_t aLayerObserverEpoch);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -7,9 +7,13 @@
|
|||||||
#include "mozilla/ProcessHangMonitor.h"
|
#include "mozilla/ProcessHangMonitor.h"
|
||||||
#include "mozilla/ProcessHangMonitorIPC.h"
|
#include "mozilla/ProcessHangMonitorIPC.h"
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "js/GCAPI.h"
|
||||||
|
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/dom/TabChild.h"
|
#include "mozilla/dom/TabChild.h"
|
||||||
#include "mozilla/dom/TabParent.h"
|
#include "mozilla/dom/TabParent.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
@ -96,8 +100,11 @@ class HangMonitorChild
|
|||||||
virtual bool RecvBeginStartingDebugger() override;
|
virtual bool RecvBeginStartingDebugger() override;
|
||||||
virtual bool RecvEndStartingDebugger() override;
|
virtual bool RecvEndStartingDebugger() override;
|
||||||
|
|
||||||
|
virtual bool RecvForcePaint(const TabId& aTabId, const uint64_t& aLayerObserverEpoch) override;
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
|
|
||||||
|
void InterruptCallback();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
static HangMonitorChild* Get() { return sInstance; }
|
static HangMonitorChild* Get() { return sInstance; }
|
||||||
@ -119,6 +126,10 @@ class HangMonitorChild
|
|||||||
bool mTerminateScript;
|
bool mTerminateScript;
|
||||||
bool mStartDebugger;
|
bool mStartDebugger;
|
||||||
bool mFinishedStartingDebugger;
|
bool mFinishedStartingDebugger;
|
||||||
|
bool mForcePaint;
|
||||||
|
TabId mForcePaintTab;
|
||||||
|
uint64_t mForcePaintEpoch;
|
||||||
|
JSContext* mContext;
|
||||||
bool mShutdownDone;
|
bool mShutdownDone;
|
||||||
|
|
||||||
// This field is only accessed on the hang thread.
|
// This field is only accessed on the hang thread.
|
||||||
@ -208,6 +219,8 @@ public:
|
|||||||
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
void ForcePaint(dom::TabParent* aTabParent, uint64_t aLayerObserverEpoch);
|
||||||
|
|
||||||
void TerminateScript();
|
void TerminateScript();
|
||||||
void BeginStartingDebugger();
|
void BeginStartingDebugger();
|
||||||
void EndStartingDebugger();
|
void EndStartingDebugger();
|
||||||
@ -224,6 +237,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool TakeBrowserMinidump(const PluginHangData& aPhd, nsString& aCrashId);
|
bool TakeBrowserMinidump(const PluginHangData& aPhd, nsString& aCrashId);
|
||||||
|
|
||||||
|
void ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch);
|
||||||
|
|
||||||
void ShutdownOnThread();
|
void ShutdownOnThread();
|
||||||
|
|
||||||
const RefPtr<ProcessHangMonitor> mHangMonitor;
|
const RefPtr<ProcessHangMonitor> mHangMonitor;
|
||||||
@ -255,10 +271,12 @@ HangMonitorChild::HangMonitorChild(ProcessHangMonitor* aMonitor)
|
|||||||
mTerminateScript(false),
|
mTerminateScript(false),
|
||||||
mStartDebugger(false),
|
mStartDebugger(false),
|
||||||
mFinishedStartingDebugger(false),
|
mFinishedStartingDebugger(false),
|
||||||
|
mForcePaint(false),
|
||||||
mShutdownDone(false),
|
mShutdownDone(false),
|
||||||
mIPCOpen(true)
|
mIPCOpen(true)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
mContext = danger::GetJSContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
HangMonitorChild::~HangMonitorChild()
|
HangMonitorChild::~HangMonitorChild()
|
||||||
@ -268,6 +286,33 @@ HangMonitorChild::~HangMonitorChild()
|
|||||||
sInstance = nullptr;
|
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
|
void
|
||||||
HangMonitorChild::Shutdown()
|
HangMonitorChild::Shutdown()
|
||||||
{
|
{
|
||||||
@ -331,6 +376,23 @@ HangMonitorChild::RecvEndStartingDebugger()
|
|||||||
return true;
|
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
|
void
|
||||||
HangMonitorChild::Open(Transport* aTransport, ProcessId aPid,
|
HangMonitorChild::Open(Transport* aTransport, ProcessId aPid,
|
||||||
MessageLoop* aIOLoop)
|
MessageLoop* aIOLoop)
|
||||||
@ -524,6 +586,25 @@ HangMonitorParent::ShutdownOnThread()
|
|||||||
mMonitor.Notify();
|
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
|
void
|
||||||
HangMonitorParent::ActorDestroy(ActorDestroyReason aWhy)
|
HangMonitorParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
{
|
{
|
||||||
@ -959,6 +1040,16 @@ HangMonitoredProcess::UserCanceled()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
InterruptCallback(JSContext* cx)
|
||||||
|
{
|
||||||
|
if (HangMonitorChild* child = HangMonitorChild::Get()) {
|
||||||
|
child->InterruptCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ProcessHangMonitor* ProcessHangMonitor::sInstance;
|
ProcessHangMonitor* ProcessHangMonitor::sInstance;
|
||||||
|
|
||||||
ProcessHangMonitor::ProcessHangMonitor()
|
ProcessHangMonitor::ProcessHangMonitor()
|
||||||
@ -1094,6 +1185,9 @@ mozilla::CreateHangMonitorChild(mozilla::ipc::Transport* aTransport,
|
|||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
JSContext* cx = danger::GetJSContext();
|
||||||
|
JS_AddInterruptCallback(cx, InterruptCallback);
|
||||||
|
|
||||||
ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
|
ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
|
||||||
HangMonitorChild* child = new HangMonitorChild(monitor);
|
HangMonitorChild* child = new HangMonitorChild(monitor);
|
||||||
|
|
||||||
@ -1142,3 +1236,13 @@ ProcessHangMonitor::ClearHang()
|
|||||||
child->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,6 +22,7 @@ namespace mozilla {
|
|||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class ContentParent;
|
class ContentParent;
|
||||||
|
class TabParent;
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
||||||
class PProcessHangMonitorParent;
|
class PProcessHangMonitorParent;
|
||||||
@ -45,6 +46,10 @@ class ProcessHangMonitor final
|
|||||||
|
|
||||||
static void ClearHang();
|
static void ClearHang();
|
||||||
|
|
||||||
|
static void ForcePaint(PProcessHangMonitorParent* aParent,
|
||||||
|
dom::TabParent* aTab,
|
||||||
|
uint64_t aLayerObserverEpoch);
|
||||||
|
|
||||||
enum SlowScriptAction {
|
enum SlowScriptAction {
|
||||||
Continue,
|
Continue,
|
||||||
Terminate,
|
Terminate,
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include "nsViewManager.h"
|
||||||
#include "nsWeakReference.h"
|
#include "nsWeakReference.h"
|
||||||
#include "nsWindowWatcher.h"
|
#include "nsWindowWatcher.h"
|
||||||
#include "PermissionMessageUtils.h"
|
#include "PermissionMessageUtils.h"
|
||||||
@ -544,6 +545,7 @@ TabChild::TabChild(nsIContentChild* aManager,
|
|||||||
, mDidSetRealShowInfo(false)
|
, mDidSetRealShowInfo(false)
|
||||||
, mDidLoadURLInit(false)
|
, mDidLoadURLInit(false)
|
||||||
, mAPZChild(nullptr)
|
, mAPZChild(nullptr)
|
||||||
|
, mLayerObserverEpoch(0)
|
||||||
{
|
{
|
||||||
// In the general case having the TabParent tell us if APZ is enabled or not
|
// 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
|
// doesn't really work because the TabParent itself may not have a reference
|
||||||
@ -2583,19 +2585,75 @@ TabChild::RecvSetUpdateHitRegion(const bool& aEnabled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TabChild::RecvSetDocShellIsActive(const bool& aIsActive, const bool& aIsHidden)
|
TabChild::RecvSetDocShellIsActive(const bool& aIsActive, const bool& aIsHidden, const uint64_t& aLayerObserverEpoch)
|
||||||
{
|
{
|
||||||
// docshell is consider prerendered only if not active yet
|
// Since SetDocShellIsActive requests come in from both the hang monitor
|
||||||
mIsPrerendered &= !aIsActive;
|
// channel and the PContent channel, we have an ordering problem. This code
|
||||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
// ensures that we respect the order in which the requests were made and
|
||||||
if (docShell) {
|
// ignore stale requests.
|
||||||
if (aIsHidden) {
|
if (mLayerObserverEpoch > aLayerObserverEpoch) {
|
||||||
docShell->SetIsActive(aIsActive);
|
return true;
|
||||||
} else {
|
}
|
||||||
docShell->SetIsActiveAndForeground(aIsActive);
|
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;
|
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();
|
||||||
|
} else {
|
||||||
|
RefPtr<nsViewManager> vm = presShell->GetViewManager();
|
||||||
|
if (nsView* view = vm->GetRootView()) {
|
||||||
|
presShell->Paint(view, view->GetBounds(),
|
||||||
|
nsIPresShell::PAINT_LAYERS |
|
||||||
|
nsIPresShell::PAINT_SYNC_DECODE_IMAGES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
APZCCallbackHelper::SuppressDisplayport(false, presShell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -2816,6 +2874,10 @@ TabChild::NotifyPainted()
|
|||||||
void
|
void
|
||||||
TabChild::MakeVisible()
|
TabChild::MakeVisible()
|
||||||
{
|
{
|
||||||
|
if (mPuppetWidget && mPuppetWidget->IsVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mPuppetWidget) {
|
if (mPuppetWidget) {
|
||||||
mPuppetWidget->Show(true);
|
mPuppetWidget->Show(true);
|
||||||
}
|
}
|
||||||
@ -2824,6 +2886,10 @@ TabChild::MakeVisible()
|
|||||||
void
|
void
|
||||||
TabChild::MakeHidden()
|
TabChild::MakeHidden()
|
||||||
{
|
{
|
||||||
|
if (mPuppetWidget && !mPuppetWidget->IsVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
|
CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
|
||||||
|
|
||||||
// Clear cached resources directly. This avoids one extra IPC
|
// Clear cached resources directly. This avoids one extra IPC
|
||||||
@ -3182,6 +3248,13 @@ TabChild::GetOuterRect()
|
|||||||
return ViewAs<ScreenPixel>(outerRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
|
return ViewAs<ScreenPixel>(outerRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TabChild::ForcePaint(uint64_t aLayerObserverEpoch)
|
||||||
|
{
|
||||||
|
nsAutoScriptBlocker scriptBlocker;
|
||||||
|
RecvSetDocShellIsActive(true, false, aLayerObserverEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
|
TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
|
||||||
: mTabChild(aTabChild)
|
: mTabChild(aTabChild)
|
||||||
{
|
{
|
||||||
|
@ -646,6 +646,9 @@ public:
|
|||||||
mAPZChild = aAPZChild;
|
mAPZChild = aAPZChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Request that the docshell be marked as active.
|
||||||
|
void ForcePaint(uint64_t aLayerObserverEpoch);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~TabChild();
|
virtual ~TabChild();
|
||||||
|
|
||||||
@ -658,7 +661,8 @@ protected:
|
|||||||
virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) override;
|
virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) override;
|
||||||
|
|
||||||
virtual bool RecvSetDocShellIsActive(const bool& aIsActive,
|
virtual bool RecvSetDocShellIsActive(const bool& aIsActive,
|
||||||
const bool& aIsHidden) override;
|
const bool& aIsHidden,
|
||||||
|
const uint64_t& aLayerObserverEpoch) override;
|
||||||
|
|
||||||
virtual bool RecvNavigateByKey(const bool& aForward,
|
virtual bool RecvNavigateByKey(const bool& aForward,
|
||||||
const bool& aForDocumentNavigation) override;
|
const bool& aForDocumentNavigation) override;
|
||||||
@ -778,6 +782,9 @@ private:
|
|||||||
// dangling pointer.
|
// dangling pointer.
|
||||||
layers::APZChild* mAPZChild;
|
layers::APZChild* mAPZChild;
|
||||||
|
|
||||||
|
// The most recently seen layer observer epoch in RecvSetDocShellIsActive.
|
||||||
|
uint64_t mLayerObserverEpoch;
|
||||||
|
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -292,13 +292,13 @@ TabParent::TabParent(nsIContentParent* aManager,
|
|||||||
, mInitedByParent(false)
|
, mInitedByParent(false)
|
||||||
, mTabId(aTabId)
|
, mTabId(aTabId)
|
||||||
, mCreatingWindow(false)
|
, mCreatingWindow(false)
|
||||||
, mNeedLayerTreeReadyNotification(false)
|
|
||||||
, mCursor(nsCursor(-1))
|
, mCursor(nsCursor(-1))
|
||||||
, mTabSetsCursor(false)
|
, mTabSetsCursor(false)
|
||||||
, mHasContentOpener(false)
|
, mHasContentOpener(false)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
, mActiveSupressDisplayportCount(0)
|
, mActiveSupressDisplayportCount(0)
|
||||||
#endif
|
#endif
|
||||||
|
, mLayerTreeEpoch(0)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aManager);
|
MOZ_ASSERT(aManager);
|
||||||
}
|
}
|
||||||
@ -493,13 +493,6 @@ TabParent::DestroyInternal()
|
|||||||
if (RenderFrameParent* frame = GetRenderFrame()) {
|
if (RenderFrameParent* frame = GetRenderFrame()) {
|
||||||
RemoveTabParentFromTable(frame->GetLayersId());
|
RemoveTabParentFromTable(frame->GetLayersId());
|
||||||
frame->Destroy();
|
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
|
// Let all PluginWidgets know we are tearing down. Prevents
|
||||||
@ -2280,12 +2273,10 @@ TabParent::GetTabIdFrom(nsIDocShell *docShell)
|
|||||||
RenderFrameParent*
|
RenderFrameParent*
|
||||||
TabParent::GetRenderFrame()
|
TabParent::GetRenderFrame()
|
||||||
{
|
{
|
||||||
if (!mLayerUpdateObserver) {
|
|
||||||
mLayerUpdateObserver = new LayerTreeUpdateObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRenderFrameParent* p = LoneManagedOrNullAsserts(ManagedPRenderFrameParent());
|
PRenderFrameParent* p = LoneManagedOrNullAsserts(ManagedPRenderFrameParent());
|
||||||
return static_cast<RenderFrameParent*>(p);
|
RenderFrameParent* frame = static_cast<RenderFrameParent*>(p);
|
||||||
|
|
||||||
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -2636,11 +2627,6 @@ TabParent::SetRenderFrame(PRenderFrameParent* aRFParent)
|
|||||||
uint64_t layersId = renderFrame->GetLayersId();
|
uint64_t layersId = renderFrame->GetLayersId();
|
||||||
AddTabParentToTable(layersId, this);
|
AddTabParentToTable(layersId, this);
|
||||||
|
|
||||||
if (mNeedLayerTreeReadyNotification) {
|
|
||||||
RequestNotifyLayerTreeReady();
|
|
||||||
mNeedLayerTreeReadyNotification = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2885,10 +2871,22 @@ TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
TabParent::SetDocShellIsActive(bool isActive)
|
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
|
// docshell is consider prerendered only if not active yet
|
||||||
mIsPrerendered &= !isActive;
|
mIsPrerendered &= !isActive;
|
||||||
mDocShellIsActive = isActive;
|
mDocShellIsActive = isActive;
|
||||||
Unused << SendSetDocShellIsActive(isActive, true);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2912,7 +2910,7 @@ TabParent::SetDocShellIsActiveAndForeground(bool isActive)
|
|||||||
// docshell is consider prerendered only if not active yet
|
// docshell is consider prerendered only if not active yet
|
||||||
mIsPrerendered &= !isActive;
|
mIsPrerendered &= !isActive;
|
||||||
mDocShellIsActive = isActive;
|
mDocShellIsActive = isActive;
|
||||||
Unused << SendSetDocShellIsActive(isActive, false);
|
Unused << SendSetDocShellIsActive(isActive, false, mLayerTreeEpoch);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2973,12 +2971,13 @@ TabParent::NavigateByKey(bool aForward, bool aForDocumentNavigation)
|
|||||||
class LayerTreeUpdateRunnable final
|
class LayerTreeUpdateRunnable final
|
||||||
: public mozilla::Runnable
|
: public mozilla::Runnable
|
||||||
{
|
{
|
||||||
RefPtr<LayerTreeUpdateObserver> mUpdateObserver;
|
uint64_t mLayersId;
|
||||||
|
uint64_t mEpoch;
|
||||||
bool mActive;
|
bool mActive;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LayerTreeUpdateRunnable(LayerTreeUpdateObserver* aObs, bool aActive)
|
explicit LayerTreeUpdateRunnable(uint64_t aLayersId, uint64_t aEpoch, bool aActive)
|
||||||
: mUpdateObserver(aObs), mActive(aActive)
|
: mLayersId(aLayersId), mEpoch(aEpoch), mActive(aActive)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
}
|
}
|
||||||
@ -2986,59 +2985,37 @@ public:
|
|||||||
private:
|
private:
|
||||||
NS_IMETHOD Run() override {
|
NS_IMETHOD Run() override {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (RefPtr<TabParent> tabParent = mUpdateObserver->GetTabParent()) {
|
if (RefPtr<TabParent> tabParent = TabParent::GetTabParentFromLayersId(mLayersId)) {
|
||||||
tabParent->LayerTreeUpdate(mActive);
|
tabParent->LayerTreeUpdate(mEpoch, mActive);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
/* static */ void
|
||||||
LayerTreeUpdateObserver::ObserveUpdate(uint64_t aLayersId, bool aActive)
|
TabParent::ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
RefPtr<LayerTreeUpdateRunnable> runnable =
|
RefPtr<LayerTreeUpdateRunnable> runnable =
|
||||||
new LayerTreeUpdateRunnable(this, aActive);
|
new LayerTreeUpdateRunnable(aLayersId, aEpoch, aActive);
|
||||||
NS_DispatchToMainThread(runnable);
|
NS_DispatchToMainThread(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
bool
|
TabParent::LayerTreeUpdate(uint64_t aEpoch, bool aActive)
|
||||||
TabParent::RequestNotifyLayerTreeReady()
|
|
||||||
{
|
{
|
||||||
RenderFrameParent* frame = GetRenderFrame();
|
// Ignore updates from old epochs. They might tell us that layers are
|
||||||
if (!frame || !frame->IsInitted()) {
|
// available when we've already sent a message to clear them. We can't trust
|
||||||
mNeedLayerTreeReadyNotification = true;
|
// the update in that case since layers could disappear anytime after that.
|
||||||
} else {
|
if (aEpoch != mLayerTreeEpoch || mIsDestroyed) {
|
||||||
GPUProcessManager::Get()->RequestNotifyLayerTreeReady(
|
return;
|
||||||
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);
|
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
NS_WARNING("Could not locate target for layer tree message.");
|
NS_WARNING("Could not locate target for layer tree message.");
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
|
RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
|
||||||
@ -3051,33 +3028,16 @@ TabParent::LayerTreeUpdate(bool aActive)
|
|||||||
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
|
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
|
||||||
bool dummy;
|
bool dummy;
|
||||||
mFrameElement->DispatchEvent(event, &dummy);
|
mFrameElement->DispatchEvent(event, &dummy);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
TabParent::SwapLayerTreeObservers(TabParent* aOther)
|
TabParent::RecvForcePaintNoOp(const uint64_t& aLayerObserverEpoch)
|
||||||
{
|
{
|
||||||
if (IsDestroyed() || aOther->IsDestroyed()) {
|
// We sent a ForcePaint message when layers were already visible. In this
|
||||||
return;
|
// case, we should act as if an update occurred even though we already have
|
||||||
}
|
// the layers.
|
||||||
|
LayerTreeUpdate(aLayerObserverEpoch, true);
|
||||||
RenderFrameParent* rfp = GetRenderFrame();
|
return true;
|
||||||
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
|
bool
|
||||||
|
@ -80,39 +80,6 @@ namespace ipc {
|
|||||||
class StructuredCloneData;
|
class StructuredCloneData;
|
||||||
} // ipc namespace
|
} // 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
|
class TabParent final : public PBrowserParent
|
||||||
, public nsIDOMEventListener
|
, public nsIDOMEventListener
|
||||||
, public nsITabParent
|
, public nsITabParent
|
||||||
@ -587,14 +554,8 @@ public:
|
|||||||
bool SendLoadRemoteScript(const nsString& aURL,
|
bool SendLoadRemoteScript(const nsString& aURL,
|
||||||
const bool& aRunInGlobalScope);
|
const bool& aRunInGlobalScope);
|
||||||
|
|
||||||
// See nsIFrameLoader requestNotifyLayerTreeReady.
|
static void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive);
|
||||||
bool RequestNotifyLayerTreeReady();
|
void LayerTreeUpdate(uint64_t aEpoch, bool aActive);
|
||||||
|
|
||||||
bool RequestNotifyLayerTreeCleared();
|
|
||||||
|
|
||||||
bool LayerTreeUpdate(bool aActive);
|
|
||||||
|
|
||||||
void SwapLayerTreeObservers(TabParent* aOther);
|
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
|
RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
|
||||||
@ -644,6 +605,8 @@ protected:
|
|||||||
|
|
||||||
virtual bool RecvRemotePaintIsReady() override;
|
virtual bool RecvRemotePaintIsReady() override;
|
||||||
|
|
||||||
|
virtual bool RecvForcePaintNoOp(const uint64_t& aLayerObserverEpoch) override;
|
||||||
|
|
||||||
virtual bool RecvSetDimensions(const uint32_t& aFlags,
|
virtual bool RecvSetDimensions(const uint32_t& aFlags,
|
||||||
const int32_t& aX, const int32_t& aY,
|
const int32_t& aX, const int32_t& aY,
|
||||||
const int32_t& aCx, const int32_t& aCy) override;
|
const int32_t& aCx, const int32_t& aCy) override;
|
||||||
@ -761,11 +724,6 @@ private:
|
|||||||
// CreateWindow response. Then TabChild loads them immediately.
|
// CreateWindow response. Then TabChild loads them immediately.
|
||||||
nsTArray<FrameScriptInfo> mDelayedFrameScripts;
|
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,
|
// Cached cursor setting from TabChild. When the cursor is over the tab,
|
||||||
// it should take this appearance.
|
// it should take this appearance.
|
||||||
nsCursor mCursor;
|
nsCursor mCursor;
|
||||||
@ -796,7 +754,7 @@ private:
|
|||||||
|
|
||||||
static void RemoveTabParentFromTable(uint64_t aLayersId);
|
static void RemoveTabParentFromTable(uint64_t aLayersId);
|
||||||
|
|
||||||
RefPtr<LayerTreeUpdateObserver> mLayerUpdateObserver;
|
uint64_t mLayerTreeEpoch;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TabParent* GetTabParentFromLayersId(uint64_t aLayersId);
|
static TabParent* GetTabParentFromLayersId(uint64_t aLayersId);
|
||||||
|
@ -511,24 +511,6 @@ GPUProcessManager::DeallocateLayerTreeId(uint64_t aLayersId)
|
|||||||
CompositorBridgeParent::DeallocateLayerTreeId(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
|
bool
|
||||||
GPUProcessManager::UpdateRemoteContentController(uint64_t aLayersId,
|
GPUProcessManager::UpdateRemoteContentController(uint64_t aLayersId,
|
||||||
dom::ContentParent* aContentParent,
|
dom::ContentParent* aContentParent,
|
||||||
|
@ -104,10 +104,6 @@ public:
|
|||||||
// Must run on the content main thread.
|
// Must run on the content main thread.
|
||||||
void DeallocateLayerTreeId(uint64_t aLayersId);
|
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
|
// Creates a new RemoteContentController for aTabId. Should only be called on
|
||||||
// the main thread.
|
// the main thread.
|
||||||
//
|
//
|
||||||
|
@ -835,6 +835,12 @@ ClientLayerManager::SetNextPaintSyncId(int32_t aSyncId)
|
|||||||
mForwarder->SetPaintSyncId(aSyncId);
|
mForwarder->SetPaintSyncId(aSyncId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
|
||||||
|
{
|
||||||
|
mForwarder->SetLayerObserverEpoch(aLayerObserverEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClientLayerManager::AddDidCompositeObserver(DidCompositeObserver* aObserver)
|
ClientLayerManager::AddDidCompositeObserver(DidCompositeObserver* aObserver)
|
||||||
{
|
{
|
||||||
|
@ -238,6 +238,8 @@ public:
|
|||||||
|
|
||||||
void SetNextPaintSyncId(int32_t aSyncId);
|
void SetNextPaintSyncId(int32_t aSyncId);
|
||||||
|
|
||||||
|
void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch);
|
||||||
|
|
||||||
class DidCompositeObserver {
|
class DidCompositeObserver {
|
||||||
public:
|
public:
|
||||||
virtual void DidComposite() = 0;
|
virtual void DidComposite() = 0;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
|
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
|
||||||
#include "mozilla/DebugOnly.h" // for DebugOnly
|
#include "mozilla/DebugOnly.h" // for DebugOnly
|
||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
|
#include "mozilla/dom/TabParent.h"
|
||||||
#include "mozilla/gfx/2D.h" // for DrawTarget
|
#include "mozilla/gfx/2D.h" // for DrawTarget
|
||||||
#include "mozilla/gfx/Point.h" // for IntSize
|
#include "mozilla/gfx/Point.h" // for IntSize
|
||||||
#include "mozilla/gfx/Rect.h" // for IntSize
|
#include "mozilla/gfx/Rect.h" // for IntSize
|
||||||
@ -1819,19 +1820,6 @@ CompositorBridgeParent::DeallocateLayerTreeId(uint64_t aId)
|
|||||||
CompositorLoop()->PostTask(NewRunnableFunction(&EraseLayerState, 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
|
static void
|
||||||
UpdateControllerForLayersId(uint64_t aLayersId,
|
UpdateControllerForLayersId(uint64_t aLayersId,
|
||||||
GeckoContentController* aController)
|
GeckoContentController* aController)
|
||||||
@ -1908,22 +1896,6 @@ 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*
|
widget::PCompositorWidgetParent*
|
||||||
CompositorBridgeParent::AllocPCompositorWidgetParent(const CompositorWidgetInitData& aInitData)
|
CompositorBridgeParent::AllocPCompositorWidgetParent(const CompositorWidgetInitData& aInitData)
|
||||||
{
|
{
|
||||||
@ -2528,10 +2500,8 @@ CrossProcessCompositorBridgeParent::ShadowLayersUpdated(
|
|||||||
mNotifyAfterRemotePaint = false;
|
mNotifyAfterRemotePaint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->mLayerTreeReadyObserver) {
|
if (aLayerTree->ShouldParentObserveEpoch()) {
|
||||||
RefPtr<CompositorUpdateObserver> observer = state->mLayerTreeReadyObserver;
|
dom::TabParent::ObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true);
|
||||||
state->mLayerTreeReadyObserver = nullptr;
|
|
||||||
observer->ObserveUpdate(id, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aLayerTree->SetPendingTransactionId(aTransactionId);
|
aLayerTree->SetPendingTransactionId(aTransactionId);
|
||||||
@ -2760,15 +2730,7 @@ CrossProcessCompositorBridgeParent::NotifyClearCachedResources(LayerTransactionP
|
|||||||
uint64_t id = aLayerTree->GetId();
|
uint64_t id = aLayerTree->GetId();
|
||||||
MOZ_ASSERT(id != 0);
|
MOZ_ASSERT(id != 0);
|
||||||
|
|
||||||
RefPtr<CompositorUpdateObserver> observer;
|
dom::TabParent::ObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), false);
|
||||||
{ // scope lock
|
|
||||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
||||||
observer = sIndirectLayerTrees[id].mLayerTreeClearedObserver;
|
|
||||||
sIndirectLayerTrees[id].mLayerTreeClearedObserver = nullptr;
|
|
||||||
}
|
|
||||||
if (observer) {
|
|
||||||
observer->ObserveUpdate(id, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -191,17 +191,6 @@ private:
|
|||||||
#endif
|
#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,
|
class CompositorBridgeParent final : public PCompositorBridgeParent,
|
||||||
public ShadowLayersManager,
|
public ShadowLayersManager,
|
||||||
public CompositorBridgeParentIPCAllocator,
|
public CompositorBridgeParentIPCAllocator,
|
||||||
@ -440,8 +429,6 @@ public:
|
|||||||
LayerTransactionParent* mLayerTree;
|
LayerTransactionParent* mLayerTree;
|
||||||
nsTArray<PluginWindowData> mPluginData;
|
nsTArray<PluginWindowData> mPluginData;
|
||||||
bool mUpdatedPluginDataAvailable;
|
bool mUpdatedPluginDataAvailable;
|
||||||
RefPtr<CompositorUpdateObserver> mLayerTreeReadyObserver;
|
|
||||||
RefPtr<CompositorUpdateObserver> mLayerTreeClearedObserver;
|
|
||||||
|
|
||||||
// Number of times the compositor has been reset without having been
|
// Number of times the compositor has been reset without having been
|
||||||
// acknowledged by the child.
|
// acknowledged by the child.
|
||||||
@ -515,10 +502,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
static void DeallocateLayerTreeId(uint64_t aId);
|
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
|
* Creates a new RemoteContentController for aTabId. Should only be called on
|
||||||
* the main thread.
|
* the main thread.
|
||||||
|
@ -149,6 +149,8 @@ LayerTransactionParent::LayerTransactionParent(LayerManagerComposite* aManager,
|
|||||||
: mLayerManager(aManager)
|
: mLayerManager(aManager)
|
||||||
, mShadowLayersManager(aLayersManager)
|
, mShadowLayersManager(aLayersManager)
|
||||||
, mId(aId)
|
, mId(aId)
|
||||||
|
, mChildEpoch(0)
|
||||||
|
, mParentEpoch(0)
|
||||||
, mPendingTransaction(0)
|
, mPendingTransaction(0)
|
||||||
, mPendingCompositorUpdates(0)
|
, mPendingCompositorUpdates(0)
|
||||||
, mDestroyed(false)
|
, mDestroyed(false)
|
||||||
@ -711,6 +713,24 @@ LayerTransactionParent::RecvUpdate(InfallibleTArray<Edit>&& cset,
|
|||||||
return true;
|
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
|
bool
|
||||||
LayerTransactionParent::RecvSetTestSampleTime(const TimeStamp& aTime)
|
LayerTransactionParent::RecvSetTestSampleTime(const TimeStamp& aTime)
|
||||||
{
|
{
|
||||||
|
@ -60,6 +60,9 @@ public:
|
|||||||
uint64_t GetId() const { return mId; }
|
uint64_t GetId() const { return mId; }
|
||||||
Layer* GetRoot() const { return mRoot; }
|
Layer* GetRoot() const { return mRoot; }
|
||||||
|
|
||||||
|
uint64_t GetChildEpoch() const { return mChildEpoch; }
|
||||||
|
bool ShouldParentObserveEpoch();
|
||||||
|
|
||||||
virtual ShmemAllocator* AsShmemAllocator() override { return this; }
|
virtual ShmemAllocator* AsShmemAllocator() override { return this; }
|
||||||
|
|
||||||
virtual bool AllocShmem(size_t aSize,
|
virtual bool AllocShmem(size_t aSize,
|
||||||
@ -139,6 +142,8 @@ protected:
|
|||||||
const mozilla::TimeStamp& aTransactionStart,
|
const mozilla::TimeStamp& aTransactionStart,
|
||||||
const int32_t& aPaintSyncId) override;
|
const int32_t& aPaintSyncId) override;
|
||||||
|
|
||||||
|
virtual bool RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
|
||||||
|
|
||||||
virtual bool RecvClearCachedResources() override;
|
virtual bool RecvClearCachedResources() override;
|
||||||
virtual bool RecvForceComposite() override;
|
virtual bool RecvForceComposite() override;
|
||||||
virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) override;
|
virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) override;
|
||||||
@ -196,6 +201,13 @@ private:
|
|||||||
// because the "real tree" is owned by the compositor.
|
// because the "real tree" is owned by the compositor.
|
||||||
uint64_t mId;
|
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;
|
uint64_t mPendingTransaction;
|
||||||
|
|
||||||
// Number of compositor updates we're waiting for the child to
|
// Number of compositor updates we're waiting for the child to
|
||||||
|
@ -70,6 +70,8 @@ parent:
|
|||||||
bool isRepeatTransaction, TimeStamp transactionStart,
|
bool isRepeatTransaction, TimeStamp transactionStart,
|
||||||
int32_t paintSyncId);
|
int32_t paintSyncId);
|
||||||
|
|
||||||
|
async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
|
||||||
|
|
||||||
// Testing APIs
|
// Testing APIs
|
||||||
|
|
||||||
// Enter test mode, set the sample time to sampleTime, and resample
|
// Enter test mode, set the sample time to sampleTime, and resample
|
||||||
|
@ -797,6 +797,15 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ShadowLayerForwarder::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
|
||||||
|
{
|
||||||
|
if (!HasShadowManager() || !mShadowManager->IPCOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Unused << mShadowManager->SendSetLayerObserverEpoch(aLayerObserverEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize,
|
ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize,
|
||||||
ipc::SharedMemory::SharedMemoryType aShmType,
|
ipc::SharedMemory::SharedMemoryType aShmType,
|
||||||
|
@ -376,6 +376,8 @@ public:
|
|||||||
|
|
||||||
void SetPaintSyncId(int32_t aSyncId) { mPaintSyncId = aSyncId; }
|
void SetPaintSyncId(int32_t aSyncId) { mPaintSyncId = aSyncId; }
|
||||||
|
|
||||||
|
void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch);
|
||||||
|
|
||||||
static void PlatformSyncBeforeUpdate();
|
static void PlatformSyncBeforeUpdate();
|
||||||
|
|
||||||
virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize,
|
virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize,
|
||||||
|
@ -360,6 +360,9 @@ js::RunScript(JSContext* cx, RunState& state)
|
|||||||
{
|
{
|
||||||
JS_CHECK_RECURSION(cx, return false);
|
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()))
|
if (!Debugger::checkNoExecute(cx, state.script()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -572,7 +572,11 @@ var PrintUtils = {
|
|||||||
|
|
||||||
// Set the original window as an active window so any mozPrintCallbacks can
|
// Set the original window as an active window so any mozPrintCallbacks can
|
||||||
// run without delayed setTimeouts.
|
// run without delayed setTimeouts.
|
||||||
this._sourceBrowser.docShellIsActive = true;
|
if (this._listener.activateBrowser) {
|
||||||
|
this._listener.activateBrowser(this._sourceBrowser);
|
||||||
|
} else {
|
||||||
|
this._sourceBrowser.docShellIsActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
// show the toolbar after we go into print preview mode so
|
// show the toolbar after we go into print preview mode so
|
||||||
// that we can initialize the toolbar with total num pages
|
// that we can initialize the toolbar with total num pages
|
||||||
|
@ -747,6 +747,10 @@ var PrintPreviewListener = {
|
|||||||
gBrowser.collapsed = false;
|
gBrowser.collapsed = false;
|
||||||
document.getElementById("viewSource-toolbox").hidden = false;
|
document.getElementById("viewSource-toolbox").hidden = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
activateBrowser(browser) {
|
||||||
|
browser.docShellIsActive = true;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// viewZoomOverlay.js uses this
|
// viewZoomOverlay.js uses this
|
||||||
|
@ -1278,6 +1278,11 @@
|
|||||||
if (aOtherBrowser._remoteFinder)
|
if (aOtherBrowser._remoteFinder)
|
||||||
aOtherBrowser._remoteFinder.swapBrowser(aOtherBrowser);
|
aOtherBrowser._remoteFinder.swapBrowser(aOtherBrowser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event = new CustomEvent("EndSwapDocShells", {"detail": aOtherBrowser});
|
||||||
|
this.dispatchEvent(event);
|
||||||
|
event = new CustomEvent("EndSwapDocShells", {"detail": this});
|
||||||
|
aOtherBrowser.dispatchEvent(event);
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
@ -1323,9 +1328,6 @@
|
|||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<!-- This will go away if the binding has been removed for some reason. -->
|
|
||||||
<field name="_alive">true</field>
|
|
||||||
</implementation>
|
</implementation>
|
||||||
|
|
||||||
<handlers>
|
<handlers>
|
||||||
|
@ -1107,6 +1107,14 @@ PuppetWidget::PaintTask::Run()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PuppetWidget::PaintNowIfNeeded()
|
||||||
|
{
|
||||||
|
if (IsVisible() && mPaintTask.IsPending()) {
|
||||||
|
Paint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PuppetWidget::MemoryPressureObserver, nsIObserver)
|
NS_IMPL_ISUPPORTS(PuppetWidget::MemoryPressureObserver, nsIObserver)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -200,6 +200,9 @@ public:
|
|||||||
|
|
||||||
virtual bool NeedsPaint() override;
|
virtual bool NeedsPaint() override;
|
||||||
|
|
||||||
|
// Paint the widget immediately if any paints are queued up.
|
||||||
|
void PaintNowIfNeeded();
|
||||||
|
|
||||||
virtual TabChild* GetOwningTabChild() override { return mTabChild; }
|
virtual TabChild* GetOwningTabChild() override { return mTabChild; }
|
||||||
|
|
||||||
void UpdateBackingScaleCache(float aDpi, double aScale)
|
void UpdateBackingScaleCache(float aDpi, double aScale)
|
||||||
|
Loading…
Reference in New Issue
Block a user