Move apiCommandExec implementation into Backend
This commit is contained in:
parent
f07207c9bf
commit
f63220b6c5
134
ext/bg/js/api.js
134
ext/bg/js/api.js
@ -65,58 +65,9 @@ function apiTemplateRender(template, data, dynamic) {
|
|||||||
return utilBackend()._onApiTemplateRender({template, data, dynamic});
|
return utilBackend()._onApiTemplateRender({template, data, dynamic});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function apiCommandExec(command, params) {
|
function apiCommandExec(command, params) {
|
||||||
const handlers = apiCommandExec.handlers;
|
return utilBackend()._onApiCommandExec({command, params});
|
||||||
if (hasOwn(handlers, command)) {
|
|
||||||
const handler = handlers[command];
|
|
||||||
handler(params);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
apiCommandExec.handlers = {
|
|
||||||
search: async (params) => {
|
|
||||||
const url = chrome.runtime.getURL('/bg/search.html');
|
|
||||||
if (!(params && params.newTab)) {
|
|
||||||
try {
|
|
||||||
const tab = await _apiFindTab(1000, (url2) => (
|
|
||||||
url2 !== null &&
|
|
||||||
url2.startsWith(url) &&
|
|
||||||
(url2.length === url.length || url2[url.length] === '?' || url2[url.length] === '#')
|
|
||||||
));
|
|
||||||
if (tab !== null) {
|
|
||||||
await _apiFocusTab(tab);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chrome.tabs.create({url});
|
|
||||||
},
|
|
||||||
|
|
||||||
help: () => {
|
|
||||||
chrome.tabs.create({url: 'https://foosoft.net/projects/yomichan/'});
|
|
||||||
},
|
|
||||||
|
|
||||||
options: (params) => {
|
|
||||||
if (!(params && params.newTab)) {
|
|
||||||
chrome.runtime.openOptionsPage();
|
|
||||||
} else {
|
|
||||||
const manifest = chrome.runtime.getManifest();
|
|
||||||
const url = chrome.runtime.getURL(manifest.options_ui.page);
|
|
||||||
chrome.tabs.create({url});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
toggle: async () => {
|
|
||||||
const optionsContext = {
|
|
||||||
depth: 0,
|
|
||||||
url: window.location.href
|
|
||||||
};
|
|
||||||
const options = await apiOptionsGet(optionsContext);
|
|
||||||
options.general.enable = !options.general.enable;
|
|
||||||
await apiOptionsSave('popup');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async function apiAudioGetUrl(definition, source, optionsContext) {
|
async function apiAudioGetUrl(definition, source, optionsContext) {
|
||||||
return audioGetUrl(definition, source, optionsContext);
|
return audioGetUrl(definition, source, optionsContext);
|
||||||
@ -208,87 +159,6 @@ async function _apiGetBrowser() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _apiGetTabUrl(tab) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
chrome.tabs.sendMessage(tab.id, {action: 'getUrl'}, {frameId: 0}, (response) => {
|
|
||||||
let url = null;
|
|
||||||
if (!chrome.runtime.lastError) {
|
|
||||||
url = (response !== null && typeof response === 'object' && !Array.isArray(response) ? response.url : null);
|
|
||||||
if (url !== null && typeof url !== 'string') {
|
|
||||||
url = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolve({tab, url});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _apiFindTab(timeout, checkUrl) {
|
|
||||||
// This function works around the need to have the "tabs" permission to access tab.url.
|
|
||||||
const tabs = await new Promise((resolve) => chrome.tabs.query({}, resolve));
|
|
||||||
let matchPromiseResolve = null;
|
|
||||||
const matchPromise = new Promise((resolve) => { matchPromiseResolve = resolve; });
|
|
||||||
|
|
||||||
const checkTabUrl = ({tab, url}) => {
|
|
||||||
if (checkUrl(url, tab)) {
|
|
||||||
matchPromiseResolve(tab);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const promises = [];
|
|
||||||
for (const tab of tabs) {
|
|
||||||
const promise = _apiGetTabUrl(tab);
|
|
||||||
promise.then(checkTabUrl);
|
|
||||||
promises.push(promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
const racePromises = [
|
|
||||||
matchPromise,
|
|
||||||
Promise.all(promises).then(() => null)
|
|
||||||
];
|
|
||||||
if (typeof timeout === 'number') {
|
|
||||||
racePromises.push(new Promise((resolve) => setTimeout(() => resolve(null), timeout)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return await Promise.race(racePromises);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _apiFocusTab(tab) {
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
chrome.tabs.update(tab.id, {active: true}, () => {
|
|
||||||
const e = chrome.runtime.lastError;
|
|
||||||
if (e) { reject(e); }
|
|
||||||
else { resolve(); }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!(typeof chrome.windows === 'object' && chrome.windows !== null)) {
|
|
||||||
// Windows not supported (e.g. on Firefox mobile)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tabWindow = await new Promise((resolve) => {
|
|
||||||
chrome.windows.get(tab.windowId, {}, (tabWindow) => {
|
|
||||||
const e = chrome.runtime.lastError;
|
|
||||||
if (e) { reject(e); }
|
|
||||||
else { resolve(tabWindow); }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (!tabWindow.focused) {
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
chrome.windows.update(tab.windowId, {focused: true}, () => {
|
|
||||||
const e = chrome.runtime.lastError;
|
|
||||||
if (e) { reject(e); }
|
|
||||||
else { resolve(); }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// Edge throws exception for no reason here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function apiClipboardGet() {
|
async function apiClipboardGet() {
|
||||||
const clipboardPasteTarget = utilBackend().clipboardPasteTarget;
|
const clipboardPasteTarget = utilBackend().clipboardPasteTarget;
|
||||||
clipboardPasteTarget.innerText = '';
|
clipboardPasteTarget.innerText = '';
|
||||||
|
@ -397,8 +397,11 @@ class Backend {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onApiCommandExec({command, params}) {
|
async _onApiCommandExec({command, params}) {
|
||||||
return apiCommandExec(command, params);
|
const handler = Backend._commandHandlers.get(command);
|
||||||
|
if (typeof handler !== 'function') { return false; }
|
||||||
|
|
||||||
|
handler(this, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onApiAudioGetUrl({definition, source, optionsContext}) {
|
_onApiAudioGetUrl({definition, source, optionsContext}) {
|
||||||
@ -429,6 +432,54 @@ class Backend {
|
|||||||
return apiClipboardGet();
|
return apiClipboardGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command handlers
|
||||||
|
|
||||||
|
async _onCommandSearch(params) {
|
||||||
|
const url = chrome.runtime.getURL('/bg/search.html');
|
||||||
|
if (!(params && params.newTab)) {
|
||||||
|
try {
|
||||||
|
const tab = await Backend._findTab(1000, (url2) => (
|
||||||
|
url2 !== null &&
|
||||||
|
url2.startsWith(url) &&
|
||||||
|
(url2.length === url.length || url2[url.length] === '?' || url2[url.length] === '#')
|
||||||
|
));
|
||||||
|
if (tab !== null) {
|
||||||
|
await Backend._focusTab(tab);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chrome.tabs.create({url});
|
||||||
|
}
|
||||||
|
|
||||||
|
_onCommandHelp() {
|
||||||
|
chrome.tabs.create({url: 'https://foosoft.net/projects/yomichan/'});
|
||||||
|
}
|
||||||
|
|
||||||
|
_onCommandOptions(params) {
|
||||||
|
if (!(params && params.newTab)) {
|
||||||
|
chrome.runtime.openOptionsPage();
|
||||||
|
} else {
|
||||||
|
const manifest = chrome.runtime.getManifest();
|
||||||
|
const url = chrome.runtime.getURL(manifest.options_ui.page);
|
||||||
|
chrome.tabs.create({url});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onCommandToggle() {
|
||||||
|
const optionsContext = {
|
||||||
|
depth: 0,
|
||||||
|
url: window.location.href
|
||||||
|
};
|
||||||
|
const source = 'popup';
|
||||||
|
|
||||||
|
const options = await this.getOptions(optionsContext);
|
||||||
|
options.general.enable = !options.general.enable;
|
||||||
|
await this._optionsSave({source});
|
||||||
|
}
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
|
|
||||||
async _injectScreenshot(definition, fields, screenshot) {
|
async _injectScreenshot(definition, fields, screenshot) {
|
||||||
@ -466,6 +517,87 @@ class Backend {
|
|||||||
|
|
||||||
definition.screenshotFileName = filename;
|
definition.screenshotFileName = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _getTabUrl(tab) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
chrome.tabs.sendMessage(tab.id, {action: 'getUrl'}, {frameId: 0}, (response) => {
|
||||||
|
let url = null;
|
||||||
|
if (!chrome.runtime.lastError) {
|
||||||
|
url = (response !== null && typeof response === 'object' && !Array.isArray(response) ? response.url : null);
|
||||||
|
if (url !== null && typeof url !== 'string') {
|
||||||
|
url = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve({tab, url});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async _findTab(timeout, checkUrl) {
|
||||||
|
// This function works around the need to have the "tabs" permission to access tab.url.
|
||||||
|
const tabs = await new Promise((resolve) => chrome.tabs.query({}, resolve));
|
||||||
|
let matchPromiseResolve = null;
|
||||||
|
const matchPromise = new Promise((resolve) => { matchPromiseResolve = resolve; });
|
||||||
|
|
||||||
|
const checkTabUrl = ({tab, url}) => {
|
||||||
|
if (checkUrl(url, tab)) {
|
||||||
|
matchPromiseResolve(tab);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
for (const tab of tabs) {
|
||||||
|
const promise = Backend._getTabUrl(tab);
|
||||||
|
promise.then(checkTabUrl);
|
||||||
|
promises.push(promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
const racePromises = [
|
||||||
|
matchPromise,
|
||||||
|
Promise.all(promises).then(() => null)
|
||||||
|
];
|
||||||
|
if (typeof timeout === 'number') {
|
||||||
|
racePromises.push(new Promise((resolve) => setTimeout(() => resolve(null), timeout)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return await Promise.race(racePromises);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async _focusTab(tab) {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
chrome.tabs.update(tab.id, {active: true}, () => {
|
||||||
|
const e = chrome.runtime.lastError;
|
||||||
|
if (e) { reject(e); }
|
||||||
|
else { resolve(); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!(typeof chrome.windows === 'object' && chrome.windows !== null)) {
|
||||||
|
// Windows not supported (e.g. on Firefox mobile)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tabWindow = await new Promise((resolve) => {
|
||||||
|
chrome.windows.get(tab.windowId, {}, (tabWindow) => {
|
||||||
|
const e = chrome.runtime.lastError;
|
||||||
|
if (e) { reject(e); }
|
||||||
|
else { resolve(tabWindow); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (!tabWindow.focused) {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
chrome.windows.update(tab.windowId, {focused: true}, () => {
|
||||||
|
const e = chrome.runtime.lastError;
|
||||||
|
if (e) { reject(e); }
|
||||||
|
else { resolve(); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Edge throws exception for no reason here.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend._messageHandlers = new Map([
|
Backend._messageHandlers = new Map([
|
||||||
@ -491,5 +623,12 @@ Backend._messageHandlers = new Map([
|
|||||||
['clipboardGet', (self, ...args) => self._onApiClipboardGet(...args)]
|
['clipboardGet', (self, ...args) => self._onApiClipboardGet(...args)]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Backend._commandHandlers = new Map([
|
||||||
|
['search', (self, ...args) => self._onCommandSearch(...args)],
|
||||||
|
['help', (self, ...args) => self._onCommandHelp(...args)],
|
||||||
|
['options', (self, ...args) => self._onCommandOptions(...args)],
|
||||||
|
['toggle', (self, ...args) => self._onCommandToggle(...args)]
|
||||||
|
]);
|
||||||
|
|
||||||
window.yomichan_backend = new Backend();
|
window.yomichan_backend = new Backend();
|
||||||
window.yomichan_backend.prepare();
|
window.yomichan_backend.prepare();
|
||||||
|
Loading…
Reference in New Issue
Block a user