diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/bg/data/options-schema.json | 7 | ||||
| -rw-r--r-- | ext/bg/js/options.js | 4 | ||||
| -rw-r--r-- | ext/bg/settings.html | 4 | ||||
| -rw-r--r-- | ext/fg/js/frontend.js | 18 | ||||
| -rw-r--r-- | ext/fg/js/popup-factory.js | 13 | ||||
| -rw-r--r-- | ext/fg/js/popup-window.js | 161 | ||||
| -rw-r--r-- | ext/manifest.json | 1 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 1 | 
8 files changed, 204 insertions, 5 deletions
| diff --git a/ext/bg/data/options-schema.json b/ext/bg/data/options-schema.json index b56017bc..e2dd0573 100644 --- a/ext/bg/data/options-schema.json +++ b/ext/bg/data/options-schema.json @@ -111,7 +111,8 @@                                      "showPitchAccentGraph",                                      "showIframePopupsInRootFrame",                                      "useSecurePopupFrameUrl", -                                    "usePopupShadowDom" +                                    "usePopupShadowDom", +                                    "usePopupWindow"                                  ],                                  "properties": {                                      "enable": { @@ -257,6 +258,10 @@                                      "usePopupShadowDom": {                                          "type": "boolean",                                          "default": true +                                    }, +                                    "usePopupWindow": { +                                        "type": "boolean", +                                        "default": false                                      }                                  }                              }, diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index c513f572..1cabf2cf 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -467,6 +467,7 @@ class OptionsUtil {      static _updateVersion4(options) {          // Version 4 changes:          //  Options conditions converted to string representations. +        //  Added usePopupWindow.          for (const {conditionGroups} of options.profiles) {              for (const {conditions} of conditionGroups) {                  for (const condition of conditions) { @@ -479,6 +480,9 @@ class OptionsUtil {                  }              }          } +        for (const {options: profileOptions} of options.profiles) { +            profileOptions.general.usePopupWindow = false; +        }          return options;      }  } diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 878ea02d..a999a9d9 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -181,6 +181,10 @@                  </div>                  <div class="checkbox options-advanced"> +                    <label><input type="checkbox" data-setting="general.usePopupWindow"> Use a native popup window when scanning text on web pages</label> +                </div> + +                <div class="checkbox options-advanced">                      <label><input type="checkbox" data-setting="general.useSecurePopupFrameUrl"> Use secure popup frame URL</label>                  </div> diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 8c4cfc82..b9656882 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -307,11 +307,17 @@ class Frontend {      }      async _updatePopup() { -        const showIframePopupsInRootFrame = this._options.general.showIframePopupsInRootFrame; +        const {usePopupWindow, showIframePopupsInRootFrame} = this._options.general;          const isIframe = !this._useProxyPopup && (window !== window.parent);          let popupPromise; -        if ( +        if (usePopupWindow) { +            popupPromise = this._popupCache.get('window'); +            if (typeof popupPromise === 'undefined') { +                popupPromise = this._getPopupWindow(); +                this._popupCache.set('window', popupPromise); +            } +        } else if (              isIframe &&              showIframePopupsInRootFrame &&              DocumentUtil.getFullscreenElement() === null && @@ -404,6 +410,14 @@ class Frontend {          return popup;      } +    async _getPopupWindow() { +        return await this._popupFactory.getOrCreatePopup({ +            ownerFrameId: this._frameId, +            depth: this._depth, +            popupWindow: true +        }); +    } +      _ignoreElements() {          if (this._popup !== null) {              const container = this._popup.container; diff --git a/ext/fg/js/popup-factory.js b/ext/fg/js/popup-factory.js index 72c875f7..3e817247 100644 --- a/ext/fg/js/popup-factory.js +++ b/ext/fg/js/popup-factory.js @@ -19,6 +19,7 @@   * FrameOffsetForwarder   * Popup   * PopupProxy + * PopupWindow   * api   */ @@ -52,7 +53,7 @@ class PopupFactory {          ]);      } -    async getOrCreatePopup({frameId=null, ownerFrameId=null, id=null, parentPopupId=null, depth=null}) { +    async getOrCreatePopup({frameId=null, ownerFrameId=null, id=null, parentPopupId=null, depth=null, popupWindow=false}) {          // Find by existing id          if (id !== null) {              const popup = this._popups.get(id); @@ -85,7 +86,15 @@ class PopupFactory {              depth = 0;          } -        if (frameId === this._frameId) { +        if (popupWindow) { +            // New unique id +            if (id === null) { +                id = generateId(16); +            } +            const popup = new PopupWindow(id, depth, this._frameId, ownerFrameId); +            this._popups.set(id, popup); +            return popup; +        } else if (frameId === this._frameId) {              // New unique id              if (id === null) {                  id = generateId(16); diff --git a/ext/fg/js/popup-window.js b/ext/fg/js/popup-window.js new file mode 100644 index 00000000..927a8bac --- /dev/null +++ b/ext/fg/js/popup-window.js @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2020  Yomichan Authors + * + * 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 + * api + */ + +class PopupWindow extends EventDispatcher { +    constructor(id, depth, frameId, ownerFrameId) { +        super(); +        this._id = id; +        this._depth = depth; +        this._frameId = frameId; +        this._ownerFrameId = ownerFrameId; +        this._popupTabId = null; +    } + +    // Public properties + +    get id() { +        return this._id; +    } + +    get parent() { +        return null; +    } + +    set parent(value) { +        throw new Error('Not supported on PopupProxy'); +    } + +    get child() { +        return null; +    } + +    set child(value) { +        throw new Error('Not supported on PopupProxy'); +    } + +    get depth() { +        return this._depth; +    } + +    get frameContentWindow() { +        return null; +    } + +    get container() { +        return null; +    } + +    get frameId() { +        return this._frameId; +    } + + +    // Public functions + +    setOptionsContext(optionsContext, source) { +        return this._invoke(false, 'setOptionsContext', {id: this._id, optionsContext, source}); +    } + +    hide(_changeFocus) { +        // NOP +    } + +    async isVisible() { +        return (this._popupTabId !== null && await api.isTabSearchPopup(this._popupTabId)); +    } + +    setVisibleOverride(_value, _priority) { +        return null; +    } + +    clearVisibleOverride(_token) { +        return false; +    } + +    async containsPoint(_x, _y) { +        return false; +    } + +    showContent(_details, displayDetails) { +        return this._invoke(true, 'setContent', {id: this._id, details: displayDetails}); +    } + +    setCustomCss(css) { +        return this._invoke(false, 'setCustomCss', {id: this._id, css}); +    } + +    clearAutoPlayTimer() { +        return this._invoke(false, 'clearAutoPlayTimer', {id: this._id}); +    } + +    setContentScale(_scale) { +        // NOP +    } + +    isVisibleSync() { +        throw new Error('Not supported on PopupWindow'); +    } + +    updateTheme() { +        // NOP +    } + +    async setCustomOuterCss(_css, _useWebExtensionApi) { +        // NOP +    } + +    async setChildrenSupported(_value) { +        // NOP +    } + +    getFrameRect() { +        return new DOMRect(0, 0, 0, 0); +    } + +    // Private + +    async _invoke(open, action, params={}, defaultReturnValue) { +        if (yomichan.isExtensionUnloaded) { +            return defaultReturnValue; +        } + +        const frameId = 0; +        if (this._popupTabId !== null) { +            try { +                return await api.crossFrame.invokeTab(this._popupTabId, frameId, 'popupMessage', {action, params}); +            } catch (e) { +                if (yomichan.isExtensionUnloaded) { +                    open = false; +                } +            } +            this._popupTabId = null; +        } + +        if (!open) { +            return defaultReturnValue; +        } + +        const {tabId} = await api.getOrCreateSearchPopup({focus: 'ifCreated'}); +        this._popupTabId = tabId; + +        return await api.crossFrame.invokeTab(this._popupTabId, frameId, 'popupMessage', {action, params}); +    } +} diff --git a/ext/manifest.json b/ext/manifest.json index 2851c89c..271f6e62 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -52,6 +52,7 @@                  "fg/js/popup-factory.js",                  "fg/js/frame-offset-forwarder.js",                  "fg/js/popup-proxy.js", +                "fg/js/popup-window.js",                  "fg/js/frontend.js",                  "fg/js/content-script-main.js"              ], diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 4a8605e5..ce7a4385 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -363,6 +363,7 @@ class Display extends EventDispatcher {              '/mixed/js/frame-client.js',              '/fg/js/popup.js',              '/fg/js/popup-proxy.js', +            '/fg/js/popup-window.js',              '/fg/js/popup-factory.js',              '/fg/js/frame-offset-forwarder.js',              '/fg/js/frontend.js' |