Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Bogdan Tara 2018-05-11 17:10:31 +03:00
Родитель 162414134e babf96cf0c
Коммит 2bd748f3ca
6 изменённых файлов: 55 добавлений и 174 удалений

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

@ -1540,14 +1540,6 @@ pref("browser.tabs.remote.warmup.enabled", true);
pref("browser.tabs.remote.warmup.enabled", false);
#endif
// Caches tab layers to improve perceived performance
// of tab switches.
#if defined(NIGHTLY_BUILD)
pref("browser.tabs.remote.tabCacheSize", 5);
#else
pref("browser.tabs.remote.tabCacheSize", 0);
#endif
pref("browser.tabs.remote.warmup.maxTabs", 3);
pref("browser.tabs.remote.warmup.unloadDelayMs", 2000);

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

@ -195,12 +195,6 @@ We use a few tricks and optimizations to help improve the perceived performance
4. On platforms that support ``occlusionstatechange`` events (as of this writing, only macOS) and ``sizemodechange`` events (Windows, macOS and Linux), we stop rendering the layers for the currently selected tab when the window is minimized or fully occluded by another window.
5. Based on the browser.tabs.remote.tabCacheSize pref, we keep recently used tabs'
layers around to speed up tab switches by avoiding the round trip to the content
process. This uses a simple array (``_tabLayerCache``) inside tabbrowser.js, which
we examine when determining if we want to unload a tab's layers or not. This is still
experimental as of Nightly 62.
.. _async-tab-switcher.warming:
Warming

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

@ -97,8 +97,6 @@ window._gBrowser = {
_contentWaitingCount: 0,
_tabLayerCache: [],
tabAnimationsInProgress: 0,
_XUL_NS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
@ -2758,13 +2756,6 @@ window._gBrowser = {
}
}
// this._switcher would normally cover removing a tab from this
// cache, but we may not have one at this time.
let tabCacheIndex = this._tabLayerCache.indexOf(aTab);
if (tabCacheIndex != -1) {
this._tabLayerCache.splice(tabCacheIndex, 1);
}
this._blurTab(aTab);
var closeWindow = false;

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

