aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/bg/js/backend.js117
-rw-r--r--ext/bg/js/background-main.js7
2 files changed, 106 insertions, 18 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;
+ }
+}
diff --git a/ext/bg/js/background-main.js b/ext/bg/js/background-main.js
index 345b4a77..9dd447c4 100644
--- a/ext/bg/js/background-main.js
+++ b/ext/bg/js/background-main.js
@@ -17,12 +17,15 @@
/* global
* Backend
+ * BackendEventHandler
*/
-(async () => {
+(() => {
const backend = new Backend();
+ const backendEventHandler = new BackendEventHandler(backend);
+ backendEventHandler.prepare();
if (typeof window === 'object' && window !== null) {
window.yomichanBackend = backend;
}
- await backend.prepare();
+ backend.prepare();
})();