From c6c0126394f4bf5862061aaa5be7f941ff957a07 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 18 Jul 2020 14:18:10 -0400 Subject: [PATCH] Content script ready checks (#670) * Move ready checkout of Display * Add function to wait until if a tab's content script is ready --- ext/bg/js/backend.js | 55 ++++++++++++++++++++++++++++++++++++++++ ext/fg/js/float-main.js | 1 + ext/mixed/js/display.js | 1 - ext/mixed/js/yomichan.js | 7 +++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index f17e8897..301fe135 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -1383,4 +1383,59 @@ class Backend { // Edge throws exception for no reason here. } } + + _waitUntilTabFrameIsReady(tabId, frameId, timeout=null) { + return new Promise((resolve, reject) => { + let timer = null; + let onMessage = (message, sender) => { + if ( + !sender.tab || + sender.tab.id !== tabId || + sender.frameId !== frameId || + !isObject(message) || + message.action !== 'yomichanCoreReady' + ) { + return; + } + + cleanup(); + resolve(); + }; + const cleanup = () => { + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + if (onMessage !== null) { + chrome.runtime.onMessage.removeListener(onMessage); + onMessage = null; + } + }; + + chrome.runtime.onMessage.addListener(onMessage); + + chrome.tabs.sendMessage(tabId, {action: 'isReady'}, {frameId}, (response) => { + const error = chrome.runtime.lastError; + if (error) { return; } + + try { + const value = yomichan.getMessageResponseResult(response); + if (!value) { return; } + + cleanup(); + resolve(); + } catch (e) { + // NOP + } + }); + + if (timeout !== null) { + timer = setTimeout(() => { + timer = null; + cleanup(); + reject(new Error('Timeout')); + }, timeout); + } + }); + } } diff --git a/ext/fg/js/float-main.js b/ext/fg/js/float-main.js index 3bedfe58..d31d5050 100644 --- a/ext/fg/js/float-main.js +++ b/ext/fg/js/float-main.js @@ -23,6 +23,7 @@ (async () => { try { api.forwardLogsToBackend(); + await yomichan.ready(); const display = new DisplayFloat(); await display.prepare(); diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index bf3e3eae..82e77353 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -95,7 +95,6 @@ class Display { async prepare() { this._setInteractive(true); - await yomichan.ready(); await this._displayGenerator.prepare(); yomichan.on('extensionUnloaded', this._onExtensionUnloaded.bind(this)); } diff --git a/ext/mixed/js/yomichan.js b/ext/mixed/js/yomichan.js index 33870658..3ae905c3 100644 --- a/ext/mixed/js/yomichan.js +++ b/ext/mixed/js/yomichan.js @@ -48,12 +48,14 @@ const yomichan = (() => { } this._isExtensionUnloaded = false; + this._isReady = false; const {promise, resolve} = deferPromise(); this._isBackendPreparedPromise = promise; this._isBackendPreparedPromiseResolve = resolve; this._messageHandlers = new Map([ + ['isReady', {async: false, handler: this._onMessageIsReady.bind(this)}], ['backendPrepared', {async: false, handler: this._onMessageBackendPrepared.bind(this)}], ['getUrl', {async: false, handler: this._onMessageGetUrl.bind(this)}], ['optionsUpdated', {async: false, handler: this._onMessageOptionsUpdated.bind(this)}], @@ -72,6 +74,7 @@ const yomichan = (() => { } ready() { + this._isReady = true; this.sendMessage({action: 'yomichanCoreReady'}); return this._isBackendPreparedPromise; } @@ -268,6 +271,10 @@ const yomichan = (() => { return this.invokeMessageHandler(messageHandler, params, callback, sender); } + _onMessageIsReady() { + return this._isReady; + } + _onMessageBackendPrepared() { if (this._isBackendPreparedPromiseResolve === null) { return; } this._isBackendPreparedPromiseResolve();