Moved Utils away from a static class.

Moved Firefox content script registration to the background script.

Moved onInvidious to the content script.
This commit is contained in:
Ajay Ramachandran
2020-02-01 18:47:36 -05:00
parent 4bd410f04e
commit 17381e7deb
5 changed files with 143 additions and 129 deletions

View File

@@ -1,4 +1,3 @@
interface SBObject { interface SBObject {
configListeners: Array<Function>; configListeners: Array<Function>;
defaults: any; defaults: any;

View File

@@ -1,17 +1,19 @@
import Utils from "./utils"; import * as Types from "./types";
import SB from "./SB"; import SB from "./SB";
import * as Types from "./types"; import Utils from "./utils";
var utils = new Utils({
Utils.isBackgroundScript = true; registerFirefoxContentScript,
unregisterFirefoxContentScript
});
// 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 // Register content script if needed
if (Utils.isFirefox()) { if (utils.isFirefox()) {
Utils.wait(() => SB.config !== undefined).then(function() { utils.wait(() => SB.config !== undefined).then(function() {
if (SB.config.supportInvidious) Utils.setupExtraSiteContentScripts(); if (SB.config.supportInvidious) utils.setupExtraSiteContentScripts();
}); });
} }
@@ -62,9 +64,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
registerFirefoxContentScript(request); registerFirefoxContentScript(request);
return false; return false;
case "unregisterContentScript": case "unregisterContentScript":
contentScriptRegistrations[request.id].unregister(); unregisterFirefoxContentScript(request.id)
delete contentScriptRegistrations[request.id];
return false; return false;
} }
}); });
@@ -82,7 +82,7 @@ chrome.runtime.onInstalled.addListener(function (object) {
chrome.tabs.create({url: chrome.extension.getURL("/help/index_en.html")}); chrome.tabs.create({url: chrome.extension.getURL("/help/index_en.html")});
//generate a userID //generate a userID
const newUserID = Utils.generateUserID(); const newUserID = utils.generateUserID();
//save this UUID //save this UUID
SB.config.userID = newUserID; SB.config.userID = newUserID;
@@ -111,6 +111,16 @@ function registerFirefoxContentScript(options) {
}).then((registration) => void (contentScriptRegistrations[options.id] = registration)); }).then((registration) => void (contentScriptRegistrations[options.id] = registration));
} }
/**
* Only works on Firefox.
* Firefox requires that this is handled by the background script
*
*/
function unregisterFirefoxContentScript(id: string) {
contentScriptRegistrations[id].unregister();
delete contentScriptRegistrations[id];
}
//gets the sponsor times from memory //gets the sponsor times from memory
function getSponsorTimes(videoID, callback) { function getSponsorTimes(videoID, callback) {
let sponsorTimes = []; let sponsorTimes = [];
@@ -148,12 +158,12 @@ function submitVote(type, UUID, callback) {
if (userID == undefined || userID === "undefined") { if (userID == undefined || userID === "undefined") {
//generate one //generate one
userID = Utils.generateUserID(); userID = utils.generateUserID();
SB.config.userID = userID; SB.config.userID = userID;
} }
//publish this vote //publish this vote
Utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) { utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback({ callback({
successType: 1 successType: 1
@@ -205,7 +215,7 @@ async function submitTimes(videoID, callback) {
let increasedContributionAmount = false; let increasedContributionAmount = false;
//submit the sponsorTime //submit the sponsorTime
Utils.sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] utils.sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
+ "&userID=" + userID, function(xmlhttp, error) { + "&userID=" + userID, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && !error) { if (xmlhttp.readyState == 4 && !error) {
callback({ callback({

View File

@@ -1,7 +1,9 @@
import Utils from "./utils";
import SB from "./SB"; import SB from "./SB";
import runThePopup from "./popup.js"; import Utils from "./utils";
var utils = new Utils();
import runThePopup from "./popup";
import PreviewBar from "./js-components/previewBar"; import PreviewBar from "./js-components/previewBar";
import SkipNotice from "./js-components/skipNotice"; import SkipNotice from "./js-components/skipNotice";
@@ -24,7 +26,7 @@ var sponsorSkipped = [];
//the video //the video
var v; var v;
var listenerAdded; var onInvidious;
//the video id of the last preview bar update //the video id of the last preview bar update
var lastPreviewBarUpdate; var lastPreviewBarUpdate;
@@ -48,7 +50,7 @@ var previewBar = null;
var controls = null; var controls = null;
// Direct Links // Direct Links
videoIDChange(Utils.getYouTubeVideoID(document.URL)); videoIDChange(getYouTubeVideoID(document.URL));
//the last time looked at (used to see if this time is in the interval) //the last time looked at (used to see if this time is in the interval)
var lastTime = -1; var lastTime = -1;
@@ -93,7 +95,7 @@ function messageListener(request: any, sender: any, sendResponse: (response: any
//messages from popup script //messages from popup script
switch(request.message){ switch(request.message){
case "update": case "update":
videoIDChange(Utils.getYouTubeVideoID(document.URL)); videoIDChange(getYouTubeVideoID(document.URL));
break; break;
case "sponsorStart": case "sponsorStart":
sponsorMessageStarted(sendResponse); sponsorMessageStarted(sendResponse);
@@ -239,13 +241,13 @@ function videoIDChange(id) {
// TODO: Use a better method here than using type any // TODO: Use a better method here than using type any
// This is done to be able to do channelIDPromise.isFulfilled and channelIDPromise.isRejected // This is done to be able to do channelIDPromise.isFulfilled and channelIDPromise.isRejected
let channelIDPromise: any = Utils.wait(getChannelID); let channelIDPromise: any = utils.wait(getChannelID);
channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true); channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true);
//setup the preview bar //setup the preview bar
if (previewBar == null) { if (previewBar == null) {
//create it //create it
Utils.wait(getControls).then(result => { utils.wait(getControls).then(result => {
const progressElementSelectors = [ const progressElementSelectors = [
// For YouTube // For YouTube
"ytp-progress-bar-container", "ytp-progress-bar-container",
@@ -296,7 +298,7 @@ function videoIDChange(id) {
sponsorTimesSubmitting = []; sponsorTimesSubmitting = [];
//see if the onvideo control image needs to be changed //see if the onvideo control image needs to be changed
Utils.wait(getControls).then(result => { utils.wait(getControls).then(result => {
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
message: "getSponsorTimes", message: "getSponsorTimes",
videoID: id videoID: id
@@ -321,7 +323,7 @@ function videoIDChange(id) {
}); });
}); });
//see if video controls buttons should be added //see if video controls buttons should be added
if (!Utils.onInvidious) { if (!onInvidious) {
updateVisibilityOfPlayerControlsButton(); updateVisibilityOfPlayerControlsButton();
} }
} }
@@ -346,7 +348,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) {
whitelistCheck(); whitelistCheck();
} else if (channelIDPromise.isRejected) { } else if (channelIDPromise.isRejected) {
//try again //try again
Utils.wait(getChannelID).then(whitelistCheck).catch(); utils.wait(getChannelID).then(whitelistCheck).catch();
} else { } else {
//add it as a then statement //add it as a then statement
channelIDPromise.then(whitelistCheck); channelIDPromise.then(whitelistCheck);
@@ -356,7 +358,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) {
//check database for sponsor times //check database for sponsor times
//made true once a setTimeout has been created to try again after a server error //made true once a setTimeout has been created to try again after a server error
let recheckStarted = false; let recheckStarted = false;
Utils.sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) { utils.sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
sponsorDataFound = true; sponsorDataFound = true;
@@ -412,30 +414,44 @@ function sponsorsLookup(id: string, channelIDPromise = null) {
} }
} }
function updatePreviewBar() { function getYouTubeVideoID(url: string) {
let localSponsorTimes = sponsorTimes; // For YouTube TV support
if (localSponsorTimes == null) localSponsorTimes = []; if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
//Attempt to parse url
let urlObject = null;
try {
urlObject = new URL(url);
} catch (e) {
console.error("[SB] Unable to parse URL: " + url);
return false;
}
let allSponsorTimes = localSponsorTimes.concat(sponsorTimesSubmitting); //Check if valid hostname
if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) {
//create an array of the sponsor types onInvidious = true;
let types = []; } else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) {
for (let i = 0; i < localSponsorTimes.length; i++) { if (!SB.config) {
if (!hiddenSponsorTimes.includes(i)) { // Call this later, in case this is an Invidious tab
types.push("sponsor"); this.wait(() => SB.config !== undefined).then(() => this.videoIDChange(this.getYouTubeVideoID(url)));
} else {
// Don't show this sponsor
types.push(null);
} }
}
for (let i = 0; i < sponsorTimesSubmitting.length; i++) { return false
types.push("previewSponsor");
} }
Utils.wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, v.duration)); //Get ID from searchParam
if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) {
//update last video id let id = urlObject.searchParams.get("v");
lastPreviewBarUpdate = sponsorVideoID; return id.length == 11 ? id : false;
} else if (urlObject.pathname.startsWith("/embed/")) {
try {
return urlObject.pathname.substr(7, 11);
} catch (e) {
console.error("[SB] Video ID not valid for " + url);
return false;
}
}
return false;
} }
function getChannelID() { function getChannelID() {
@@ -445,7 +461,7 @@ function getChannelID() {
channelURLContainer = document.querySelector("#channel-name > #container > #text-container > #text"); channelURLContainer = document.querySelector("#channel-name > #container > #text-container > #text");
if (channelURLContainer !== null) { if (channelURLContainer !== null) {
channelURLContainer = channelURLContainer.firstElementChild; channelURLContainer = channelURLContainer.firstElementChild;
} else if (Utils.onInvidious) { } else if (onInvidious) {
// Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers... // Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers...
channelURLContainer = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a"); channelURLContainer = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a");
} else { } else {
@@ -466,7 +482,7 @@ function getChannelID() {
let currentTitle = ""; let currentTitle = "";
if (titleInfoContainer != null) { if (titleInfoContainer != null) {
currentTitle = (<HTMLElement> titleInfoContainer.firstElementChild.firstElementChild.querySelector(".title").firstElementChild).innerText; currentTitle = (<HTMLElement> titleInfoContainer.firstElementChild.firstElementChild.querySelector(".title").firstElementChild).innerText;
} else if (Utils.onInvidious) { } else if (onInvidious) {
// Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers... // Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers...
currentTitle = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a > div > span").textContent; currentTitle = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a > div > span").textContent;
} else { } else {
@@ -487,6 +503,32 @@ function getChannelID() {
channelWhitelisted = false; channelWhitelisted = false;
} }
function updatePreviewBar() {
let localSponsorTimes = sponsorTimes;
if (localSponsorTimes == null) localSponsorTimes = [];
let allSponsorTimes = localSponsorTimes.concat(sponsorTimesSubmitting);
//create an array of the sponsor types
let types = [];
for (let i = 0; i < localSponsorTimes.length; i++) {
if (!hiddenSponsorTimes.includes(i)) {
types.push("sponsor");
} else {
// Don't show this sponsor
types.push(null);
}
}
for (let i = 0; i < sponsorTimesSubmitting.length; i++) {
types.push("previewSponsor");
}
utils.wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, v.duration));
//update last video id
lastPreviewBarUpdate = sponsorVideoID;
}
//checks if this channel is whitelisted, should be done only after the channelID has been loaded //checks if this channel is whitelisted, should be done only after the channelID has been loaded
function whitelistCheck() { function whitelistCheck() {
//see if this is a whitelisted channel //see if this is a whitelisted channel
@@ -595,7 +637,7 @@ function skipToTime(v, index, sponsorTimes, openNotice) {
//send telemetry that a this sponsor was skipped //send telemetry that a this sponsor was skipped
if (SB.config.trackViewCount && !sponsorSkipped[index]) { if (SB.config.trackViewCount && !sponsorSkipped[index]) {
Utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID); utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
if (!SB.config.disableAutoSkip) { if (!SB.config.disableAutoSkip) {
// Count this as a skip // Count this as a skip
@@ -659,7 +701,7 @@ function getControls() {
//adds all the player controls buttons //adds all the player controls buttons
async function createButtons() { async function createButtons() {
let result = await Utils.wait(getControls).catch(); let result = await utils.wait(getControls).catch();
//set global controls variable //set global controls variable
controls = result; controls = result;
@@ -677,7 +719,7 @@ async function updateVisibilityOfPlayerControlsButton() {
await createButtons(); await createButtons();
if (SB.config.hideVideoPlayerControls || Utils.onInvidious) { if (SB.config.hideVideoPlayerControls || onInvidious) {
document.getElementById("startSponsorButton").style.display = "none"; document.getElementById("startSponsorButton").style.display = "none";
document.getElementById("submitButton").style.display = "none"; document.getElementById("submitButton").style.display = "none";
} else { } else {
@@ -685,13 +727,13 @@ async function updateVisibilityOfPlayerControlsButton() {
} }
//don't show the info button on embeds //don't show the info button on embeds
if (SB.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || Utils.onInvidious) { if (SB.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || onInvidious) {
document.getElementById("infoButton").style.display = "none"; document.getElementById("infoButton").style.display = "none";
} else { } else {
document.getElementById("infoButton").style.removeProperty("display"); document.getElementById("infoButton").style.removeProperty("display");
} }
if (SB.config.hideDeleteButtonPlayerControls || Utils.onInvidious) { if (SB.config.hideDeleteButtonPlayerControls || onInvidious) {
document.getElementById("deleteButton").style.display = "none"; document.getElementById("deleteButton").style.display = "none";
} }
} }
@@ -740,10 +782,10 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
if(!sponsorVideoID) return false; if(!sponsorVideoID) return false;
//make sure submit button is loaded //make sure submit button is loaded
await Utils.wait(isSubmitButtonLoaded); await utils.wait(isSubmitButtonLoaded);
//if it isn't visible, there is no data //if it isn't visible, there is no data
let shouldHide = (uploadButtonVisible && !(SB.config.hideDeleteButtonPlayerControls || Utils.onInvidious)) ? "unset" : "none" let shouldHide = (uploadButtonVisible && !(SB.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none"
document.getElementById("deleteButton").style.display = shouldHide; document.getElementById("deleteButton").style.display = shouldHide;
if (showStartSponsor) { if (showStartSponsor) {
@@ -911,7 +953,7 @@ function vote(type, UUID, skipNotice) {
skipNotice.addNoticeInfoMessage.bind(skipNotice)(chrome.i18n.getMessage("voteFail")) skipNotice.addNoticeInfoMessage.bind(skipNotice)(chrome.i18n.getMessage("voteFail"))
skipNotice.resetVoteButtonInfo.bind(skipNotice)(); skipNotice.resetVoteButtonInfo.bind(skipNotice)();
} else if (response.successType == -1) { } else if (response.successType == -1) {
skipNotice.addNoticeInfoMessage.bind(skipNotice)(Utils.getErrorMessage(response.statusCode)) skipNotice.addNoticeInfoMessage.bind(skipNotice)(utils.getErrorMessage(response.statusCode))
skipNotice.resetVoteButtonInfo.bind(skipNotice)(); skipNotice.resetVoteButtonInfo.bind(skipNotice)();
} }
} }
@@ -1016,7 +1058,7 @@ function sendSubmitMessage(){
sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting); sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting);
for (let i = 0; i < sponsorTimesSubmitting.length; i++) { for (let i = 0; i < sponsorTimesSubmitting.length; i++) {
// Add some random IDs // Add some random IDs
UUIDs.push(Utils.generateUserID()); UUIDs.push(utils.generateUserID());
} }
// Empty the submitting times // Empty the submitting times
@@ -1028,7 +1070,7 @@ function sendSubmitMessage(){
document.getElementById("submitButton").style.animation = "unset"; document.getElementById("submitButton").style.animation = "unset";
(<HTMLImageElement> document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png"); (<HTMLImageElement> document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png");
alert(Utils.getErrorMessage(response.statusCode)); alert(utils.getErrorMessage(response.statusCode));
} }
} }
}); });

View File

@@ -1,6 +1,8 @@
import Utils from "./utils";
import SB from "./SB"; import SB from "./SB";
import Utils from "./utils";
var utils = new Utils();
interface MessageListener { interface MessageListener {
(request: any, sender: any, callback: (response: any) => void): void; (request: any, sender: any, callback: (response: any) => void): void;
} }
@@ -38,9 +40,9 @@ class MessageHandler {
async function runThePopup(messageListener?: MessageListener) { async function runThePopup(messageListener?: MessageListener) {
var messageHandler = new MessageHandler(); var messageHandler = new MessageHandler();
Utils.localizeHtmlPage(); utils.localizeHtmlPage();
await Utils.wait(() => SB.config !== undefined); await utils.wait(() => SB.config !== undefined);
var OptionsElements: any = {}; var OptionsElements: any = {};
@@ -168,7 +170,7 @@ async function runThePopup(messageListener?: MessageListener) {
if (userID != undefined) { if (userID != undefined) {
//there are probably some views on these submissions then //there are probably some views on these submissions then
//get the amount of views from the sponsors submitted //get the amount of views from the sponsors submitted
Utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let viewCount = JSON.parse(xmlhttp.responseText).viewCount; let viewCount = JSON.parse(xmlhttp.responseText).viewCount;
if (viewCount != 0) { if (viewCount != 0) {
@@ -185,7 +187,7 @@ async function runThePopup(messageListener?: MessageListener) {
}); });
//get this time in minutes //get this time in minutes
Utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved;
if (minutesSaved != 0) { if (minutesSaved != 0) {
@@ -802,7 +804,7 @@ async function runThePopup(messageListener?: MessageListener) {
clearTimes(); clearTimes();
} else { } else {
document.getElementById("submitTimesInfoMessage").innerText = Utils.getErrorMessage(response.statusCode); document.getElementById("submitTimesInfoMessage").innerText = utils.getErrorMessage(response.statusCode);
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset"; document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
OptionsElements.submitTimesInfoMessageContainer.style.display = "unset"; OptionsElements.submitTimesInfoMessageContainer.style.display = "unset";
@@ -854,7 +856,7 @@ async function runThePopup(messageListener?: MessageListener) {
//make the options username setting option visible //make the options username setting option visible
function setUsernameButton() { function setUsernameButton() {
//get username from the server //get username from the server
Utils.sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { utils.sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
OptionsElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; OptionsElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName;
@@ -871,7 +873,7 @@ async function runThePopup(messageListener?: MessageListener) {
OptionsElements.usernameInput.style.display = "none"; OptionsElements.usernameInput.style.display = "none";
OptionsElements.setUsernameStatusContainer.style.display = "unset"; OptionsElements.setUsernameStatusContainer.style.display = "unset";
OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); OptionsElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status);
} }
}); });
} }
@@ -883,7 +885,7 @@ async function runThePopup(messageListener?: MessageListener) {
OptionsElements.setUsernameStatus.innerText = "Loading..."; OptionsElements.setUsernameStatus.innerText = "Loading...";
//get the userID //get the userID
Utils.sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) { utils.sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//submitted //submitted
OptionsElements.submitUsername.style.display = "none"; OptionsElements.submitUsername.style.display = "none";
@@ -891,7 +893,7 @@ async function runThePopup(messageListener?: MessageListener) {
OptionsElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); OptionsElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success");
} else if (xmlhttp.readyState == 4) { } else if (xmlhttp.readyState == 4) {
OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); OptionsElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status);
} }
}); });
@@ -944,7 +946,7 @@ async function runThePopup(messageListener?: MessageListener) {
//failure: duplicate vote //failure: duplicate vote
addVoteMessage(chrome.i18n.getMessage("voteFail"), UUID) addVoteMessage(chrome.i18n.getMessage("voteFail"), UUID)
} else if (response.successType == -1) { } else if (response.successType == -1) {
addVoteMessage(Utils.getErrorMessage(response.statusCode), UUID) addVoteMessage(utils.getErrorMessage(response.statusCode), UUID)
} }
} }
}); });

View File

@@ -3,11 +3,15 @@ import SB from "./SB";
class Utils { class Utils {
static isBackgroundScript = false; // Contains functions needed from the background script
static onInvidious = false; backgroundScriptContainer: any = null;
constructor(backgroundScriptContainer?: any) {
this.backgroundScriptContainer = backgroundScriptContainer;
}
// Function that can be used to wait for a condition before returning // Function that can be used to wait for a condition before returning
static async wait(condition, timeout = 5000, check = 100) { async wait(condition, timeout = 5000, check = 100) {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
setTimeout(() => reject("TIMEOUT"), timeout); setTimeout(() => reject("TIMEOUT"), timeout);
@@ -26,46 +30,6 @@ class Utils {
}); });
} }
static getYouTubeVideoID(url: string) {
// For YouTube TV support
if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
//Attempt to parse url
let urlObject = null;
try {
urlObject = new URL(url);
} catch (e) {
console.error("[SB] Unable to parse URL: " + url);
return false;
}
//Check if valid hostname
if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) {
onInvidious = true;
} else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) {
if (!SB.config) {
// Call this later, in case this is an Invidious tab
this.wait(() => SB.config !== undefined).then(() => this.videoIDChange(this.getYouTubeVideoID(url)));
}
return false
}
//Get ID from searchParam
if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) {
let id = urlObject.searchParams.get("v");
return id.length == 11 ? id : false;
} else if (urlObject.pathname.startsWith("/embed/")) {
try {
return urlObject.pathname.substr(7, 11);
} catch (e) {
console.error("[SB] Video ID not valid for " + url);
return false;
}
}
return false;
}
/** /**
* Asks for the optional permissions required for all extra sites. * Asks for the optional permissions required for all extra sites.
* It also starts the content script registrations. * It also starts the content script registrations.
@@ -74,7 +38,7 @@ class Utils {
* *
* @param {CallableFunction} callback * @param {CallableFunction} callback
*/ */
static setupExtraSitePermissions(callback) { setupExtraSitePermissions(callback) {
// Request permission // Request permission
let permissions = ["declarativeContent"]; let permissions = ["declarativeContent"];
if (this.isFirefox()) permissions = []; if (this.isFirefox()) permissions = [];
@@ -100,7 +64,7 @@ class Utils {
* *
* For now, it is just SB.config.invidiousInstances. * For now, it is just SB.config.invidiousInstances.
*/ */
static setupExtraSiteContentScripts() { setupExtraSiteContentScripts() {
let js = [ let js = [
"config.js", "config.js",
"SB.js", "SB.js",
@@ -135,8 +99,8 @@ class Utils {
matches: this.getInvidiousInstancesRegex() matches: this.getInvidiousInstancesRegex()
}; };
if (this.isBackgroundScript) { if (this.backgroundScriptContainer) {
registerFirefoxContentScript(registration); this.backgroundScriptContainer.registerFirefoxContentScript(registration);
} else { } else {
chrome.runtime.sendMessage(registration); chrome.runtime.sendMessage(registration);
} }
@@ -169,15 +133,12 @@ class Utils {
/** /**
* Removes the permission and content script registration. * Removes the permission and content script registration.
*/ */
static removeExtraSiteRegistration() { removeExtraSiteRegistration() {
if (this.isFirefox()) { if (this.isFirefox()) {
let id = "invidious"; let id = "invidious";
if (this.isBackgroundScript) { if (this.backgroundScriptContainer) {
if (contentScriptRegistrations[id]) { this.backgroundScriptContainer.unregisterFirefoxContentScript(id);
contentScriptRegistrations[id].unregister();
delete contentScriptRegistrations[id];
}
} else { } else {
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
message: "unregisterContentScript", message: "unregisterContentScript",
@@ -193,7 +154,7 @@ class Utils {
}); });
} }
static localizeHtmlPage() { 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;
for (var j = 0; j < objects.length; j++) { for (var j = 0; j < objects.length; j++) {
@@ -204,7 +165,7 @@ class Utils {
} }
} }
static getLocalizedMessage(text) { getLocalizedMessage(text) {
var valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) { var valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) {
return v1 ? chrome.i18n.getMessage(v1) : ""; return v1 ? chrome.i18n.getMessage(v1) : "";
}); });
@@ -219,7 +180,7 @@ class Utils {
/** /**
* @returns {String[]} Invidious Instances in regex form * @returns {String[]} Invidious Instances in regex form
*/ */
static getInvidiousInstancesRegex() { getInvidiousInstancesRegex() {
var invidiousInstancesRegex = []; var invidiousInstancesRegex = [];
for (const url of SB.config.invidiousInstances) { for (const url of SB.config.invidiousInstances) {
invidiousInstancesRegex.push("https://*." + url + "/*"); invidiousInstancesRegex.push("https://*." + url + "/*");
@@ -229,7 +190,7 @@ class Utils {
return invidiousInstancesRegex; return invidiousInstancesRegex;
} }
static generateUserID(length = 36) { generateUserID(length = 36) {
let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = ""; let result = "";
if (window.crypto && window.crypto.getRandomValues) { if (window.crypto && window.crypto.getRandomValues) {
@@ -253,7 +214,7 @@ class Utils {
* @param {int} statusCode * @param {int} statusCode
* @returns {string} errorMessage * @returns {string} errorMessage
*/ */
static getErrorMessage(statusCode) { getErrorMessage(statusCode) {
let errorMessage = ""; let errorMessage = "";
if([400, 429, 409, 502, 0].includes(statusCode)) { if([400, 429, 409, 502, 0].includes(statusCode)) {
@@ -276,7 +237,7 @@ class Utils {
* @param address The address to add to the SponsorBlock server address * @param address The address to add to the SponsorBlock server address
* @param callback * @param callback
*/ */
static sendRequestToServer(type: string, address: string, callback?: (xmlhttp: XMLHttpRequest, err: boolean) => any) { sendRequestToServer(type: string, address: string, callback?: (xmlhttp: XMLHttpRequest, err: boolean) => any) {
let xmlhttp = new XMLHttpRequest(); let xmlhttp = new XMLHttpRequest();
xmlhttp.open(type, CompileConfig.serverAddress + address, true); xmlhttp.open(type, CompileConfig.serverAddress + address, true);
@@ -298,7 +259,7 @@ class Utils {
/** /**
* Is this Firefox (web-extensions) * Is this Firefox (web-extensions)
*/ */
static isFirefox() { isFirefox() {
return typeof(browser) !== "undefined"; return typeof(browser) !== "undefined";
} }
} }