aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/js/background/backend.js151
-rw-r--r--ext/js/comm/api.js129
-rw-r--r--types/ext/api.d.ts9
-rw-r--r--types/ext/backend.d.ts49
-rw-r--r--types/ext/cross-frame-api.d.ts7
5 files changed, 3 insertions, 342 deletions
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index d62c852b..c62685b2 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -22,9 +22,9 @@ import {AnkiConnect} from '../comm/anki-connect.js';
import {ClipboardMonitor} from '../comm/clipboard-monitor.js';
import {ClipboardReader} from '../comm/clipboard-reader.js';
import {Mecab} from '../comm/mecab.js';
-import {clone, deferPromise, generateId, invokeMessageHandler, isObject, log, promiseTimeout} from '../core.js';
+import {clone, deferPromise, invokeMessageHandler, isObject, log, promiseTimeout} from '../core.js';
import {ExtensionError} from '../core/extension-error.js';
-import {parseJson, readResponseJson} from '../core/json.js';
+import {readResponseJson} from '../core/json.js';
import {AnkiUtil} from '../data/anki-util.js';
import {OptionsUtil} from '../data/options-util.js';
import {PermissionsUtil} from '../data/permissions-util.js';
@@ -36,7 +36,6 @@ import {JapaneseUtil} from '../language/sandbox/japanese-util.js';
import {Translator} from '../language/translator.js';
import {AudioDownloader} from '../media/audio-downloader.js';
import {MediaUtil} from '../media/media-util.js';
-import {yomitan} from '../yomitan.js';
import {ClipboardReaderProxy, DictionaryDatabaseProxy, OffscreenProxy, TranslatorProxy} from './offscreen-proxy.js';
import {ProfileConditionsUtil} from './profile-conditions-util.js';
import {RequestBuilder} from './request-builder.js';
@@ -179,7 +178,6 @@ export class Backend {
['getMedia', this._onApiGetMedia.bind(this)],
['log', this._onApiLog.bind(this)],
['logIndicatorClear', this._onApiLogIndicatorClear.bind(this)],
- ['createActionPort', this._onApiCreateActionPort.bind(this)],
['modifySettings', this._onApiModifySettings.bind(this)],
['getSettings', this._onApiGetSettings.bind(this)],
['setAllSettings', this._onApiSetAllSettings.bind(this)],
@@ -194,10 +192,6 @@ export class Backend {
['openCrossFramePort', this._onApiOpenCrossFramePort.bind(this)]
]));
/* eslint-enable no-multi-spaces */
- /** @type {import('backend').MessageHandlerWithProgressMap} */
- this._messageHandlersWithProgress = new Map(/** @type {import('backend').MessageHandlerWithProgressMapInit} */ ([
- // Empty
- ]));
/** @type {Map<string, (params?: import('core').SerializableObject) => void>} */
this._commandHandlers = new Map(/** @type {[name: string, handler: (params?: import('core').SerializableObject) => void][]} */ ([
@@ -746,31 +740,6 @@ export class Backend {
this._updateBadge();
}
- /** @type {import('api').Handler<import('api').CreateActionPortDetails, import('api').CreateActionPortResult, true>} */
- _onApiCreateActionPort(_params, sender) {
- if (!sender || !sender.tab) { throw new Error('Invalid sender'); }
- const tabId = sender.tab.id;
- if (typeof tabId !== 'number') { throw new Error('Sender has invalid tab ID'); }
-
- const frameId = sender.frameId;
- const id = generateId(16);
- /** @type {import('cross-frame-api').ActionPortDetails} */
- const details = {
- name: 'action-port',
- id
- };
-
- const port = chrome.tabs.connect(tabId, {name: JSON.stringify(details), frameId});
- try {
- this._createActionListenerPort(port, sender, this._messageHandlersWithProgress);
- } catch (e) {
- port.disconnect();
- throw e;
- }
-
- return details;
- }
-
/** @type {import('api').Handler<import('api').ModifySettingsDetails, import('api').ModifySettingsResult>} */
_onApiModifySettings({targets, source}) {
return this._modifySettings(targets, source);
@@ -1484,107 +1453,6 @@ export class Backend {
}
/**
- * @param {chrome.runtime.Port} port
- * @param {chrome.runtime.MessageSender} sender
- * @param {import('backend').MessageHandlerWithProgressMap} handlers
- */
- _createActionListenerPort(port, sender, handlers) {
- let done = false;
- let hasStarted = false;
- /** @type {?string} */
- let messageString = '';
-
- /**
- * @param {...unknown} data
- */
- const onProgress = (...data) => {
- try {
- if (done) { return; }
- port.postMessage(/** @type {import('backend').InvokeWithProgressResponseProgressMessage} */ ({type: 'progress', data}));
- } catch (e) {
- // NOP
- }
- };
-
- /**
- * @param {import('backend').InvokeWithProgressRequestMessage} message
- */
- const onMessage = (message) => {
- if (hasStarted) { return; }
-
- try {
- const {action} = message;
- switch (action) {
- case 'fragment':
- messageString += message.data;
- break;
- case 'invoke':
- if (messageString !== null) {
- hasStarted = true;
- port.onMessage.removeListener(onMessage);
-
- /** @type {{action: string, params?: import('core').SerializableObject}} */
- const messageData = parseJson(messageString);
- messageString = null;
- onMessageComplete(messageData);
- }
- break;
- }
- } catch (e) {
- cleanup(e);
- }
- };
-
- /**
- * @param {{action: string, params?: import('core').SerializableObject}} message
- */
- const onMessageComplete = async (message) => {
- try {
- const {action, params} = message;
- port.postMessage(/** @type {import('backend').InvokeWithProgressResponseAcknowledgeMessage} */ ({type: 'ack'}));
-
- const messageHandler = handlers.get(action);
- if (typeof messageHandler === 'undefined') {
- throw new Error('Invalid action');
- }
- const {handler, async, contentScript} = messageHandler;
-
- if (!contentScript) {
- this._validatePrivilegedMessageSender(sender);
- }
-
- const promiseOrResult = handler(params, sender, onProgress);
- const result = async ? await promiseOrResult : promiseOrResult;
- port.postMessage(/** @type {import('backend').InvokeWithProgressResponseCompleteMessage} */ ({type: 'complete', data: result}));
- } catch (e) {
- cleanup(e);
- }
- };
-
- const onDisconnect = () => {
- cleanup(null);
- };
-
- /**
- * @param {unknown} error
- */
- const cleanup = (error) => {
- if (done) { return; }
- if (error !== null) {
- port.postMessage(/** @type {import('backend').InvokeWithProgressResponseErrorMessage} */ ({type: 'error', data: ExtensionError.serialize(error)}));
- }
- if (!hasStarted) {
- port.onMessage.removeListener(onMessage);
- }
- port.onDisconnect.removeListener(onDisconnect);
- done = true;
- };
-
- port.onMessage.addListener(onMessage);
- port.onDisconnect.addListener(onDisconnect);
- }
-
- /**
* @param {?import('log').LogLevel} errorLevel
* @returns {number}
*/
@@ -1693,21 +1561,6 @@ export class Backend {
}
/**
- * @param {chrome.runtime.MessageSender} sender
- * @throws {Error}
- */
- _validatePrivilegedMessageSender(sender) {
- let {url} = sender;
- if (typeof url === 'string' && yomitan.isExtensionUrl(url)) { return; }
- const {tab} = sender;
- if (typeof tab === 'object' && tab !== null) {
- ({url} = tab);
- if (typeof url === 'string' && yomitan.isExtensionUrl(url)) { return; }
- }
- throw new Error('Invalid message sender');
- }
-
- /**
* @returns {Promise<string>}
*/
_getBrowserIconTitle() {
diff --git a/ext/js/comm/api.js b/ext/js/comm/api.js
index 43f707e2..de19650d 100644
--- a/ext/js/comm/api.js
+++ b/ext/js/comm/api.js
@@ -16,9 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {deferPromise} from '../core.js';
import {ExtensionError} from '../core/extension-error.js';
-import {parseJson} from '../core/json.js';
export class API {
/**
@@ -427,133 +425,6 @@ export class API {
// Utilities
/**
- * @param {number} timeout
- * @returns {Promise<chrome.runtime.Port>}
- */
- _createActionPort(timeout) {
- return new Promise((resolve, reject) => {
- /** @type {?import('core').Timeout} */
- let timer = null;
- /** @type {import('core').DeferredPromiseDetails<import('api').CreateActionPortResult>} */
- const portDetails = deferPromise();
-
- /**
- * @param {chrome.runtime.Port} port
- */
- const onConnect = async (port) => {
- try {
- const {name: expectedName, id: expectedId} = await portDetails.promise;
- /** @type {import('cross-frame-api').PortDetails} */
- const portDetails2 = parseJson(port.name);
- if (portDetails2.name !== expectedName || portDetails2.id !== expectedId || timer === null) { return; }
- } catch (e) {
- return;
- }
-
- clearTimeout(timer);
- timer = null;
-
- chrome.runtime.onConnect.removeListener(onConnect);
- resolve(port);
- };
-
- /**
- * @param {Error} e
- */
- const onError = (e) => {
- if (timer !== null) {
- clearTimeout(timer);
- timer = null;
- }
- chrome.runtime.onConnect.removeListener(onConnect);
- portDetails.reject(e);
- reject(e);
- };
-
- timer = setTimeout(() => onError(new Error('Timeout')), timeout);
-
- chrome.runtime.onConnect.addListener(onConnect);
- /** @type {Promise<import('api').CreateActionPortResult>} */
- const createActionPortResult = this._invoke('createActionPort');
- createActionPortResult.then(portDetails.resolve, onError);
- });
- }
-
- /**
- * @template [TReturn=unknown]
- * @param {string} action
- * @param {import('core').SerializableObject} params
- * @param {?(...args: unknown[]) => void} onProgress0
- * @param {number} [timeout]
- * @returns {Promise<TReturn>}
- */
- _invokeWithProgress(action, params, onProgress0, timeout = 5000) {
- return new Promise((resolve, reject) => {
- /** @type {?chrome.runtime.Port} */
- let port = null;
-
- const onProgress = typeof onProgress0 === 'function' ? onProgress0 : () => {};
-
- /**
- * @param {import('backend').InvokeWithProgressResponseMessage<TReturn>} message
- */
- const onMessage = (message) => {
- switch (message.type) {
- case 'progress':
- try {
- onProgress(...message.data);
- } catch (e) {
- // NOP
- }
- break;
- case 'complete':
- cleanup();
- resolve(message.data);
- break;
- case 'error':
- cleanup();
- reject(ExtensionError.deserialize(message.data));
- break;
- }
- };
-
- const onDisconnect = () => {
- cleanup();
- reject(new Error('Disconnected'));
- };
-
- const cleanup = () => {
- if (port !== null) {
- port.onMessage.removeListener(onMessage);
- port.onDisconnect.removeListener(onDisconnect);
- port.disconnect();
- port = null;
- }
- };
-
- (async () => {
- try {
- port = await this._createActionPort(timeout);
- port.onMessage.addListener(onMessage);
- port.onDisconnect.addListener(onDisconnect);
-
- // Chrome has a maximum message size that can be sent, so longer messages must be fragmented.
- const messageString = JSON.stringify({action, params});
- const fragmentSize = 1e7; // 10 MB
- for (let i = 0, ii = messageString.length; i < ii; i += fragmentSize) {
- const data = messageString.substring(i, i + fragmentSize);
- port.postMessage(/** @type {import('backend').InvokeWithProgressRequestFragmentMessage} */ ({action: 'fragment', data}));
- }
- port.postMessage(/** @type {import('backend').InvokeWithProgressRequestInvokeMessage} */ ({action: 'invoke'}));
- } catch (e) {
- cleanup();
- reject(e);
- }
- })();
- });
- }
-
- /**
* @template [TReturn=unknown]
* @param {string} action
* @param {import('core').SerializableObject} [params]
diff --git a/types/ext/api.d.ts b/types/ext/api.d.ts
index 41d3a96d..93004447 100644
--- a/types/ext/api.d.ts
+++ b/types/ext/api.d.ts
@@ -461,12 +461,3 @@ export type OpenCrossFramePortResult = {
export type RequestBackendReadySignalDetails = Record<string, never>;
export type RequestBackendReadySignalResult = boolean;
-
-// createActionPort
-
-export type CreateActionPortDetails = Record<string, never>;
-
-export type CreateActionPortResult = {
- name: 'action-port';
- id: string;
-};
diff --git a/types/ext/backend.d.ts b/types/ext/backend.d.ts
index 6cbe7938..13f3bfe4 100644
--- a/types/ext/backend.d.ts
+++ b/types/ext/backend.d.ts
@@ -16,15 +16,6 @@
*/
import type * as Api from './api';
-import type * as Core from './core';
-
-export type MessageHandlerWithProgressDetails = {
- async: boolean;
- contentScript: boolean;
- handler: (params: Core.SerializableObject | undefined, sender: chrome.runtime.MessageSender, onProgress: (...data: unknown[]) => void) => (Promise<unknown> | unknown);
-};
-export type MessageHandlerWithProgressMap = Map<string, MessageHandlerWithProgressDetails>;
-export type MessageHandlerWithProgressMapInit = [key: string, handlerDetails: MessageHandlerWithProgressDetails][];
export type DatabaseUpdateType = 'dictionary';
export type DatabaseUpdateCause = 'purge' | 'delete' | 'import';
@@ -40,43 +31,3 @@ export type TabInfo = {
};
export type FindTabsPredicate = (tabInfo: TabInfo) => boolean | Promise<boolean>;
-
-export type InvokeWithProgressRequestMessage = (
- InvokeWithProgressRequestFragmentMessage |
- InvokeWithProgressRequestInvokeMessage
-);
-
-export type InvokeWithProgressRequestFragmentMessage = {
- action: 'fragment';
- data: string;
-};
-
-export type InvokeWithProgressRequestInvokeMessage = {
- action: 'invoke';
-};
-
-export type InvokeWithProgressResponseMessage<TReturn = unknown> = (
- InvokeWithProgressResponseProgressMessage |
- InvokeWithProgressResponseCompleteMessage<TReturn> |
- InvokeWithProgressResponseErrorMessage |
- InvokeWithProgressResponseAcknowledgeMessage
-);
-
-export type InvokeWithProgressResponseProgressMessage = {
- type: 'progress';
- data: unknown[];
-};
-
-export type InvokeWithProgressResponseCompleteMessage<TReturn = unknown> = {
- type: 'complete';
- data: TReturn;
-};
-
-export type InvokeWithProgressResponseErrorMessage = {
- type: 'error';
- data: Core.SerializedError;
-};
-
-export type InvokeWithProgressResponseAcknowledgeMessage = {
- type: 'ack';
-};
diff --git a/types/ext/cross-frame-api.d.ts b/types/ext/cross-frame-api.d.ts
index e31079b7..b9cf8ad1 100644
--- a/types/ext/cross-frame-api.d.ts
+++ b/types/ext/cross-frame-api.d.ts
@@ -53,15 +53,10 @@ export type Invocation = {
timer: Core.Timeout | null;
};
-export type PortDetails = CrossFrameCommunicationPortDetails | ActionPortDetails;
+export type PortDetails = CrossFrameCommunicationPortDetails;
export type CrossFrameCommunicationPortDetails = {
name: 'cross-frame-communication-port';
otherTabId: number;
otherFrameId: number;
};
-
-export type ActionPortDetails = {
- name: 'action-port';
- id: string;
-};