Bug 1500180 - Take around only geometry data of the fallback tab for pended operations. r=mixedpuppy

This commit is contained in:
YUKI "Piro" Hiroshi 2018-10-23 10:12:46 +09:00
parent c084508ace
commit 1451abf5f2
4 changed files with 73 additions and 25 deletions

View File

@ -444,16 +444,21 @@ class TabTracker extends TabTrackerBase {
windowId: windowTracker.getId(nativeTab.ownerGlobal),
});
} else {
// Save the current tab, since the newly-created tab will likely be
// active by the time the promise below resolves and the event is
// dispatched.
let currentTab = nativeTab.ownerGlobal.gBrowser.selectedTab;
// Save the size of the current tab, since the newly-created tab will
// likely be active by the time the promise below resolves and the
// event is dispatched.
const currentTab = nativeTab.ownerGlobal.gBrowser.selectedTab;
const {frameLoader} = currentTab.linkedBrowser;
const currentTabSize = {
width: frameLoader.lazyWidth,
height: frameLoader.lazyHeight,
};
// We need to delay sending this event until the next tick, since the
// tab could have been created with a lazy browser but still not have
// been assigned a SessionStore tab state with the URL and title.
Promise.resolve().then(() => {
this.emitCreated(event.originalTarget, currentTab);
this.emitCreated(event.originalTarget, currentTabSize);
});
}
break;
@ -584,12 +589,12 @@ class TabTracker extends TabTrackerBase {
*
* @param {NativeTab} nativeTab
* The tab element which is being created.
* @param {NativeTab} [currentTab]
* The tab element for the currently active tab.
* @param {Object} [currentTabSize]
* The size of the tab element for the currently active tab.
* @private
*/
emitCreated(nativeTab, currentTab) {
this.emit("tab-created", {nativeTab, currentTab});
emitCreated(nativeTab, currentTabSize) {
this.emit("tab-created", {nativeTab, currentTabSize});
}
/**

View File

@ -403,7 +403,7 @@ this.tabs = class extends ExtensionAPI {
name: "tabs.onCreated",
register: fire => {
let listener = (eventName, event) => {
fire.async(tabManager.convert(event.nativeTab, event.currentTab));
fire.async(tabManager.convert(event.nativeTab, event.currentTabSize));
};
tabTracker.on("tab-created", listener);
@ -564,7 +564,12 @@ this.tabs = class extends ExtensionAPI {
}
tabListener.initTabReady();
let currentTab = window.gBrowser.selectedTab;
const currentTab = window.gBrowser.selectedTab;
const {frameLoader} = currentTab.linkedBrowser;
const currentTabSize = {
width: frameLoader.lazyWidth,
height: frameLoader.lazyHeight,
};
if (createProperties.openerTabId !== null) {
options.ownerTab = tabTracker.getTab(createProperties.openerTabId);
@ -631,7 +636,7 @@ this.tabs = class extends ExtensionAPI {
tabListener.initializingTabs.add(nativeTab);
}
return tabManager.convert(nativeTab, currentTab);
return tabManager.convert(nativeTab, currentTabSize);
});
},

View File

@ -372,3 +372,41 @@ add_task(async function testTabCreateRelated() {
BrowserTestUtils.removeTab(openerTab);
});
add_task(async function testLastTabRemoval() {
await SpecialPowers.pushPrefEnv({set: [
["browser.tabs.closeWindowWithLastTab", false],
]});
async function background() {
let windowId;
browser.tabs.onCreated.addListener(tab => {
browser.test.assertEq(windowId, tab.windowId,
"expecting onCreated after onRemoved on the same window");
browser.test.sendMessage("tabCreated", `${tab.width}x${tab.height}`);
});
browser.tabs.onRemoved.addListener((tabId, info) => {
windowId = info.windowId;
});
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
},
background,
});
let newWin = await BrowserTestUtils.openNewBrowserWindow();
await extension.startup();
const oldBrowser = newWin.gBrowser.selectedBrowser;
const expectedDims = `${oldBrowser.clientWidth}x${oldBrowser.clientHeight}`;
BrowserTestUtils.removeTab(newWin.gBrowser.selectedTab);
const actualDims = await extension.awaitMessage("tabCreated");
is(actualDims, expectedDims, "created tab reports a size same to the removed last tab");
await extension.unload();
await BrowserTestUtils.closeWindow(newWin);
});

View File

@ -296,7 +296,7 @@ class TabBase {
* @readonly
*/
get frameLoader() {
return this.browser.frameLoader;
return this.browser && this.browser.frameLoader;
}
/**
@ -581,12 +581,12 @@ class TabBase {
* of its properties which the extension is permitted to access, in the format
* required to be returned by WebExtension APIs.
*
* @param {Tab} [fallbackTab]
* A tab to retrieve geometry data from if the lazy geometry data for
* this tab hasn't been initialized yet.
* @param {Object} [fallbackTabSize]
* A geometry data if the lazy geometry data for this tab hasn't been
* initialized yet.
* @returns {object}
*/
convert(fallbackTab = null) {
convert(fallbackTabSize = null) {
let result = {
id: this.id,
index: this.index,
@ -611,9 +611,9 @@ class TabBase {
// If the tab has not been fully layed-out yet, fallback to the geometry
// from a different tab (usually the currently active tab).
if (fallbackTab && (!result.width || !result.height)) {
result.width = fallbackTab.width;
result.height = fallbackTab.height;
if (fallbackTabSize && (!result.width || !result.height)) {
result.width = fallbackTabSize.width;
result.height = fallbackTabSize.height;
}
let opener = this.openerTabId;
@ -1831,15 +1831,15 @@ class TabManagerBase {
*
* @param {NativeTab} nativeTab
* The native tab to convert.
* @param {NativeTab} [fallbackTab]
* A tab to retrieve geometry data from if the lazy geometry data for
* this tab hasn't been initialized yet.
* @param {Object} [fallbackTabSize]
* A geometry data if the lazy geometry data for this tab hasn't been
* initialized yet.
*
* @returns {Object}
*/
convert(nativeTab, fallbackTab = null) {
convert(nativeTab, fallbackTabSize = null) {
return this.getWrapper(nativeTab)
.convert(fallbackTab && this.getWrapper(fallbackTab));
.convert(fallbackTabSize);
}
// The JSDoc validator does not support @returns tags in abstract functions or