summaryrefslogtreecommitdiff
path: root/.config/qutebrowser/greasemonkey/autostop.js
diff options
context:
space:
mode:
Diffstat (limited to '.config/qutebrowser/greasemonkey/autostop.js')
-rw-r--r--.config/qutebrowser/greasemonkey/autostop.js171
1 files changed, 171 insertions, 0 deletions
diff --git a/.config/qutebrowser/greasemonkey/autostop.js b/.config/qutebrowser/greasemonkey/autostop.js
new file mode 100644
index 0000000..a0196c9
--- /dev/null
+++ b/.config/qutebrowser/greasemonkey/autostop.js
@@ -0,0 +1,171 @@
+// ==UserScript==
+// @name Autostop
+// @description Autoplay sucks, even on youtube
+// @namespace github.com/seebye/autostop
+// @match <all_urls>
+// @run-at document-start
+// ==/UserScript==
+/*
+Copyright (C) 2017 Nico Baeurer
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+(function() {
+ "use strict";
+
+ let playable = false;
+ let proto = (() => {
+ let iframe = document.createElement('iframe');
+ let protos = {};
+
+ try {
+ iframe.sandbox = 'allow-same-origin';
+ document.documentElement.insertBefore(iframe, document.documentElement.firstChild);
+
+ for (let i of Object.getOwnPropertyNames(iframe.contentWindow)) {
+ try {
+ protos[i] = iframe.contentWindow[i].prototype;
+ }
+ catch (e) {
+ // some members are still protected (cross origin)
+ }
+ }
+
+ return protos;
+ }
+ finally {
+ document.documentElement.removeChild(iframe);
+ }
+ })();
+
+
+ let accessUnmodified = function(target, cb) {
+ let tmp = target.__proto__;
+
+ try {
+ target.__proto__ = proto[tmp.constructor.name];
+ return cb(target);
+ }
+ finally {
+ target.__proto__ = tmp;
+ }
+ };
+
+
+ let hook = function(proto) {
+ let helper = {};
+
+ for (let member in proto) {
+ try {
+ if (proto[member] instanceof Function) {
+ helper[member] = {
+ override: function(creator) {
+ proto[member] = creator(proto[member]);
+ return helper;
+ }
+ };
+ }
+ }
+ catch (e) {
+ helper[member] = {
+ property: function({getter, setter=() => {}}) {
+ Object.defineProperty(proto, member, {
+ get: getter,
+ configurable: false,
+ enumerable: true,
+ set: setter
+ });
+ return helper;
+ },
+ constant: function(val) {
+ Object.defineProperty(proto, member, {
+ value: val,
+ configurable: false,
+ enumerable: true
+ });
+ return helper;
+ }
+ };
+ }
+ }
+
+ return helper;
+ };
+
+
+ let disableAutoplay = function(target) {
+ for (let v of target.getElementsByTagName('video')) {
+ v.pause();
+ }
+ };
+
+
+ let onceTrustedEvent = function(target, ev, cb) {
+ target.addEventListener(ev, (() => {
+ let listener = (e) => {
+ if (e.isTrusted) {
+ target.removeEventListener(ev, listener);
+ cb(e);
+ }
+ };
+ return listener;
+ })());
+ };
+
+
+ let init = (function() {
+ onceTrustedEvent(document, "click", (e) => {
+ playable = true;
+ });
+
+ hook(window.HTMLMediaElement.prototype)
+ // block javascript code from playing a video till the first user interaction
+ .play.override((orig) => function() {
+ try {
+ return orig.apply(this);
+ }
+ finally {
+ // pause video instead of block calling play
+ // (e.g. youtube produces a high load otherwise..)
+ if (!playable) {
+ this.pause();
+ }
+ }
+ })
+ // block javascript code from enabling autoplay
+ .autoplay.property({getter: function() {
+ return accessUnmodified(this, (self) => self.autoplay);
+ }});
+
+ // disable autoplay via html attribute
+ hook(window.Element.prototype)
+ .innerHTML.property({
+ getter: function() {
+ return accessUnmodified(this, (self) => self.innerHTML);
+ },
+ setter: function(val) {
+ accessUnmodified(this, (self) => {
+ self.innerHTML = val;
+ });
+
+ disableAutoplay(this);
+ }});
+
+ document.addEventListener("DOMContentLoaded", (e) => {
+ disableAutoplay(document);
+ }, {once: true});
+ })();
+})();
+