Make content script reregister on firefox every browser restart

This commit is contained in:
Ajay Ramachandran 2020-01-09 22:13:00 -05:00
parent 338fbcea9c
commit 1f4c4c0901
4 changed files with 163 additions and 88 deletions

View file

@ -1,6 +1,15 @@
isBackgroundScript = true;
// Used only on Firefox, which does not support non persistent background pages. // Used only on Firefox, which does not support non persistent background pages.
var contentScriptRegistrations = {}; var contentScriptRegistrations = {};
// Register content script if needed
if (isFirefox()) {
wait(() => SB.config !== undefined).then(function() {
if (SB.config.supportInvidious) setupExtraSiteContentScripts();
});
}
chrome.tabs.onUpdated.addListener(function(tabId) { chrome.tabs.onUpdated.addListener(function(tabId) {
chrome.tabs.sendMessage(tabId, { chrome.tabs.sendMessage(tabId, {
message: 'update', message: 'update',
@ -44,16 +53,7 @@ chrome.runtime.onMessage.addListener(async function (request, sender, callback)
iconUrl: "./icons/LogoSponsorBlocker256px.png" iconUrl: "./icons/LogoSponsorBlocker256px.png"
}); });
case "registerContentScript": case "registerContentScript":
let oldRegistration = contentScriptRegistrations[request.id]; registerFirefoxContentScript(request);
if (oldRegistration) oldRegistration.unregister();
browser.contentScripts.register({
allFrames: request.allFrames,
js: request.js,
css: request.css,
matches: request.matches
}).then(() => void (contentScriptRegistrations[request.id] = registration));
return false; return false;
case "unregisterContentScript": case "unregisterContentScript":
contentScriptRegistrations[request.id].unregister(); contentScriptRegistrations[request.id].unregister();
@ -81,6 +81,24 @@ chrome.runtime.onInstalled.addListener(function (object) {
}, 1500); }, 1500);
}); });
/**
* Only works on Firefox.
* Firefox requires that it be applied after every extension restart.
*
* @param {JSON} options
*/
function registerFirefoxContentScript(options) {
let oldRegistration = contentScriptRegistrations[options.id];
if (oldRegistration) oldRegistration.unregister();
browser.contentScripts.register({
allFrames: options.allFrames,
js: options.js,
css: options.css,
matches: options.matches
}).then(() => void (contentScriptRegistrations[options.id] = registration));
}
//gets the sponsor times from memory //gets the sponsor times from memory
function getSponsorTimes(videoID, callback) { function getSponsorTimes(videoID, callback) {
let sponsorTimes = []; let sponsorTimes = [];

View file

@ -76,5 +76,10 @@
"page": "options/options.html", "page": "options/options.html",
"open_in_tab": true "open_in_tab": true
}, },
"manifest_version": 2 "manifest_version": 2,
"browser_specific_settings": {
"gecko": {
"id": "sponsorBlocker@ajay.app"
}
}
} }

View file

@ -185,75 +185,10 @@ function invidiousInit(checkbox, option) {
*/ */
function invidiousOnClick(checkbox, option) { function invidiousOnClick(checkbox, option) {
if (checkbox.checked) { if (checkbox.checked) {
// Request permission setupExtraSitePermissions(function (granted) {
let permissions = ["declarativeContent"]; if (!granted) {
if (isFirefox()) permissions = [];
chrome.permissions.request({
origins: getInvidiousInstancesRegex(),
permissions: permissions
}, async function (granted) {
if (granted) {
let js = [
"config.js",
"SB.js",
"utils/previewBar.js",
"utils/skipNotice.js",
"utils.js",
"content.js",
"popup.js"
];
let css = [
"content.css",
"./libs/Source+Sans+Pro.css",
"popup.css"
];
if (isFirefox()) {
let firefoxJS = [];
for (const file of js) {
firefoxJS.push({file});
}
let firefoxCSS = [];
for (const file of css) {
firefoxCSS.push({file});
}
chrome.runtime.sendMessage({
message: "registerContentScript",
id: "invidious",
allFrames: true,
js: firefoxJS,
css: firefoxCSS,
matches: getInvidiousInstancesRegex()
});
} else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() {
let conditions = [];
for (const regex of getInvidiousInstancesRegex()) {
conditions.push(new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: regex }
}));
}
// Add page rule
let rule = {
id: "invidious",
conditions,
actions: [new chrome.declarativeContent.RequestContentScript({
allFrames: true,
js,
css
})]
};
chrome.declarativeContent.onPageChanged.addRules([rule]);
});
}
} else {
SB.config[option] = false; SB.config[option] = false;
checkbox.checked = false; checkbox.checked = false;
chrome.declarativeContent.onPageChanged.removeRules(["invidious"]);
} }
}); });
} else { } else {
@ -359,13 +294,3 @@ function activateTextChange(element) {
element.querySelector(".option-hidden-section").classList.remove("hidden"); element.querySelector(".option-hidden-section").classList.remove("hidden");
} }
function getInvidiousInstancesRegex() {
var invidiousInstancesRegex = [];
for (const url of SB.config.invidiousInstances) {
invidiousInstancesRegex.push("https://*." + url + "/*");
invidiousInstancesRegex.push("http://*." + url + "/*");
}
return invidiousInstancesRegex;
}

