зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1385453 - Add API to tabbrowser to speculatively warm-up tabs for tab switching. r=billm
MozReview-Commit-ID: FIVx5d6ZOqq --HG-- extra : rebase_source : 3756ef4f6ae24b215ace6cffa889c6682953a7b5
This commit is contained in:
Родитель
c62c2c21b4
Коммит
772b1ab159
|
@ -1551,6 +1551,11 @@ pref("browser.tabs.remote.autostart.1", false);
|
|||
pref("browser.tabs.remote.autostart.2", true);
|
||||
#endif
|
||||
|
||||
// For speculatively warming up tabs to improve perceived
|
||||
// performance while using the async tab switcher.
|
||||
pref("browser.tabs.remote.maxWarmingTabs", 3);
|
||||
pref("browser.tabs.remote.warmingUnloadDelayMs", 2000);
|
||||
|
||||
// For the about:tabcrashed page
|
||||
pref("browser.tabs.crashReporting.sendReport", true);
|
||||
pref("browser.tabs.crashReporting.includeURL", false);
|
||||
|
|
|
@ -4100,6 +4100,12 @@
|
|||
// removed from the set upon MozAfterPaint.
|
||||
maybeVisibleTabs: new Set([this.selectedTab]),
|
||||
|
||||
// This holds onto the set of tabs that we've been asked to warm up.
|
||||
// This is used only for Telemetry and logging, and (in order to not
|
||||
// over-complicate the async tab switcher any further) has nothing to do
|
||||
// with how warmed tabs are loaded and unloaded.
|
||||
warmingTabs: new WeakSet(),
|
||||
|
||||
STATE_UNLOADED: 0,
|
||||
STATE_LOADING: 1,
|
||||
STATE_LOADED: 2,
|
||||
|
@ -4154,6 +4160,7 @@
|
|||
this.onLayersReady(browser);
|
||||
}
|
||||
} else if (state == this.STATE_UNLOADING) {
|
||||
this.unwarmTab(tab);
|
||||
browser.docShellIsActive = false;
|
||||
if (!tabParent) {
|
||||
this.onLayersCleared(browser);
|
||||
|
@ -4182,6 +4189,11 @@
|
|||
init() {
|
||||
this.log("START");
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "MAX_WARMING_TABS",
|
||||
"browser.tabs.remote.maxWarmingTabs", 3);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "WARMING_UNLOAD_DELAY" /* ms */,
|
||||
"browser.tabs.remote.warmingUnloadDelayMs", 2000);
|
||||
|
||||
// If we minimized the window before the switcher was activated,
|
||||
// we might have set the preserveLayers flag for the current
|
||||
// browser. Let's clear it.
|
||||
|
@ -4431,6 +4443,7 @@
|
|||
for (let [tab, ] of this.tabState) {
|
||||
if (!tab.linkedBrowser) {
|
||||
this.tabState.delete(tab);
|
||||
this.unwarmTab(tab);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4488,6 +4501,7 @@
|
|||
|
||||
// See how many tabs still have work to do.
|
||||
let numPending = 0;
|
||||
let numWarming = 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)) {
|
||||
|
@ -4496,6 +4510,10 @@
|
|||
|
||||
if (state == this.STATE_LOADED && tab !== this.requestedTab) {
|
||||
numPending++;
|
||||
|
||||
if (tab !== this.visibleTab) {
|
||||
numWarming++;
|
||||
}
|
||||
}
|
||||
if (state == this.STATE_LOADING || state == this.STATE_UNLOADING) {
|
||||
numPending++;
|
||||
|
@ -4511,8 +4529,14 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.blankTab) {
|
||||
this.maybeFinishTabSwitch();
|
||||
this.maybeFinishTabSwitch();
|
||||
|
||||
if (numWarming > this.MAX_WARMING_TABS) {
|
||||
this.logState("Hit MAX_WARMING_TABS");
|
||||
if (this.unloadTimer) {
|
||||
this.clearTimer(this.unloadTimer);
|
||||
}
|
||||
this.onUnloadTimeout();
|
||||
}
|
||||
|
||||
if (numPending == 0) {
|
||||
|
@ -4526,6 +4550,7 @@
|
|||
onUnloadTimeout() {
|
||||
this.logState("onUnloadTimeout");
|
||||
this.unloadTimer = null;
|
||||
this.warmingTabs = new WeakSet();
|
||||
this.preActions();
|
||||
|
||||
let numPending = 0;
|
||||
|
@ -4575,8 +4600,6 @@
|
|||
this.getTabState(tab) == this.STATE_LOADED);
|
||||
this.setTabState(tab, this.STATE_LOADED);
|
||||
|
||||
this.maybeFinishTabSwitch();
|
||||
|
||||
if (this.loadingTab === tab) {
|
||||
this.clearTimer(this.loadTimer);
|
||||
this.loadTimer = null;
|
||||
|
@ -4589,7 +4612,6 @@
|
|||
// around.
|
||||
onPaint() {
|
||||
this.maybeVisibleTabs.clear();
|
||||
this.maybeFinishTabSwitch();
|
||||
},
|
||||
|
||||
// Called when we're done clearing the layers for a tab.
|
||||
|
@ -4720,19 +4742,66 @@
|
|||
this.setTabState(tab, this.STATE_LOADING);
|
||||
},
|
||||
|
||||
canWarmTab(tab) {
|
||||
// If the tab is not yet inserted, closing, not remote,
|
||||
// crashed, already visible, or already requested, warming
|
||||
// up the tab makes no sense.
|
||||
if (this.minimizedOrFullyOccluded ||
|
||||
!tab.linkedPanel ||
|
||||
tab.closing ||
|
||||
!tab.linkedBrowser.isRemoteBrowser ||
|
||||
!tab.linkedBrowser.frameLoader.tabParent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Similarly, if the tab is already in STATE_LOADING or
|
||||
// STATE_LOADED somehow, there's no point in trying to
|
||||
// warm it up.
|
||||
let state = this.getTabState(tab);
|
||||
if (state === this.STATE_LOADING ||
|
||||
state === this.STATE_LOADED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
unwarmTab(tab) {
|
||||
this.warmingTabs.delete(tab);
|
||||
},
|
||||
|
||||
warmupTab(tab) {
|
||||
if (!this.canWarmTab(tab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logState("warmupTab " + this.tinfo(tab));
|
||||
|
||||
this.warmingTabs.add(tab);
|
||||
this.setTabState(tab, this.STATE_LOADING);
|
||||
this.suppressDisplayPortAndQueueUnload(tab, this.WARMING_UNLOAD_DELAY);
|
||||
},
|
||||
|
||||
// Called when the user asks to switch to a given tab.
|
||||
requestTab(tab) {
|
||||
if (tab === this.requestedTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.unwarmTab(tab);
|
||||
|
||||
this._requestingTab = true;
|
||||
this.logState("requestTab " + this.tinfo(tab));
|
||||
this.startTabSwitch();
|
||||
|
||||
this.requestedTab = tab;
|
||||
|
||||
let browser = this.requestedTab.linkedBrowser;
|
||||
this.suppressDisplayPortAndQueueUnload(this.requestedTab, this.UNLOAD_DELAY);
|
||||
this._requestingTab = false;
|
||||
},
|
||||
|
||||
suppressDisplayPortAndQueueUnload(tab, unloadTimeout) {
|
||||
let browser = tab.linkedBrowser;
|
||||
let fl = browser.frameLoader;
|
||||
|
||||
if (fl && fl.tabParent && !this.activeSuppressDisplayport.has(fl.tabParent)) {
|
||||
|
@ -4745,10 +4814,9 @@
|
|||
if (this.unloadTimer) {
|
||||
this.clearTimer(this.unloadTimer);
|
||||
}
|
||||
this.unloadTimer = this.setTimer(() => this.onUnloadTimeout(), this.UNLOAD_DELAY);
|
||||
this.unloadTimer = this.setTimer(() => this.onUnloadTimeout(), unloadTimeout);
|
||||
|
||||
this.postActions();
|
||||
this._requestingTab = false;
|
||||
},
|
||||
|
||||
handleEvent(event, delayed = false) {
|
||||
|
@ -4838,7 +4906,6 @@
|
|||
TelemetryStopwatch.finish("FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS", window);
|
||||
this.addMarker("AsyncTabSwitch:SpinnerHidden");
|
||||
// we do not get a onPaint after displaying the spinner
|
||||
this.maybeFinishTabSwitch();
|
||||
},
|
||||
|
||||
addMarker(marker) {
|
||||
|
@ -4890,12 +4957,14 @@
|
|||
for (let i = 0; i < this.tabbrowser.tabs.length; i++) {
|
||||
let tab = this.tabbrowser.tabs[i];
|
||||
let state = this.getTabState(tab);
|
||||
let isWarming = this.warmingTabs.has(tab);
|
||||
|
||||
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";
|
||||
if (isWarming) accum += "(W)";
|
||||
if (state == this.STATE_LOADED) accum += "(+)";
|
||||
if (state == this.STATE_LOADING) accum += "(+?)";
|
||||
if (state == this.STATE_UNLOADED) accum += "(-)";
|
||||
|
@ -4915,6 +4984,15 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="warmupTab">
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._getSwitcher().warmupTab(aTab);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
|
||||
MAKE SURE TO ADD IT HERE AS WELL. -->
|
||||
<property name="canGoBack"
|
||||
|
|
Загрузка…
Ссылка в новой задаче