diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/js/background/backend.js | 61 | ||||
| -rw-r--r-- | ext/js/background/offscreen.js | 78 | 
2 files changed, 133 insertions, 6 deletions
| diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index cccfcbb3..2c007973 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -50,15 +50,15 @@ export class Backend {      constructor() {          this._japaneseUtil = new JapaneseUtil(wanakana);          this._environment = new Environment(); -        this._dictionaryDatabase = new DictionaryDatabase(); -        this._translator = new Translator({ -            japaneseUtil: this._japaneseUtil, -            database: this._dictionaryDatabase -        });          this._anki = new AnkiConnect();          this._mecab = new Mecab();          if (!chrome.offscreen) { +            this._dictionaryDatabase = new DictionaryDatabase(); +            this._translator = new Translator({ +                japaneseUtil: this._japaneseUtil, +                database: this._dictionaryDatabase +            });              this._clipboardReader = new ClipboardReader({                  // eslint-disable-next-line no-undef                  document: (typeof document === 'object' && document !== null ? document : null), @@ -66,6 +66,19 @@ export class Backend {                  richContentPasteTargetSelector: '#clipboard-rich-content-paste-target'              });          } else { +            this._dictionaryDatabase = { +                prepare: () => this._sendMessagePromise({action: 'databasePrepareOffscreen'}), +                getDictionaryInfo: () => this._sendMessagePromise({action: 'getDictionaryInfoOffscreen'}), +                purge: () => this._sendMessagePromise({action: 'databasePurgeOffscreen'}), +                getMedia: this._getMediaOffscreen.bind(this) +            }; +            this._translator = { +                prepare: (deinflectionReasons) => this._sendMessagePromise({action: 'translatorPrepareOffscreen', params: {deinflectionReasons}}), +                findKanji: this._findKanjiOffscreen.bind(this), +                findTerms: this._findTermsOffscreen.bind(this), +                getTermFrequencies: this._getTermFrequenciesOffscreen.bind(this), +                clearDatabaseCaches: () => this._sendMessagePromise({action: 'clearDatabaseCachesOffscreen'}) +            };              this._clipboardReader = {                  getText: this._getTextOffscreen.bind(this),                  getImage: this._getImageOffscreen.bind(this) @@ -2240,6 +2253,44 @@ export class Backend {          return results;      } +    async _getMediaOffscreen(targets) { +        const serializedMedia = await this._sendMessagePromise({action: 'databaseGetMediaOffscreen', params: {targets}}); +        const media = serializedMedia.map((m) => ({...m, content: ArrayBufferUtil.base64ToArrayBuffer(m.content)})); +        return media; +    } + +    async _findKanjiOffscreen(text, findKanjiOptions) { +        const enabledDictionaryMapList = [...findKanjiOptions.enabledDictionaryMap]; +        const modifiedKanjiOptions = { +            ...findKanjiOptions, +            enabledDictionaryMap: enabledDictionaryMapList +        }; +        return this._sendMessagePromise({action: 'findKanjiOffscreen', params: {text, findKanjiOptions: modifiedKanjiOptions}}); +    } + +    async _findTermsOffscreen(mode, text, findTermsOptions) { +        const {enabledDictionaryMap, excludeDictionaryDefinitions, textReplacements} = findTermsOptions; +        const enabledDictionaryMapList = [...enabledDictionaryMap]; +        const excludeDictionaryDefinitionsList = excludeDictionaryDefinitions ? [...excludeDictionaryDefinitions] : null; +        const textReplacementsSerialized = textReplacements.map((group) => { +            if (!group) { +                return group; +            } +            return group.map((opt) => ({...opt, pattern: opt.pattern.toString()})); +        }); +        const modifiedFindTermsOptions = { +            ...findTermsOptions, +            enabledDictionaryMap: enabledDictionaryMapList, +            excludeDictionaryDefinitions: excludeDictionaryDefinitionsList, +            textReplacementsOptions: textReplacementsSerialized +        }; +        return this._sendMessagePromise({action: 'findTermsOffscreen', params: {mode, text, findTermsOptions: modifiedFindTermsOptions}}); +    } + +    async _getTermFrequenciesOffscreen(termReadingList, dictionaries) { +        return this._sendMessagePromise({action: 'getTermFrequenciesOffscreen', params: {termReadingList, dictionaries}}); +    } +      async _getTextOffscreen(useRichText) {          return this._sendMessagePromise({action: 'clipboardGetTextOffscreen', params: {useRichText}});      } diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js index c37cdedc..1553d996 100644 --- a/ext/js/background/offscreen.js +++ b/ext/js/background/offscreen.js @@ -16,8 +16,13 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ +import * as wanakana from '../../lib/wanakana.js';  import {ClipboardReader} from '../comm/clipboard-reader.js';  import {invokeMessageHandler} from '../core.js'; +import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; +import {DictionaryDatabase} from '../language/dictionary-database.js'; +import {JapaneseUtil} from '../language/sandbox/japanese-util.js'; +import {Translator} from '../language/translator.js';  import {yomichan} from '../yomichan.js';  /** @@ -29,6 +34,12 @@ export class Offscreen {       * Creates a new instance.       */      constructor() { +        this._japaneseUtil = new JapaneseUtil(wanakana); +        this._dictionaryDatabase = new DictionaryDatabase(); +        this._translator = new Translator({ +            japaneseUtil: this._japaneseUtil, +            database: this._dictionaryDatabase +        });          this._clipboardReader = new ClipboardReader({              // eslint-disable-next-line no-undef              document: (typeof document === 'object' && document !== null ? document : null), @@ -38,11 +49,23 @@ export class Offscreen {          this._messageHandlers = new Map([              ['clipboardGetTextOffscreen',                 {async: true,  contentScript: true,  handler: this._getTextHandler.bind(this)}], -            ['clipboardGetImageOffscreen',                 {async: true,  contentScript: true,  handler: this._getImageHandler.bind(this)}] +            ['clipboardGetImageOffscreen',                 {async: true,  contentScript: true,  handler: this._getImageHandler.bind(this)}], +            ['databasePrepareOffscreen',                 {async: true,  contentScript: true,  handler: this._prepareDatabaseHandler.bind(this)}], +            ['getDictionaryInfoOffscreen',                 {async: true,  contentScript: true,  handler: this._getDictionaryInfoHandler.bind(this)}], +            ['databasePurgeOffscreen',                 {async: true,  contentScript: true,  handler: this._purgeDatabaseHandler.bind(this)}], +            ['databaseGetMediaOffscreen',                 {async: true,  contentScript: true,  handler: this._getMediaHandler.bind(this)}], +            ['translatorPrepareOffscreen',                 {async: false,  contentScript: true,  handler: this._prepareTranslatorHandler.bind(this)}], +            ['findKanjiOffscreen',                 {async: true,  contentScript: true,  handler: this._findKanjiHandler.bind(this)}], +            ['findTermsOffscreen',                 {async: true,  contentScript: true,  handler: this._findTermsHandler.bind(this)}], +            ['getTermFrequenciesOffscreen',                 {async: true,  contentScript: true,  handler: this._getTermFrequenciesHandler.bind(this)}], +            ['clearDatabaseCachesOffscreen',                 {async: false,  contentScript: true,  handler: this._clearDatabaseCachesHandler.bind(this)}] +          ]);          const onMessage = this._onMessage.bind(this);          chrome.runtime.onMessage.addListener(onMessage); + +        this._prepareDatabasePromise = null;      }      _getTextHandler({useRichText}) { @@ -53,6 +76,59 @@ export class Offscreen {          return this._clipboardReader.getImage();      } +    _prepareDatabaseHandler() { +        if (this._prepareDatabasePromise !== null) { +            return this._prepareDatabasePromise; +        } +        this._prepareDatabasePromise = this._dictionaryDatabase.prepare(); +        return this._prepareDatabasePromise; +    } + +    _getDictionaryInfoHandler() { +        return this._dictionaryDatabase.getDictionaryInfo(); +    } + +    _purgeDatabaseHandler() { +        return this._dictionaryDatabase.purge(); +    } + +    async _getMediaHandler({targets}) { +        const media = await this._dictionaryDatabase.getMedia(targets); +        const serializedMedia = media.map((m) => ({...m, content: ArrayBufferUtil.arrayBufferToBase64(m.content)})); +        return serializedMedia; +    } + +    _prepareTranslatorHandler({deinflectionReasons}) { +        return this._translator.prepare(deinflectionReasons); +    } + +    _findKanjiHandler({text, findKanjiOptions}) { +        findKanjiOptions.enabledDictionaryMap = new Map(findKanjiOptions.enabledDictionaryMap); +        return this._translator.findKanji(text, findKanjiOptions); +    } + +    _findTermsHandler({mode, text, findTermsOptions}) { +        findTermsOptions.enabledDictionaryMap = new Map(findTermsOptions.enabledDictionaryMap); +        if (findTermsOptions.excludeDictionaryDefinitions) { +            findTermsOptions.excludeDictionaryDefinitions = new Set(findTermsOptions.excludeDictionaryDefinitions); +        } +        findTermsOptions.textReplacements = findTermsOptions.textReplacements.map((group) => { +            if (!group) { +                return group; +            } +            return group.map((opt) => ({...opt, pattern: new RegExp(opt.pattern)})); +        }); +        return this._translator.findTerms(mode, text, findTermsOptions); +    } + +    _getTermFrequenciesHandler({termReadingList, dictionaries}) { +        return this._translator.getTermFrequencies(termReadingList, dictionaries); +    } + +    _clearDatabaseCachesHandler() { +        return this._translator.clearDatabaseCaches(); +    } +      _onMessage({action, params}, sender, callback) {          const messageHandler = this._messageHandlers.get(action);          if (typeof messageHandler === 'undefined') { return false; } |