summaryrefslogtreecommitdiff
path: root/ext/fg
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fg')
-rw-r--r--ext/fg/js/float.js50
-rw-r--r--ext/fg/js/popup.js15
2 files changed, 55 insertions, 10 deletions
diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js
index 440a9731..8f21a9c5 100644
--- a/ext/fg/js/float.js
+++ b/ext/fg/js/float.js
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-/*global popupNestedInitialize, apiForward, Display*/
+/*global popupNestedInitialize, apiForward, apiGetMessageToken, Display*/
class DisplayFloat extends Display {
constructor() {
@@ -30,6 +30,8 @@ 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);
@@ -75,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) {
@@ -94,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;
}
diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js
index 900e7325..4927f4bd 100644
--- a/ext/fg/js/popup.js
+++ b/ext/fg/js/popup.js
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-/*global apiInjectStylesheet*/
+/*global apiInjectStylesheet, apiGetMessageToken*/
class Popup {
constructor(id, depth, frameIdPromise) {
@@ -34,6 +34,7 @@ class Popup {
this._contentScale = 1.0;
this._containerSizeContentScale = null;
this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, '');
+ this._messageToken = null;
this._container = document.createElement('iframe');
this._container.className = 'yomichan-float';
@@ -198,6 +199,10 @@ class Popup {
// NOP
}
+ if (this._messageToken === null) {
+ this._messageToken = await apiGetMessageToken();
+ }
+
return new Promise((resolve) => {
const parentFrameId = (typeof this._frameId === 'number' ? this._frameId : null);
this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html'));
@@ -349,9 +354,11 @@ class Popup {
}
_invokeApi(action, params={}) {
- if (this._container.contentWindow) {
- this._container.contentWindow.postMessage({action, params}, this._targetOrigin);
- }
+ const token = this._messageToken;
+ const contentWindow = this._container.contentWindow;
+ if (token === null || contentWindow === null) { return; }
+
+ contentWindow.postMessage({action, params, token}, this._targetOrigin);
}
static _getFullscreenElement() {