Merge pull request #447 from toasted-nutbread/util-conversions

Util conversions
This commit is contained in:
toasted-nutbread 2020-04-18 14:12:41 -04:00 committed by GitHub
commit 106172e2c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 105 additions and 71 deletions

View File

@ -100,7 +100,13 @@ class Backend {
['getQueryParserTemplatesHtml', {handler: this._onApiGetQueryParserTemplatesHtml.bind(this), async: true}], ['getQueryParserTemplatesHtml', {handler: this._onApiGetQueryParserTemplatesHtml.bind(this), async: true}],
['getZoom', {handler: this._onApiGetZoom.bind(this), async: true}], ['getZoom', {handler: this._onApiGetZoom.bind(this), async: true}],
['getMessageToken', {handler: this._onApiGetMessageToken.bind(this), async: false}], ['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([ this._commandHandlers = new Map([
@ -722,6 +728,36 @@ class Backend {
return this.defaultAnkiFieldTemplates; 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 // Command handlers
async _onCommandSearch(params) { async _onCommandSearch(params) {
@ -818,6 +854,13 @@ class Backend {
// Utilities // 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) { async _getAudioUri(definition, source, details) {
let optionsContext = (typeof details === 'object' && details !== null ? details.optionsContext : null); let optionsContext = (typeof details === 'object' && details !== null ? details.optionsContext : null);
if (!(typeof optionsContext === 'object' && optionsContext !== null)) { if (!(typeof optionsContext === 'object' && optionsContext !== null)) {

View File

@ -15,14 +15,23 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
/* global
* utilStringHashCode
*/
/* /*
* Generic options functions * 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) { function optionsGenericApplyUpdates(options, updates) {
const targetVersion = updates.length; const targetVersion = updates.length;
const currentVersion = options.version; const currentVersion = options.version;
@ -63,12 +72,12 @@ const profileOptionsVersionUpdates = [
options.anki.fieldTemplates = null; options.anki.fieldTemplates = null;
}, },
(options) => { (options) => {
if (utilStringHashCode(options.anki.fieldTemplates) === 1285806040) { if (optionsGetStringHashCode(options.anki.fieldTemplates) === 1285806040) {
options.anki.fieldTemplates = null; options.anki.fieldTemplates = null;
} }
}, },
(options) => { (options) => {
if (utilStringHashCode(options.anki.fieldTemplates) === -250091611) { if (optionsGetStringHashCode(options.anki.fieldTemplates) === -250091611) {
options.anki.fieldTemplates = null; options.anki.fieldTemplates = null;
} }
}, },
@ -87,7 +96,7 @@ const profileOptionsVersionUpdates = [
(options) => { (options) => {
// Version 12 changes: // Version 12 changes:
// The preferred default value of options.anki.fieldTemplates has been changed to null. // 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; options.anki.fieldTemplates = null;
} }
}, },

View File

@ -16,13 +16,13 @@
*/ */
/* global /* global
* apiGetAnkiDeckNames
* apiGetAnkiModelFieldNames
* apiGetAnkiModelNames
* getOptionsContext * getOptionsContext
* getOptionsMutable * getOptionsMutable
* onFormOptionsChanged * onFormOptionsChanged
* settingsSaveOptions * settingsSaveOptions
* utilAnkiGetDeckNames
* utilAnkiGetModelFieldNames
* utilAnkiGetModelNames
* utilBackgroundIsolate * utilBackgroundIsolate
*/ */
@ -107,7 +107,7 @@ async function _ankiDeckAndModelPopulate(options) {
const kanjiModel = {value: options.anki.kanji.model, selector: '#anki-kanji-model'}; const kanjiModel = {value: options.anki.kanji.model, selector: '#anki-kanji-model'};
try { try {
_ankiSpinnerShow(true); _ankiSpinnerShow(true);
const [deckNames, modelNames] = await Promise.all([utilAnkiGetDeckNames(), utilAnkiGetModelNames()]); const [deckNames, modelNames] = await Promise.all([apiGetAnkiDeckNames(), apiGetAnkiModelNames()]);
deckNames.sort(); deckNames.sort();
modelNames.sort(); modelNames.sort();
termsDeck.values = deckNames; termsDeck.values = deckNames;
@ -180,7 +180,7 @@ async function _onAnkiModelChanged(e) {
let fieldNames; let fieldNames;
try { try {
const modelName = node.value; const modelName = node.value;
fieldNames = await utilAnkiGetModelFieldNames(modelName); fieldNames = await apiGetAnkiModelFieldNames(modelName);
_ankiSetError(null); _ankiSetError(null);
} catch (error) { } catch (error) {
_ankiSetError(error); _ankiSetError(error);

View File

@ -17,8 +17,11 @@
/* global /* global
* PageExitPrevention * PageExitPrevention
* apiGetDictionaryCounts
* apiGetDictionaryInfo
* apiOptionsGet * apiOptionsGet
* apiOptionsGetFull * apiOptionsGetFull
* apiPurgeDatabase
* getOptionsContext * getOptionsContext
* getOptionsFullMutable * getOptionsFullMutable
* getOptionsMutable * getOptionsMutable
@ -27,10 +30,7 @@
* storageUpdateStats * storageUpdateStats
* utilBackgroundIsolate * utilBackgroundIsolate
* utilDatabaseDeleteDictionary * utilDatabaseDeleteDictionary
* utilDatabaseGetDictionaryCounts
* utilDatabaseGetDictionaryInfo
* utilDatabaseImport * utilDatabaseImport
* utilDatabasePurge
*/ */
let dictionaryUI = null; let dictionaryUI = null;
@ -431,7 +431,7 @@ async function onDictionaryOptionsChanged() {
async function onDatabaseUpdated() { async function onDatabaseUpdated() {
try { try {
const dictionaries = await utilDatabaseGetDictionaryInfo(); const dictionaries = await apiGetDictionaryInfo();
dictionaryUI.setDictionaries(dictionaries); dictionaryUI.setDictionaries(dictionaries);
document.querySelector('#dict-warning').hidden = (dictionaries.length > 0); document.querySelector('#dict-warning').hidden = (dictionaries.length > 0);
@ -439,7 +439,7 @@ async function onDatabaseUpdated() {
updateMainDictionarySelectOptions(dictionaries); updateMainDictionarySelectOptions(dictionaries);
await updateMainDictionarySelectValue(); 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); dictionaryUI.setCounts(counts, total);
} catch (e) { } catch (e) {
dictionaryErrorsShow([e]); dictionaryErrorsShow([e]);
@ -618,7 +618,7 @@ async function onDictionaryPurge(e) {
dictionaryErrorsShow(null); dictionaryErrorsShow(null);
dictionarySpinnerShow(true); dictionarySpinnerShow(true);
await utilDatabasePurge(); await apiPurgeDatabase();
for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) { for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) {
options.dictionaries = utilBackgroundIsolate({}); options.dictionaries = utilBackgroundIsolate({});
options.general.mainDictionary = ''; options.general.mainDictionary = '';

View File

@ -58,19 +58,6 @@ function utilBackgroundFunctionIsolate(func) {
return backgroundPage.utilFunctionIsolate(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() { function utilBackend() {
const backend = chrome.extension.getBackgroundPage().yomichanBackend; const backend = chrome.extension.getBackgroundPage().yomichanBackend;
if (!backend.isPrepared) { if (!backend.isPrepared) {
@ -79,35 +66,6 @@ function utilBackend() {
return backend; 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) { async function utilDatabaseDeleteDictionary(dictionaryName, onProgress) {
return utilIsolate(await utilBackend().translator.database.deleteDictionary( return utilIsolate(await utilBackend().translator.database.deleteDictionary(
utilBackgroundIsolate(dictionaryName), utilBackgroundIsolate(dictionaryName),

View File

@ -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) { static async _injectStylesheet(id, type, value, useWebExtensionApi) {
const injectedStylesheets = Popup._injectedStylesheets; 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 // Permissions error will occur if trying to use the WebExtension API to inject
// into an extension page. // into an extension page.
useWebExtensionApi = false; useWebExtensionApi = false;

View File

@ -116,6 +116,30 @@ function apiGetDefaultAnkiFieldTemplates() {
return _apiInvoke('getDefaultAnkiFieldTemplates'); 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={}) { function _apiInvoke(action, params={}) {
const data = {action, params}; const data = {action, params};
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -316,6 +316,15 @@ const yomichan = (() => {
this.trigger('orphaned', {error}); 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) { getTemporaryListenerResult(eventHandler, userCallback, timeout=null) {
if (!( if (!(
typeof eventHandler.addListener === 'function' && typeof eventHandler.addListener === 'function' &&