diff options
| author | Darius Jahandarie <djahandarie@gmail.com> | 2023-10-01 12:43:45 +0900 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-01 12:43:45 +0900 | 
| commit | 0fbfeb883eb4ca03b9a802757138fef9a6835cdc (patch) | |
| tree | d752d7594d8302f149eb6aa30485a324ab7aa883 /ext/js | |
| parent | ea1c147730bef183855f5dc079c9a2d19e1c623e (diff) | |
| parent | 0fa8d441a269b13474e6ad4108f49497d4d3abfd (diff) | |
Merge branch 'master' into dependabot/github_actions/cardinalby/schema-validator-action-3.0.0
Diffstat (limited to 'ext/js')
| -rw-r--r-- | ext/js/background/backend.js | 4 | ||||
| -rw-r--r-- | ext/js/background/request-builder.js | 1 | ||||
| -rw-r--r-- | ext/js/background/script-manager.js | 115 | ||||
| -rw-r--r-- | ext/js/language/text-scanner.js | 3 | ||||
| -rw-r--r-- | ext/js/pages/settings/recommended-permissions-controller.js | 74 | ||||
| -rw-r--r-- | ext/js/pages/welcome-main.js | 4 | 
6 files changed, 95 insertions, 106 deletions
| diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index db6cfada..dd233abb 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -593,7 +593,7 @@ class Backend {      async _onApiInjectStylesheet({type, value}, sender) {          const {frameId, tab} = sender;          if (!isObject(tab)) { throw new Error('Invalid tab'); } -        return await this._scriptManager.injectStylesheet(type, value, tab.id, frameId, false, true, 'document_start'); +        return await this._scriptManager.injectStylesheet(type, value, tab.id, frameId, false);      }      async _onApiGetStylesheetContent({url}) { @@ -790,7 +790,7 @@ class Backend {          if (typeof tabId !== 'number') { throw new Error('Sender has invalid tab ID'); }          const {frameId} = sender;          for (const file of files) { -            await this._scriptManager.injectScript(file, tabId, frameId, false, true, 'document_start'); +            await this._scriptManager.injectScript(file, tabId, frameId, false);          }      } diff --git a/ext/js/background/request-builder.js b/ext/js/background/request-builder.js index eca7d0d3..663e242b 100644 --- a/ext/js/background/request-builder.js +++ b/ext/js/background/request-builder.js @@ -54,7 +54,6 @@ class RequestBuilder {       * @returns {Promise<Response>} The response of the `fetch` call.       */      async fetchAnonymous(url, init) { -        fetch(1, 2);          if (isObject(chrome.declarativeNetRequest)) {              return await this._fetchAnonymousDeclarative(url, init);          } diff --git a/ext/js/background/script-manager.js b/ext/js/background/script-manager.js index 722a46f0..694b64db 100644 --- a/ext/js/background/script-manager.js +++ b/ext/js/background/script-manager.js @@ -36,14 +36,10 @@ class ScriptManager {       * @param {number} tabId The id of the tab to inject into.       * @param {number} [frameId] The id of the frame to inject into.       * @param {boolean} [allFrames] Whether or not the stylesheet should be injected into all frames. -     * @param {boolean} [matchAboutBlank] Whether or not the stylesheet should be injected into about:blank frames. -     * @param {string} [runAt] The time to inject the stylesheet at.       * @returns {Promise<void>}       */ -    injectStylesheet(type, content, tabId, frameId, allFrames, matchAboutBlank, runAt) { -        if (isObject(chrome.tabs) && typeof chrome.tabs.insertCSS === 'function') { -            return this._injectStylesheetMV2(type, content, tabId, frameId, allFrames, matchAboutBlank, runAt); -        } else if (isObject(chrome.scripting) && typeof chrome.scripting.insertCSS === 'function') { +    injectStylesheet(type, content, tabId, frameId, allFrames) { +        if (isObject(chrome.scripting) && typeof chrome.scripting.insertCSS === 'function') {              return this._injectStylesheetMV3(type, content, tabId, frameId, allFrames);          } else {              return Promise.reject(new Error('Stylesheet injection not supported')); @@ -56,14 +52,10 @@ class ScriptManager {       * @param {number} tabId The id of the tab to inject into.       * @param {number} [frameId] The id of the frame to inject into.       * @param {boolean} [allFrames] Whether or not the script should be injected into all frames. -     * @param {boolean} [matchAboutBlank] Whether or not the script should be injected into about:blank frames. -     * @param {string} [runAt] The time to inject the script at.       * @returns {Promise<{frameId: number, result: object}>} The id of the frame and the result of the script injection.       */ -    injectScript(file, tabId, frameId, allFrames, matchAboutBlank, runAt) { -        if (isObject(chrome.tabs) && typeof chrome.tabs.executeScript === 'function') { -            return this._injectScriptMV2(file, tabId, frameId, allFrames, matchAboutBlank, runAt); -        } else if (isObject(chrome.scripting) && typeof chrome.scripting.executeScript === 'function') { +    injectScript(file, tabId, frameId, allFrames) { +        if (isObject(chrome.scripting) && typeof chrome.scripting.executeScript === 'function') {              return this._injectScriptMV3(file, tabId, frameId, allFrames);          } else {              return Promise.reject(new Error('Script injection not supported')); @@ -122,19 +114,6 @@ class ScriptManager {              throw new Error('Registration already exists');          } -        // Firefox -        if ( -            typeof browser === 'object' && browser !== null && -            isObject(browser.contentScripts) && -            typeof browser.contentScripts.register === 'function' -        ) { -            const details2 = this._convertContentScriptRegistrationDetails(details, id, true); -            const registration = await browser.contentScripts.register(details2); -            this._contentScriptRegistrations.set(id, registration); -            return; -        } - -        // Chrome          if (isObject(chrome.scripting) && typeof chrome.scripting.registerContentScripts === 'function') {              const details2 = this._convertContentScriptRegistrationDetails(details, id, false);              await new Promise((resolve, reject) => { @@ -161,18 +140,17 @@ class ScriptManager {       * @returns {Promise<boolean>} `true` if the content script was unregistered, `false` otherwise.       */      async unregisterContentScript(id) { -        // Chrome          if (isObject(chrome.scripting) && typeof chrome.scripting.unregisterContentScripts === 'function') {              this._contentScriptRegistrations.delete(id);              try { -                await this._unregisterContentScriptChrome(id); +                await this._unregisterContentScriptMV3(id);                  return true;              } catch (e) {                  return false;              }          } -        // Firefox or fallback +        // Fallback          const registration = this._contentScriptRegistrations.get(id);          if (typeof registration === 'undefined') { return false; }          this._contentScriptRegistrations.delete(id); @@ -187,19 +165,7 @@ class ScriptManager {       * @returns {string[]} An array of the required permissions, which may be empty.       */      getRequiredContentScriptRegistrationPermissions() { -        if ( -            // Firefox -            ( -                typeof browser === 'object' && browser !== null && -                isObject(browser.contentScripts) && -                typeof browser.contentScripts.register === 'function' -            ) || -            // Chrome -            ( -                isObject(chrome.scripting) && -                typeof chrome.scripting.registerContentScripts === 'function' -            ) -        ) { +        if (isObject(chrome.scripting) && typeof chrome.scripting.registerContentScripts === 'function') {              return [];          } @@ -209,45 +175,12 @@ class ScriptManager {      // Private -    _injectStylesheetMV2(type, content, tabId, frameId, allFrames, matchAboutBlank, runAt) { -        return new Promise((resolve, reject) => { -            const details = ( -                type === 'file' ? -                { -                    file: content, -                    runAt, -                    cssOrigin: 'author', -                    allFrames, -                    matchAboutBlank -                } : -                { -                    code: content, -                    runAt, -                    cssOrigin: 'user', -                    allFrames, -                    matchAboutBlank -                } -            ); -            if (typeof frameId === 'number') { -                details.frameId = frameId; -            } -            chrome.tabs.insertCSS(tabId, details, () => { -                const e = chrome.runtime.lastError; -                if (e) { -                    reject(new Error(e.message)); -                } else { -                    resolve(); -                } -            }); -        }); -    } -      _injectStylesheetMV3(type, content, tabId, frameId, allFrames) {          return new Promise((resolve, reject) => {              const details = (                  type === 'file' ? -                {origin: chrome.scripting.StyleOrigin.AUTHOR, files: [content]} : -                {origin: chrome.scripting.StyleOrigin.USER,   css: content} +                {origin: 'AUTHOR', files: [content]} : +                {origin: 'USER',   css: content}              );              details.target = {                  tabId, @@ -267,27 +200,6 @@ class ScriptManager {          });      } -    _injectScriptMV2(file, tabId, frameId, allFrames, matchAboutBlank, runAt) { -        return new Promise((resolve, reject) => { -            const details = { -                allFrames, -                frameId, -                file, -                matchAboutBlank, -                runAt -            }; -            chrome.tabs.executeScript(tabId, details, (results) => { -                const e = chrome.runtime.lastError; -                if (e) { -                    reject(new Error(e.message)); -                } else { -                    const result = results[0]; -                    resolve({frameId, result}); -                } -            }); -        }); -    } -      _injectScriptMV3(file, tabId, frameId, allFrames) {          return new Promise((resolve, reject) => {              const details = { @@ -310,7 +222,7 @@ class ScriptManager {          });      } -    _unregisterContentScriptChrome(id) { +    _unregisterContentScriptMV3(id) {          return new Promise((resolve, reject) => {              chrome.scripting.unregisterContentScripts({ids: [id]}, () => {                  const e = chrome.runtime.lastError; @@ -407,7 +319,7 @@ class ScriptManager {          const {urlRegex} = details;          if (urlRegex !== null && !urlRegex.test(url)) { return; } -        let {allFrames, css, js, matchAboutBlank, runAt} = details; +        let {allFrames, css, js, runAt} = details;          if (isWebNavigation) {              if (allFrames) { @@ -425,14 +337,13 @@ class ScriptManager {          const promises = [];          if (Array.isArray(css)) { -            const runAtCss = (typeof runAt === 'string' ? runAt : 'document_start');              for (const file of css) { -                promises.push(this.injectStylesheet('file', file, tabId, frameId, allFrames, matchAboutBlank, runAtCss)); +                promises.push(this.injectStylesheet('file', file, tabId, frameId, allFrames));              }          }          if (Array.isArray(js)) {              for (const file of js) { -                promises.push(this.injectScript(file, tabId, frameId, allFrames, matchAboutBlank, runAt)); +                promises.push(this.injectScript(file, tabId, frameId, allFrames));              }          }          await Promise.all(promises); diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js index 6fa7a454..af5cc8fe 100644 --- a/ext/js/language/text-scanner.js +++ b/ext/js/language/text-scanner.js @@ -145,7 +145,8 @@ class TextScanner extends EventDispatcher {          if (value) {              this._hookEvents(); -            this._userHasNotSelectedAnythingManually = window.getSelection().isCollapsed; +            const selection = window.getSelection(); +            this._userHasNotSelectedAnythingManually = (selection === null) ? true : selection.isCollapsed;          }      } diff --git a/ext/js/pages/settings/recommended-permissions-controller.js b/ext/js/pages/settings/recommended-permissions-controller.js new file mode 100644 index 00000000..3d25d5eb --- /dev/null +++ b/ext/js/pages/settings/recommended-permissions-controller.js @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023  Yomitan Authors + * Copyright (C) 2021-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/>. + */ + +class RecommendedPermissionsController { +    constructor(settingsController) { +        this._settingsController = settingsController; +        this._originToggleNodes = null; +        this._eventListeners = new EventListenerCollection(); +        this._errorContainer = null; +    } + +    async prepare() { +        this._originToggleNodes = document.querySelectorAll('.recommended-permissions-toggle'); +        this._errorContainer = document.querySelector('#recommended-permissions-error'); +        for (const node of this._originToggleNodes) { +            node.addEventListener('change', this._onOriginToggleChange.bind(this), false); +        } + +        this._settingsController.on('permissionsChanged', this._onPermissionsChanged.bind(this)); +        await this._updatePermissions(); +    } + +    // Private + +    _onPermissionsChanged({permissions}) { +        this._eventListeners.removeAllEventListeners(); +        const originsSet = new Set(permissions.origins); +        for (const node of this._originToggleNodes) { +            node.checked = originsSet.has(node.dataset.origin); +        } +    } + +    _onOriginToggleChange(e) { +        const node = e.currentTarget; +        const value = node.checked; +        node.checked = !value; + +        const {origin} = node.dataset; +        this._setOriginPermissionEnabled(origin, value); +    } + +    async _updatePermissions() { +        const permissions = await this._settingsController.permissionsUtil.getAllPermissions(); +        this._onPermissionsChanged({permissions}); +    } + +    async _setOriginPermissionEnabled(origin, enabled) { +        let added = false; +        try { +            added = await this._settingsController.permissionsUtil.setPermissionsGranted({origins: [origin]}, enabled); +        } catch (e) { +            this._errorContainer.hidden = false; +            this._errorContainer.textContent = e.message; +        } +        if (!added) { return false; } +        await this._updatePermissions(); +        return true; +    } +} diff --git a/ext/js/pages/welcome-main.js b/ext/js/pages/welcome-main.js index eb8bd675..521ce2c2 100644 --- a/ext/js/pages/welcome-main.js +++ b/ext/js/pages/welcome-main.js @@ -23,6 +23,7 @@   * ExtensionContentController   * GenericSettingController   * ModalController + * RecommendedPermissionsController   * ScanInputsSimpleController   * SettingsController   * SettingsDisplayController @@ -77,6 +78,9 @@ async function setupGenericSettingsController(genericSettingController) {          const simpleScanningInputController = new ScanInputsSimpleController(settingsController);          simpleScanningInputController.prepare(); +        const recommendedPermissionsController = new RecommendedPermissionsController(settingsController); +        recommendedPermissionsController.prepare(); +          await Promise.all(preparePromises);          document.documentElement.dataset.loaded = 'true'; |