From 962c2a381f3dace4d97fd0625504ec841e378354 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Fri, 13 Mar 2020 23:23:08 +0200 Subject: apply all options on profile change --- ext/fg/js/frontend-initialize.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 8424b21d..3a191247 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -26,7 +26,7 @@ async function main() { await yomichan.prepare(); const data = window.frontendInitializationData || {}; - const {id, depth=0, parentFrameId, ignoreNodes, url, proxy=false} = data; + const {id, depth=0, parentFrameId, url, proxy=false} = data; let popup; if (proxy) { @@ -38,7 +38,7 @@ async function main() { popup = popupHost.getOrCreatePopup(null, null, depth); } - const frontend = new Frontend(popup, ignoreNodes); + const frontend = new Frontend(popup); await frontend.prepare(); } -- cgit v1.2.3 From 6806e7055f312ad1ff382118255ffe1004b7eace Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 19 Mar 2020 00:00:42 +0200 Subject: show iframe popups in root frame --- ext/fg/js/frontend-initialize.js | 21 ++++++++++++++++++++- ext/fg/js/frontend.js | 3 ++- ext/fg/js/popup.js | 19 +++++++++++++++++++ ext/manifest.json | 2 ++ 4 files changed, 43 insertions(+), 2 deletions(-) (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 3a191247..7f70d9c4 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -20,6 +20,7 @@ * Frontend * PopupProxy * PopupProxyHost + * apiForward */ async function main() { @@ -29,7 +30,25 @@ async function main() { const {id, depth=0, parentFrameId, url, proxy=false} = data; let popup; - if (proxy) { + if (!proxy && (window !== window.parent)) { + let rootPopupInformationResolve; + const rootPopupInformationPromise = new Promise((resolve) => (rootPopupInformationResolve = resolve)); + + const runtimeMessageCallback = ({action, params}, sender, callback) => { + if (action === 'rootPopupInformation') { + chrome.runtime.onMessage.removeListener(runtimeMessageCallback); + callback(); + rootPopupInformationResolve(params); + return false; + } + }; + chrome.runtime.onMessage.addListener(runtimeMessageCallback); + apiForward('rootPopupInformationGet'); + + const {popupId, frameId} = await rootPopupInformationPromise; + + popup = new PopupProxy(popupId, 0, null, frameId, url); + } else if (proxy) { popup = new PopupProxy(null, depth + 1, id, parentFrameId, url); } else { const popupHost = new PopupProxyHost(); diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index d6c5eac6..af5341c4 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -52,7 +52,8 @@ class Frontend extends TextScanner { ]); this._runtimeMessageHandlers = new Map([ - ['popupSetVisibleOverride', ({visible}) => { this.popup.setVisibleOverride(visible); }] + ['popupSetVisibleOverride', ({visible}) => { this.popup.setVisibleOverride(visible); }], + ['rootPopupInformationGet', () => { this.popup.broadcastRootPopupInformation(); }] ]); } diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index e6e93a76..e6596a1a 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -17,6 +17,7 @@ */ /* global + * apiForward * apiGetMessageToken * apiInjectStylesheet */ @@ -79,6 +80,20 @@ class Popup { return false; } + async broadcastRootPopupInformation() { + if (this._depth === 0) { + try { + const {frameId} = await this._frameIdPromise; + if (typeof frameId === 'number') { + this._frameId = frameId; + } + } catch (e) { + // NOP + } + apiForward('rootPopupInformation', {popupId: this._id, frameId: this._frameId}); + } + } + async setOptions(options) { this._options = options; this.updateTheme(); @@ -202,6 +217,10 @@ class Popup { // NOP } + if (this._depth === 0) { + apiForward('rootPopupInformation', {popupId: this._id, frameId: this._frameId}); + } + if (this._messageToken === null) { this._messageToken = await apiGetMessageToken(); } diff --git a/ext/manifest.json b/ext/manifest.json index 3cea8647..97d59e49 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -23,9 +23,11 @@ "mixed/js/api.js", "mixed/js/text-scanner.js", "fg/js/document.js", + "fg/js/frontend-api-sender.js", "fg/js/frontend-api-receiver.js", "fg/js/popup.js", "fg/js/source.js", + "fg/js/popup-proxy.js", "fg/js/popup-proxy-host.js", "fg/js/frontend.js", "fg/js/frontend-initialize.js" -- cgit v1.2.3 From 09151a1a860f35b8dcbdbe9a25c09be5abeb4e37 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 19 Mar 2020 15:55:12 +0200 Subject: simplify popup proxy prepare --- ext/fg/js/frontend-initialize.js | 2 ++ ext/fg/js/popup-proxy.js | 46 +++++++++------------------------------- 2 files changed, 12 insertions(+), 36 deletions(-) (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 7f70d9c4..352c6bd9 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -48,8 +48,10 @@ async function main() { const {popupId, frameId} = await rootPopupInformationPromise; popup = new PopupProxy(popupId, 0, null, frameId, url); + await popup.prepare(); } else if (proxy) { popup = new PopupProxy(null, depth + 1, id, parentFrameId, url); + await popup.prepare(); } else { const popupHost = new PopupProxyHost(); await popupHost.prepare(); diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 242da04c..8693ef17 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -25,7 +25,6 @@ class PopupProxy { this._parentId = parentId; this._parentFrameId = parentFrameId; this._id = id; - this._idPromise = null; this._depth = depth; this._url = url; this._apiSender = new FrontendApiSender(); @@ -57,6 +56,11 @@ class PopupProxy { // Public functions + async prepare() { + const {id} = await this._invokeHostApi('getOrCreatePopup', {id: this._id, parentId: this._parentId}); + this._id = id; + } + isProxy() { return true; } @@ -66,33 +70,22 @@ class PopupProxy { } async setOptions(options) { - const id = await this._getPopupId(); - return await this._invokeHostApi('setOptions', {id, options}); + return await this._invokeHostApi('setOptions', {id: this._id, options}); } hide(changeFocus) { - if (this._id === null) { - return; - } this._invokeHostApi('hide', {id: this._id, changeFocus}); } async isVisible() { - const id = await this._getPopupId(); - return await this._invokeHostApi('isVisible', {id}); + return await this._invokeHostApi('isVisible', {id: this._id}); } setVisibleOverride(visible) { - if (this._id === null) { - return; - } this._invokeHostApi('setVisibleOverride', {id: this._id, visible}); } async containsPoint(x, y) { - if (this._id === null) { - return false; - } if (this._depth === 0) { [x, y] = await PopupProxy._convertIframePointToRootPagePoint(x, y); } @@ -100,30 +93,24 @@ class PopupProxy { } async showContent(elementRect, writingMode, type=null, details=null) { - const id = await this._getPopupId(); let {x, y, width, height} = elementRect; if (this._depth === 0) { [x, y] = await PopupProxy._convertIframePointToRootPagePoint(x, y); } elementRect = {x, y, width, height}; - return await this._invokeHostApi('showContent', {id, elementRect, writingMode, type, details}); + return await this._invokeHostApi('showContent', {id: this._id, elementRect, writingMode, type, details}); } async setCustomCss(css) { - const id = await this._getPopupId(); - return await this._invokeHostApi('setCustomCss', {id, css}); + return await this._invokeHostApi('setCustomCss', {id: this._id, css}); } clearAutoPlayTimer() { - if (this._id === null) { - return; - } this._invokeHostApi('clearAutoPlayTimer', {id: this._id}); } async setContentScale(scale) { - const id = await this._getPopupId(); - this._invokeHostApi('setContentScale', {id, scale}); + this._invokeHostApi('setContentScale', {id: this._id, scale}); } // Window message handlers @@ -153,19 +140,6 @@ class PopupProxy { // Private - _getPopupId() { - if (this._idPromise === null) { - this._idPromise = this._getPopupIdAsync(); - } - return this._idPromise; - } - - async _getPopupIdAsync() { - const {id} = await this._invokeHostApi('getOrCreatePopup', {id: this._id, parentId: this._parentId}); - this._id = id; - return id; - } - _invokeHostApi(action, params={}) { if (typeof this._parentFrameId !== 'number') { return Promise.reject(new Error('Invalid frame')); -- cgit v1.2.3 From d20ece9f074bb9d241a902f29344e5906e3c8210 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 19 Mar 2020 17:46:05 +0200 Subject: move frame offset forwarding code to a class --- ext/bg/js/search-frontend.js | 1 + ext/fg/js/frame-offset-forwarder.js | 94 +++++++++++++++++++++++++++++++++++++ ext/fg/js/frontend-initialize.js | 6 ++- ext/fg/js/popup-proxy-host.js | 31 ------------ ext/fg/js/popup-proxy.js | 67 ++------------------------ ext/manifest.json | 1 + 6 files changed, 105 insertions(+), 95 deletions(-) create mode 100644 ext/fg/js/frame-offset-forwarder.js (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/bg/js/search-frontend.js b/ext/bg/js/search-frontend.js index 2d2aa8d4..f130a6fa 100644 --- a/ext/bg/js/search-frontend.js +++ b/ext/bg/js/search-frontend.js @@ -35,6 +35,7 @@ async function searchFrontendSetup() { const scriptSrcs = [ '/mixed/js/text-scanner.js', '/fg/js/frontend-api-receiver.js', + '/fg/js/frame-offset-forwarder.js', '/fg/js/popup.js', '/fg/js/popup-proxy-host.js', '/fg/js/frontend.js', diff --git a/ext/fg/js/frame-offset-forwarder.js b/ext/fg/js/frame-offset-forwarder.js new file mode 100644 index 00000000..b3715c2a --- /dev/null +++ b/ext/fg/js/frame-offset-forwarder.js @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2020 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* global + * apiForward + */ + +class FrameOffsetForwarder { + constructor() { + this._forwardFrameOffset = window !== window.parent ? + this._forwardFrameOffsetParent.bind(this) : + this._forwardFrameOffsetOrigin.bind(this); + + this._windowMessageHandlers = new Map([ + ['getFrameOffset', ({offset, uniqueId}, e) => { return this._onGetFrameOffset(offset, uniqueId, e); }] + ]); + + window.addEventListener('message', this.onMessage.bind(this), false); + } + + async applyOffset(x, y) { + const uniqueId = yomichan.generateId(16); + + let frameOffsetResolve = null; + const frameOffsetPromise = new Promise((resolve) => (frameOffsetResolve = resolve)); + + const runtimeMessageCallback = ({action, params}, sender, callback) => { + if (action === 'frameOffset' && isObject(params) && params.uniqueId === uniqueId) { + chrome.runtime.onMessage.removeListener(runtimeMessageCallback); + callback(); + frameOffsetResolve(params); + return false; + } + }; + chrome.runtime.onMessage.addListener(runtimeMessageCallback); + + window.parent.postMessage({ + action: 'getFrameOffset', + params: { + uniqueId, + offset: [x, y] + } + }, '*'); + + const {offset} = await frameOffsetPromise; + return offset; + } + + onMessage(e) { + const {action, params} = e.data; + const handler = this._windowMessageHandlers.get(action); + if (typeof handler !== 'function') { return; } + handler(params, e); + } + + _onGetFrameOffset(offset, uniqueId, e) { + let sourceFrame = null; + for (const frame of document.querySelectorAll('frame, iframe:not(.yomichan-float)')) { + if (frame.contentWindow !== e.source) { continue; } + sourceFrame = frame; + break; + } + if (sourceFrame === null) { return; } + + const [forwardedX, forwardedY] = offset; + const {x, y} = sourceFrame.getBoundingClientRect(); + offset = [forwardedX + x, forwardedY + y]; + + this._forwardFrameOffset(offset, uniqueId); + } + + _forwardFrameOffsetParent(offset, uniqueId) { + window.parent.postMessage({action: 'getFrameOffset', params: {offset, uniqueId}}, '*'); + } + + _forwardFrameOffsetOrigin(offset, uniqueId) { + apiForward('frameOffset', {offset, uniqueId}); + } +} diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 352c6bd9..777291fe 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -17,6 +17,7 @@ */ /* global + * FrameOffsetForwarder * Frontend * PopupProxy * PopupProxyHost @@ -47,12 +48,15 @@ async function main() { const {popupId, frameId} = await rootPopupInformationPromise; - popup = new PopupProxy(popupId, 0, null, frameId, url); + window._frameOffsetForwarder = new FrameOffsetForwarder(); + const applyFrameOffset = window._frameOffsetForwarder.applyOffset.bind(window._frameOffsetForwarder); + popup = new PopupProxy(popupId, 0, null, frameId, url, applyFrameOffset); await popup.prepare(); } else if (proxy) { popup = new PopupProxy(null, depth + 1, id, parentFrameId, url); await popup.prepare(); } else { + window._frameOffsetForwarder = new FrameOffsetForwarder(); const popupHost = new PopupProxyHost(); await popupHost.prepare(); diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index 487dda90..4b136e41 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -19,7 +19,6 @@ /* global * FrontendApiReceiver * Popup - * apiForward * apiFrameInformationGet */ @@ -49,12 +48,6 @@ class PopupProxyHost { ['clearAutoPlayTimer', this._onApiClearAutoPlayTimer.bind(this)], ['setContentScale', this._onApiSetContentScale.bind(this)] ])); - - this._windowMessageHandlers = new Map([ - ['getIframeOffset', ({offset, uniqueId}, e) => { return this._onGetIframeOffset(offset, uniqueId, e); }] - ]); - - window.addEventListener('message', this.onMessage.bind(this), false); } getOrCreatePopup(id=null, parentId=null, depth=null) { @@ -159,30 +152,6 @@ class PopupProxyHost { return popup.setContentScale(scale); } - // Window message handlers - - onMessage(e) { - const {action, params} = e.data; - const handler = this._windowMessageHandlers.get(action); - if (typeof handler !== 'function') { return; } - handler(params, e); - } - - _onGetIframeOffset(offset, uniqueId, e) { - let sourceIframe = null; - for (const iframe of document.querySelectorAll('iframe:not(.yomichan-float)')) { - if (iframe.contentWindow !== e.source) { continue; } - sourceIframe = iframe; - break; - } - if (sourceIframe === null) { return; } - - const [forwardedX, forwardedY] = offset; - const {x, y} = sourceIframe.getBoundingClientRect(); - offset = [forwardedX + x, forwardedY + y]; - apiForward('iframeOffset', {offset, uniqueId}); - } - // Private functions _getPopup(id) { diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 8693ef17..73148eee 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -21,19 +21,14 @@ */ class PopupProxy { - constructor(id, depth, parentId, parentFrameId, url) { + constructor(id, depth, parentId, parentFrameId, url, applyFrameOffset=async (x, y) => [x, y]) { this._parentId = parentId; this._parentFrameId = parentFrameId; this._id = id; this._depth = depth; this._url = url; this._apiSender = new FrontendApiSender(); - - this._windowMessageHandlers = new Map([ - ['getIframeOffset', ({offset, uniqueId}, e) => { return this._onGetIframeOffset(offset, uniqueId, e); }] - ]); - - window.addEventListener('message', this.onMessage.bind(this), false); + this._applyFrameOffset = applyFrameOffset; } // Public properties @@ -87,7 +82,7 @@ class PopupProxy { async containsPoint(x, y) { if (this._depth === 0) { - [x, y] = await PopupProxy._convertIframePointToRootPagePoint(x, y); + [x, y] = await this._applyFrameOffset(x, y); } return await this._invokeHostApi('containsPoint', {id: this._id, x, y}); } @@ -95,7 +90,7 @@ class PopupProxy { async showContent(elementRect, writingMode, type=null, details=null) { let {x, y, width, height} = elementRect; if (this._depth === 0) { - [x, y] = await PopupProxy._convertIframePointToRootPagePoint(x, y); + [x, y] = await this._applyFrameOffset(x, y); } elementRect = {x, y, width, height}; return await this._invokeHostApi('showContent', {id: this._id, elementRect, writingMode, type, details}); @@ -113,31 +108,6 @@ class PopupProxy { this._invokeHostApi('setContentScale', {id: this._id, scale}); } - // Window message handlers - - onMessage(e) { - const {action, params} = e.data; - const handler = this._windowMessageHandlers.get(action); - if (typeof handler !== 'function') { return; } - handler(params, e); - } - - _onGetIframeOffset(offset, uniqueId, e) { - let sourceIframe = null; - for (const iframe of document.querySelectorAll('iframe:not(.yomichan-float)')) { - if (iframe.contentWindow !== e.source) { continue; } - sourceIframe = iframe; - break; - } - if (sourceIframe === null) { return; } - - const [forwardedX, forwardedY] = offset; - const {x, y} = sourceIframe.getBoundingClientRect(); - offset = [forwardedX + x, forwardedY + y]; - window.parent.postMessage({action: 'getIframeOffset', params: {offset, uniqueId}}, '*'); - } - - // Private _invokeHostApi(action, params={}) { @@ -146,33 +116,4 @@ class PopupProxy { } return this._apiSender.invoke(action, params, `popup-proxy-host#${this._parentFrameId}`); } - - static async _convertIframePointToRootPagePoint(x, y) { - const uniqueId = yomichan.generateId(16); - - let frameOffsetResolve = null; - const frameOffsetPromise = new Promise((resolve) => (frameOffsetResolve = resolve)); - - const runtimeMessageCallback = ({action, params}, sender, callback) => { - if (action === 'iframeOffset' && isObject(params) && params.uniqueId === uniqueId) { - chrome.runtime.onMessage.removeListener(runtimeMessageCallback); - callback(); - frameOffsetResolve(params); - return false; - } - }; - chrome.runtime.onMessage.addListener(runtimeMessageCallback); - - window.parent.postMessage({ - action: 'getIframeOffset', - params: { - uniqueId, - offset: [x, y] - } - }, '*'); - - const {offset} = await frameOffsetPromise; - - return offset; - } } diff --git a/ext/manifest.json b/ext/manifest.json index 97d59e49..98965389 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -27,6 +27,7 @@ "fg/js/frontend-api-receiver.js", "fg/js/popup.js", "fg/js/source.js", + "fg/js/frame-offset-forwarder.js", "fg/js/popup-proxy.js", "fg/js/popup-proxy-host.js", "fg/js/frontend.js", -- cgit v1.2.3 From 9fe1e38afb056164dbcc4369160bb9fd4790a2c0 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 22 Mar 2020 03:29:09 +0200 Subject: refactor --- ext/fg/js/frame-offset-forwarder.js | 15 +++++++++++---- ext/fg/js/frontend-initialize.js | 13 ++++++++----- ext/fg/js/frontend.js | 2 +- ext/fg/js/popup-proxy.js | 6 +++--- ext/fg/js/popup.js | 1 - 5 files changed, 23 insertions(+), 14 deletions(-) (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/fg/js/frame-offset-forwarder.js b/ext/fg/js/frame-offset-forwarder.js index b3715c2a..09eb89a6 100644 --- a/ext/fg/js/frame-offset-forwarder.js +++ b/ext/fg/js/frame-offset-forwarder.js @@ -22,15 +22,23 @@ class FrameOffsetForwarder { constructor() { - this._forwardFrameOffset = window !== window.parent ? + this._started = false; + + this._forwardFrameOffset = ( + window !== window.parent ? this._forwardFrameOffsetParent.bind(this) : - this._forwardFrameOffsetOrigin.bind(this); + this._forwardFrameOffsetOrigin.bind(this) + ); this._windowMessageHandlers = new Map([ - ['getFrameOffset', ({offset, uniqueId}, e) => { return this._onGetFrameOffset(offset, uniqueId, e); }] + ['getFrameOffset', ({offset, uniqueId}, e) => this._onGetFrameOffset(offset, uniqueId, e)] ]); + } + start() { + if (this._started) { return; } window.addEventListener('message', this.onMessage.bind(this), false); + this._started = true; } async applyOffset(x, y) { @@ -44,7 +52,6 @@ class FrameOffsetForwarder { chrome.runtime.onMessage.removeListener(runtimeMessageCallback); callback(); frameOffsetResolve(params); - return false; } }; chrome.runtime.onMessage.addListener(runtimeMessageCallback); diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 777291fe..51fa8d7a 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -40,23 +40,26 @@ async function main() { chrome.runtime.onMessage.removeListener(runtimeMessageCallback); callback(); rootPopupInformationResolve(params); - return false; } }; chrome.runtime.onMessage.addListener(runtimeMessageCallback); - apiForward('rootPopupInformationGet'); + apiForward('rootPopupRequestInformationBroadcast'); const {popupId, frameId} = await rootPopupInformationPromise; - window._frameOffsetForwarder = new FrameOffsetForwarder(); - const applyFrameOffset = window._frameOffsetForwarder.applyOffset.bind(window._frameOffsetForwarder); + const frameOffsetForwarder = new FrameOffsetForwarder(); + frameOffsetForwarder.start(); + const applyFrameOffset = frameOffsetForwarder.applyOffset.bind(frameOffsetForwarder); + popup = new PopupProxy(popupId, 0, null, frameId, url, applyFrameOffset); await popup.prepare(); } else if (proxy) { popup = new PopupProxy(null, depth + 1, id, parentFrameId, url); await popup.prepare(); } else { - window._frameOffsetForwarder = new FrameOffsetForwarder(); + const frameOffsetForwarder = new FrameOffsetForwarder(); + frameOffsetForwarder.start(); + const popupHost = new PopupProxyHost(); await popupHost.prepare(); diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index d6fe7af4..c160b9e3 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -53,7 +53,7 @@ class Frontend extends TextScanner { this._runtimeMessageHandlers = new Map([ ['popupSetVisibleOverride', ({visible}) => { this.popup.setVisibleOverride(visible); }], - ['rootPopupInformationGet', () => { this.popup.broadcastRootPopupInformation(); }] + ['rootPopupRequestInformationBroadcast', () => { this.popup.broadcastRootPopupInformation(); }] ]); } diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 73148eee..a25f9183 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -21,7 +21,7 @@ */ class PopupProxy { - constructor(id, depth, parentId, parentFrameId, url, applyFrameOffset=async (x, y) => [x, y]) { + constructor(id, depth, parentId, parentFrameId, url, applyFrameOffset=null) { this._parentId = parentId; this._parentFrameId = parentFrameId; this._id = id; @@ -81,7 +81,7 @@ class PopupProxy { } async containsPoint(x, y) { - if (this._depth === 0) { + if (this._applyFrameOffset !== null) { [x, y] = await this._applyFrameOffset(x, y); } return await this._invokeHostApi('containsPoint', {id: this._id, x, y}); @@ -89,7 +89,7 @@ class PopupProxy { async showContent(elementRect, writingMode, type=null, details=null) { let {x, y, width, height} = elementRect; - if (this._depth === 0) { + if (this._applyFrameOffset !== null) { [x, y] = await this._applyFrameOffset(x, y); } elementRect = {x, y, width, height}; diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 4c979911..47e32963 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -368,7 +368,6 @@ class Popup { chrome.runtime.onMessage.removeListener(runtimeMessageCallback); callback(); resolve(); - return false; } }; chrome.runtime.onMessage.addListener(runtimeMessageCallback); -- cgit v1.2.3 From d88635cbb28862e0efd79080e5c67865d0410238 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 22 Mar 2020 04:55:16 +0200 Subject: temporary listener abstraction --- ext/fg/js/frame-offset-forwarder.js | 17 +++++++---------- ext/fg/js/frontend-initialize.js | 18 +++++++----------- ext/mixed/js/core.js | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 21 deletions(-) (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/fg/js/frame-offset-forwarder.js b/ext/fg/js/frame-offset-forwarder.js index 09eb89a6..781a9018 100644 --- a/ext/fg/js/frame-offset-forwarder.js +++ b/ext/fg/js/frame-offset-forwarder.js @@ -44,17 +44,14 @@ class FrameOffsetForwarder { async applyOffset(x, y) { const uniqueId = yomichan.generateId(16); - let frameOffsetResolve = null; - const frameOffsetPromise = new Promise((resolve) => (frameOffsetResolve = resolve)); - - const runtimeMessageCallback = ({action, params}, sender, callback) => { - if (action === 'frameOffset' && isObject(params) && params.uniqueId === uniqueId) { - chrome.runtime.onMessage.removeListener(runtimeMessageCallback); - callback(); - frameOffsetResolve(params); + const frameOffsetPromise = yomichan.getTemporaryListenerResult( + chrome.runtime.onMessage, + ({action, params}, {resolve}) => { + if (action === 'frameOffset' && isObject(params) && params.uniqueId === uniqueId) { + resolve(params); + } } - }; - chrome.runtime.onMessage.addListener(runtimeMessageCallback); + ); window.parent.postMessage({ action: 'getFrameOffset', diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 51fa8d7a..97e315b5 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -32,19 +32,15 @@ async function main() { let popup; if (!proxy && (window !== window.parent)) { - let rootPopupInformationResolve; - const rootPopupInformationPromise = new Promise((resolve) => (rootPopupInformationResolve = resolve)); - - const runtimeMessageCallback = ({action, params}, sender, callback) => { - if (action === 'rootPopupInformation') { - chrome.runtime.onMessage.removeListener(runtimeMessageCallback); - callback(); - rootPopupInformationResolve(params); + const rootPopupInformationPromise = yomichan.getTemporaryListenerResult( + chrome.runtime.onMessage, + ({action, params}, {resolve}) => { + if (action === 'rootPopupInformation') { + resolve(params); + } } - }; - chrome.runtime.onMessage.addListener(runtimeMessageCallback); + ); apiForward('rootPopupRequestInformationBroadcast'); - const {popupId, frameId} = await rootPopupInformationPromise; const frameOffsetForwarder = new FrameOffsetForwarder(); diff --git a/ext/mixed/js/core.js b/ext/mixed/js/core.js index fd762e97..f21bac23 100644 --- a/ext/mixed/js/core.js +++ b/ext/mixed/js/core.js @@ -312,6 +312,42 @@ const yomichan = (() => { this.trigger('orphaned', {error}); } + getTemporaryListenerResult(eventHandler, userCallback, timeout=30000) { + let resolved = false; + let resolve; + let reject; + const listenerPromise = new Promise((_resolve, _reject) => { + resolve = _resolve; + reject = _reject; + }); + + if (eventHandler === chrome.runtime.onMessage) { + const runtimeMessageCallback = ({action, params}, sender, sendResponse) => { + const cleanupResolve = (value) => { + resolved = true; + eventHandler.removeListener(runtimeMessageCallback); + sendResponse(); + resolve(value); + }; + + setTimeout(() => { + if (!resolved) { + reject(new Error(`Listener timed out in ${timeout} ms`)); + eventHandler.removeListener(runtimeMessageCallback); + } + }, timeout); + + userCallback({action, params}, {resolve: cleanupResolve, sender}); + }; + + eventHandler.addListener(runtimeMessageCallback); + } else { + throw new Error('Event handler type not supported'); + } + + return listenerPromise; + } + // Private _onMessage({action, params}, sender, callback) { -- cgit v1.2.3 From 9f9ea1d5fb9f383992523a2a9a8a02259ced838e Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 22 Mar 2020 14:11:43 +0200 Subject: throttle frame offset getting --- ext/fg/js/frame-offset-forwarder.js | 4 ++-- ext/fg/js/frontend-initialize.js | 4 ++-- ext/fg/js/popup-proxy.js | 46 ++++++++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 10 deletions(-) (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/fg/js/frame-offset-forwarder.js b/ext/fg/js/frame-offset-forwarder.js index 38fc0b03..c32c2ec1 100644 --- a/ext/fg/js/frame-offset-forwarder.js +++ b/ext/fg/js/frame-offset-forwarder.js @@ -41,7 +41,7 @@ class FrameOffsetForwarder { this._started = true; } - async applyOffset(x, y) { + async getOffset() { const uniqueId = yomichan.generateId(16); const frameOffsetPromise = yomichan.getTemporaryListenerResult( @@ -58,7 +58,7 @@ class FrameOffsetForwarder { action: 'getFrameOffset', params: { uniqueId, - offset: [x, y] + offset: [0, 0] } }, '*'); diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 97e315b5..2f86f5c8 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -45,9 +45,9 @@ async function main() { const frameOffsetForwarder = new FrameOffsetForwarder(); frameOffsetForwarder.start(); - const applyFrameOffset = frameOffsetForwarder.applyOffset.bind(frameOffsetForwarder); + const getFrameOffset = frameOffsetForwarder.getOffset.bind(frameOffsetForwarder); - popup = new PopupProxy(popupId, 0, null, frameId, url, applyFrameOffset); + popup = new PopupProxy(popupId, 0, null, frameId, url, getFrameOffset); await popup.prepare(); } else if (proxy) { popup = new PopupProxy(null, depth + 1, id, parentFrameId, url); diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index a25f9183..0cd5bbad 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -21,14 +21,18 @@ */ class PopupProxy { - constructor(id, depth, parentId, parentFrameId, url, applyFrameOffset=null) { + constructor(id, depth, parentId, parentFrameId, url, getFrameOffset=null) { this._parentId = parentId; this._parentFrameId = parentFrameId; this._id = id; this._depth = depth; this._url = url; this._apiSender = new FrontendApiSender(); - this._applyFrameOffset = applyFrameOffset; + this._getFrameOffset = getFrameOffset; + + this._frameOffset = null; + this._frameOffsetPromise = null; + this._frameOffsetUpdatedAt = null; } // Public properties @@ -81,16 +85,18 @@ class PopupProxy { } async containsPoint(x, y) { - if (this._applyFrameOffset !== null) { - [x, y] = await this._applyFrameOffset(x, y); + if (this._getFrameOffset !== null) { + await this._updateFrameOffset(); + [x, y] = this._applyFrameOffset(x, y); } return await this._invokeHostApi('containsPoint', {id: this._id, x, y}); } async showContent(elementRect, writingMode, type=null, details=null) { let {x, y, width, height} = elementRect; - if (this._applyFrameOffset !== null) { - [x, y] = await this._applyFrameOffset(x, y); + if (this._getFrameOffset !== null) { + await this._updateFrameOffset(); + [x, y] = this._applyFrameOffset(x, y); } elementRect = {x, y, width, height}; return await this._invokeHostApi('showContent', {id: this._id, elementRect, writingMode, type, details}); @@ -116,4 +122,32 @@ class PopupProxy { } return this._apiSender.invoke(action, params, `popup-proxy-host#${this._parentFrameId}`); } + + async _updateFrameOffset() { + const firstRun = this._frameOffsetUpdatedAt === null; + const expired = firstRun || this._frameOffsetUpdatedAt < Date.now() - 1000; + if (this._frameOffsetPromise === null && !expired) { return; } + + if (this._frameOffsetPromise !== null) { + await this._frameOffsetPromise; + return; + } + + if (firstRun) { + this._frameOffsetPromise = this._getFrameOffset(); + this._frameOffset = await this._frameOffsetPromise; + this._frameOffsetPromise = null; + this._frameOffsetUpdatedAt = Date.now(); + } else { + this._getFrameOffset().then((offset) => { + this._frameOffset = offset; + this._frameOffsetUpdatedAt = Date.now(); + }); + } + } + + _applyFrameOffset(x, y) { + const [offsetX, offsetY] = this._frameOffset; + return [x + offsetX, y + offsetY]; + } } -- cgit v1.2.3 From 31a326fe636683e71fa61f11ed25b4f2adaead44 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 5 Apr 2020 01:43:12 +0300 Subject: add option for iframe popups --- ext/bg/data/options-schema.json | 7 ++++++- ext/bg/js/options.js | 3 ++- ext/bg/js/settings/main.js | 2 ++ ext/bg/settings.html | 4 ++++ ext/fg/js/frontend-initialize.js | 6 +++++- 5 files changed, 19 insertions(+), 3 deletions(-) (limited to 'ext/fg/js/frontend-initialize.js') diff --git a/ext/bg/data/options-schema.json b/ext/bg/data/options-schema.json index cb759b72..da1f1ce0 100644 --- a/ext/bg/data/options-schema.json +++ b/ext/bg/data/options-schema.json @@ -108,7 +108,8 @@ "enableClipboardMonitor", "showPitchAccentDownstepNotation", "showPitchAccentPositionNotation", - "showPitchAccentGraph" + "showPitchAccentGraph", + "showIframePopupsInRootFrame" ], "properties": { "enable": { @@ -242,6 +243,10 @@ "showPitchAccentGraph": { "type": "boolean", "default": false + }, + "showIframePopupsInRootFrame": { + "type": "boolean", + "default": false } } }, diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index b36fe812..5c68c403 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -127,7 +127,8 @@ function profileOptionsCreateDefaults() { enableClipboardMonitor: false, showPitchAccentDownstepNotation: true, showPitchAccentPositionNotation: true, - showPitchAccentGraph: false + showPitchAccentGraph: false, + showIframePopupsInRootFrame: false }, audio: { diff --git a/ext/bg/js/settings/main.js b/ext/bg/js/settings/main.js index 7caeaea0..1653ee35 100644 --- a/ext/bg/js/settings/main.js +++ b/ext/bg/js/settings/main.js @@ -87,6 +87,7 @@ async function formRead(options) { options.general.showPitchAccentDownstepNotation = $('#show-pitch-accent-downstep-notation').prop('checked'); options.general.showPitchAccentPositionNotation = $('#show-pitch-accent-position-notation').prop('checked'); options.general.showPitchAccentGraph = $('#show-pitch-accent-graph').prop('checked'); + options.general.showIframePopupsInRootFrame = $('#show-iframe-popups-in-root-frame').prop('checked'); options.general.popupTheme = $('#popup-theme').val(); options.general.popupOuterTheme = $('#popup-outer-theme').val(); options.general.customPopupCss = $('#custom-popup-css').val(); @@ -167,6 +168,7 @@ async function formWrite(options) { $('#show-pitch-accent-downstep-notation').prop('checked', options.general.showPitchAccentDownstepNotation); $('#show-pitch-accent-position-notation').prop('checked', options.general.showPitchAccentPositionNotation); $('#show-pitch-accent-graph').prop('checked', options.general.showPitchAccentGraph); + $('#show-iframe-popups-in-root-frame').prop('checked', options.general.showIframePopupsInRootFrame); $('#popup-theme').val(options.general.popupTheme); $('#popup-outer-theme').val(options.general.popupOuterTheme); $('#custom-popup-css').val(options.general.customPopupCss); diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 0b2e4f9c..237162c7 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -174,6 +174,10 @@ +
+ +
+
diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 2f86f5c8..4a1409db 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -22,6 +22,7 @@ * PopupProxy * PopupProxyHost * apiForward + * apiOptionsGet */ async function main() { @@ -30,8 +31,11 @@ async function main() { const data = window.frontendInitializationData || {}; const {id, depth=0, parentFrameId, url, proxy=false} = data; + const optionsContext = {depth, url}; + const options = await apiOptionsGet(optionsContext); + let popup; - if (!proxy && (window !== window.parent)) { + if (!proxy && (window !== window.parent) && options.general.showIframePopupsInRootFrame) { const rootPopupInformationPromise = yomichan.getTemporaryListenerResult( chrome.runtime.onMessage, ({action, params}, {resolve}) => { -- cgit v1.2.3