Fix Bug 1509755 - Wait for browser initialization to finish before adding CFR trigger listeners (#4580)

This commit is contained in:
Andrei Oprea 2019-01-15 11:16:44 +00:00 коммит произвёл GitHub
Родитель 35b5b9a35d
Коммит abb7a49a25
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 49 добавлений и 9 удалений

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

@ -430,7 +430,7 @@ class _ASRouter {
const unseenListeners = new Set(ASRouterTriggerListeners.keys());
for (const {trigger} of newState.messages) {
if (trigger && ASRouterTriggerListeners.has(trigger.id)) {
ASRouterTriggerListeners.get(trigger.id).init(this._triggerHandler, trigger.params);
await ASRouterTriggerListeners.get(trigger.id).init(this._triggerHandler, trigger.params);
unseenListeners.delete(trigger.id);
}
}

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

@ -24,11 +24,30 @@ this.ASRouterTriggerListeners = new Map([
_triggerHandler: null,
_hosts: null,
/**
* Wait for browser startup to finish to avoid accessing uninitialized
* properties
*/
async _checkStartupFinished(win) {
if (!win.gBrowserInit.delayedStartupFinished) {
await new Promise(resolve => {
let delayedStartupObserver = (subject, topic) => {
if (topic === "browser-delayed-startup-finished" && subject === win) {
Services.obs.removeObserver(delayedStartupObserver, "browser-delayed-startup-finished");
resolve();
}
};
Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished");
});
}
},
/*
* If the listener is already initialised, `init` will replace the trigger
* handler and add any new hosts to `this._hosts`.
*/
init(triggerHandler, hosts = []) {
async init(triggerHandler, hosts = []) {
if (!this._initialized) {
this.onLocationChange = this.onLocationChange.bind(this);
@ -40,6 +59,7 @@ this.ASRouterTriggerListeners = new Map([
if (win.closed || PrivateBrowsingUtils.isWindowPrivate(win)) {
continue;
}
await this._checkStartupFinished(win);
win.gBrowser.addTabsProgressListener(this);
}

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

@ -20,7 +20,7 @@ describe("ASRouterTriggerListeners", () => {
sandbox = sinon.createSandbox();
registerWindowNotificationStub = sandbox.stub(global.Services.ww, "registerNotification");
unregisterWindoNotificationStub = sandbox.stub(global.Services.ww, "unregisterNotification");
existingWindow = {gBrowser: {addTabsProgressListener: sandbox.stub(), removeTabsProgressListener: sandbox.stub()}};
existingWindow = {gBrowser: {addTabsProgressListener: sandbox.stub(), removeTabsProgressListener: sandbox.stub()}, gBrowserInit: {delayedStartupFinished: true}};
windowEnumeratorStub = sandbox.stub(global.Services.wm, "getEnumerator");
resetEnumeratorStub([existingWindow]);
sandbox.spy(openURLListener, "init");
@ -37,8 +37,8 @@ describe("ASRouterTriggerListeners", () => {
});
describe("#init", () => {
beforeEach(() => {
openURLListener.init(triggerHandler, hosts);
beforeEach(async () => {
await openURLListener.init(triggerHandler, hosts);
});
afterEach(() => {
openURLListener.uninit();
@ -77,8 +77,8 @@ describe("ASRouterTriggerListeners", () => {
});
describe("#uninit", () => {
beforeEach(() => {
openURLListener.init(triggerHandler, hosts);
beforeEach(async () => {
await openURLListener.init(triggerHandler, hosts);
// Ensure that the window enumerator will return the existing window for uninit as well
resetEnumeratorStub([existingWindow]);
openURLListener.uninit();
@ -113,9 +113,13 @@ describe("ASRouterTriggerListeners", () => {
});
describe("#onLocationChange", () => {
it("should call the ._triggerHandler with the right arguments", () => {
afterEach(() => {
openURLListener.uninit();
});
it("should call the ._triggerHandler with the right arguments", async () => {
const newTriggerHandler = sinon.stub();
openURLListener.init(newTriggerHandler, hosts);
await openURLListener.init(newTriggerHandler, hosts);
const browser = {};
const webProgress = {isTopLevel: true};
@ -125,5 +129,21 @@ describe("ASRouterTriggerListeners", () => {
assert.calledWithExactly(newTriggerHandler, browser, {id: "openURL", param: "www.mozilla.org"});
});
});
describe("delayed startup finished", () => {
beforeEach(() => {
existingWindow.gBrowserInit.delayedStartupFinished = false;
sandbox.stub(global.Services.obs, "addObserver").callsFake(fn => fn(existingWindow, "browser-delayed-startup-finished"));
});
afterEach(() => {
openURLListener.uninit();
});
it("should wait for startup and then add the tabs listener", async () => {
await openURLListener.init(triggerHandler, hosts);
assert.calledOnce(existingWindow.gBrowser.addTabsProgressListener);
});
});
});
});