aboutsummaryrefslogtreecommitdiff
path: root/ext/fg/js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fg/js')
-rw-r--r--ext/fg/js/content-script-main.js31
-rw-r--r--ext/fg/js/float.js23
-rw-r--r--ext/fg/js/frontend.js55
-rw-r--r--ext/fg/js/popup-proxy-host.js17
-rw-r--r--ext/fg/js/popup-proxy.js19
-rw-r--r--ext/fg/js/popup.js27
6 files changed, 104 insertions, 68 deletions
diff --git a/ext/fg/js/content-script-main.js b/ext/fg/js/content-script-main.js
index 14285536..0b852644 100644
--- a/ext/fg/js/content-script-main.js
+++ b/ext/fg/js/content-script-main.js
@@ -25,7 +25,7 @@
* apiOptionsGet
*/
-async function createIframePopupProxy(url, frameOffsetForwarder, setDisabled) {
+async function createIframePopupProxy(frameOffsetForwarder, setDisabled) {
const rootPopupInformationPromise = yomichan.getTemporaryListenerResult(
chrome.runtime.onMessage,
({action, params}, {resolve}) => {
@@ -39,7 +39,7 @@ async function createIframePopupProxy(url, frameOffsetForwarder, setDisabled) {
const getFrameOffset = frameOffsetForwarder.getOffset.bind(frameOffsetForwarder);
- const popup = new PopupProxy(popupId, 0, null, frameId, url, getFrameOffset, setDisabled);
+ const popup = new PopupProxy(popupId, 0, null, frameId, getFrameOffset, setDisabled);
await popup.prepare();
return popup;
@@ -54,8 +54,8 @@ async function getOrCreatePopup(depth) {
return popup;
}
-async function createPopupProxy(depth, id, parentFrameId, url) {
- const popup = new PopupProxy(null, depth + 1, id, parentFrameId, url);
+async function createPopupProxy(depth, id, parentFrameId) {
+ const popup = new PopupProxy(null, depth + 1, id, parentFrameId);
await popup.prepare();
return popup;
@@ -86,8 +86,22 @@ async function createPopupProxy(depth, id, parentFrameId, url) {
applyOptions();
};
+ let urlUpdatedAt = 0;
+ let proxyHostUrlCached = url;
+ const getProxyHostUrl = async () => {
+ const now = Date.now();
+ if (popups.proxy !== null && now - urlUpdatedAt > 500) {
+ proxyHostUrlCached = await popups.proxy.getHostUrl();
+ urlUpdatedAt = now;
+ }
+ return proxyHostUrlCached;
+ };
+
const applyOptions = async () => {
- const optionsContext = {depth: isSearchPage ? 0 : depth, url};
+ const optionsContext = {
+ depth: isSearchPage ? 0 : depth,
+ url: proxy ? await getProxyHostUrl() : window.location.href
+ };
const options = await apiOptionsGet(optionsContext);
if (!proxy && frameOffsetForwarder === null) {
@@ -97,10 +111,10 @@ async function createPopupProxy(depth, id, parentFrameId, url) {
let popup;
if (isIframe && options.general.showIframePopupsInRootFrame && DOM.getFullscreenElement() === null && iframePopupsInRootFrameAvailable) {
- popup = popups.iframe || await createIframePopupProxy(url, frameOffsetForwarder, disableIframePopupsInRootFrame);
+ popup = popups.iframe || await createIframePopupProxy(frameOffsetForwarder, disableIframePopupsInRootFrame);
popups.iframe = popup;
} else if (proxy) {
- popup = popups.proxy || await createPopupProxy(depth, id, parentFrameId, url);
+ popup = popups.proxy || await createPopupProxy(depth, id, parentFrameId);
popups.proxy = popup;
} else {
popup = popups.normal || await getOrCreatePopup(depth);
@@ -108,7 +122,8 @@ async function createPopupProxy(depth, id, parentFrameId, url) {
}
if (frontend === null) {
- frontend = new Frontend(popup);
+ const getUrl = proxy ? getProxyHostUrl : null;
+ frontend = new Frontend(popup, getUrl);
frontendPreparePromise = frontend.prepare();
await frontendPreparePromise;
} else {
diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js
index 18d15a72..2a5eba83 100644
--- a/ext/fg/js/float.js
+++ b/ext/fg/js/float.js
@@ -29,11 +29,6 @@ class DisplayFloat extends Display {
this._popupId = null;
- this.optionsContext = {
- depth: 0,
- url: window.location.href
- };
-
this._orphaned = false;
this._prepareInvoked = false;
this._messageToken = null;
@@ -51,10 +46,11 @@ class DisplayFloat extends Display {
]);
this._windowMessageHandlers = new Map([
+ ['setOptionsContext', ({optionsContext}) => this.setOptionsContext(optionsContext)],
['setContent', ({type, details}) => this.setContent(type, details)],
['clearAutoPlayTimer', () => this.clearAutoPlayTimer()],
['setCustomCss', ({css}) => this.setCustomCss(css)],
- ['prepare', ({popupInfo, url, childrenSupported, scale}) => this.prepare(popupInfo, url, childrenSupported, scale)],
+ ['prepare', ({popupInfo, optionsContext, childrenSupported, scale}) => this.prepare(popupInfo, optionsContext, childrenSupported, scale)],
['setContentScale', ({scale}) => this.setContentScale(scale)]
]);
@@ -62,18 +58,20 @@ class DisplayFloat extends Display {
window.addEventListener('message', this.onMessage.bind(this), false);
}
- async prepare(popupInfo, url, childrenSupported, scale) {
+ async prepare(popupInfo, optionsContext, childrenSupported, scale) {
if (this._prepareInvoked) { return; }
this._prepareInvoked = true;
- const {id, depth, parentFrameId} = popupInfo;
+ const {id, parentFrameId} = popupInfo;
this._popupId = id;
- this.optionsContext.depth = depth;
- this.optionsContext.url = url;
+
+ this.optionsContext = optionsContext;
await super.prepare();
+ await this.updateOptions();
if (childrenSupported) {
+ const {depth, url} = optionsContext;
popupNestedInitialize(id, depth, parentFrameId, url);
}
@@ -158,6 +156,11 @@ class DisplayFloat extends Display {
}
}
+ async setOptionsContext(optionsContext) {
+ this.optionsContext = optionsContext;
+ await this.updateOptions();
+ }
+
setContentScale(scale) {
document.body.style.fontSize = `${scale}em`;
}
diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js
index eecfe2e1..46921d36 100644
--- a/ext/fg/js/frontend.js
+++ b/ext/fg/js/frontend.js
@@ -26,24 +26,23 @@
*/
class Frontend extends TextScanner {
- constructor(popup) {
+ constructor(popup, getUrl=null) {
super(
window,
() => this.popup.isProxy() ? [] : [this.popup.getContainer()],
[(x, y) => this.popup.containsPoint(x, y)]
);
+ this._id = yomichan.generateId(16);
+
this.popup = popup;
+ this._getUrl = getUrl;
+
this._disabledOverride = false;
this.options = null;
- this.optionsContext = {
- depth: popup.depth,
- url: popup.url
- };
-
this._pageZoomFactor = 1.0;
this._contentScale = 1.0;
this._orphaned = false;
@@ -143,11 +142,12 @@ class Frontend extends TextScanner {
async setPopup(popup) {
this.onSearchClear(false);
this.popup = popup;
- await popup.setOptions(this.options);
+ await popup.setOptionsContext(await this.getOptionsContext(), this._id);
}
async updateOptions() {
- this.options = await apiOptionsGet(this.getOptionsContext());
+ const optionsContext = await this.getOptionsContext();
+ this.options = await apiOptionsGet(optionsContext);
this.setOptions(this.options, this._canEnable());
const ignoreNodes = ['.scan-disable', '.scan-disable *'];
@@ -156,7 +156,7 @@ class Frontend extends TextScanner {
}
this.ignoreNodes = ignoreNodes.join(',');
- await this.popup.setOptions(this.options);
+ await this.popup.setOptionsContext(optionsContext, this._id);
this._updateContentScale();
@@ -170,19 +170,20 @@ class Frontend extends TextScanner {
try {
if (textSource !== null) {
+ const optionsContext = await this.getOptionsContext();
results = (
- await this.findTerms(textSource) ||
- await this.findKanji(textSource)
+ await this.findTerms(textSource, optionsContext) ||
+ await this.findKanji(textSource, optionsContext)
);
if (results !== null) {
const focus = (cause === 'mouse');
- this.showContent(textSource, focus, results.definitions, results.type);
+ this.showContent(textSource, focus, results.definitions, results.type, optionsContext);
}
}
} catch (e) {
if (this._orphaned) {
if (textSource !== null && this.options.scanning.modifier !== 'none') {
- this._showPopupContent(textSource, 'orphaned');
+ this._showPopupContent(textSource, await this.getOptionsContext(), 'orphaned');
}
} else {
this.onError(e);
@@ -196,11 +197,12 @@ class Frontend extends TextScanner {
return results;
}
- showContent(textSource, focus, definitions, type) {
+ showContent(textSource, focus, definitions, type, optionsContext) {
+ const {url} = optionsContext;
const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
- const url = window.location.href;
this._showPopupContent(
textSource,
+ optionsContext,
type,
{definitions, context: {sentence, url, focus, disableHistory: true}}
);
@@ -210,13 +212,13 @@ class Frontend extends TextScanner {
return this._lastShowPromise;
}
- async findTerms(textSource) {
+ async findTerms(textSource, optionsContext) {
this.setTextSourceScanLength(textSource, this.options.scanning.length);
const searchText = textSource.text();
if (searchText.length === 0) { return null; }
- const {definitions, length} = await apiTermsFind(searchText, {}, this.getOptionsContext());
+ const {definitions, length} = await apiTermsFind(searchText, {}, optionsContext);
if (definitions.length === 0) { return null; }
textSource.setEndOffset(length);
@@ -224,13 +226,13 @@ class Frontend extends TextScanner {
return {definitions, type: 'terms'};
}
- async findKanji(textSource) {
+ async findKanji(textSource, optionsContext) {
this.setTextSourceScanLength(textSource, 1);
const searchText = textSource.text();
if (searchText.length === 0) { return null; }
- const definitions = await apiKanjiFind(searchText, this.getOptionsContext());
+ const definitions = await apiKanjiFind(searchText, optionsContext);
if (definitions.length === 0) { return null; }
return {definitions, type: 'kanji'};
@@ -242,17 +244,20 @@ class Frontend extends TextScanner {
super.onSearchClear(changeFocus);
}
- getOptionsContext() {
- this.optionsContext.url = this.popup.url;
- return this.optionsContext;
+ async getOptionsContext() {
+ const url = this._getUrl !== null ? await this._getUrl() : window.location.href;
+ const depth = this.popup.depth;
+ return {depth, url};
}
- _showPopupContent(textSource, type=null, details=null) {
+ _showPopupContent(textSource, optionsContext, type=null, details=null) {
+ const context = {optionsContext, source: this._id};
this._lastShowPromise = this.popup.showContent(
textSource.getRect(),
textSource.getWritingMode(),
type,
- details
+ details,
+ context
);
return this._lastShowPromise;
}
@@ -294,7 +299,7 @@ class Frontend extends TextScanner {
async _updatePopupPosition() {
const textSource = this.getCurrentTextSource();
if (textSource !== null && await this.popup.isVisible()) {
- this._showPopupContent(textSource);
+ this._showPopupContent(textSource, await this.getOptionsContext());
}
}
diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js
index 958462ff..d87553e6 100644
--- a/ext/fg/js/popup-proxy-host.js
+++ b/ext/fg/js/popup-proxy-host.js
@@ -37,7 +37,7 @@ class PopupProxyHost {
this._apiReceiver = new FrontendApiReceiver(`popup-proxy-host#${this._frameId}`, new Map([
['getOrCreatePopup', this._onApiGetOrCreatePopup.bind(this)],
- ['setOptions', this._onApiSetOptions.bind(this)],
+ ['setOptionsContext', this._onApiSetOptionsContext.bind(this)],
['hide', this._onApiHide.bind(this)],
['isVisible', this._onApiIsVisibleAsync.bind(this)],
['setVisibleOverride', this._onApiSetVisibleOverride.bind(this)],
@@ -45,7 +45,8 @@ class PopupProxyHost {
['showContent', this._onApiShowContent.bind(this)],
['setCustomCss', this._onApiSetCustomCss.bind(this)],
['clearAutoPlayTimer', this._onApiClearAutoPlayTimer.bind(this)],
- ['setContentScale', this._onApiSetContentScale.bind(this)]
+ ['setContentScale', this._onApiSetContentScale.bind(this)],
+ ['getHostUrl', this._onApiGetHostUrl.bind(this)]
]));
}
@@ -103,9 +104,9 @@ class PopupProxyHost {
};
}
- async _onApiSetOptions({id, options}) {
+ async _onApiSetOptionsContext({id, optionsContext, source}) {
const popup = this._getPopup(id);
- return await popup.setOptions(options);
+ return await popup.setOptionsContext(optionsContext, source);
}
async _onApiHide({id, changeFocus}) {
@@ -129,11 +130,11 @@ class PopupProxyHost {
return await popup.containsPoint(x, y);
}
- async _onApiShowContent({id, elementRect, writingMode, type, details}) {
+ async _onApiShowContent({id, elementRect, writingMode, type, details, context}) {
const popup = this._getPopup(id);
elementRect = PopupProxyHost._convertJsonRectToDOMRect(popup, elementRect);
if (!PopupProxyHost._popupCanShow(popup)) { return; }
- return await popup.showContent(elementRect, writingMode, type, details);
+ return await popup.showContent(elementRect, writingMode, type, details, context);
}
async _onApiSetCustomCss({id, css}) {
@@ -151,6 +152,10 @@ class PopupProxyHost {
return popup.setContentScale(scale);
}
+ async _onApiGetHostUrl() {
+ return window.location.href;
+ }
+
// Private functions
_getPopup(id) {
diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js
index 3af83db2..cd3c1bc9 100644
--- a/ext/fg/js/popup-proxy.js
+++ b/ext/fg/js/popup-proxy.js
@@ -20,12 +20,11 @@
*/
class PopupProxy {
- constructor(id, depth, parentId, parentFrameId, url, getFrameOffset=null, setDisabled=null) {
+ constructor(id, depth, parentId, parentFrameId, getFrameOffset=null, setDisabled=null) {
this._parentId = parentId;
this._parentFrameId = parentFrameId;
this._id = id;
this._depth = depth;
- this._url = url;
this._apiSender = new FrontendApiSender();
this._getFrameOffset = getFrameOffset;
this._setDisabled = setDisabled;
@@ -49,10 +48,6 @@ class PopupProxy {
return this._depth;
}
- get url() {
- return this._url;
- }
-
// Public functions
async prepare() {
@@ -64,8 +59,8 @@ class PopupProxy {
return true;
}
- async setOptions(options) {
- return await this._invokeHostApi('setOptions', {id: this._id, options});
+ async setOptionsContext(optionsContext, source) {
+ return await this._invokeHostApi('setOptionsContext', {id: this._id, optionsContext, source});
}
hide(changeFocus) {
@@ -88,14 +83,14 @@ class PopupProxy {
return await this._invokeHostApi('containsPoint', {id: this._id, x, y});
}
- async showContent(elementRect, writingMode, type=null, details=null) {
+ async showContent(elementRect, writingMode, type, details, context) {
let {x, y, width, height} = elementRect;
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});
+ return await this._invokeHostApi('showContent', {id: this._id, elementRect, writingMode, type, details, context});
}
async setCustomCss(css) {
@@ -110,6 +105,10 @@ class PopupProxy {
this._invokeHostApi('setContentScale', {id: this._id, scale});
}
+ async getHostUrl() {
+ return await this._invokeHostApi('getHostUrl', {});
+ }
+
// Private
_invokeHostApi(action, params={}) {
diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js
index ae158263..e735431b 100644
--- a/ext/fg/js/popup.js
+++ b/ext/fg/js/popup.js
@@ -19,6 +19,7 @@
* DOM
* apiGetMessageToken
* apiInjectStylesheet
+ * apiOptionsGet
*/
class Popup {
@@ -33,10 +34,12 @@ class Popup {
this._visible = false;
this._visibleOverride = null;
this._options = null;
+ this._optionsContext = null;
this._contentScale = 1.0;
this._containerSizeContentScale = null;
this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, '');
this._messageToken = null;
+ this._previousOptionsContextSource = null;
this._container = document.createElement('iframe');
this._container.className = 'yomichan-float';
@@ -72,19 +75,20 @@ class Popup {
return this._frameId;
}
- get url() {
- return window.location.href;
- }
-
// Public functions
isProxy() {
return false;
}
- async setOptions(options) {
- this._options = options;
+ async setOptionsContext(optionsContext, source) {
+ this._optionsContext = optionsContext;
+ this._previousOptionsContextSource = source;
+
+ this._options = await apiOptionsGet(optionsContext);
this.updateTheme();
+
+ this._invokeApi('setOptionsContext', {optionsContext});
}
hide(changeFocus) {
@@ -120,8 +124,14 @@ class Popup {
return false;
}
- async showContent(elementRect, writingMode, type=null, details=null) {
+ async showContent(elementRect, writingMode, type, details, context) {
if (this._options === null) { throw new Error('Options not assigned'); }
+
+ const {optionsContext, source} = context;
+ if (source !== this._previousOptionsContextSource) {
+ await this.setOptionsContext(optionsContext, source);
+ }
+
await this._show(elementRect, writingMode);
if (type === null) { return; }
this._invokeApi('setContent', {type, details});
@@ -219,10 +229,9 @@ class Popup {
this._invokeApi('prepare', {
popupInfo: {
id: this._id,
- depth: this._depth,
parentFrameId
},
- url: this.url,
+ optionsContext: this._optionsContext,
childrenSupported: this._childrenSupported,
scale: this._contentScale
});