From 295ffa6e54d04cedef35a4798cabdae71f824ee1 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Wed, 8 Jul 2020 19:50:13 -0400 Subject: [PATCH] Refactor DisplayFloat=>Frontend message passing (#652) * Change getOrCreatePopup arguments to be an object * Add ownerFrameId to popup and DisplayFloat * Refactor DisplayFloat host action invocation * Use CrossFrameAPI instead of window.postMessage * Update popup closing functionality on the search page --- ext/bg/js/search.js | 2 +- ext/fg/js/float.js | 12 +++++++--- ext/fg/js/frontend.js | 45 +++++++++++++------------------------- ext/fg/js/popup-factory.js | 8 +++---- ext/fg/js/popup-proxy.js | 5 +++-- ext/fg/js/popup.js | 4 +++- 6 files changed, 35 insertions(+), 41 deletions(-) diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index 90e9fce8..239027f7 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -255,7 +255,7 @@ class DisplaySearch extends Display { this.clearContent(); } this._setTitleText(query); - window.parent.postMessage('popupClose', '*'); + yomichan.trigger('closePopups'); } catch (e) { this.onError(e); } diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 83355c5c..2837f748 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -30,6 +30,7 @@ class DisplayFloat extends Display { this._secret = yomichan.generateId(16); this._token = null; this._nestedPopupsPrepared = false; + this._ownerFrameId = null; this._windowMessageHandlers = new Map([ ['initialize', {handler: this._onMessageInitialize.bind(this), authenticate: false}], ['configure', {handler: this._onMessageConfigure.bind(this)}], @@ -60,7 +61,7 @@ class DisplayFloat extends Display { } onEscape() { - window.parent.postMessage('popupClose', '*'); + this._invoke('closePopup'); } async setOptionsContext(optionsContext) { @@ -134,7 +135,8 @@ class DisplayFloat extends Display { this._initialize(params); } - async _onMessageConfigure({messageId, frameId, popupId, optionsContext, childrenSupported, scale}) { + async _onMessageConfigure({messageId, frameId, ownerFrameId, popupId, optionsContext, childrenSupported, scale}) { + this._ownerFrameId = ownerFrameId; this.setOptionsContext(optionsContext); await this.updateOptions(); @@ -173,7 +175,7 @@ class DisplayFloat extends Display { // Private _copySelection() { - window.parent.postMessage('selectionCopy', '*'); + this._invoke('copySelection'); } _clearAutoPlayTimer() { @@ -266,4 +268,8 @@ class DisplayFloat extends Display { ); await frontend.prepare(); } + + _invoke(action, params={}) { + return api.crossFrame.invoke(this._ownerFrameId, action, params); + } } diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 33cb0b90..86dcf57a 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -33,7 +33,6 @@ class Frontend { this._pageZoomFactor = 1.0; this._contentScale = 1.0; this._lastShowPromise = Promise.resolve(); - this._enabledEventListeners = new EventListenerCollection(); this._activeModifiers = new Set(); this._optionsUpdatePending = false; this._textScanner = new TextScanner({ @@ -63,11 +62,6 @@ class Frontend { this._popupCache = new Map(); this._updatePopupToken = null; - this._windowMessageHandlers = new Map([ - ['popupClose', this._onMessagePopupClose.bind(this)], - ['selectionCopy', this._onMessageSelectionCopy.bind()] - ]); - this._runtimeMessageHandlers = new Map([ ['popupSetVisibleOverride', this._onMessagePopupSetVisibleOverride.bind(this)], ['rootPopupRequestInformationBroadcast', this._onMessageRootPopupRequestInformationBroadcast.bind(this)], @@ -111,13 +105,16 @@ class Frontend { yomichan.on('optionsUpdated', this.updateOptions.bind(this)); yomichan.on('zoomChanged', this._onZoomChanged.bind(this)); + yomichan.on('closePopups', this._onApiClosePopup.bind(this)); chrome.runtime.onMessage.addListener(this._onRuntimeMessage.bind(this)); this._textScanner.on('clearSelection', this._onClearSelection.bind(this)); this._textScanner.on('activeModifiersChanged', this._onActiveModifiersChanged.bind(this)); api.crossFrame.registerHandlers([ - ['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}] + ['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}], + ['closePopup', {async: false, handler: this._onApiClosePopup.bind(this)}], + ['copySelection', {async: false, handler: this._onApiCopySelection.bind(this)}] ]); this._updateContentScale(); @@ -179,14 +176,6 @@ class Frontend { // Message handlers - _onMessagePopupClose() { - this._textScanner.clearSelection(false); - } - - _onMessageSelectionCopy() { - document.execCommand('copy'); - } - _onMessagePopupSetVisibleOverride({visible}) { this._popup.setVisibleOverride(visible); } @@ -205,20 +194,20 @@ class Frontend { return window.location.href; } + _onApiClosePopup() { + this._textScanner.clearSelection(false); + } + + _onApiCopySelection() { + document.execCommand('copy'); + } + // Private _onResize() { this._updatePopupPosition(); } - _onWindowMessage(e) { - const action = e.data; - const handler = this._windowMessageHandlers.get(action); - if (typeof handler !== 'function') { return false; } - - handler(); - } - _onRuntimeMessage({action, params}, sender, callback) { const handler = this._runtimeMessageHandlers.get(action); if (typeof handler !== 'function') { return false; } @@ -307,11 +296,11 @@ class Frontend { } async _getDefaultPopup() { - return this._popupFactory.getOrCreatePopup(null, null, this._depth); + return this._popupFactory.getOrCreatePopup({depth: this._depth, ownerFrameId: this._frameId}); } async _getProxyPopup() { - const popup = new PopupProxy(null, this._depth + 1, this._proxyPopupId, this._parentFrameId); + const popup = new PopupProxy(null, this._depth + 1, this._proxyPopupId, this._parentFrameId, this._frameId); await popup.prepare(); return popup; } @@ -328,7 +317,7 @@ class Frontend { api.broadcastTab('rootPopupRequestInformationBroadcast'); const {popupId, frameId: parentFrameId} = await rootPopupInformationPromise; - const popup = new PopupProxy(popupId, 0, null, parentFrameId, this._frameOffsetForwarder); + const popup = new PopupProxy(popupId, 0, null, parentFrameId, this._frameId, this._frameOffsetForwarder); popup.on('offsetNotFound', () => { this._allowRootFramePopupProxy = false; this._updatePopup(); @@ -444,11 +433,7 @@ class Frontend { this._depth <= this._options.scanning.popupNestingMaxDepth && !this._disabledOverride ); - this._enabledEventListeners.removeAllEventListeners(); this._textScanner.setEnabled(enabled); - if (enabled) { - this._enabledEventListeners.addEventListener(window, 'message', this._onWindowMessage.bind(this)); - } } _updateContentScale() { diff --git a/ext/fg/js/popup-factory.js b/ext/fg/js/popup-factory.js index 904f18b9..c48db51a 100644 --- a/ext/fg/js/popup-factory.js +++ b/ext/fg/js/popup-factory.js @@ -43,7 +43,7 @@ class PopupFactory { ]); } - getOrCreatePopup(id=null, parentId=null, depth=null) { + getOrCreatePopup({id=null, parentId=null, ownerFrameId=null, depth=null}) { // Find by existing id if (id !== null) { const popup = this._popups.get(id); @@ -80,7 +80,7 @@ class PopupFactory { } else if (depth === null) { depth = 0; } - const popup = new Popup(id, depth, this._frameId); + const popup = new Popup(id, depth, this._frameId, ownerFrameId); if (parent !== null) { popup.setParent(parent); } @@ -91,8 +91,8 @@ class PopupFactory { // API message handlers - _onApiGetOrCreatePopup({id, parentId}) { - const popup = this.getOrCreatePopup(id, parentId); + _onApiGetOrCreatePopup({id, parentId, ownerFrameId}) { + const popup = this.getOrCreatePopup({id, parentId, ownerFrameId}); return { id: popup.id }; diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 3f4473c6..352c5b34 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -20,12 +20,13 @@ */ class PopupProxy extends EventDispatcher { - constructor(id, depth, parentPopupId, parentFrameId, frameOffsetForwarder=null) { + constructor(id, depth, parentPopupId, parentFrameId, ownerFrameId, frameOffsetForwarder=null) { super(); this._id = id; this._depth = depth; this._parentPopupId = parentPopupId; this._parentFrameId = parentFrameId; + this._ownerFrameId = ownerFrameId; this._frameOffsetForwarder = frameOffsetForwarder; this._frameOffset = null; @@ -51,7 +52,7 @@ class PopupProxy extends EventDispatcher { // Public functions async prepare() { - const {id} = await this._invoke('getOrCreatePopup', {id: this._id, parentId: this._parentPopupId}); + const {id} = await this._invoke('getOrCreatePopup', {id: this._id, parentId: this._parentPopupId, ownerFrameId: this._ownerFrameId}); this._id = id; } diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index f9305bcd..a856d773 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -22,10 +22,11 @@ */ class Popup { - constructor(id, depth, frameId) { + constructor(id, depth, frameId, ownerFrameId) { this._id = id; this._depth = depth; this._frameId = frameId; + this._ownerFrameId = ownerFrameId; this._parent = null; this._child = null; this._childrenSupported = true; @@ -382,6 +383,7 @@ class Popup { this._invokeApi('configure', { messageId, frameId: this._frameId, + ownerFrameId: this._ownerFrameId, popupId: this._id, optionsContext: this._optionsContext, childrenSupported: this._childrenSupported,