aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAjay Ramachandran <[email protected]>2021-05-10 16:25:17 -0400
committerGitHub <[email protected]>2021-05-10 16:25:17 -0400
commit08c5c73f4ad51057869d581364171baa6abd206e (patch)
treefcd4b502bc82bed40be7c03fa99b4965f9169089
parent35fc238891444d10ac059d9b9ae321e7843985c1 (diff)
parentbf84139ea7530f2b03fecc5b8429a4f818d99e8b (diff)
downloadSponsorBlock-08c5c73f4ad51057869d581364171baa6abd206e.tar.gz
SponsorBlock-08c5c73f4ad51057869d581364171baa6abd206e.zip
Merge pull request #738 from ajayyy/fix-video2.0.14
Prompt to accept youtube.com permission if video info fails to load
-rw-r--r--public/_locales/en/messages.json15
-rw-r--r--public/permissions/index.html28
-rw-r--r--public/permissions/styles.css356
-rw-r--r--src/background.ts3
-rw-r--r--src/content.ts23
-rw-r--r--src/options.ts2
-rw-r--r--src/permissions.ts33
-rw-r--r--src/utils.ts41
-rw-r--r--webpack/webpack.common.js3
9 files changed, 483 insertions, 21 deletions
diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json
index 51eceee8..fbf06ec7 100644
--- a/public/_locales/en/messages.json
+++ b/public/_locales/en/messages.json
@@ -594,9 +594,24 @@
"adblockerIssue": {
"message": "It seems that something is blocking SponsorBlock's ability to get video data. This is probably your ad blocker. Please check https://github.com/ajayyy/SponsorBlock/wiki/Fix-Ad-Blocker-Blocking-SponsorBlock's-Requests"
},
+ "youtubePermissionRequest": {
+ "message": "It seems that SponsorBlock is unable to reach the YouTube API. To fix this, accept the permission prompt that will appear next, wait a few seconds, and then reload the page."
+ },
+ "acceptPermission": {
+ "message": "Accept permission"
+ },
+ "permissionRequestSuccess": {
+ "message": "Permission success succeeded!"
+ },
+ "permissionRequestFailed": {
+ "message": "Permission request failed, did you click deny?"
+ },
"adblockerIssueUnlistedVideosInfo": {
"message": "If you are unable to resolve this, then disable the setting 'Ignore unlisted/private videos', as SponsorBlock is unable to retrieve the visibility information for this video"
},
+ "adblockerIssueWhitelist": {
+ "message": "If you are unable to resolve this, then disable the setting 'Force Channel Check Before Skipping', as SponsorBlock is unable to retrieve the visibility information for this video"
+ },
"itCouldBeAdblockerIssue": {
"message": "If this keeps occuring, it could be caused by your ad blocker. Please check https://github.com/ajayyy/SponsorBlock/wiki/Fix-Ad-Blocker-Blocking-SponsorBlock's-Requests"
},
diff --git a/public/permissions/index.html b/public/permissions/index.html
new file mode 100644
index 00000000..4475f039
--- /dev/null
+++ b/public/permissions/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+
+<head>
+ <title>Permissions - SponsorBlock</title>
+ <meta charset="utf-8">
+
+ <link href="styles.css" rel="stylesheet"/>
+
+ <script src="../js/vendor.js"></script>
+ <script src="../js/permissions.js"></script>
+</head>
+
+<body class="sponsorBlockPageBody">
+
+ <div id="title" class="titleBar">
+ <img src="../icons/LogoSponsorBlocker256px.png" height="80" class="profilepic"/>
+ SponsorBlock
+ </div>
+
+ <br/>
+
+ <div class="center">
+ <div id="acceptPermissionButton" class="option-button inline">
+ __MSG_acceptPermission__
+ </div>
+ </div>
+
+</body>
diff --git a/public/permissions/styles.css b/public/permissions/styles.css
new file mode 100644
index 00000000..971c6893
--- /dev/null
+++ b/public/permissions/styles.css
@@ -0,0 +1,356 @@
+/* Options page CSS */
+body {
+ font-family: sans-serif;
+}
+
+.center {
+ text-align: center;
+}
+
+.inline {
+ display: inline-block;
+}
+
+.bold {
+ font-weight: bold;
+}
+
+.hidden {
+ display: none !important;
+}
+
+.keybind-status {
+ display: inline;
+}
+
+.small-description {
+ color: white;
+ font-size: 13px;
+}
+
+.medium-description {
+ color: white;
+ font-size: 15px;
+}
+
+.option-text-box {
+ width: 300px;
+}
+
+.option-button {
+ cursor: pointer;
+
+ background-color: #c00000;
+ padding: 10px;
+ color: white;
+ border-radius: 5px;
+ font-size: 14px;
+
+ width: max-content;
+}
+
+.option-button:hover {
+ background-color: #fc0303;
+}
+
+.option-button.disabled {
+ cursor: default;
+
+ background-color: #520000;
+ color: grey;
+}
+
+#options {
+ max-width: 60%;
+ text-align: left;
+ display: inline-block;
+}
+
+.switch-container:after {
+ content: attr(label-name);
+ position: absolute;
+ padding: 4px;
+ width: max-content;
+
+ font-size: 14px;
+ color: white;
+}
+
+.text-label-container {
+ font-size: 14px;
+ color: white;
+}
+
+.switch {
+ position: relative;
+ display: inline-block;
+ width: 40px;
+ height: 24px;
+}
+
+.switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #707070;
+}
+
+.animated * {
+ -webkit-transition: .4s;
+ transition: .4s;
+}
+
+.slider:before {
+ position: absolute;
+ content: "";
+ height: 16px;
+ width: 16px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+}
+
+.animated .slider:before {
+ -webkit-transition: .4s;
+ transition: .4s;
+}
+
+input:checked + .slider {
+ background-color: #fc0303;
+}
+
+input:checked + .slider:before {
+ -webkit-transform: translateX(16px);
+ -ms-transform: translateX(16px);
+ transform: translateX(16px);
+}
+
+/* Rounded sliders */
+.slider.round {
+ border-radius: 34px;
+}
+
+.slider.round:before {
+ border-radius: 50%;
+}
+
+
+/* Boilerplate CSS from https://ajay.app */
+
+body {
+ background-color: #333333;
+}
+
+.projectPreview {
+ position: relative;
+}
+
+.projectPreviewImage {
+ position: absolute;
+ left: -90px;
+ width: 80px;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+.projectPreviewImageLarge {
+ position: absolute;
+ left: -210px;
+ width: 200px;
+ top: 50%;
+ transform: translateY(-20%);
+}
+
+.projectPreviewImageLargeRight {
+ position: absolute;
+ right: -210px;
+ width: 200px;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+.createdBy {
+ font-size: 14px;
+ text-align: center;
+ padding-top: 0px;
+ padding-bottom: 0px;
+
+ display: inline-block;
+}
+
+#title {
+ background-color: #636363;
+
+ text-align: center;
+ vertical-align: middle;
+
+ font-size: 50px;
+ color: #212121;
+
+ padding: 20px;
+
+ text-decoration: none;
+
+ transition: font-size 1s;
+}
+
+.subtitle {
+ font-size: 40px;
+ color: #dad8d8;
+
+ padding-top: 10px;
+
+ transition: font-size 0.4s;
+}
+
+.subtitle:hover {
+ font-size: 45px;
+
+ transition: font-size 0.4s;
+}
+
+.profilepic {
+ background-color: #636363 !important;
+ vertical-align: middle;
+}
+
+.profilepiccircle {
+ vertical-align: middle;
+ overflow: hidden;
+ border-radius: 50%;
+}
+
+a {
+ text-decoration: underline;
+ color: inherit;
+}
+
+.link {
+ padding: 20px;
+
+ height: 80px;
+
+ transition: height 0.2s;
+}
+
+.link:hover {
+ height: 95px;
+
+ transition: height 0.2s;
+}
+
+#contact,.smalllink {
+ font-size: 25px;
+ color: #e8e8e8;
+
+ text-align: center;
+
+ padding: 10px;
+}
+
+#contact {
+ text-decoration: none;
+}
+
+p,li {
+ font-size: 20px;
+ color: #c4c4c4;
+
+ padding: 10px;
+}
+
+p,li,code,a {
+ max-width: 60%;
+ text-align: left;
+ overflow-wrap: break-word;
+}
+
+@media screen and (orientation:portrait) {
+ p,li,code,a {
+ max-width: 100%;
+ }
+
+ .projectPreviewImage {
+ position: unset;
+ width: 130px;
+ display: block;
+ margin: auto;
+ transform: none;
+ }
+}
+
+.previewImage {
+ max-height: 200px;
+}
+
+img {
+ max-width: 100%;
+
+ text-align: center;
+}
+
+#recentPostTitle {
+ font-size: 30px;
+ color: #dad8d8;
+}
+
+#recentPostDate {
+ font-size: 15px;
+ color: #dad8d8;
+}
+
+h1,h2,h3,h4,h5,h6 {
+ color: #dad8d8;
+}
+
+svg {
+ text-decoration: none;
+}
+
+.number-container:before {
+ content: attr(label-name);
+ padding-right: 4px;
+ width: max-content;
+
+ font-size: 14px;
+ color: white;
+}
+
+/* React styles */
+
+.categoryTableElement {
+ font-size: 16px;
+
+ color: white;
+}
+
+.categoryTableElement > * {
+ padding-right: 15px;
+ padding-bottom: 15px;
+}
+
+.categoryOptionsSelector {
+ background-color: #c00000;
+ color: white;
+
+ border: none;
+ font-size: 14px;
+ padding: 5px;
+ border-radius: 5px;
+}
+
+.categoryColorTextBox {
+ width: 60px;
+
+ background: none;
+ border: none;
+} \ No newline at end of file
diff --git a/src/background.ts b/src/background.ts
index b562c4e7..e44dd28a 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -37,6 +37,9 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
case "openHelp":
chrome.tabs.create({url: chrome.runtime.getURL('help/index_en.html')});
return;
+ case "openPage":
+ chrome.tabs.create({url: chrome.runtime.getURL(request.url)});
+ return;
case "sendRequest":
sendRequestToCustomServer(request.type, request.url, request.data).then(async (response) => {
callback({
diff --git a/src/content.ts b/src/content.ts
index 33842dd3..dd219456 100644
--- a/src/content.ts
+++ b/src/content.ts
@@ -258,7 +258,7 @@ async function videoIDChange(id) {
try {
await utils.wait(() => !!videoInfo, 5000, 1);
} catch (err) {
- alert(chrome.i18n.getMessage("adblockerIssue") + "\n\n" + chrome.i18n.getMessage("adblockerIssueUnlistedVideosInfo"));
+ await videoInfoFetchFailed("adblockerIssueUnlistedVideosInfo");
}
if (isUnlisted()) {
@@ -268,7 +268,11 @@ async function videoIDChange(id) {
}
// Update whitelist data when the video data is loaded
- utils.wait(() => !!videoInfo, 5000, 10).then(whitelistCheck);
+ utils.wait(() => !!videoInfo, 5000, 10).then(whitelistCheck).catch(() => {
+ if (Config.config.forceChannelCheck) {
+ videoInfoFetchFailed("adblockerIssueWhitelist");
+ }
+ });
//setup the preview bar
if (previewBar === null) {
@@ -727,6 +731,21 @@ async function getVideoInfo(): Promise<void> {
}
}
+async function videoInfoFetchFailed(errorMessage: string): Promise<void> {
+ console.log("failed\t" + errorMessage)
+ if (utils.isFirefox()) {
+ // Attempt to ask permission for youtube.com domain
+ alert(chrome.i18n.getMessage("youtubePermissionRequest"));
+
+ chrome.runtime.sendMessage({
+ message: "openPage",
+ url: "permissions/index.html#youtube.com"
+ });
+ } else {
+ alert(chrome.i18n.getMessage("adblockerIssue") + "\n\n" + chrome.i18n.getMessage(errorMessage));
+ }
+}
+
function getYouTubeVideoID(url: string) {
// For YouTube TV support
if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
diff --git a/src/options.ts b/src/options.ts
index 186e442a..815aff02 100644
--- a/src/options.ts
+++ b/src/options.ts
@@ -288,7 +288,7 @@ function invidiousInit(checkbox: HTMLInputElement, option: string) {
if (utils.isFirefox()) permissions = [];
chrome.permissions.contains({
- origins: utils.getInvidiousInstancesRegex(),
+ origins: utils.getPermissionRegex(),
permissions: permissions
}, function (result) {
if (result != checkbox.checked) {
diff --git a/src/permissions.ts b/src/permissions.ts
new file mode 100644
index 00000000..b6a41dce
--- /dev/null
+++ b/src/permissions.ts
@@ -0,0 +1,33 @@
+import Config from "./config";
+import Utils from "./utils";
+const utils = new Utils();
+
+// This is needed, if Config is not imported before Utils, things break.
+// Probably due to cyclic dependencies
+Config.config;
+
+window.addEventListener('DOMContentLoaded', init);
+
+async function init() {
+ utils.localizeHtmlPage();
+
+ const domains = document.location.hash.replace("#", "").split(",");
+
+ const acceptButton = document.getElementById("acceptPermissionButton");
+ acceptButton.addEventListener("click", () => {
+ chrome.permissions.request({
+ origins: utils.getPermissionRegex(domains),
+ permissions: []
+ }, (granted) => {
+ if (granted) {
+ alert(chrome.i18n.getMessage("permissionRequestSuccess"));
+
+ chrome.tabs.getCurrent((tab) => {
+ chrome.tabs.remove(tab.id);
+ });
+ } else {
+ alert(chrome.i18n.getMessage("permissionRequestFailed"));
+ }
+ });
+ });
+} \ No newline at end of file
diff --git a/src/utils.ts b/src/utils.ts
index 7658cab0..bb42afc5 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -3,10 +3,10 @@ import { CategorySelection, SponsorTime, FetchResponse, BackgroundScriptContaine
import * as CompileConfig from "../config.json";
-class Utils {
+export default class Utils {
// Contains functions needed from the background script
- backgroundScriptContainer: BackgroundScriptContainer | null = null;
+ backgroundScriptContainer: BackgroundScriptContainer | null;
// Used to add content scripts and CSS required
js = [
@@ -19,7 +19,7 @@ class Utils {
"popup.css"
];
- constructor(backgroundScriptContainer?: BackgroundScriptContainer) {
+ constructor(backgroundScriptContainer: BackgroundScriptContainer = null) {
this.backgroundScriptContainer = backgroundScriptContainer;
}
@@ -43,6 +43,12 @@ class Utils {
});
}
+ containsPermission(permissions: chrome.permissions.Permissions): Promise<boolean> {
+ return new Promise((resolve) => {
+ chrome.permissions.contains(permissions, resolve)
+ });
+ }
+
/**
* Asks for the optional permissions required for all extra sites.
* It also starts the content script registrations.
@@ -57,7 +63,7 @@ class Utils {
if (this.isFirefox()) permissions = [];
chrome.permissions.request({
- origins: this.getInvidiousInstancesRegex(),
+ origins: this.getPermissionRegex(),
permissions: permissions
}, async (granted) => {
if (granted) {
@@ -78,7 +84,6 @@ class Utils {
* For now, it is just SB.config.invidiousInstances.
*/
setupExtraSiteContentScripts(): void {
-
if (this.isFirefox()) {
const firefoxJS = [];
for (const file of this.js) {
@@ -95,7 +100,7 @@ class Utils {
allFrames: true,
js: firefoxJS,
css: firefoxCSS,
- matches: this.getInvidiousInstancesRegex()
+ matches: this.getPermissionRegex()
};
if (this.backgroundScriptContainer) {
@@ -106,7 +111,7 @@ class Utils {
} else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"], () => {
const conditions = [];
- for (const regex of this.getInvidiousInstancesRegex()) {
+ for (const regex of this.getPermissionRegex()) {
conditions.push(new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: regex }
}));
@@ -149,7 +154,7 @@ class Utils {
}
chrome.permissions.remove({
- origins: this.getInvidiousInstancesRegex()
+ origins: this.getPermissionRegex()
});
}
@@ -250,16 +255,20 @@ class Utils {
}
/**
- * @returns {String[]} Invidious Instances in regex form
+ * @returns {String[]} Domains in regex form
*/
- getInvidiousInstancesRegex(): string[] {
- const invidiousInstancesRegex: string[] = [];
- for (const url of Config.config.invidiousInstances) {
- invidiousInstancesRegex.push("https://*." + url + "/*");
- invidiousInstancesRegex.push("http://*." + url + "/*");
+ getPermissionRegex(domains: string[] = []): string[] {
+ const permissionRegex: string[] = [];
+ if (domains.length === 0) {
+ domains = [...Config.config.invidiousInstances];
+ }
+
+ for (const url of domains) {
+ permissionRegex.push("https://*." + url + "/*");
+ permissionRegex.push("http://*." + url + "/*");
}
- return invidiousInstancesRegex;
+ return permissionRegex;
}
generateUserID(length = 36): string {
@@ -434,5 +443,3 @@ class Utils {
}
}
-
-export default Utils;
diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js
index 79fea60b..1d130af0 100644
--- a/webpack/webpack.common.js
+++ b/webpack/webpack.common.js
@@ -9,7 +9,8 @@ module.exports = env => ({
popup: path.join(__dirname, srcDir + 'popup.ts'),
background: path.join(__dirname, srcDir + 'background.ts'),
content: path.join(__dirname, srcDir + 'content.ts'),
- options: path.join(__dirname, srcDir + 'options.ts')
+ options: path.join(__dirname, srcDir + 'options.ts'),
+ permissions: path.join(__dirname, srcDir + 'permissions.ts')
},
output: {
path: path.join(__dirname, '../dist/js'),