@ -20,8 +20,6 @@ XPCOMUtils.defineLazyPreferenceGetter(this, "gTabWarmingMax",
"browser.tabs.remote.warmup.maxTabs");
XPCOMUtils.defineLazyPreferenceGetter(this, "gTabWarmingUnloadDelayMs",
"browser.tabs.remote.warmup.unloadDelayMs");
XPCOMUtils.defineLazyPreferenceGetter(this, "gTabCacheSize",
"browser.tabs.remote.tabCacheSize");
/**
* The tab switcher is responsible for asynchronously switching
@ -293,10 +291,6 @@ class AsyncTabSwitcher {
this.window.isFullyOccluded;
}
get tabLayerCache() {
return this.tabbrowser._tabLayerCache;
}
finish() {
this.log("FINISH");
@ -514,15 +508,6 @@ class AsyncTabSwitcher {
this.assert(this.tabbrowser._switcher);
this.assert(this.tabbrowser._switcher === this);
for (let i = 0; i < this.tabLayerCache.length; i++) {
let tab = this.tabLayerCache[i];
if (!tab.linkedBrowser) {
this.tabState.delete(tab);
this.tabLayerCache.splice(i, 1);
i--;
}
}
for (let [tab, ] of this.tabState) {
if (!tab.linkedBrowser) {
this.tabState.delete(tab);
@ -581,13 +566,6 @@ class AsyncTabSwitcher {
this.loadRequestedTab();
}
let numBackgroundCached = 0;
for (let tab of this.tabLayerCache) {
if (tab !== this.requestedTab) {
numBackgroundCached++;
}
}
// See how many tabs still have work to do.
let numPending = 0;
let numWarming = 0;
@ -597,9 +575,7 @@ class AsyncTabSwitcher {
continue;
}
if (state == this.STATE_LOADED &&
tab !== this.requestedTab &&
!this.tabLayerCache.includes(tab)) {
if (state == this.STATE_LOADED && tab !== this.requestedTab) {
numPending++;
if (tab !== this.visibleTab) {
@ -622,10 +598,8 @@ class AsyncTabSwitcher {
this.maybeFinishTabSwitch();
if (numWarming > gTabWarmingMax || numBackgroundCached > 0) {
if (numWarming > gTabWarmingMax) {
this.logState("Hit tabWarmingMax");
}
if (numWarming > gTabWarmingMax) {
this.logState("Hit tabWarmingMax");
if (this.unloadTimer) {
this.clearTimer(this.unloadTimer);
}
@ -658,34 +632,21 @@ class AsyncTabSwitcher {
this.warmingTabs = new WeakSet();
let numPending = 0;
for (let tab of this.tabLayerCache) {
if (tab !== this.requestedTab) {
let browser = tab.linkedBrowser;
browser.preserveLayers(true);
browser.docShellIsActive = false;
}
}
// Unload any tabs that can be unloaded.
for (let [tab, state] of this.tabState) {
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
continue;
}
let isInLayerCache = this.tabLayerCache.includes(tab);
if (state == this.STATE_LOADED &&
!this.maybeVisibleTabs.has(tab) &&
tab !== this.lastVisibleTab &&
tab !== this.loadingTab &&
tab !== this.requestedTab &&
!isInLayerCache) {
tab !== this.requestedTab) {
this.setTabState(tab, this.STATE_UNLOADING);
}
if (state != this.STATE_UNLOADED &&
tab !== this.requestedTab &&
!isInLayerCache) {
if (state != this.STATE_UNLOADED && tab !== this.requestedTab) {
numPending++;
}
}
@ -909,49 +870,17 @@ class AsyncTabSwitcher {
this.queueUnload(gTabWarmingUnloadDelayMs);
}
cleanUpTabAfterEviction(tab) {
this.assert(tab !== this.requestedTab);
let browser = tab.linkedBrowser;
if (browser) {
browser.preserveLayers(false);
}
this.setTabState(tab, this.STATE_UNLOADING);
}
evictOldestTabFromCache() {
let tab = this.tabLayerCache.shift();
this.cleanUpTabAfterEviction(tab);
}
maybePromoteTabInLayerCache(tab) {
if (gTabCacheSize > 1 &&
tab.linkedBrowser.isRemoteBrowser &&
tab.linkedBrowser.currentURI.spec != "about:blank") {
let tabIndex = this.tabLayerCache.indexOf(tab);
if (tabIndex != -1) {
this.tabLayerCache.splice(tabIndex, 1);
}
this.tabLayerCache.push(tab);
if (this.tabLayerCache.length > gTabCacheSize) {
this.evictOldestTabFromCache();
}
}
}
// Called when the user asks to switch to a given tab.
requestTab(tab) {
if (tab === this.requestedTab) {
return;
}
let tabState = this.getTabState(tab);
if (gTabWarmingEnabled) {
let warmingState = "disqualified";
if (this.canWarmTab(tab)) {
let tabState = this.getTabState(tab);
if (tabState == this.STATE_LOADING) {
warmingState = "stillLoading";
} else if (tabState == this.STATE_LOADED) {
@ -977,9 +906,6 @@ class AsyncTabSwitcher {
this.startTabSwitch();
this.requestedTab = tab;
if (tabState == this.STATE_LOADED) {
this.maybeVisibleTabs.clear();
}
tab.linkedBrowser.setAttribute("primary", "true");
if (this.lastPrimaryTab && this.lastPrimaryTab != tab) {
@ -1066,10 +992,6 @@ class AsyncTabSwitcher {
if (this.switchInProgress && this.requestedTab &&
(this.getTabState(this.requestedTab) == this.STATE_LOADED ||
this.requestedTab === this.blankTab)) {
if (this.requestedTab !== this.blankTab) {
this.maybePromoteTabInLayerCache(this.requestedTab);
}
// After this point the tab has switched from the content thread's point of view.
// The changes will be visible after the next refresh driver tick + composite.
let time = TelemetryStopwatch.timeElapsed("FX_TAB_SWITCH_TOTAL_E10S_MS", this.window);
@ -1156,37 +1078,19 @@ class AsyncTabSwitcher {
let tab = this.tabbrowser.tabs[i];
let state = this.getTabState(tab);
let isWarming = this.warmingTabs.has(tab);
let isCached = this.tabLayerCache.includes(tab);
let isClosing = tab.closing;
let linkedBrowser = tab.linkedBrowser;
let isActive = linkedBrowser && linkedBrowser.docShellIsActive;
let isRendered = linkedBrowser && linkedBrowser.renderLayers;
accum += i + ":";
if (tab === this.lastVisibleTab) accum += "V";
if (tab === this.loadingTab) accum += "L";
if (tab === this.requestedTab) accum += "R";
if (tab === this.blankTab) accum += "B";
let extraStates = "";
if (isWarming) extraStates += "W";
if (isCached) extraStates += "C";
if (isClosing) extraStates += "X";
if (isActive) extraStates += "A";
if (isRendered) extraStates += "R";
if (extraStates != "") {
accum += `(${extraStates})`;
}
if (isWarming) accum += "(W)";
if (state == this.STATE_LOADED) accum += "(+)";
if (state == this.STATE_LOADING) accum += "(+?)";
if (state == this.STATE_UNLOADED) accum += "(-)";
if (state == this.STATE_UNLOADING) accum += "(-?)";
accum += " ";
}
accum += "cached: " + this.tabLayerCache.length;
if (this._useDumpForLogging) {
dump(accum + "\n");
} else {

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

@ -14,10 +14,6 @@ const kMaxPaints = 10;
add_task(async function() {
let result, tabSwitchedPromise;
// We want to make sure that we will paint in cases where we need to. The
// tab layer cache just gets in the way of measuring that.
await SpecialPowers.pushPrefEnv({set: [["browser.tabs.remote.tabCacheSize", 0]]});
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
let testTab = gBrowser.selectedTab;

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

@ -1,33 +1,5 @@
var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
function waitForPluginVisibility(browser, shouldBeVisible, errorMessage) {
return new Promise((resolve, reject) => {
let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let lastTransactionId = windowUtils.lastTransactionId;
let listener = async (event) => {
let visibility = await ContentTask.spawn(browser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
if (visibility == shouldBeVisible) {
window.removeEventListener("MozAfterPaint", listener);
resolve();
} else if (event && event.transactionId > lastTransactionId) {
// We want to allow for one failed check since we call listener
// directly, but if we get a MozAfterPaint notification and we
// still don't have the correct visibility, that's likely a
// problem.
reject(new Error("MozAfterPaint had a mismatched plugin visibility"));
}
};
window.addEventListener("MozAfterPaint", listener);
listener(null);
});
}
// tests that we get plugin updates when we flip between tabs that
// have the same plugin in the same position in the page.
@ -57,44 +29,76 @@ add_task(async function() {
// plugin tab 2 should be selected
is(gBrowser.selectedTab == pluginTab2, true, "plugin2 is selected");
await waitForPluginVisibility(pluginTab1.linkedBrowser,
false, "plugin1 should be hidden");
result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, false, "plugin1 is hidden");
await waitForPluginVisibility(pluginTab2.linkedBrowser,
true, "plugin2 should be visible");
result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, true, "plugin2 is visible");
// select plugin1 tab
tabSwitchedPromise = waitTabSwitched();
gBrowser.selectedTab = pluginTab1;
await tabSwitchedPromise;
await waitForPluginVisibility(pluginTab1.linkedBrowser,
true, "plugin1 should be visible");
result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, true, "plugin1 is visible");
await waitForPluginVisibility(pluginTab2.linkedBrowser,
false, "plugin2 should be hidden");
result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, false, "plugin2 is hidden");
// select plugin2 tab
tabSwitchedPromise = waitTabSwitched();
gBrowser.selectedTab = pluginTab2;
await tabSwitchedPromise;
await waitForPluginVisibility(pluginTab1.linkedBrowser,
false, "plugin1 should be hidden");
result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, false, "plugin1 is hidden");
await waitForPluginVisibility(pluginTab2.linkedBrowser,
true, "plugin2 should be visible");
result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, true, "plugin2 is visible");
// select test tab
tabSwitchedPromise = waitTabSwitched();
gBrowser.selectedTab = testTab;
await tabSwitchedPromise;
await waitForPluginVisibility(pluginTab1.linkedBrowser,
false, "plugin1 should be hidden");
result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, false, "plugin1 is hidden");
await waitForPluginVisibility(pluginTab2.linkedBrowser,
false, "plugin2 should be hidden");
result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
let doc = content.document;
let plugin = doc.getElementById("testplugin");
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
});
is(result, false, "plugin2 is hidden");
gBrowser.removeTab(pluginTab1);
gBrowser.removeTab(pluginTab2);