127
utils.js
View file

@ -1,3 +1,4 @@
var isBackgroundScript = false;
var onInvidious = false; var onInvidious = false;
// Function that can be used to wait for a condition before returning // Function that can be used to wait for a condition before returning
@ -60,6 +61,119 @@ function getYouTubeVideoID(url) {
return false; return false;
} }
/**
* Asks for the optional permissions required for all extra sites.
* It also starts the content script registrations.
*
* For now, it is just SB.config.invidiousInstances.
*
* @param {CallableFunction} callback
*/
function setupExtraSitePermissions(callback) {
// Request permission
let permissions = ["declarativeContent"];
if (isFirefox()) permissions = [];
chrome.permissions.request({
origins: getInvidiousInstancesRegex(),
permissions: permissions
}, async function (granted) {
if (granted) {
setupExtraSiteContentScripts();
} else {
if (isFirefox()) {
if (isBackgroundScript) {
if (contentScriptRegistrations[request.id]) {
contentScriptRegistrations[request.id].unregister();
delete contentScriptRegistrations[request.id];
}
} else {
chrome.runtime.sendMessage({
message: "unregisterContentScript",
id: "invidious"
});
}
} else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"]);
}
}
callback(granted);
});
}
/**
* Registers the content scripts for the extra sites.
* Will use a different method depending on the browser.
* This is called by setupExtraSitePermissions().
*
* For now, it is just SB.config.invidiousInstances.
*/
function setupExtraSiteContentScripts() {
let js = [
"config.js",
"SB.js",
"utils/previewBar.js",
"utils/skipNotice.js",
"utils.js",
"content.js",
"popup.js"
];
let css = [
"content.css",
"./libs/Source+Sans+Pro.css",
"popup.css"
];
if (isFirefox()) {
let firefoxJS = [];
for (const file of js) {
firefoxJS.push({file});
}
let firefoxCSS = [];
for (const file of css) {
firefoxCSS.push({file});
}
let registration = {
message: "registerContentScript",
id: "invidious",
allFrames: true,
js: firefoxJS,
css: firefoxCSS,
matches: getInvidiousInstancesRegex()
};
if (isBackgroundScript) {
registerFirefoxContentScript(registration);
} else {
chrome.runtime.sendMessage(registration);
}
} else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() {
let conditions = [];
for (const regex of getInvidiousInstancesRegex()) {
conditions.push(new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: regex }
}));
}
// Add page rule
let rule = {
id: "invidious",
conditions,
actions: [new chrome.declarativeContent.RequestContentScript({
allFrames: true,
js,
css
})]
};
chrome.declarativeContent.onPageChanged.addRules([rule]);
});
}
}
function localizeHtmlPage() { function localizeHtmlPage() {
//Localize by replacing __MSG_***__ meta tags //Localize by replacing __MSG_***__ meta tags
var objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children; var objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children;
@ -83,6 +197,19 @@ function getLocalizedMessage(text) {
} }
} }
/**
* @returns {String[]} Invidious Instances in regex form
*/
function getInvidiousInstancesRegex() {
var invidiousInstancesRegex = [];
for (const url of SB.config.invidiousInstances) {
invidiousInstancesRegex.push("https://*." + url + "/*");
invidiousInstancesRegex.push("http://*." + url + "/*");
}
return invidiousInstancesRegex;
}
function generateUserID(length = 36) { function generateUserID(length = 36) {
let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = ""; let result = "";