diff options
Diffstat (limited to 'ext/fg')
| -rw-r--r-- | ext/fg/js/content-script-main.js | 31 | ||||
| -rw-r--r-- | ext/fg/js/float.js | 23 | ||||
| -rw-r--r-- | ext/fg/js/frontend.js | 55 | ||||
| -rw-r--r-- | ext/fg/js/popup-proxy-host.js | 17 | ||||
| -rw-r--r-- | ext/fg/js/popup-proxy.js | 19 | ||||
| -rw-r--r-- | ext/fg/js/popup.js | 27 | 
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              }); |