diff options
| -rw-r--r-- | dev/data/manifest-variants.json | 26 | ||||
| -rw-r--r-- | docs/permissions.md | 5 | ||||
| -rw-r--r-- | ext/css/offscreen.css | 30 | ||||
| -rw-r--r-- | ext/js/background/backend.js | 52 | ||||
| -rw-r--r-- | ext/js/background/offscreen-main.js (renamed from ext/js/offscreen/offscreen-main.js) | 0 | ||||
| -rw-r--r-- | ext/js/background/offscreen.js (renamed from ext/js/offscreen/offscreen.js) | 7 | ||||
| -rw-r--r-- | ext/offscreen.html | 4 | 
7 files changed, 61 insertions, 63 deletions
| diff --git a/dev/data/manifest-variants.json b/dev/data/manifest-variants.json index 7f91e582..82f78961 100644 --- a/dev/data/manifest-variants.json +++ b/dev/data/manifest-variants.json @@ -82,7 +82,8 @@              "unlimitedStorage",              "webRequest",              "declarativeNetRequest", -            "scripting" +            "scripting", +            "offscreen"          ],          "optional_permissions": [              "clipboardRead", @@ -167,15 +168,6 @@                      "pattern": "^(.*)(?:\\.\\s*)?$",                      "patternFlags": "",                      "replacement": "$1. This is a development build." -                }, -                { -                    "action": "add", -                    "path": [ -                        "permissions" -                    ], -                    "items": [ -                        "offscreen" -                    ]                  }              ]          }, @@ -263,6 +255,13 @@                          "permissions"                      ],                      "item": "declarativeNetRequest" +                }, +                { +                    "action": "remove", +                    "path": [ +                        "permissions" +                    ], +                    "item": "offscreen"                  }              ],              "excludeFiles": [ @@ -338,6 +337,13 @@                      "item": "webRequestBlocking"                  },                  { +                    "action": "remove", +                    "path": [ +                        "permissions" +                    ], +                    "item": "offscreen" +                }, +                {                      "action": "delete",                      "path": [                          "content_scripts", diff --git a/docs/permissions.md b/docs/permissions.md index b337bb31..4fa7ab83 100644 --- a/docs/permissions.md +++ b/docs/permissions.md @@ -23,6 +23,11 @@    Yomichan will sometimes need to inject stylesheets into webpages in order to    properly display the search popup. +* `offscreen` __(Manifest v3 only)_ <br> +  Yomitan uses this permission to create a secondary backend document that has DOM access, given that Manifest v3 +  service workers do not. Service workers can then reach out to out to this document in order to complete +  actions that require access to DOM APIs, such as any that require clipboard access. +  * `clipboardWrite` <br>    Yomichan supports simulating the `Ctrl+C` (copy to clipboard) keyboard shortcut    when a definitions popup is open and focused. diff --git a/ext/css/offscreen.css b/ext/css/offscreen.css deleted file mode 100644 index ab283025..00000000 --- a/ext/css/offscreen.css +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2023  Yomitan Authors - * Copyright (C) 2022  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/>. - */ - -/* stylelint-disable declaration-no-important */ -#clipboard-rich-content-paste-target * { -    background-image: none !important; -    list-style-image: none !important; -    content: none !important; -    cursor: auto !important; -    border-image-source: none !important; -    offset-path: none !important; -    -webkit-mask-image: none !important; -    mask-image: none !important; -} -/* stylelint-enable declaration-no-important */ diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index f5cbb349..308ae4d5 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -58,16 +58,18 @@ class Backend {          this._anki = new AnkiConnect();          this._mecab = new Mecab(); -        this._clipboardReader = { -            getText: this._getTextOffscreen.bind(this) -        }; -        if (!chrome || !chrome.offscreen) { +        if (!chrome.offscreen) {              this._clipboardReader = new ClipboardReader({                  // eslint-disable-next-line no-undef                  document: (typeof document === 'object' && document !== null ? document : null),                  pasteTargetSelector: '#clipboard-paste-target',                  richContentPasteTargetSelector: '#clipboard-rich-content-paste-target'              }); +        } else { +            this._clipboardReader = { +                getText: this._getTextOffscreen.bind(this), +                getImage: this._getImageOffscreen.bind(this) +            };          }          this._clipboardMonitor = new ClipboardMonitor({ @@ -227,6 +229,9 @@ class Backend {              await this._requestBuilder.prepare();              await this._environment.prepare(); +            if (chrome.offscreen) { +                await this._setupOffscreenDocument(); +            }              this._clipboardReader.browser = this._environment.getInfo().browser;              try { @@ -566,21 +571,6 @@ class Backend {          return this._clipboardReader.getText(false);      } -    async _getTextOffscreen(useRichText) { -        await this._setupOffscreenDocument(); -        return new Promise((resolve, reject) => { -            const callback = (response) => { -                try { -                    resolve(this._getMessageResponseResult(response)); -                } catch (error) { -                    reject(error); -                } -            }; - -            chrome.runtime.sendMessage({action: 'clipboardGetOffscreen', params: {useRichText}}, callback); -        }); -    } -      async _onApiGetDisplayTemplatesHtml() {          return await this._fetchAsset('/display-templates.html');      } @@ -1634,6 +1624,20 @@ class Backend {          return await (json ? response.json() : response.text());      } +    _sendMessagePromise(...args) { +        return new Promise((resolve, reject) => { +            const callback = (response) => { +                try { +                    resolve(this._getMessageResponseResult(response)); +                } catch (error) { +                    reject(error); +                } +            }; + +            chrome.runtime.sendMessage(...args, callback); +        }); +    } +      _sendMessageIgnoreResponse(...args) {          const callback = () => this._checkLastError(chrome.runtime.lastError);          chrome.runtime.sendMessage(...args, callback); @@ -2244,6 +2248,14 @@ class Backend {          return results;      } +    async _getTextOffscreen(useRichText) { +        return this._sendMessagePromise({action: 'clipboardGetTextOffscreen', params: {useRichText}}); +    } + +    async _getImageOffscreen() { +        return this._sendMessagePromise({action: 'clipboardGetImageOffscreen'}); +    } +      _onApiOpenCrossFramePort({targetTabId, targetFrameId}, sender) {          const sourceTabId = (sender && sender.tab ? sender.tab.id : null);          if (typeof sourceTabId !== 'number') { @@ -2300,7 +2312,7 @@ class Backend {          this._creatingOffscreen = chrome.offscreen.createDocument({              url: 'offscreen.html',              reasons: ['CLIPBOARD'], -            justification: 'reason for needing the document' +            justification: 'Access to the clipboard'          });          await this._creatingOffscreen;          this._creatingOffscreen = null; diff --git a/ext/js/offscreen/offscreen-main.js b/ext/js/background/offscreen-main.js index 808e7766..808e7766 100644 --- a/ext/js/offscreen/offscreen-main.js +++ b/ext/js/background/offscreen-main.js diff --git a/ext/js/offscreen/offscreen.js b/ext/js/background/offscreen.js index 31e2c5d6..bc41d189 100644 --- a/ext/js/offscreen/offscreen.js +++ b/ext/js/background/offscreen.js @@ -37,7 +37,8 @@ class Offscreen {          });          this._messageHandlers = new Map([ -            ['clipboardGetOffscreen',                 {async: true,  contentScript: true,  handler: this._getTextHandler.bind(this)}] +            ['clipboardGetTextOffscreen',                 {async: true,  contentScript: true,  handler: this._getTextHandler.bind(this)}], +            ['clipboardGetImageOffscreen',                 {async: true,  contentScript: true,  handler: this._getImageHandler.bind(this)}]          ]);          const onMessage = this._onMessage.bind(this); @@ -48,6 +49,10 @@ class Offscreen {          return this._clipboardReader.getText(useRichText);      } +    _getImageHandler() { +        return this._clipboardReader.getImage(); +    } +      _onMessage({action, params}, sender, callback) {          const messageHandler = this._messageHandlers.get(action);          if (typeof messageHandler === 'undefined') { return false; } diff --git a/ext/offscreen.html b/ext/offscreen.html index 11694636..f773e5b1 100644 --- a/ext/offscreen.html +++ b/ext/offscreen.html @@ -24,8 +24,8 @@  <script src="/js/comm/clipboard-reader.js"></script> -<script src="/js/offscreen/offscreen.js"></script> -<script src="/js/offscreen/offscreen-main.js"></script> +<script src="/js/background/offscreen.js"></script> +<script src="/js/background/offscreen-main.js"></script>  <!--      Due to a Firefox bug, this next element is purposefully terminated incorrectly. |