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)]  ]);  |