Pop-up dictionary browser extension for language learning. Successor to Yomichan. (PERSONAL FORK)
at lambda-fork/main 147 lines 4.6 kB view raw
1/* 2 * Copyright (C) 2023-2025 Yomitan Authors 3 * Copyright (C) 2021-2022 Yomichan Authors 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 19import {getFieldMarkers} from './anki-util.js'; 20 21/** 22 * This function returns whether an Anki field marker might require clipboard permissions. 23 * This is speculative and may not guarantee that the field marker actually does require the permission, 24 * as the custom handlebars template is not deeply inspected. 25 * @param {string} marker 26 * @returns {boolean} 27 */ 28function ankiFieldMarkerMayUseClipboard(marker) { 29 switch (marker) { 30 case 'clipboard-image': 31 case 'clipboard-text': 32 return true; 33 default: 34 return false; 35 } 36} 37 38/** 39 * @param {chrome.permissions.Permissions} permissions 40 * @returns {Promise<boolean>} 41 */ 42export function hasPermissions(permissions) { 43 return new Promise((resolve, reject) => { 44 chrome.permissions.contains(permissions, (result) => { 45 const e = chrome.runtime.lastError; 46 if (e) { 47 reject(new Error(e.message)); 48 } else { 49 resolve(result); 50 } 51 }); 52 }); 53} 54 55/** 56 * @param {chrome.permissions.Permissions} permissions 57 * @param {boolean} shouldHave 58 * @returns {Promise<boolean>} 59 */ 60export function setPermissionsGranted(permissions, shouldHave) { 61 return ( 62 shouldHave ? 63 new Promise((resolve, reject) => { 64 chrome.permissions.request(permissions, (result) => { 65 const e = chrome.runtime.lastError; 66 if (e) { 67 reject(new Error(e.message)); 68 } else { 69 resolve(result); 70 } 71 }); 72 }) : 73 new Promise((resolve, reject) => { 74 chrome.permissions.remove(permissions, (result) => { 75 const e = chrome.runtime.lastError; 76 if (e) { 77 reject(new Error(e.message)); 78 } else { 79 resolve(!result); 80 } 81 }); 82 }) 83 ); 84} 85 86/** 87 * @returns {Promise<chrome.permissions.Permissions>} 88 */ 89export function getAllPermissions() { 90 return new Promise((resolve, reject) => { 91 chrome.permissions.getAll((result) => { 92 const e = chrome.runtime.lastError; 93 if (e) { 94 reject(new Error(e.message)); 95 } else { 96 resolve(result); 97 } 98 }); 99 }); 100} 101 102/** 103 * @param {string} fieldValue 104 * @returns {string[]} 105 */ 106export function getRequiredPermissionsForAnkiFieldValue(fieldValue) { 107 const markers = getFieldMarkers(fieldValue); 108 for (const marker of markers) { 109 if (ankiFieldMarkerMayUseClipboard(marker)) { 110 return ['clipboardRead']; 111 } 112 } 113 return []; 114} 115 116/** 117 * @param {chrome.permissions.Permissions} permissions 118 * @param {import('settings').ProfileOptions} options 119 * @returns {boolean} 120 */ 121export function hasRequiredPermissionsForOptions(permissions, options) { 122 const permissionsSet = new Set(permissions.permissions); 123 124 if (!permissionsSet.has('nativeMessaging') && (options.parsing.enableMecabParser || options.general.enableYomitanApi)) { 125 return false; 126 } 127 128 if (!permissionsSet.has('clipboardRead')) { 129 if (options.clipboard.enableBackgroundMonitor || options.clipboard.enableSearchPageMonitor) { 130 return false; 131 } 132 const fieldsList = options.anki.cardFormats.map((cardFormat) => cardFormat.fields); 133 134 for (const fields of fieldsList) { 135 for (const {value: fieldValue} of Object.values(fields)) { 136 const markers = getFieldMarkers(fieldValue); 137 for (const marker of markers) { 138 if (ankiFieldMarkerMayUseClipboard(marker)) { 139 return false; 140 } 141 } 142 } 143 } 144 } 145 146 return true; 147}