Merge pull request #417 from siikamiika/iframe-popups-2

Show iframe popups on root page
This commit is contained in:
siikamiika 2020-04-05 21:19:28 +03:00 committed by GitHub
commit 3df78904cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 308 additions and 108 deletions

View File

@ -108,7 +108,8 @@
"enableClipboardMonitor", "enableClipboardMonitor",
"showPitchAccentDownstepNotation", "showPitchAccentDownstepNotation",
"showPitchAccentPositionNotation", "showPitchAccentPositionNotation",
"showPitchAccentGraph" "showPitchAccentGraph",
"showIframePopupsInRootFrame"
], ],
"properties": { "properties": {
"enable": { "enable": {
@ -242,6 +243,10 @@
"showPitchAccentGraph": { "showPitchAccentGraph": {
"type": "boolean", "type": "boolean",
"default": false "default": false
},
"showIframePopupsInRootFrame": {
"type": "boolean",
"default": false
} }
} }
}, },

View File

@ -127,7 +127,8 @@ function profileOptionsCreateDefaults() {
enableClipboardMonitor: false, enableClipboardMonitor: false,
showPitchAccentDownstepNotation: true, showPitchAccentDownstepNotation: true,
showPitchAccentPositionNotation: true, showPitchAccentPositionNotation: true,
showPitchAccentGraph: false showPitchAccentGraph: false,
showIframePopupsInRootFrame: false
}, },
audio: { audio: {

View File

@ -35,6 +35,7 @@ async function searchFrontendSetup() {
const scriptSrcs = [ const scriptSrcs = [
'/mixed/js/text-scanner.js', '/mixed/js/text-scanner.js',
'/fg/js/frontend-api-receiver.js', '/fg/js/frontend-api-receiver.js',
'/fg/js/frame-offset-forwarder.js',
'/fg/js/popup.js', '/fg/js/popup.js',
'/fg/js/popup-proxy-host.js', '/fg/js/popup-proxy-host.js',
'/fg/js/frontend.js', '/fg/js/frontend.js',

View File

@ -87,6 +87,7 @@ async function formRead(options) {
options.general.showPitchAccentDownstepNotation = $('#show-pitch-accent-downstep-notation').prop('checked'); options.general.showPitchAccentDownstepNotation = $('#show-pitch-accent-downstep-notation').prop('checked');
options.general.showPitchAccentPositionNotation = $('#show-pitch-accent-position-notation').prop('checked'); options.general.showPitchAccentPositionNotation = $('#show-pitch-accent-position-notation').prop('checked');
options.general.showPitchAccentGraph = $('#show-pitch-accent-graph').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.popupTheme = $('#popup-theme').val();
options.general.popupOuterTheme = $('#popup-outer-theme').val(); options.general.popupOuterTheme = $('#popup-outer-theme').val();
options.general.customPopupCss = $('#custom-popup-css').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-downstep-notation').prop('checked', options.general.showPitchAccentDownstepNotation);
$('#show-pitch-accent-position-notation').prop('checked', options.general.showPitchAccentPositionNotation); $('#show-pitch-accent-position-notation').prop('checked', options.general.showPitchAccentPositionNotation);
$('#show-pitch-accent-graph').prop('checked', options.general.showPitchAccentGraph); $('#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-theme').val(options.general.popupTheme);
$('#popup-outer-theme').val(options.general.popupOuterTheme); $('#popup-outer-theme').val(options.general.popupOuterTheme);
$('#custom-popup-css').val(options.general.customPopupCss); $('#custom-popup-css').val(options.general.customPopupCss);

View File

@ -174,6 +174,10 @@
<label><input type="checkbox" id="show-pitch-accent-graph"> Show graph for pitch accents</label> <label><input type="checkbox" id="show-pitch-accent-graph"> Show graph for pitch accents</label>
</div> </div>
<div class="checkbox options-advanced">
<label><input type="checkbox" id="show-iframe-popups-in-root-frame"> Show iframe popups in root frame</label>
</div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="show-debug-info"> Show debug information</label> <label><input type="checkbox" id="show-debug-info"> Show debug information</label>
</div> </div>

View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2020 Alex Yatskov <alex@foosoft.net>
* Author: Alex Yatskov <alex@foosoft.net>
*
* 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 <https://www.gnu.org/licenses/>.
*/
/* global
* apiForward
*/
class FrameOffsetForwarder {
constructor() {
this._started = false;
this._forwardFrameOffset = (
window !== window.parent ?
this._forwardFrameOffsetParent.bind(this) :
this._forwardFrameOffsetOrigin.bind(this)
);
this._windowMessageHandlers = new Map([
['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 getOffset() {
const uniqueId = yomichan.generateId(16);
const frameOffsetPromise = yomichan.getTemporaryListenerResult(
chrome.runtime.onMessage,
({action, params}, {resolve}) => {
if (action === 'frameOffset' && isObject(params) && params.uniqueId === uniqueId) {
resolve(params);
}
},
5000
);
window.parent.postMessage({
action: 'getFrameOffset',
params: {
uniqueId,
offset: [0, 0]
}
}, '*');
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) {
this._forwardFrameOffsetOrigin(null, uniqueId);
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});
}
}

View File

@ -17,9 +17,12 @@
*/ */
/* global /* global
* FrameOffsetForwarder
* Frontend * Frontend
* PopupProxy * PopupProxy
* PopupProxyHost * PopupProxyHost
* apiForward
* apiOptionsGet
*/ */
async function main() { async function main() {
@ -28,10 +31,35 @@ async function main() {
const data = window.frontendInitializationData || {}; const data = window.frontendInitializationData || {};
const {id, depth=0, parentFrameId, url, proxy=false} = data; const {id, depth=0, parentFrameId, url, proxy=false} = data;
const optionsContext = {depth, url};
const options = await apiOptionsGet(optionsContext);
let popup; let popup;
if (proxy) { if (!proxy && (window !== window.parent) && options.general.showIframePopupsInRootFrame) {
const rootPopupInformationPromise = yomichan.getTemporaryListenerResult(
chrome.runtime.onMessage,
({action, params}, {resolve}) => {
if (action === 'rootPopupInformation') {
resolve(params);
}
}
);
apiForward('rootPopupRequestInformationBroadcast');
const {popupId, frameId} = await rootPopupInformationPromise;
const frameOffsetForwarder = new FrameOffsetForwarder();
frameOffsetForwarder.start();
const getFrameOffset = frameOffsetForwarder.getOffset.bind(frameOffsetForwarder);
popup = new PopupProxy(popupId, 0, null, frameId, url, getFrameOffset);
await popup.prepare();
} else if (proxy) {
popup = new PopupProxy(null, depth + 1, id, parentFrameId, url); popup = new PopupProxy(null, depth + 1, id, parentFrameId, url);
await popup.prepare();
} else { } else {
const frameOffsetForwarder = new FrameOffsetForwarder();
frameOffsetForwarder.start();
const popupHost = new PopupProxyHost(); const popupHost = new PopupProxyHost();
await popupHost.prepare(); await popupHost.prepare();

View File

@ -18,6 +18,7 @@
/* global /* global
* TextScanner * TextScanner
* apiForward
* apiGetZoom * apiGetZoom
* apiKanjiFind * apiKanjiFind
* apiOptionsGet * apiOptionsGet
@ -52,7 +53,8 @@ class Frontend extends TextScanner {
]); ]);
this._runtimeMessageHandlers = new Map([ this._runtimeMessageHandlers = new Map([
['popupSetVisibleOverride', ({visible}) => { this.popup.setVisibleOverride(visible); }] ['popupSetVisibleOverride', ({visible}) => { this.popup.setVisibleOverride(visible); }],
['rootPopupRequestInformationBroadcast', () => { this._broadcastRootPopupInformation(); }]
]); ]);
} }
@ -76,6 +78,7 @@ class Frontend extends TextScanner {
chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this)); chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this));
this._updateContentScale(); this._updateContentScale();
this._broadcastRootPopupInformation();
} catch (e) { } catch (e) {
this.onError(e); this.onError(e);
} }
@ -255,6 +258,12 @@ class Frontend extends TextScanner {
this._updatePopupPosition(); this._updatePopupPosition();
} }
_broadcastRootPopupInformation() {
if (!this.popup.isProxy() && this.popup.depth === 0) {
apiForward('rootPopupInformation', {popupId: this.popup.id, frameId: this.popup.frameId});
}
}
async _updatePopupPosition() { async _updatePopupPosition() {
const textSource = this.getCurrentTextSource(); const textSource = this.getCurrentTextSource();
if (textSource !== null && await this.popup.isVisible()) { if (textSource !== null && await this.popup.isVisible()) {

View File

@ -26,17 +26,17 @@ class PopupProxyHost {
constructor() { constructor() {
this._popups = new Map(); this._popups = new Map();
this._apiReceiver = null; this._apiReceiver = null;
this._frameIdPromise = null; this._frameId = null;
} }
// Public functions // Public functions
async prepare() { async prepare() {
this._frameIdPromise = apiFrameInformationGet(); const {frameId} = await apiFrameInformationGet();
const {frameId} = await this._frameIdPromise;
if (typeof frameId !== 'number') { return; } if (typeof frameId !== 'number') { return; }
this._frameId = frameId;
this._apiReceiver = new FrontendApiReceiver(`popup-proxy-host#${frameId}`, new Map([ this._apiReceiver = new FrontendApiReceiver(`popup-proxy-host#${this._frameId}`, new Map([
['getOrCreatePopup', this._onApiGetOrCreatePopup.bind(this)], ['getOrCreatePopup', this._onApiGetOrCreatePopup.bind(this)],
['setOptions', this._onApiSetOptions.bind(this)], ['setOptions', this._onApiSetOptions.bind(this)],
['hide', this._onApiHide.bind(this)], ['hide', this._onApiHide.bind(this)],
@ -87,7 +87,7 @@ class PopupProxyHost {
} else if (depth === null) { } else if (depth === null) {
depth = 0; depth = 0;
} }
const popup = new Popup(id, depth, this._frameIdPromise); const popup = new Popup(id, depth, this._frameId);
if (parent !== null) { if (parent !== null) {
popup.setParent(parent); popup.setParent(parent);
} }
@ -95,7 +95,7 @@ class PopupProxyHost {
return popup; return popup;
} }
// Message handlers // API message handlers
async _onApiGetOrCreatePopup({id, parentId}) { async _onApiGetOrCreatePopup({id, parentId}) {
const popup = this.getOrCreatePopup(id, parentId); const popup = this.getOrCreatePopup(id, parentId);

View File

@ -21,14 +21,18 @@
*/ */
class PopupProxy { class PopupProxy {
constructor(id, depth, parentId, parentFrameId, url) { constructor(id, depth, parentId, parentFrameId, url, getFrameOffset=null) {
this._parentId = parentId; this._parentId = parentId;
this._parentFrameId = parentFrameId; this._parentFrameId = parentFrameId;
this._id = id; this._id = id;
this._idPromise = null;
this._depth = depth; this._depth = depth;
this._url = url; this._url = url;
this._apiSender = new FrontendApiSender(); this._apiSender = new FrontendApiSender();
this._getFrameOffset = getFrameOffset;
this._frameOffset = null;
this._frameOffsetPromise = null;
this._frameOffsetUpdatedAt = null;
} }
// Public properties // Public properties
@ -51,79 +55,63 @@ class PopupProxy {
// Public functions // Public functions
async prepare() {
const {id} = await this._invokeHostApi('getOrCreatePopup', {id: this._id, parentId: this._parentId});
this._id = id;
}
isProxy() { isProxy() {
return true; return true;
} }
async setOptions(options) { async setOptions(options) {
const id = await this._getPopupId(); return await this._invokeHostApi('setOptions', {id: this._id, options});
return await this._invokeHostApi('setOptions', {id, options});
} }
hide(changeFocus) { hide(changeFocus) {
if (this._id === null) {
return;
}
this._invokeHostApi('hide', {id: this._id, changeFocus}); this._invokeHostApi('hide', {id: this._id, changeFocus});
} }
async isVisible() { async isVisible() {
const id = await this._getPopupId(); return await this._invokeHostApi('isVisible', {id: this._id});
return await this._invokeHostApi('isVisible', {id});
} }
setVisibleOverride(visible) { setVisibleOverride(visible) {
if (this._id === null) {
return;
}
this._invokeHostApi('setVisibleOverride', {id: this._id, visible}); this._invokeHostApi('setVisibleOverride', {id: this._id, visible});
} }
async containsPoint(x, y) { async containsPoint(x, y) {
if (this._id === null) { if (this._getFrameOffset !== null) {
return false; await this._updateFrameOffset();
[x, y] = this._applyFrameOffset(x, y);
} }
return await this._invokeHostApi('containsPoint', {id: this._id, x, y}); return await this._invokeHostApi('containsPoint', {id: this._id, x, y});
} }
async showContent(elementRect, writingMode, type=null, details=null) { async showContent(elementRect, writingMode, type=null, details=null) {
const id = await this._getPopupId(); let {x, y, width, height} = elementRect;
elementRect = PopupProxy._convertDOMRectToJson(elementRect); if (this._getFrameOffset !== null) {
return await this._invokeHostApi('showContent', {id, elementRect, writingMode, type, details}); 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});
} }
async setCustomCss(css) { async setCustomCss(css) {
const id = await this._getPopupId(); return await this._invokeHostApi('setCustomCss', {id: this._id, css});
return await this._invokeHostApi('setCustomCss', {id, css});
} }
clearAutoPlayTimer() { clearAutoPlayTimer() {
if (this._id === null) {
return;
}
this._invokeHostApi('clearAutoPlayTimer', {id: this._id}); this._invokeHostApi('clearAutoPlayTimer', {id: this._id});
} }
async setContentScale(scale) { async setContentScale(scale) {
const id = await this._getPopupId(); this._invokeHostApi('setContentScale', {id: this._id, scale});
this._invokeHostApi('setContentScale', {id, scale});
} }
// Private // 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={}) { _invokeHostApi(action, params={}) {
if (typeof this._parentFrameId !== 'number') { if (typeof this._parentFrameId !== 'number') {
return Promise.reject(new Error('Invalid frame')); return Promise.reject(new Error('Invalid frame'));
@ -131,12 +119,42 @@ class PopupProxy {
return this._apiSender.invoke(action, params, `popup-proxy-host#${this._parentFrameId}`); return this._apiSender.invoke(action, params, `popup-proxy-host#${this._parentFrameId}`);
} }
static _convertDOMRectToJson(domRect) { async _updateFrameOffset() {
return { const now = Date.now();
x: domRect.x, const firstRun = this._frameOffsetUpdatedAt === null;
y: domRect.y, const expired = firstRun || this._frameOffsetUpdatedAt < now - PopupProxy._frameOffsetExpireTimeout;
width: domRect.width, if (this._frameOffsetPromise === null && !expired) { return; }
height: domRect.height
}; if (this._frameOffsetPromise !== null) {
if (firstRun) {
await this._frameOffsetPromise;
}
return;
}
const promise = this._updateFrameOffsetInner(now);
if (firstRun) {
await promise;
}
}
async _updateFrameOffsetInner(now) {
this._frameOffsetPromise = this._getFrameOffset();
try {
const offset = await this._frameOffsetPromise;
this._frameOffset = offset !== null ? offset : [0, 0];
this._frameOffsetUpdatedAt = now;
} catch (e) {
logError(e);
} finally {
this._frameOffsetPromise = null;
}
}
_applyFrameOffset(x, y) {
const [offsetX, offsetY] = this._frameOffset;
return [x + offsetX, y + offsetY];
} }
} }
PopupProxy._frameOffsetExpireTimeout = 1000;

View File

@ -22,11 +22,10 @@
*/ */
class Popup { class Popup {
constructor(id, depth, frameIdPromise) { constructor(id, depth, frameId) {
this._id = id; this._id = id;
this._depth = depth; this._depth = depth;
this._frameIdPromise = frameIdPromise; this._frameId = frameId;
this._frameId = null;
this._parent = null; this._parent = null;
this._child = null; this._child = null;
this._childrenSupported = true; this._childrenSupported = true;
@ -69,6 +68,10 @@ class Popup {
return this._depth; return this._depth;
} }
get frameId() {
return this._frameId;
}
get url() { get url() {
return window.location.href; return window.location.href;
} }
@ -193,25 +196,26 @@ class Popup {
} }
async _createInjectPromise() { async _createInjectPromise() {
try {
const {frameId} = await this._frameIdPromise;
if (typeof frameId === 'number') {
this._frameId = frameId;
}
} catch (e) {
// NOP
}
if (this._messageToken === null) { if (this._messageToken === null) {
this._messageToken = await apiGetMessageToken(); this._messageToken = await apiGetMessageToken();
} }
return new Promise((resolve) => { const popupPreparedPromise = yomichan.getTemporaryListenerResult(
chrome.runtime.onMessage,
({action, params}, {resolve}) => {
if (
action === 'popupPrepareCompleted' &&
isObject(params) &&
params.targetPopupId === this._id
) {
resolve();
}
}
);
const parentFrameId = (typeof this._frameId === 'number' ? this._frameId : null); const parentFrameId = (typeof this._frameId === 'number' ? this._frameId : null);
this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html')); this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html'));
this._container.addEventListener('load', () => { this._container.addEventListener('load', () => {
this._listenForDisplayPrepareCompleted(resolve);
this._invokeApi('prepare', { this._invokeApi('prepare', {
popupInfo: { popupInfo: {
id: this._id, id: this._id,
@ -226,7 +230,8 @@ class Popup {
this._observeFullscreen(true); this._observeFullscreen(true);
this._onFullscreenChanged(); this._onFullscreenChanged();
this._injectStyles(); this._injectStyles();
});
return popupPreparedPromise;
} }
async _injectStyles() { async _injectStyles() {
@ -361,22 +366,6 @@ class Popup {
contentWindow.postMessage({action, params, token}, this._targetOrigin); contentWindow.postMessage({action, params, token}, this._targetOrigin);
} }
_listenForDisplayPrepareCompleted(resolve) {
const runtimeMessageCallback = ({action, params}, sender, callback) => {
if (
action === 'popupPrepareCompleted' &&
isObject(params) &&
params.targetPopupId === this._id
) {
chrome.runtime.onMessage.removeListener(runtimeMessageCallback);
callback();
resolve();
return false;
}
};
chrome.runtime.onMessage.addListener(runtimeMessageCallback);
}
static _getFullscreenElement() { static _getFullscreenElement() {
return ( return (
document.fullscreenElement || document.fullscreenElement ||

View File

@ -23,9 +23,12 @@
"mixed/js/api.js", "mixed/js/api.js",
"mixed/js/text-scanner.js", "mixed/js/text-scanner.js",
"fg/js/document.js", "fg/js/document.js",
"fg/js/frontend-api-sender.js",
"fg/js/frontend-api-receiver.js", "fg/js/frontend-api-receiver.js",
"fg/js/popup.js", "fg/js/popup.js",
"fg/js/source.js", "fg/js/source.js",
"fg/js/frame-offset-forwarder.js",
"fg/js/popup-proxy.js",
"fg/js/popup-proxy-host.js", "fg/js/popup-proxy-host.js",
"fg/js/frontend.js", "fg/js/frontend.js",
"fg/js/frontend-initialize.js" "fg/js/frontend-initialize.js"

View File

@ -278,11 +278,16 @@ const yomichan = (() => {
constructor() { constructor() {
super(); super();
this._isBackendPreparedResolve = null; this._isBackendPreparedPromise = this.getTemporaryListenerResult(
this._isBackendPreparedPromise = new Promise((resolve) => (this._isBackendPreparedResolve = resolve)); chrome.runtime.onMessage,
({action}, {resolve}) => {
if (action === 'backendPrepared') {
resolve();
}
}
);
this._messageHandlers = new Map([ this._messageHandlers = new Map([
['backendPrepared', this._onBackendPrepared.bind(this)],
['getUrl', this._onMessageGetUrl.bind(this)], ['getUrl', this._onMessageGetUrl.bind(this)],
['optionsUpdated', this._onMessageOptionsUpdated.bind(this)], ['optionsUpdated', this._onMessageOptionsUpdated.bind(this)],
['zoomChanged', this._onMessageZoomChanged.bind(this)] ['zoomChanged', this._onMessageZoomChanged.bind(this)]
@ -312,6 +317,42 @@ const yomichan = (() => {
this.trigger('orphaned', {error}); this.trigger('orphaned', {error});
} }
getTemporaryListenerResult(eventHandler, userCallback, timeout=null) {
if (!(
typeof eventHandler.addListener === 'function' &&
typeof eventHandler.removeListener === 'function'
)) {
throw new Error('Event handler type not supported');
}
return new Promise((resolve, reject) => {
const runtimeMessageCallback = ({action, params}, sender, sendResponse) => {
let timeoutId = null;
if (timeout !== null) {
timeoutId = window.setTimeout(() => {
timeoutId = null;
eventHandler.removeListener(runtimeMessageCallback);
reject(new Error(`Listener timed out in ${timeout} ms`));
}, timeout);
}
const cleanupResolve = (value) => {
if (timeoutId !== null) {
window.clearTimeout(timeoutId);
timeoutId = null;
}
eventHandler.removeListener(runtimeMessageCallback);
sendResponse();
resolve(value);
};
userCallback({action, params}, {resolve: cleanupResolve, sender});
};
eventHandler.addListener(runtimeMessageCallback);
});
}
// Private // Private
_onMessage({action, params}, sender, callback) { _onMessage({action, params}, sender, callback) {
@ -323,10 +364,6 @@ const yomichan = (() => {
return false; return false;
} }
_onBackendPrepared() {
this._isBackendPreparedResolve();
}
_onMessageGetUrl() { _onMessageGetUrl() {
return {url: window.location.href}; return {url: window.location.href};
} }

View File

@ -27,7 +27,8 @@ require('fake-indexeddb/auto');
const chrome = { const chrome = {
runtime: { runtime: {
onMessage: { onMessage: {
addListener() { /* NOP */ } addListener() { /* NOP */ },
removeListener() { /* NOP */ }
}, },
getURL(path2) { getURL(path2) {
return url.pathToFileURL(path.join(__dirname, '..', 'ext', path2.replace(/^\//, ''))); return url.pathToFileURL(path.join(__dirname, '..', 'ext', path2.replace(/^\//, '')));