diff options
Diffstat (limited to 'ext/bg/js/backend.js')
-rw-r--r-- | ext/bg/js/backend.js | 117 |
1 files changed, 101 insertions, 16 deletions
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 7971d16f..faba6c42 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -75,9 +75,15 @@ class Backend { this.popupWindow = null; - this._defaultBrowserActionTitle = null; this._isPrepared = false; this._prepareError = false; + this._preparePromise = null; + this._prepareCompletePromise = new Promise((resolve, reject) => { + this._prepareCompleteResolve = resolve; + this._prepareCompleteReject = reject; + }); + + this._defaultBrowserActionTitle = null; this._badgePrepareDelayTimer = null; this._logErrorLevel = null; @@ -134,7 +140,26 @@ class Backend { ]); } - async prepare() { + prepare() { + if (this._preparePromise === null) { + const promise = this._prepareInternal(); + promise.then( + (value) => { + this._isPrepared = true; + this._prepareCompleteResolve(value); + }, + (error) => { + this._prepareError = true; + this._prepareCompleteReject(error); + } + ); + promise.finally(() => this._updateBadge()); + this._preparePromise = promise; + } + return this._prepareCompletePromise; + } + + async _prepareInternal() { try { this._defaultBrowserActionTitle = await this._getBrowserIconTitle(); this._badgePrepareDelayTimer = setTimeout(() => { @@ -156,15 +181,6 @@ class Backend { this.onOptionsUpdated('background'); - if (isObject(chrome.commands) && isObject(chrome.commands.onCommand)) { - chrome.commands.onCommand.addListener(this._runCommand.bind(this)); - } - if (isObject(chrome.tabs) && isObject(chrome.tabs.onZoomChange)) { - chrome.tabs.onZoomChange.addListener(this._onZoomChange.bind(this)); - } - chrome.runtime.onMessage.addListener(this.onMessage.bind(this)); - chrome.runtime.onConnect.addListener(this._onConnect.bind(this)); - const options = this.getOptions(this.optionsContext); if (options.general.showGuide) { chrome.tabs.create({url: chrome.runtime.getURL('/bg/guide.html')}); @@ -175,10 +191,7 @@ class Backend { this._sendMessageAllTabs('backendPrepared'); const callback = () => this.checkLastError(chrome.runtime.lastError); chrome.runtime.sendMessage({action: 'backendPrepared'}, callback); - - this._isPrepared = true; } catch (e) { - this._prepareError = true; yomichan.logError(e); throw e; } finally { @@ -186,15 +199,33 @@ class Backend { clearTimeout(this._badgePrepareDelayTimer); this._badgePrepareDelayTimer = null; } - - this._updateBadge(); } } + prepareComplete() { + return this._prepareCompletePromise; + } + isPrepared() { return this._isPrepared; } + handleCommand(...args) { + return this._runCommand(...args); + } + + handleZoomChange(...args) { + return this._onZoomChange(...args); + } + + handleConnect(...args) { + return this._onConnect(...args); + } + + handleMessage(...args) { + return this.onMessage(...args); + } + _sendMessageAllTabs(action, params={}) { const callback = () => this.checkLastError(chrome.runtime.lastError); chrome.tabs.query({}, (tabs) => { @@ -1293,3 +1324,57 @@ class Backend { } } } + +class BackendEventHandler { + constructor(backend) { + this._backend = backend; + } + + prepare() { + if (isObject(chrome.commands) && isObject(chrome.commands.onCommand)) { + const onCommand = this._createGenericEventHandler((...args) => this._backend.handleCommand(...args)); + chrome.commands.onCommand.addListener(onCommand); + } + + if (isObject(chrome.tabs) && isObject(chrome.tabs.onZoomChange)) { + const onZoomChange = this._createGenericEventHandler((...args) => this._backend.handleZoomChange(...args)); + chrome.tabs.onZoomChange.addListener(onZoomChange); + } + + const onConnect = this._createGenericEventHandler((...args) => this._backend.handleConnect(...args)); + chrome.runtime.onConnect.addListener(onConnect); + + const onMessage = this._onMessage.bind(this); + chrome.runtime.onMessage.addListener(onMessage); + } + + // Event handlers + + _createGenericEventHandler(handler) { + return this._onGenericEvent.bind(this, handler); + } + + _onGenericEvent(handler, ...args) { + if (this._backend.isPrepared()) { + handler(...args); + return; + } + + this._backend.prepareComplete().then( + () => { handler(...args); }, + () => {} // NOP + ); + } + + _onMessage(message, sender, sendResponse) { + if (this._backend.isPrepared()) { + return this._backend.handleMessage(message, sender, sendResponse); + } + + this._backend.prepareComplete().then( + () => { this._backend.handleMessage(message, sender, sendResponse); }, + () => { sendResponse(); } // NOP + ); + return true; + } +} |