diff options
-rw-r--r-- | ext/bg/js/backend.js | 45 | ||||
-rw-r--r-- | ext/bg/js/options.js | 23 | ||||
-rw-r--r-- | ext/bg/js/settings/anki.js | 10 | ||||
-rw-r--r-- | ext/bg/js/settings/dictionaries.js | 12 | ||||
-rw-r--r-- | ext/bg/js/util.js | 42 | ||||
-rw-r--r-- | ext/fg/js/popup.js | 11 | ||||
-rw-r--r-- | ext/mixed/js/api.js | 24 | ||||
-rw-r--r-- | ext/mixed/js/core.js | 9 |
8 files changed, 105 insertions, 71 deletions
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 2265c1a9..04a3b932 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -100,7 +100,13 @@ class Backend { ['getQueryParserTemplatesHtml', {handler: this._onApiGetQueryParserTemplatesHtml.bind(this), async: true}], ['getZoom', {handler: this._onApiGetZoom.bind(this), async: true}], ['getMessageToken', {handler: this._onApiGetMessageToken.bind(this), async: false}], - ['getDefaultAnkiFieldTemplates', {handler: this._onApiGetDefaultAnkiFieldTemplates.bind(this), async: false}] + ['getDefaultAnkiFieldTemplates', {handler: this._onApiGetDefaultAnkiFieldTemplates.bind(this), async: false}], + ['getAnkiDeckNames', {handler: this._onApiGetAnkiDeckNames.bind(this), async: true}], + ['getAnkiModelNames', {handler: this._onApiGetAnkiModelNames.bind(this), async: true}], + ['getAnkiModelFieldNames', {handler: this._onApiGetAnkiModelFieldNames.bind(this), async: true}], + ['getDictionaryInfo', {handler: this._onApiGetDictionaryInfo.bind(this), async: true}], + ['getDictionaryCounts', {handler: this._onApiGetDictionaryCounts.bind(this), async: true}], + ['purgeDatabase', {handler: this._onApiPurgeDatabase.bind(this), async: true}] ]); this._commandHandlers = new Map([ @@ -722,6 +728,36 @@ class Backend { return this.defaultAnkiFieldTemplates; } + async _onApiGetAnkiDeckNames(params, sender) { + this._validatePrivilegedMessageSender(sender); + return await this.anki.getDeckNames(); + } + + async _onApiGetAnkiModelNames(params, sender) { + this._validatePrivilegedMessageSender(sender); + return await this.anki.getModelNames(); + } + + async _onApiGetAnkiModelFieldNames({modelName}, sender) { + this._validatePrivilegedMessageSender(sender); + return await this.anki.getModelFieldNames(modelName); + } + + async _onApiGetDictionaryInfo(params, sender) { + this._validatePrivilegedMessageSender(sender); + return await this.translator.database.getDictionaryInfo(); + } + + async _onApiGetDictionaryCounts({dictionaryNames, getTotal}, sender) { + this._validatePrivilegedMessageSender(sender); + return await this.translator.database.getDictionaryCounts(dictionaryNames, getTotal); + } + + async _onApiPurgeDatabase(params, sender) { + this._validatePrivilegedMessageSender(sender); + return await this.translator.purgeDatabase(); + } + // Command handlers async _onCommandSearch(params) { @@ -818,6 +854,13 @@ class Backend { // Utilities + _validatePrivilegedMessageSender(sender) { + const url = sender.url; + if (!(typeof url === 'string' && yomichan.isExtensionUrl(url))) { + throw new Error('Invalid message sender'); + } + } + async _getAudioUri(definition, source, details) { let optionsContext = (typeof details === 'object' && details !== null ? details.optionsContext : null); if (!(typeof optionsContext === 'object' && optionsContext !== null)) { diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index f3e5f60d..da26b628 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -15,14 +15,23 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -/* global - * utilStringHashCode - */ - /* * Generic options functions */ +function optionsGetStringHashCode(string) { + let hashCode = 0; + + if (typeof string !== 'string') { return hashCode; } + + for (let i = 0, charCode = string.charCodeAt(i); i < string.length; charCode = string.charCodeAt(++i)) { + hashCode = ((hashCode << 5) - hashCode) + charCode; + hashCode |= 0; + } + + return hashCode; +} + function optionsGenericApplyUpdates(options, updates) { const targetVersion = updates.length; const currentVersion = options.version; @@ -63,12 +72,12 @@ const profileOptionsVersionUpdates = [ options.anki.fieldTemplates = null; }, (options) => { - if (utilStringHashCode(options.anki.fieldTemplates) === 1285806040) { + if (optionsGetStringHashCode(options.anki.fieldTemplates) === 1285806040) { options.anki.fieldTemplates = null; } }, (options) => { - if (utilStringHashCode(options.anki.fieldTemplates) === -250091611) { + if (optionsGetStringHashCode(options.anki.fieldTemplates) === -250091611) { options.anki.fieldTemplates = null; } }, @@ -87,7 +96,7 @@ const profileOptionsVersionUpdates = [ (options) => { // Version 12 changes: // The preferred default value of options.anki.fieldTemplates has been changed to null. - if (utilStringHashCode(options.anki.fieldTemplates) === 1444379824) { + if (optionsGetStringHashCode(options.anki.fieldTemplates) === 1444379824) { options.anki.fieldTemplates = null; } }, diff --git a/ext/bg/js/settings/anki.js b/ext/bg/js/settings/anki.js index b32a9517..ff1277ed 100644 --- a/ext/bg/js/settings/anki.js +++ b/ext/bg/js/settings/anki.js @@ -16,13 +16,13 @@ */ /* global + * apiGetAnkiDeckNames + * apiGetAnkiModelFieldNames + * apiGetAnkiModelNames * getOptionsContext * getOptionsMutable * onFormOptionsChanged * settingsSaveOptions - * utilAnkiGetDeckNames - * utilAnkiGetModelFieldNames - * utilAnkiGetModelNames * utilBackgroundIsolate */ @@ -107,7 +107,7 @@ async function _ankiDeckAndModelPopulate(options) { const kanjiModel = {value: options.anki.kanji.model, selector: '#anki-kanji-model'}; try { _ankiSpinnerShow(true); - const [deckNames, modelNames] = await Promise.all([utilAnkiGetDeckNames(), utilAnkiGetModelNames()]); + const [deckNames, modelNames] = await Promise.all([apiGetAnkiDeckNames(), apiGetAnkiModelNames()]); deckNames.sort(); modelNames.sort(); termsDeck.values = deckNames; @@ -180,7 +180,7 @@ async function _onAnkiModelChanged(e) { let fieldNames; try { const modelName = node.value; - fieldNames = await utilAnkiGetModelFieldNames(modelName); + fieldNames = await apiGetAnkiModelFieldNames(modelName); _ankiSetError(null); } catch (error) { _ankiSetError(error); diff --git a/ext/bg/js/settings/dictionaries.js b/ext/bg/js/settings/dictionaries.js index 1a6d452b..7eed4273 100644 --- a/ext/bg/js/settings/dictionaries.js +++ b/ext/bg/js/settings/dictionaries.js @@ -17,8 +17,11 @@ /* global * PageExitPrevention + * apiGetDictionaryCounts + * apiGetDictionaryInfo * apiOptionsGet * apiOptionsGetFull + * apiPurgeDatabase * getOptionsContext * getOptionsFullMutable * getOptionsMutable @@ -27,10 +30,7 @@ * storageUpdateStats * utilBackgroundIsolate * utilDatabaseDeleteDictionary - * utilDatabaseGetDictionaryCounts - * utilDatabaseGetDictionaryInfo * utilDatabaseImport - * utilDatabasePurge */ let dictionaryUI = null; @@ -431,7 +431,7 @@ async function onDictionaryOptionsChanged() { async function onDatabaseUpdated() { try { - const dictionaries = await utilDatabaseGetDictionaryInfo(); + const dictionaries = await apiGetDictionaryInfo(); dictionaryUI.setDictionaries(dictionaries); document.querySelector('#dict-warning').hidden = (dictionaries.length > 0); @@ -439,7 +439,7 @@ async function onDatabaseUpdated() { updateMainDictionarySelectOptions(dictionaries); await updateMainDictionarySelectValue(); - const {counts, total} = await utilDatabaseGetDictionaryCounts(dictionaries.map((v) => v.title), true); + const {counts, total} = await apiGetDictionaryCounts(dictionaries.map((v) => v.title), true); dictionaryUI.setCounts(counts, total); } catch (e) { dictionaryErrorsShow([e]); @@ -618,7 +618,7 @@ async function onDictionaryPurge(e) { dictionaryErrorsShow(null); dictionarySpinnerShow(true); - await utilDatabasePurge(); + await apiPurgeDatabase(); for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) { options.dictionaries = utilBackgroundIsolate({}); options.general.mainDictionary = ''; diff --git a/ext/bg/js/util.js b/ext/bg/js/util.js index 69536f02..5edcc193 100644 --- a/ext/bg/js/util.js +++ b/ext/bg/js/util.js @@ -58,19 +58,6 @@ function utilBackgroundFunctionIsolate(func) { return backgroundPage.utilFunctionIsolate(func); } -function utilStringHashCode(string) { - let hashCode = 0; - - if (typeof string !== 'string') { return hashCode; } - - for (let i = 0, charCode = string.charCodeAt(i); i < string.length; charCode = string.charCodeAt(++i)) { - hashCode = ((hashCode << 5) - hashCode) + charCode; - hashCode |= 0; - } - - return hashCode; -} - function utilBackend() { const backend = chrome.extension.getBackgroundPage().yomichanBackend; if (!backend.isPrepared) { @@ -79,35 +66,6 @@ function utilBackend() { return backend; } -async function utilAnkiGetModelNames() { - return utilIsolate(await utilBackend().anki.getModelNames()); -} - -async function utilAnkiGetDeckNames() { - return utilIsolate(await utilBackend().anki.getDeckNames()); -} - -async function utilDatabaseGetDictionaryInfo() { - return utilIsolate(await utilBackend().translator.database.getDictionaryInfo()); -} - -async function utilDatabaseGetDictionaryCounts(dictionaryNames, getTotal) { - return utilIsolate(await utilBackend().translator.database.getDictionaryCounts( - utilBackgroundIsolate(dictionaryNames), - utilBackgroundIsolate(getTotal) - )); -} - -async function utilAnkiGetModelFieldNames(modelName) { - return utilIsolate(await utilBackend().anki.getModelFieldNames( - utilBackgroundIsolate(modelName) - )); -} - -async function utilDatabasePurge() { - return utilIsolate(await utilBackend().translator.purgeDatabase()); -} - async function utilDatabaseDeleteDictionary(dictionaryName, onProgress) { return utilIsolate(await utilBackend().translator.database.deleteDictionary( utilBackgroundIsolate(dictionaryName), diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 42f08afa..99610e17 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -539,19 +539,10 @@ class Popup { }; } - static _isOnExtensionPage() { - try { - const url = chrome.runtime.getURL('/'); - return window.location.href.substring(0, url.length) === url; - } catch (e) { - // NOP - } - } - static async _injectStylesheet(id, type, value, useWebExtensionApi) { const injectedStylesheets = Popup._injectedStylesheets; - if (Popup._isOnExtensionPage()) { + if (yomichan.isExtensionUrl(window.location.href)) { // Permissions error will occur if trying to use the WebExtension API to inject // into an extension page. useWebExtensionApi = false; diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index 30c08347..7080d93a 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -116,6 +116,30 @@ function apiGetDefaultAnkiFieldTemplates() { return _apiInvoke('getDefaultAnkiFieldTemplates'); } +function apiGetAnkiDeckNames() { + return _apiInvoke('getAnkiDeckNames'); +} + +function apiGetAnkiModelNames() { + return _apiInvoke('getAnkiModelNames'); +} + +function apiGetAnkiModelFieldNames(modelName) { + return _apiInvoke('getAnkiModelFieldNames', {modelName}); +} + +function apiGetDictionaryInfo() { + return _apiInvoke('getDictionaryInfo'); +} + +function apiGetDictionaryCounts(dictionaryNames, getTotal) { + return _apiInvoke('getDictionaryCounts', {dictionaryNames, getTotal}); +} + +function apiPurgeDatabase() { + return _apiInvoke('purgeDatabase'); +} + function _apiInvoke(action, params={}) { const data = {action, params}; return new Promise((resolve, reject) => { diff --git a/ext/mixed/js/core.js b/ext/mixed/js/core.js index 2d11c11a..6a3298fc 100644 --- a/ext/mixed/js/core.js +++ b/ext/mixed/js/core.js @@ -316,6 +316,15 @@ const yomichan = (() => { this.trigger('orphaned', {error}); } + isExtensionUrl(url) { + try { + const urlBase = chrome.runtime.getURL('/'); + return url.substring(0, urlBase.length) === urlBase; + } catch (e) { + return false; + } + } + getTemporaryListenerResult(eventHandler, userCallback, timeout=null) { if (!( typeof eventHandler.addListener === 'function' && |