about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSimonBrazell <simon@brazell.com.au>2020-03-21 20:34:32 +1100
committerSimonBrazell <simon@brazell.com.au>2020-03-21 20:34:32 +1100
commitabb1115b58ea2c48031eeef20a983b4e7fed918f (patch)
treeb3380fdb6df02e36e24f492d3592f4572e6ff9e6
parentAdd 'Always proxy video' as a settings & avoid youtube-dl.org redirects (diff)
downloadlibredirect-abb1115b58ea2c48031eeef20a983b4e7fed918f.zip
Address issues #21, #22, #23, #24, #25 & #26
-rw-r--r--background.js98
-rw-r--r--manifest.json2
-rw-r--r--pages/options/options.html21
-rw-r--r--pages/options/options.js98
-rw-r--r--pages/popup/open.svg5
-rw-r--r--pages/popup/popup.html9
-rw-r--r--pages/popup/popup.js4
-rw-r--r--pages/styles.css13
8 files changed, 198 insertions, 52 deletions
diff --git a/background.js b/background.js
index ed042da2..4811994f 100644
--- a/background.js
+++ b/background.js
@@ -1,9 +1,24 @@
 'use strict';
 
 const invidiousDefault = 'https://invidio.us';
-const youtubeRegex = /((www|m)\.)?(youtube|ytimg(-nocookie)?\.com|youtu.be)/;
+const youtubeDomains = [
+  'm.youtube.com',
+  'youtube.com',
+  'img.youtube.com',
+  'www.youtube.com',
+  'youtube-nocookie.com',
+  'www.youtube-nocookie.com',
+  'youtu.be',
+  's.ytimg.com',
+];
 const nitterDefault = 'https://nitter.net';
-const twitterRegex = /((www|mobile)\.)?twitter\.com/;
+const twitterDomains = [
+  'twitter.com',
+  'www.twitter.com',
+  'mobile.twitter.com',
+  'pbs.twimg.com',
+  'video.twimg.com',
+];
 const bibliogramDefault = 'https://bibliogram.art';
 const instagramRegex = /((www|about|help)\.)?instagram\.com/;
 const instagramPathsRegex = /\/(a|admin|api|favicon.ico|static|imageproxy|p|u|developer|about|legal|explore|director)/;
@@ -34,6 +49,8 @@ let invidiousInstance;
 let bibliogramInstance;
 let osmInstance;
 let alwaysProxy;
+let onlyEmbeddedVideo;
+let videoQuality;
 
 window.browser = window.browser || window.chrome;
 
@@ -46,7 +63,10 @@ browser.storage.sync.get(
     'disableNitter',
     'disableInvidious',
     'disableBibliogram',
-    'disableOsm'
+    'disableOsm',
+    'alwaysProxy',
+    'onlyEmbeddedVideo',
+    'videoQuality'
   ],
   result => {
     disableNitter = result.disableNitter;
@@ -58,6 +78,8 @@ browser.storage.sync.get(
     bibliogramInstance = result.bibliogramInstance || bibliogramDefault;
     osmInstance = result.osmInstance || osmDefault;
     alwaysProxy = result.alwaysProxy;
+    onlyEmbeddedVideo = result.onlyEmbeddedVideo;
+    videoQuality = result.videoQuality;
   }
 );
 
