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:
Wes Kocher 2016-08-22 16:00:34 -07:00
Родитель 730c59fce4
Коммит b38dbd1378
41 изменённых файлов: 413 добавлений и 602 удалений

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

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