summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpraschke <stel@comfy.monster>2023-08-16 11:37:13 +0100
committerpraschke <stel@comfy.monster>2023-08-17 14:17:18 +0100
commit4b7f91fa5f43ba6023f1c9991348b56b3e26a11b (patch)
tree5cec40168436308445f1f58fa8bae14218d0f7be
parent6c21818eba54b9c5191845086bec28e4a548ee3b (diff)
fix script and style injection in Firefox
Firefox added the scripting API in 102. This should fix the majority of warnings listed in #96: - insertCSS - executeScript - getRegisteredContentScripts - contentScripts.register - registerContentScripts - unregisterContentScripts
-rw-r--r--dev/data/manifest-variants.json2
-rw-r--r--ext/js/background/backend.js4
-rw-r--r--ext/js/background/script-manager.js111
3 files changed, 14 insertions, 103 deletions
diff --git a/dev/data/manifest-variants.json b/dev/data/manifest-variants.json
index 7d762951..e167c755 100644
--- a/dev/data/manifest-variants.json
+++ b/dev/data/manifest-variants.json
@@ -228,7 +228,7 @@
"value": {
"gecko": {
"id": "{cb7c0bec-7085-4f84-8422-7b55a7c4467c}",
- "strict_min_version": "101.0"
+ "strict_min_version": "102.0"
}
}
},
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index db6cfada..dd233abb 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -593,7 +593,7 @@ class Backend {
async _onApiInjectStylesheet({type, value}, sender) {
const {frameId, tab} = sender;
if (!isObject(tab)) { throw new Error('Invalid tab'); }
- return await this._scriptManager.injectStylesheet(type, value, tab.id, frameId, false, true, 'document_start');
+ return await this._scriptManager.injectStylesheet(type, value, tab.id, frameId, false);
}
async _onApiGetStylesheetContent({url}) {
@@ -790,7 +790,7 @@ class Backend {
if (typeof tabId !== 'number') { throw new Error('Sender has invalid tab ID'); }
const {frameId} = sender;
for (const file of files) {
- await this._scriptManager.injectScript(file, tabId, frameId, false, true, 'document_start');
+ await this._scriptManager.injectScript(file, tabId, frameId, false);
}
}
diff --git a/ext/js/background/script-manager.js b/ext/js/background/script-manager.js
index 722a46f0..a0aed2a3 100644
--- a/ext/js/background/script-manager.js
+++ b/ext/js/background/script-manager.js
@@ -36,14 +36,10 @@ class ScriptManager {
* @param {number} tabId The id of the tab to inject into.
* @param {number} [frameId] The id of the frame to inject into.
* @param {boolean} [allFrames] Whether or not the stylesheet should be injected into all frames.
- * @param {boolean} [matchAboutBlank] Whether or not the stylesheet should be injected into about:blank frames.
- * @param {string} [runAt] The time to inject the stylesheet at.
* @returns {Promise<void>}
*/
- injectStylesheet(type, content, tabId, frameId, allFrames, matchAboutBlank, runAt) {
- if (isObject(chrome.tabs) && typeof chrome.tabs.insertCSS === 'function') {
- return this._injectStylesheetMV2(type, content, tabId, frameId, allFrames, matchAboutBlank, runAt);
- } else if (isObject(chrome.scripting) && typeof chrome.scripting.insertCSS === 'function') {
+ injectStylesheet(type, content, tabId, frameId, allFrames) {
+ if (isObject(chrome.scripting) && typeof chrome.scripting.insertCSS === 'function') {
return this._injectStylesheetMV3(type, content, tabId, frameId, allFrames);
} else {
return Promise.reject(new Error('Stylesheet injection not supported'));
@@ -56,14 +52,10 @@ class ScriptManager {
* @param {number} tabId The id of the tab to inject into.
* @param {number} [frameId] The id of the frame to inject into.
* @param {boolean} [allFrames] Whether or not the script should be injected into all frames.
- * @param {boolean} [matchAboutBlank] Whether or not the script should be injected into about:blank frames.
- * @param {string} [runAt] The time to inject the script at.
* @returns {Promise<{frameId: number, result: object}>} The id of the frame and the result of the script injection.
*/
- injectScript(file, tabId, frameId, allFrames, matchAboutBlank, runAt) {
- if (isObject(chrome.tabs) && typeof chrome.tabs.executeScript === 'function') {
- return this._injectScriptMV2(file, tabId, frameId, allFrames, matchAboutBlank, runAt);
- } else if (isObject(chrome.scripting) && typeof chrome.scripting.executeScript === 'function') {
+ injectScript(file, tabId, frameId, allFrames) {
+ if (isObject(chrome.scripting) && typeof chrome.scripting.executeScript === 'function') {
return this._injectScriptMV3(file, tabId, frameId, allFrames);
} else {
return Promise.reject(new Error('Script injection not supported'));
@@ -122,19 +114,6 @@ class ScriptManager {
throw new Error('Registration already exists');
}
- // Firefox
- if (
- typeof browser === 'object' && browser !== null &&
- isObject(browser.contentScripts) &&
- typeof browser.contentScripts.register === 'function'
- ) {
- const details2 = this._convertContentScriptRegistrationDetails(details, id, true);
- const registration = await browser.contentScripts.register(details2);
- this._contentScriptRegistrations.set(id, registration);
- return;
- }
-
- // Chrome
if (isObject(chrome.scripting) && typeof chrome.scripting.registerContentScripts === 'function') {
const details2 = this._convertContentScriptRegistrationDetails(details, id, false);
await new Promise((resolve, reject) => {
@@ -161,18 +140,17 @@ class ScriptManager {
* @returns {Promise<boolean>} `true` if the content script was unregistered, `false` otherwise.
*/
async unregisterContentScript(id) {
- // Chrome
if (isObject(chrome.scripting) && typeof chrome.scripting.unregisterContentScripts === 'function') {
this._contentScriptRegistrations.delete(id);
try {
- await this._unregisterContentScriptChrome(id);
+ await this._unregisterContentScriptMV3(id);
return true;
} catch (e) {
return false;
}
}
- // Firefox or fallback
+ // Fallback
const registration = this._contentScriptRegistrations.get(id);
if (typeof registration === 'undefined') { return false; }
this._contentScriptRegistrations.delete(id);
@@ -187,19 +165,7 @@ class ScriptManager {
* @returns {string[]} An array of the required permissions, which may be empty.
*/
getRequiredContentScriptRegistrationPermissions() {
- if (
- // Firefox
- (
- typeof browser === 'object' && browser !== null &&
- isObject(browser.contentScripts) &&
- typeof browser.contentScripts.register === 'function'
- ) ||
- // Chrome
- (
- isObject(chrome.scripting) &&
- typeof chrome.scripting.registerContentScripts === 'function'
- )
- ) {
+ if (isObject(chrome.scripting) && typeof chrome.scripting.registerContentScripts === 'function') {
return [];
}
@@ -209,39 +175,6 @@ class ScriptManager {
// Private
- _injectStylesheetMV2(type, content, tabId, frameId, allFrames, matchAboutBlank, runAt) {
- return new Promise((resolve, reject) => {
- const details = (
- type === 'file' ?
- {
- file: content,
- runAt,
- cssOrigin: 'author',
- allFrames,
- matchAboutBlank
- } :
- {
- code: content,
- runAt,
- cssOrigin: 'user',
- allFrames,
- matchAboutBlank
- }
- );
- if (typeof frameId === 'number') {
- details.frameId = frameId;
- }
- chrome.tabs.insertCSS(tabId, details, () => {
- const e = chrome.runtime.lastError;
- if (e) {
- reject(new Error(e.message));
- } else {
- resolve();
- }
- });
- });
- }
-
_injectStylesheetMV3(type, content, tabId, frameId, allFrames) {
return new Promise((resolve, reject) => {
const details = (
@@ -267,27 +200,6 @@ class ScriptManager {
});
}
- _injectScriptMV2(file, tabId, frameId, allFrames, matchAboutBlank, runAt) {
- return new Promise((resolve, reject) => {
- const details = {
- allFrames,
- frameId,
- file,
- matchAboutBlank,
- runAt
- };
- chrome.tabs.executeScript(tabId, details, (results) => {
- const e = chrome.runtime.lastError;
- if (e) {
- reject(new Error(e.message));
- } else {
- const result = results[0];
- resolve({frameId, result});
- }
- });
- });
- }
-
_injectScriptMV3(file, tabId, frameId, allFrames) {
return new Promise((resolve, reject) => {
const details = {
@@ -310,7 +222,7 @@ class ScriptManager {
});
}
- _unregisterContentScriptChrome(id) {
+ _unregisterContentScriptMV3(id) {
return new Promise((resolve, reject) => {
chrome.scripting.unregisterContentScripts({ids: [id]}, () => {
const e = chrome.runtime.lastError;
@@ -407,7 +319,7 @@ class ScriptManager {
const {urlRegex} = details;
if (urlRegex !== null && !urlRegex.test(url)) { return; }
- let {allFrames, css, js, matchAboutBlank, runAt} = details;
+ let {allFrames, css, js, runAt} = details;
if (isWebNavigation) {
if (allFrames) {
@@ -425,14 +337,13 @@ class ScriptManager {
const promises = [];
if (Array.isArray(css)) {
- const runAtCss = (typeof runAt === 'string' ? runAt : 'document_start');
for (const file of css) {
- promises.push(this.injectStylesheet('file', file, tabId, frameId, allFrames, matchAboutBlank, runAtCss));
+ promises.push(this.injectStylesheet('file', file, tabId, frameId, allFrames));
}
}
if (Array.isArray(js)) {
for (const file of js) {
- promises.push(this.injectScript(file, tabId, frameId, allFrames, matchAboutBlank, runAt));
+ promises.push(this.injectScript(file, tabId, frameId, allFrames));
}
}
await Promise.all(promises);