diff options
Diffstat (limited to 'ext/fg/js/float.js')
-rw-r--r-- | ext/fg/js/float.js | 85 |
1 files changed, 65 insertions, 20 deletions
diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 8d61d8f6..8f21a9c5 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -16,6 +16,7 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +/*global popupNestedInitialize, apiForward, apiGetMessageToken, Display*/ class DisplayFloat extends Display { constructor() { @@ -28,11 +29,33 @@ class DisplayFloat extends Display { }; this._orphaned = false; + this._prepareInvoked = false; + this._messageToken = null; + this._messageTokenPromise = null; yomichan.on('orphaned', () => this.onOrphaned()); window.addEventListener('message', (e) => this.onMessage(e), false); } + async prepare(options, popupInfo, url, childrenSupported, scale, uniqueId) { + if (this._prepareInvoked) { return; } + this._prepareInvoked = true; + + await super.prepare(options); + + const {id, depth, parentFrameId} = popupInfo; + this.optionsContext.depth = depth; + this.optionsContext.url = url; + + if (childrenSupported) { + popupNestedInitialize(id, depth, parentFrameId, url); + } + + this.setContentScale(scale); + + apiForward('popupPrepareCompleted', {uniqueId}); + } + onError(error) { if (this._orphaned) { this.setContent('orphaned'); @@ -54,11 +77,23 @@ class DisplayFloat extends Display { } onMessage(e) { - const {action, params} = e.data; - const handler = DisplayFloat._messageHandlers.get(action); - if (typeof handler !== 'function') { return; } - - handler(this, params); + const data = e.data; + if (typeof data !== 'object' || data === null) { return; } // Invalid data + + const token = data.token; + if (typeof token !== 'string') { return; } // Invalid data + + if (this._messageToken === null) { + // Async + this.getMessageToken() + .then( + () => { this.handleAction(token, data); }, + () => {} + ); + } else { + // Sync + this.handleAction(token, data); + } } onKeyDown(e) { @@ -73,6 +108,30 @@ class DisplayFloat extends Display { return super.onKeyDown(e); } + async getMessageToken() { + // this._messageTokenPromise is used to ensure that only one call to apiGetMessageToken is made. + if (this._messageTokenPromise === null) { + this._messageTokenPromise = apiGetMessageToken(); + } + const messageToken = await this._messageTokenPromise; + if (this._messageToken === null) { + this._messageToken = messageToken; + } + this._messageTokenPromise = null; + } + + handleAction(token, {action, params}) { + if (token !== this._messageToken) { + // Invalid token + return; + } + + const handler = DisplayFloat._messageHandlers.get(action); + if (typeof handler !== 'function') { return; } + + handler(this, params); + } + getOptionsContext() { return this.optionsContext; } @@ -92,20 +151,6 @@ class DisplayFloat extends Display { setContentScale(scale) { document.body.style.fontSize = `${scale}em`; } - - async initialize(options, popupInfo, url, childrenSupported, scale) { - await super.initialize(options); - - const {id, depth, parentFrameId} = popupInfo; - this.optionsContext.depth = depth; - this.optionsContext.url = url; - - if (childrenSupported) { - popupNestedInitialize(id, depth, parentFrameId, url); - } - - this.setContentScale(scale); - } } DisplayFloat._onKeyDownHandlers = new Map([ @@ -122,7 +167,7 @@ DisplayFloat._messageHandlers = new Map([ ['setContent', (self, {type, details}) => self.setContent(type, details)], ['clearAutoPlayTimer', (self) => self.clearAutoPlayTimer()], ['setCustomCss', (self, {css}) => self.setCustomCss(css)], - ['initialize', (self, {options, popupInfo, url, childrenSupported, scale}) => self.initialize(options, popupInfo, url, childrenSupported, scale)], + ['prepare', (self, {options, popupInfo, url, childrenSupported, scale, uniqueId}) => self.prepare(options, popupInfo, url, childrenSupported, scale, uniqueId)], ['setContentScale', (self, {scale}) => self.setContentScale(scale)] ]); |