@@ -89,6 +111,12 @@ browser.storage.onChanged.addListener(changes => {
   if ('alwaysProxy' in changes) {
     alwaysProxy = changes.alwaysProxy.newValue;
   }
+  if ('onlyEmbeddedVideo' in changes) {
+    onlyEmbeddedVideo = changes.onlyEmbeddedVideo.newValue;
+  }
+  if ('videoQuality' in changes) {
+    videoQuality = changes.videoQuality.newValue;
+  }
 });
 
 function addressToLatLng(address, callback) {
@@ -117,11 +145,11 @@ function addressToLatLng(address, callback) {
   xmlhttp.send();
 }
 
-function redirectYouTube(url) {
-  if (url.host.split('.')[0] === 'studio') {
-    // Avoid redirecting `studio.youtube.com`
+function redirectYouTube(url, type) {
+  if (disableInvidious) {
     return null;
-  } else if (url.pathname.match(/iframe_api/)) {
+  }
+  if (url.pathname.match(/iframe_api/)) {
     // Redirect requests for YouTube Player API to local files instead
     return browser.runtime.getURL('assets/iframe_api.js');
   } else if (url.pathname.match(/www-widgetapi/)) {
@@ -132,20 +160,33 @@ function redirectYouTube(url) {
     if (alwaysProxy) {
       url.searchParams.append('local', true);
     }
+    if (videoQuality) {
+      url.searchParams.append('quality', videoQuality);
+    }
+    if (onlyEmbeddedVideo && type !== 'sub_frame') {
+      return null;
+    }
     return `${invidiousInstance}${url.pathname}${url.search}`;
   }
 }
 
 function redirectTwitter(url) {
-  if (url.host.split('.')[0] === 'tweetdeck') {
-    // Avoid redirecting `tweetdeck.twitter.com`
+  if (disableNitter) {
     return null;
+  }
+  if (url.host.split('.')[0] === 'pbs') {
+    return `${nitterInstance}/pic/${encodeURIComponent(url.href)}`;
+  } else if (url.host.split('.')[0] === 'video') {
+    return `${nitterInstance}/gif/${encodeURIComponent(url.href)}`;
   } else {
     return `${nitterInstance}${url.pathname}${url.search}`;
   }
 }
 
 function redirectInstagram(url) {
+  if (disableBibliogram) {
+    return null;
+  }
   if (url.pathname === '/' || url.pathname.match(instagramPathsRegex)) {
     return `${bibliogramInstance}${url.pathname}${url.search}`;
   } else {
@@ -155,6 +196,9 @@ function redirectInstagram(url) {
 }
 
 function redirectGoogleMaps(url) {
+  if (disableOsm) {
+    return null;
+  }
   let redirect;
   let mapCentre = '';
   let params = '';
@@ -224,30 +268,22 @@ browser.webRequest.onBeforeRequest.addListener(
   details => {
     const url = new URL(details.url);
     let redirect;
-    if (url.host.match(youtubeRegex) && !url.host.includes('youtube-dl.org')) {
-      if (!disableInvidious) {
-        redirect = {
-          redirectUrl: redirectYouTube(url)
-        };
-      }
-    } else if (url.host.match(twitterRegex)) {
-      if (!disableNitter) {
-        redirect = {
-          redirectUrl: redirectTwitter(url)
-        };
-      }
+    if (youtubeDomains.includes(url.host)) {
+      redirect = {
+        redirectUrl: redirectYouTube(url, details.type)
+      };
+    } else if (twitterDomains.includes(url.host)) {
+      redirect = {
+        redirectUrl: redirectTwitter(url)
+      };
     } else if (url.host.match(instagramRegex)) {
-      if (!disableBibliogram) {
-        redirect = {
-          redirectUrl: redirectInstagram(url)
-        };
-      }
+      redirect = {
+        redirectUrl: redirectInstagram(url)
+      };
     } else if (url.href.match(googleMapsRegex)) {
-      if (!disableOsm) {
-        redirect = {
-          redirectUrl: redirectGoogleMaps(url)
-        };
-      }
+      redirect = {
+        redirectUrl: redirectGoogleMaps(url)
+      };
     }
     if (redirect && redirect.redirectUrl) {
       console.info(
diff --git a/manifest.json b/manifest.json
index 188862b7..3d000b24 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
 {
   "name": "Privacy Redirect",
   "description": "Redirects Twitter, YouTube, Instagram & Google Maps requests to privacy friendly alternatives.",
-  "version": "1.1.15",
+  "version": "1.1.16",
   "manifest_version": 2,
   "background": {
     "scripts": [
diff --git a/pages/options/options.html b/pages/options/options.html
index 2c9c3e81..b7e273f9 100644
--- a/pages/options/options.html
+++ b/pages/options/options.html
@@ -92,9 +92,24 @@
     </div>
   </section>
 
-  <footer>
-    <a class="button" id="save">Save</a>
-  </footer>
+  <section class="options settings_block">
+    <div class="onoffswitch switch" aria-label="Only redirect embedded video to Invidious">
+      <h1>Only redirect embedded video to Invidious?</h1>
+      <input aria-hidden="true" id="only-embed" type="checkbox" checked>&nbsp;
+      <label for="only-embed" class="checkbox-label">
+      </label>
+    </div>
+  </section>
+
+  <section class="options settings_block">
+    <h1>Invidious Video Quality</h1>
+    <select id="video-quality">
+      <option value="">Default</option>
+      <option value="hd720">720p</option>
+      <option value="medium">480p</option>
+      <option value="dash">DASH (Dynamic Adaptive Streaming over HTTP)</option>
+    </select>
+  </section>
 
   <script src="./options.js"></script>
 
diff --git a/pages/options/options.js b/pages/options/options.js
index 8b30d90d..4a1c198c 100644
--- a/pages/options/options.js
+++ b/pages/options/options.js
@@ -9,6 +9,8 @@ let disableInvidious = document.querySelector('#disable-invidious');
 let disableBibliogram = document.querySelector('#disable-bibliogram');
 let disableOsm = document.querySelector('#disable-osm');
 let alwaysProxy = document.querySelector('#always-proxy');
+let onlyEmbeddedVideo = document.querySelector('#only-embed');
+let videoQuality = document.querySelector('#video-quality');
 
 window.browser = window.browser || window.chrome;
 
@@ -22,7 +24,9 @@ browser.storage.sync.get(
     'disableInvidious',
     'disableBibliogram',
     'disableOsm',
-    'alwaysProxy'
+    'alwaysProxy',
+    'onlyEmbeddedVideo',
+    'videoQuality'
   ],
   result => {
     nitterInstance.value = result.nitterInstance || '';
@@ -34,20 +38,88 @@ browser.storage.sync.get(
     disableBibliogram.checked = !result.disableBibliogram;
     disableOsm.checked = !result.disableOsm;
     alwaysProxy.checked = result.alwaysProxy;
+    onlyEmbeddedVideo.checked = result.onlyEmbeddedVideo;
+    videoQuality.value = result.videoQuality || '';
   }
 );
 
-document.querySelector('#save').addEventListener('click', () => {
+function debounce(func, wait, immediate) {
+  let timeout;
+  return () => {
+    let context = this, args = arguments;
+    let later = () => {
+      timeout = null;
+      if (!immediate) func.apply(context, args);
+    };
+    let callNow = immediate && !timeout;
+    clearTimeout(timeout);
+    timeout = setTimeout(later, wait);
+    if (callNow) func.apply(context, args);
+  };
+};
+
+let nitterInstanceChange = debounce(() => {
+  if (nitterInstance.checkValidity()) {
+    browser.storage.sync.set({
+      nitterInstance: nitterInstance.value ? new URL(nitterInstance.value).origin : ''
+    });
+  }
+}, 500);
+nitterInstance.addEventListener('input', nitterInstanceChange);
+
+let invidiousInstanceChange = debounce(() => {
+  if (invidiousInstance.checkValidity()) {
+    browser.storage.sync.set({
+      invidiousInstance: invidiousInstance.value ? new URL(invidiousInstance.value).origin : ''
+    });
+  }
+}, 500);
+invidiousInstance.addEventListener('input', invidiousInstanceChange);
+
+let bibliogramInstanceChange = debounce(() => {
+  if (bibliogramInstance.checkValidity()) {
+    browser.storage.sync.set({
+      bibliogramInstance: bibliogramInstance.value ? new URL(bibliogramInstance.value).origin : ''
+    });
+  }
+}, 500);
+bibliogramInstance.addEventListener('input', bibliogramInstanceChange);
+
+let osmInstanceChange = debounce(() => {
+  if (osmInstance.checkValidity()) {
+    browser.storage.sync.set({
+      osmInstance: osmInstance.value ? new URL(osmInstance.value).origin : ''
+    });
+  }
+}, 500);
+osmInstance.addEventListener('input', osmInstanceChange);
+
+disableNitter.addEventListener('change', event => {
+  browser.storage.sync.set({ disableNitter: !event.target.checked });
+});
+
+disableInvidious.addEventListener('change', event => {
+  browser.storage.sync.set({ disableInvidious: !event.target.checked });
+});
+
+disableBibliogram.addEventListener('change', event => {
+  browser.storage.sync.set({ disableBibliogram: !event.target.checked });
+});
+
+disableOsm.addEventListener('change', event => {
+  browser.storage.sync.set({ disableOsm: !event.target.checked });
+});
+
+alwaysProxy.addEventListener('change', event => {
+  browser.storage.sync.set({ alwaysProxy: event.target.checked });
+});
+
+onlyEmbeddedVideo.addEventListener('change', event => {
+  browser.storage.sync.set({ onlyEmbeddedVideo: event.target.checked });
+});
+
+videoQuality.addEventListener('change', event => {
   browser.storage.sync.set({
-    nitterInstance: nitterInstance.value && nitterInstance.checkValidity() ? new URL(nitterInstance.value).origin : '',
-    invidiousInstance: invidiousInstance.value && invidiousInstance.checkValidity() ? new URL(invidiousInstance.value).origin : '',
-    bibliogramInstance: bibliogramInstance.value && bibliogramInstance.checkValidity() ? new URL(bibliogramInstance.value).origin : '',
-    osmInstance: osmInstance.value && osmInstance.checkValidity() ? new URL(osmInstance.value).origin : '',
-    disableNitter: !disableNitter.checked,
-    disableInvidious: !disableInvidious.checked,
-    disableBibliogram: !disableBibliogram.checked,
-    disableOsm: !disableOsm.checked,
-    alwaysProxy: alwaysProxy.checked
+    videoQuality: event.target.options[videoQuality.selectedIndex].value
   });
-  window.close();
-});
\ No newline at end of file
+});
diff --git a/pages/popup/open.svg b/pages/popup/open.svg
new file mode 100644
index 00000000..04f56c15
--- /dev/null
+++ b/pages/popup/open.svg
@@ -0,0 +1,5 @@
+<svg xmlns='http://www.w3.org/2000/svg' width='512' height='512' viewBox='0 0 512 512'>
+  <path d='M384,224V408a40,40,0,0,1-40,40H104a40,40,0,0,1-40-40V168a40,40,0,0,1,40-40H271.48' style='fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px'/>
+  <polyline points='336 64 448 64 448 176' style='fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px'/>
+  <line x1='224' y1='288' x2='440' y2='72' style='fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px'/>
+</svg>
\ No newline at end of file
diff --git a/pages/popup/popup.html b/pages/popup/popup.html
index 40cf3e7f..2f05f87f 100644
--- a/pages/popup/popup.html
+++ b/pages/popup/popup.html
@@ -8,7 +8,7 @@
   <link href="../styles.css" rel="stylesheet">
 </head>
 
-<body>
+<body class="popup">
   <header>
     <div class="logo-container">
       <img src="../../images/logo.png" alt="Privacy Redirect logo">
@@ -90,6 +90,13 @@
     </datalist>
   </section>
 
+  <footer>
+    <a class="button" id="more-options">
+      <span>More Options&nbsp;</span>
+      <img height="18px" src="open.svg" alt="more-options" />
+    </a>
+  </footer>
+
   <script src="./popup.js"></script>
 
 </body>
diff --git a/pages/popup/popup.js b/pages/popup/popup.js
index 9b30c039..172a66e7 100644
--- a/pages/popup/popup.js
+++ b/pages/popup/popup.js
@@ -103,3 +103,7 @@ disableBibliogram.addEventListener('change', event => {
 disableOsm.addEventListener('change', event => {
   browser.storage.sync.set({ disableOsm: !event.target.checked });
 });
+
+document.querySelector('#more-options').addEventListener('click', () => {
+  browser.runtime.openOptionsPage();
+});
diff --git a/pages/styles.css b/pages/styles.css
index 89ae5a83..a68d9bbc 100644
--- a/pages/styles.css
+++ b/pages/styles.css
@@ -12,9 +12,13 @@
 body {
   color: var(--text-secondary);
   margin: 0;
+  background-color: var(--dark-grey);
+}
+
+.popup {
   max-width: 400px;
   min-width: 300px;
-  background-color: var(--dark-grey);
+  overflow: hidden;
 }
 
 header {
@@ -80,7 +84,7 @@ footer a.button {
 
 /* Elements */
 
-input[type=url] {
+input[type=url], select {
   width: 100%;
   margin-bottom: 5px;
 }
@@ -148,6 +152,10 @@ input:checked+label:after {
   transition-duration: 0.4s;
 }
 
+.button * {
+  vertical-align: middle;
+}
+
 .button:hover {
   background-color: var(--active);
   color: #fff;
@@ -168,4 +176,3 @@ input[type="url"]:invalid {
 .margin-bottom {
   margin-bottom: 20px;
 }
-