diff options
Diffstat (limited to 'ext/js/background/backend.js')
| -rw-r--r-- | ext/js/background/backend.js | 73 | 
1 files changed, 67 insertions, 6 deletions
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 565f4abf..57565eec 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -57,12 +57,19 @@ class Backend {          });          this._anki = new AnkiConnect();          this._mecab = new Mecab(); -        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' -        }); + +        this._clipboardReader = { +            getText: this._getTextOffscreen.bind(this) +        }; +        if (!chrome || !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' +            }); +        } +          this._clipboardMonitor = new ClipboardMonitor({              japaneseUtil: this._japaneseUtil,              clipboardReader: this._clipboardReader @@ -97,6 +104,8 @@ class Backend {          this._permissions = null;          this._permissionsUtil = new PermissionsUtil(); +        this._creatingOffscreen = null; +          this._messageHandlers = new Map([              ['requestBackendReadySignal',    {async: false, contentScript: true,  handler: this._onApiRequestBackendReadySignal.bind(this)}],              ['optionsGet',                   {async: false, contentScript: true,  handler: this._onApiOptionsGet.bind(this)}], @@ -557,6 +566,21 @@ 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');      } @@ -2262,4 +2286,41 @@ class Backend {          return {targetTabId, targetFrameId};      } + +    // https://developer.chrome.com/docs/extensions/reference/offscreen/ +    async _setupOffscreenDocument() { +        // Check all windows controlled by the service worker to see if one +        // of them is the offscreen document with the given path +        if (await this._hasOffscreenDocument()) { +            return; +        } + +        // create offscreen document +        if (this._creatingOffscreen) { +            await this._creatingOffscreen; +        } else { +            this._creatingOffscreen = chrome.offscreen.createDocument({ +                url: 'offscreen.html', +                reasons: ['CLIPBOARD'], +                justification: 'reason for needing the document' +            }); +            await this._creatingOffscreen; +            this._creatingOffscreen = null; +        } +    } +    async _hasOffscreenDocument() { +        const offscreenUrl = chrome.runtime.getURL('offscreen.html'); +        if (chrome.runtime.getContexts) { +            const contexts = await chrome.runtime.getContexts({ +                contextTypes: ['OFFSCREEN_DOCUMENT'], +                documentUrls: [offscreenUrl] +            }); +            return Boolean(contexts.length); +        } else { +            const matchedClients = await clients.matchAll(); +            return await matchedClients.some((client) => { +                client.url.includes(chrome.runtime.id); +            }); +        } +    }  }  |