chrome-extension-archive/AutoplayStopper/script/handler.js

289 lines
19 KiB
JavaScript
Raw Normal View History

2021-02-10 18:28:04 +00:00
"use strict";
function registerHandlers(handlers, TRACE, isHandlingUserInput, setHandlingUserInput, lastUserInput, data = {})
{
var dummyid = Math.floor(Math.random() * 100);
function testUserInput(el, delay)
{
var win = el.ownerDocument.defaultView, _last = lastUserInput(win), e = _last && _last.e;
if (!e || Date.now() - _last.time > delay) return false;
var px = e.pageX - win.scrollX, py = win.scrollY ? e.pageY - win.scrollY : e.clientY, r = el.getBoundingClientRect(), {width ,height} = r;
for (var i = 0; i < 5 && el.parentNode && (r.top + win.scrollY < 0 || r.left + win.scrollX < 0 || r.width < 10 || r.height < 10); i++) r = (el = el.parentNode).getBoundingClientRect();
r.width = Math.max(r.width, width), r.height = Math.max(r.height, height);
return px >= r.left && px <= r.right && py >= r.top && py <= r.bottom;
};
// htmlmedia
handlers.add(function handleHtmlMedia(aElement){
const simEvents = {play: 0, playing: 50, pause: 350}, eventTypes = Object.keys(simEvents), props = ["preload","autoplay","poster","setAttribute","removeAttribute"];
const document = aElement.ownerDocument, window = document.defaultView;
if (aElement.localName == "video" || aElement.localName == "audio")
{
aElement.id || (aElement.id = "dummyid" + (++dummyid % 100));
TRACE('handleElement html5 media - tag: %s id: %s autoplay: %s preload: "%s" poster: %s paused: %s')(aElement.localName, aElement.id, aElement.autoplay, aElement.preload, !!aElement.poster, aElement.paused);
if (aElement.wrappedJSObject.play !== window.wrappedJSObject.HTMLMediaElement.prototype.play) TRACE('handleElement html5 media - %s.play() != HTMLMediaElement.play !!!')(aElement.id);
// Yendifplayer .autoplay = 1 => ...
var autoplay = aElement.autoplay || !aElement.paused, count = 0, released = false;
Object.defineProperties(aElement.wrappedJSObject, { preload: {configurable: true, set: (a) => TRACE('%s.preload = "%s"')(aElement.id, a)/* || (aElement.preload = "metadata")*/, get: () => aElement.preload}
, autoplay: {configurable: true, set: (a) => TRACE("%s.autoplay = %s")(aElement.id, a) || (a && aElement.wrappedJSObject.play()), get: () => aElement.autoplay}});
aElement.wrappedJSObject.setAttribute = (a, b) => (props.indexOf(a) != -1) ? TRACE("%s.setAttribute(%s, %s)")(aElement.id, a, b) || (aElement.wrappedJSObject[a] = b): aElement.setAttribute(a, b);
aElement.wrappedJSObject.removeAttribute = (a) => (props.indexOf(a) != -1) ? TRACE("%s.removeAttribute(%s)")(aElement.id, a) : aElement.removeAttribute(a);
function simPlay(e) {
e && aElement.removeEventListener(e.type, simPlay);
if (aElement.simPlay !== false && aElement.paused)
eventTypes.forEach((key) => window.setTimeout(() => !released && (TRACE("simPlay - %s.%s")(aElement.id, key) || aElement.dispatchEvent(new window.Event(key))), simEvents[key]));
};
aElement.wrappedJSObject.play = () => {
var force = aElement.allowPlay || testUserInput(aElement, 5000);
var userInput = isHandlingUserInput(window);
TRACE("%s.play(%s) - force: %s state: %s user: %s")(aElement.id, count, !!force, aElement.readyState, userInput);
if (!userInput && !force) {
count++ == 0 && (aElement.preload = "metadata") && (aElement.simPlay || aElement.readyState >= 2 ? simPlay() : aElement.addEventListener("loadeddata", simPlay));
return count < 5 ? Promise.reject(new window.DOMException("The play method is not allowed by the user agent.", "NotAllowedError")) : simPlay() || Promise.resolve();
}
released = !data.strict && delete aElement.wrappedJSObject.play; // jwplayer: zapiks.fr rottentomatoes baeblemusic
force && !userInput && setHandlingUserInput(window);
return aElement.play();
};
window.wrappedJSObject.Object.defineProperty(aElement.wrappedJSObject.play, "toString", window.Object.assign(window.Object(), {value: () => "[native code]"}));
aElement.autoplay = false;
aElement.preload != "none" && (aElement.preload = "metadata"); // mediaelement.js
!data.strict && aElement.addEventListener("play", function cleanup(e){ e.isTrusted && !aElement.paused && (aElement.removeEventListener("play", cleanup), aElement.muted = false,
TRACE("%s cleanup...")(aElement.id), props.forEach((prop) => delete aElement.wrappedJSObject[prop]), delete aElement.wrappedJSObject.play)});
autoplay && aElement.wrappedJSObject.play(); // flowplayer
!aElement.paused ? !released && aElement.pause() : window.setTimeout(() => !released && aElement.pause(), 0); // dbtv.no html5box
};
});
// simplay
const hosts = [{host: "cnn.com$", val: true}, {host: "twitch.tv$"}, {host: "yastatic.net$"},
{host: "bbc.(com|co.uk)$"}, {host: "(yahoo|yimg).com$", class: "html5-video", val: true}, {class: "\\b(video-js|vjs-tech)\\b"}];
handlers.add(function handleSimplay(aElement){
if (aElement.localName == "video")
for (var a of hosts) if (aElement.ownerDocument.location.hostname.match(a.host) && aElement.className.match(a.class)) aElement.simPlay = !!a.val;
});
// YouTube
handlers.add(function handleYouTube(aElement){
const document = aElement.ownerDocument, window = document.defaultView, jsWin = window.wrappedJSObject;
if (document.location.hostname.search("\.youtube(-nocookie)?\.com$") != -1)
{
TRACE("handleElement ytplayer - tag: %s player: %s")(aElement.localName, aElement.id);
if (document.location.search.search("feature=youtube-anywhere-player") == -1)
{
function stopPlayer(ytplayer){
if (testUserInput(ytplayer, 5000)) return !TRACE("ytplayer released...")();
var vid = ytplayer.getVideoData && ytplayer.getVideoData().video_id;
TRACE("ytplayer stopPlayer(%s) - videoId: %s t: %s")(ytplayer.id || "", vid, ytplayer.getCurrentTime());
ytplayer.cueVideoById(vid, ytplayer.getCurrentTime());
var nop = false, _seekTo = ytplayer.seekTo, _playVideo = ytplayer.playVideo;
ytplayer.playVideo = function doNothing() { nop || (nop = testUserInput(ytplayer, 1000)) ? _playVideo.apply(this) : TRACE("@@@@@@ ytplayer doNothing @@@@@")()};
ytplayer.seekTo = function seekTo(tm) { nop || (nop = testUserInput(ytplayer, 1000)) ? _seekTo.apply(this, arguments) : ytplayer.cueVideoById(vid, tm), TRACE("ytplayer seekTo(%s)")(tm); };
function onstate(a) { if (a == 1) { nop = true; ytplayer.playVideo = _playVideo; ytplayer.seekTo = _seekTo; TRACE("ytplayer - removed doNothing")(); ytplayer.removeEventListener("onStateChange", onstate); }};
ytplayer.addEventListener("onStateChange", onstate);
}
if (aElement.localName == "video" && aElement.parentNode.classList.contains("html5-video-container")) {
if (!data.strict && aElement.parentNode.parentNode.id == "movie_player")
window.setTimeout(() => aElement.allowPlay = true, document.location.search.search("feature=youtube-anywhere-player") == -1 ? 5000 : 0);
aElement.simPlay = false;
if (aElement.parentNode.parentNode.classList.contains("html5-video-player"))
window.setTimeout(() => stopPlayer(aElement.wrappedJSObject.parentNode.parentNode));
}
}
return true;
}
});
// googleads
handlers.add(function handleGoogleAds(aElement){
const document = aElement.ownerDocument, window = document.defaultView;
var host = aElement.getRootNode().host;
if (host && host.localName == "lima-video") {
TRACE("handleElement googleads - tag: %s")(aElement.localName);
window.addEventListener("visibilitychange", (e) => e.stopPropagation(), true);
aElement.wrappedJSObject.addEventListener("play", function(){ if (!testUserInput(this, 100)) this.pause()}, {once: true});
return true;
}
});
// ifunny.co
handlers.add(function handleIFunny(aElement){
const document = aElement.ownerDocument, window = document.defaultView;
if (document.location.hostname.match("ifunny.co$") && aElement.paused) {
(isHandlingUserInput(window) || testUserInput(aElement.parentNode, 1000)) ? aElement.play() : aElement.src = "";
return true;
}
});
// msn.com
handlers.add(function handleMsn(aElement){
const document = aElement.ownerDocument, window = document.defaultView, jsWin = window.wrappedJSObject;
if (document.location.hostname.search(/\.msn\.com$/) != -1)
{
var obj = aElement.wrappedJSObject;
if (aElement.className.indexOf("vxFlashPlayer") != -1 && aElement.localName == "embed"){
obj.MsnVideoCallback = function(msg) { msg == "playVideo" ? delete obj.MsnVideoCallback : obj.__proto__.MsnVideoCallback.apply(obj, arguments)};
var flashvars = (aElement.getAttribute("flashvars") || "").replace(/(&ap=)true/gi, "$1false")
aElement.setAttribute("flashvars", flashvars);
TRACE("handleElement msnplayer - tag: %s id: %s ")(aElement.localName, aElement.id);
return true;
}
}
});
// BBC
handlers.add(function handleBBC(aElement){
const document = aElement.ownerDocument, window = document.defaultView, jsWin = window.wrappedJSObject;
if (jsWin.embeddedMedia && jsWin.embeddedMedia.players)
for (var player of jsWin.embeddedMedia.players || []) if (player._swf && player._swf.id == aElement.id) {
TRACE("handleElement BBC - embeddedMedia.players id: %s autoplay: %s")(player._swf.id, player._settings.autoplay);
Object.defineProperty(player._settings, "autoplay", {get: () => false});
player.setData = (info) => ( info.data && (info.data.autoPlayFirstItem = false), player.__proto__.setData.call(player, info));
window.setTimeout(function(){ player._settings.autoplay = true; handlers.remove(window, handleBBC); }, 2500);
return true;
};
});
// metacafe
handlers.add(function handleMetacafe(aElement){
if (aElement.localName == "object" && (aElement.data || "").search(/s.mcstatic.com\/Flash\/.*\.swf/) != -1)
{
var param = aElement.querySelector("#" + aElement.id + ">param[name=flashvars]");
param.value = param.value.replace(/&beacons=.*(?=&)/,"");
var id = param.value.match(/itemID=([^&]*)(?=&)/)[1];
var data = aElement.data;
aElement.data = "http://www.metacafe.com/fplayer/" + id + "/.swf";
function onClick(aEvent){
aEvent.stopImmediatePropagation();
aElement.removeEventListener(aEvent.type, onClick, true);
aElement.data = data;
}
aElement.addEventListener("mouseup", onClick, true);
TRACE("handleElement metacafe - data: %s")(aElement.data);
return true;
}
});
// jwplayer
handlers.add(function handleJWPlayer(aElement){ // return;
const document = aElement.ownerDocument, window = document.defaultView, jsWin = window.wrappedJSObject;
aElement.id || (aElement.id = "dummyid" + (++dummyid % 100));
if (jsWin.jwplayer && !aElement.querySelector("[id='" + aElement.id + "']>param[name=flashvars]"))
{
if (testUserInput(aElement, 5000)) return !TRACE("jwplayer released...")();
function closest(node, selector) { while(node && !node.matches(selector)) node = node.parentElement; return node};
var res, ar, player = jsWin.jwplayer(aElement).config ?
jsWin.jwplayer(aElement) : (res = closest(aElement, ".jwplayer")) ? jsWin.jwplayer(res) : null;
if (player && (player.config || (player.config = player.getConfig())) && player.config.autostart != false)
{
TRACE("handleElement jwplayer setup - id: %s autostart: %s")(player.id, player.config.autostart);
player.config.autoStart = player.config.autostart = false;
(ar = player.config.aspectratio) && ar.indexOf("%") != -1 && (player.config.aspectratio = "100:" + ar.slice(0,-1));
aElement.localName == "video" && window.setTimeout(() => aElement.src = "");
player.setup(player.config);
}
TRACE("handleElement jwplayer - id: %s config: %s")((player && player.id), !!(player && player.config));
return player && player.config;
}
});
// flowplayer
handlers.add(function handleFlowplayer(aElement){ //return;
aElement.id || (aElement.id = "dummyid" + (++dummyid % 100));
var param = aElement.querySelector("[id='" + aElement.id + "']>param[name=flashvars]")
var config, flashvars = param ? param.value : aElement.getAttribute("flashvars");
if (flashvars && flashvars.search(/^config={/) != -1)
if ((config = JSON.parse(flashvars.slice(7).replace(/'/g,'"').replace(/("autoPlay":)true/g,"$1false"))) && (config.playlist || config.clip))
{
var playlist = (config.playlist = (config.playlist || [config.clip]));
(typeof playlist[0] == 'string') && (playlist[0] = {url: playlist[0]});
playlist[0].autoPlay = (typeof playlist[0].url == 'string' && playlist[0].url.search(/(.png|.jpg)/) != -1);
(playlist[0].autoBuffering && (playlist[0].autoBuffering = false)) || (playlist[0].autoPlay && playlist[1] && (playlist[1].autoPlay = false));
flashvars = "config=" + JSON.stringify(config);
param ? param.value = flashvars : aElement.setAttribute("flashvars", flashvars);
if (aElement.data) aElement.data = aElement.data;
TRACE("handleElement flowplayer - id: %s flashvars: %s")(aElement.id, flashvars);
return true;
}
});
// aol
handlers.add(function handleAol(aElement){
if (aElement.localName == "object" && (aElement.data || "").search(/cdn(-ssl)?.vidible.tv\/.*\.swf/) != -1)
{
aElement.id || (aElement.id = "dummyid" + (++dummyid % 100));
var param = aElement.querySelector("[id='" + aElement.id + "']>param[name=flashvars]");
if (param)
{
param.value = param.value.replace(/(initialization%22%3A%22)autoplay/, "$1click");
aElement.wrappedJSObject.doPlay = function() { TRACE("doNothing - doPlay")()};
aElement.ownerDocument.defaultView.setTimeout(() => {delete aElement.wrappedJSObject.doPlay; TRACE("handleElement aol - removed doPlay")()}, 5000);
return !TRACE("handleElement aol - data: %s")(aElement.data);
}
}
});
// general
var colValues = {"true":"false", "1":"0", "yes":"no", "on":"off", "y":"n", "Y":"N"}
function replace(match,p0,p1,p2) {
var res = p0 + (!p1 && p2 && colValues[p2] ? colValues[p2] : !!p1);
TRACE(">>> handleElement replace - match: %s p0: %s p1: %s p2: %s res: %s <<<")(match, p0, p1, p2, res);
return res;
}
function modifyParams(str) { return (str || "").replace(/((no)?auto_?(?:play|start|run)\w*(?:["']?\s?[=:]\s?["']?|%22%3A(?!\W)))(true|1|yes|y|on|null|)(?=\W|$)/gi, replace)};
function handleGeneral(aElement){
if (aElement.localName != "object" && aElement.localName != "embed")
return;
var data = modifyParams(aElement.getAttribute("data"));
if (data != aElement.getAttribute("data") && data != "")
{
aElement.setAttribute("data", data);
TRACE("handleElement - %s.data: %s")(aElement.localName, data);
}
var flashvars = modifyParams(aElement.getAttribute("flashvars")); // cnn | (remove) neulion nhl embed
if (aElement.localName == "embed" )
{
aElement.setAttribute("menu","true");
if (flashvars == aElement.getAttribute("flashvars") || flashvars == "" )
{
flashvars += "&autoplay=false&autostart=false&autoPlay=0"; // youtube(autoplay) | ustream live
aElement.setAttribute("play","false"); // basic flash
}
aElement.setAttribute("flashvars", flashvars);
if (aElement.src)
{
var src = modifyParams(aElement.src); // embed dailymotion
if (src != aElement.src) {
aElement.src = src;
var parent = aElement.parentNode, next = aElement.nextSibling; // workaround for chrome embed.src =
if (aElement.src && parent) { aElement.remove(); parent.insertBefore(aElement.wrappedJSObject, next); };
TRACE("handleElement embed.src: %s")(src);
}
}
}
aElement.id || (aElement.id = "dummyid" + (++dummyid % 100)); // [id =''] works with numeric ids!!!
var param = aElement.querySelector("[id='" + aElement.id + "']>param[name=flashvars], [id='" + aElement.id + "']>param[name=FlashVars], [id='" + aElement.id + "']>param[name=flashVars]");
if (param)
{
flashvars = modifyParams(param.value); // ustream(autoplay=false) | bbc / metacafe.embed(no) / tv.com(vid)
if (flashvars == param.value) {
if (flashvars.search(/auto(_?play(vid)?|start|run)["']?\s?[=:]/i) != -1) return; // false already exists...
flashvars += "&autoplay=false&autoPlay=0&autoStart=0&_autoPlay=no&auto_start=off"; // justin.tv(autoPlay=0)|nba.com(autostart)|espn(!autoplay)|discovery(_autoPlay=no)|56.com(auto_start)
}
param.value = flashvars;
if (aElement.data) aElement.data = aElement.data;
}
(param = aElement.querySelector("[id='" + aElement.id + "']>param[name=play]")) && (param.value = false);
if (param && aElement.data) aElement.data = aElement.data;
TRACE("handleElement - id: %s %s.flashvars: %s")(aElement.id, aElement.localName, flashvars);
};
handlers.add(handleGeneral);
};