Add AutoplayStopper v1.8.7
This commit is contained in:
		
							parent
							
								
									f5620cbc84
								
							
						
					
					
						commit
						69eb447c28
					
				
							
								
								
									
										5
									
								
								AutoplayStopper/README.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								AutoplayStopper/README.txt
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
This is an extracted copy of https://chrome.google.com/webstore/detail/autoplaystopper/ejddcgojdblidajhngkogefpkknnebdh version 1.8.7. I then loaded it into Chrome as an unpacked extension. 
 | 
			
		||||
This was done to bypass auto extension updates that may eventually be injected with malware.
 | 
			
		||||
The extraction was done using the "Chrome extension source viewer" addon (https://github.com/Rob--W/crxviewer).
 | 
			
		||||
 | 
			
		||||
I reviewed the code for malicious changes and made other small tweaks.
 | 
			
		||||
							
								
								
									
										201
									
								
								AutoplayStopper/_locales/en/messages.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								AutoplayStopper/_locales/en/messages.json
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,201 @@
 | 
			
		|||
{
 | 
			
		||||
	"extensionDescription": {
 | 
			
		||||
		"message": "Stops video autoplay gracefully."
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"allowSite": {
 | 
			
		||||
		"message": "Allow autoplay for %S"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"allowSession": {
 | 
			
		||||
		"message": "Allow session autoplay for %S"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"disableSite": {
 | 
			
		||||
		"message": "Block flash detection for %S"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"allowAll": {
 | 
			
		||||
		"message": "Disable everywhere"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"settings": {
 | 
			
		||||
		"message": "Settings"
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"version": {
 | 
			
		||||
		"message": "Version"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"autoplayTabLabel": {
 | 
			
		||||
		"message": "Autoplay"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"permissions": {
 | 
			
		||||
		"message": "Websites Permissions:"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"manageExceptions": {
 | 
			
		||||
		"message": "Exceptions..."
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"defaultMode": {
 | 
			
		||||
		"message": "Default Mode:"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"disableAutoplay": {
 | 
			
		||||
		"message": "Block Autoplay"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"allowAutoplay": {
 | 
			
		||||
		"message": "Allow Autoplay"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"flashTabLabel": {
 | 
			
		||||
		"message": "Flash"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"allowFlash": {
 | 
			
		||||
		"message": "Allow Detection"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"disableFlash": {
 | 
			
		||||
		"message": "Block Detection"
 | 
			
		||||
	},	
 | 
			
		||||
		
 | 
			
		||||
	"autoplayExceptions": {
 | 
			
		||||
		"message": "Autoplay exceptions"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"flashExceptions": {
 | 
			
		||||
		"message": "Flash detection exceptions"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"exceptionHostnameHeader": {
 | 
			
		||||
		"message": "Hostname"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"exceptionBehaviorHeader": {
 | 
			
		||||
		"message": "Behavior"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"exceptionAllow": {
 | 
			
		||||
		"message": "Allow"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"exceptionBlock": {
 | 
			
		||||
		"message": "Block"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"exceptionPrompt": {
 | 
			
		||||
		"message": "Block (strict)"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"exceptionSession": {
 | 
			
		||||
		"message": "Session"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"exceptionUndefined": {
 | 
			
		||||
		"message": "Undefined"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"apply": {
 | 
			
		||||
		"message": "Apply"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"removeAll": {
 | 
			
		||||
		"message": "Remove All"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"done": {
 | 
			
		||||
		"message": "Done"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"play": {
 | 
			
		||||
		"message": "Play"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"pause": {
 | 
			
		||||
		"message": "Pause"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"selector": {
 | 
			
		||||
		"message": "Selector"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"text": {
 | 
			
		||||
		"message": "Text"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"reset": {
 | 
			
		||||
		"message": "Reset"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"script": {
 | 
			
		||||
		"message": "Script"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"userScript": {
 | 
			
		||||
		"message": "User Script"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"path": {
 | 
			
		||||
		"message": "Path"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"actions": {
 | 
			
		||||
		"message": "Actions"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"edit": {
 | 
			
		||||
		"message": "Edit"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"load": {
 | 
			
		||||
		"message": "Load"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"export": {
 | 
			
		||||
		"message": "Export..."
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"setPath": {
 | 
			
		||||
		"message": "Set Path"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"selectFile": {
 | 
			
		||||
		"message": "File..."
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"advanced": {
 | 
			
		||||
		"message": "Advanced"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"devtools": {
 | 
			
		||||
		"message": "Devtools Panel"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"overwrite": {
 | 
			
		||||
		"message": "Disable overwrite on update"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"debug": {
 | 
			
		||||
		"message": "Log debug info"
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"loadError": {
 | 
			
		||||
		"message": "Load script error: "
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"allowFileUrls": {
 | 
			
		||||
		"message": "Error:  Cannot use user script without permission to access file URLs."
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"fileNotFound": {
 | 
			
		||||
		"message": "AutoplayStopper - error: File not found.\n  Check that the script folder is in the workspace and verify the path."
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"evalError": {
 | 
			
		||||
		"message": "AutoplayStopper - exception: "
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										186
									
								
								AutoplayStopper/background.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								AutoplayStopper/background.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,186 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
var Background = new function() {
 | 
			
		||||
 | 
			
		||||
    console.log("loading background.js ...");
 | 
			
		||||
 | 
			
		||||
    const {js, css} = chrome.runtime.getManifest().content_scripts[0];
 | 
			
		||||
    const badgeColor = "#646464";
 | 
			
		||||
    const playMsg = chrome.i18n.getMessage("play");
 | 
			
		||||
    const pauseMsg = chrome.i18n.getMessage("pause");
 | 
			
		||||
    const sArea = "local";
 | 
			
		||||
    const permsAutoplayKey = Permissions.key("autoplay");
 | 
			
		||||
    const permsAutoplayDefaultKey = Permissions.defaultKey("autoplay");
 | 
			
		||||
    const permsFlashKey = Permissions.key("flash");
 | 
			
		||||
    const permsFlashDefaultKey = Permissions.defaultKey("flash");
 | 
			
		||||
    const sKeys = ["disabled", "debug", permsFlashKey, permsFlashDefaultKey, permsAutoplayKey,
 | 
			
		||||
                    permsAutoplayDefaultKey, "selector-css", "uhandler", "handler", "disableOverwrite", "devtools"];
 | 
			
		||||
 | 
			
		||||
    var selector = null;
 | 
			
		||||
    var permissions = null;
 | 
			
		||||
    var permsAutoplayCache = {};
 | 
			
		||||
    var permsFlashCache = {};
 | 
			
		||||
    var tabs = { get(id) { return this[id] || (this[id] = {id, count: 0})}};
 | 
			
		||||
    var menuitem = null;
 | 
			
		||||
 | 
			
		||||
    var storage = new Storage(sKeys, sArea);
 | 
			
		||||
    storage.addChangeListener(function(changes){
 | 
			
		||||
        if (changes.indexOf("selector-css") != -1) selector = storage.data["selector-css"].split("{")[0];
 | 
			
		||||
        if (changes.indexOf(permsAutoplayKey) != -1 || changes.indexOf(permsAutoplayDefaultKey) != -1) permsAutoplayCache = {};
 | 
			
		||||
        if (changes.indexOf(permsFlashKey) != -1 || changes.indexOf(permsFlashDefaultKey) != -1) permsFlashCache = {};
 | 
			
		||||
        if (changes.indexOf("disabled") != -1) updateIcon();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    storage.ready.then(function() {
 | 
			
		||||
        console.log("storage.ready");
 | 
			
		||||
        updateIcon();
 | 
			
		||||
        permissions = new Permissions(storage.data);
 | 
			
		||||
        if (permissions.default("autoplay") === undefined) permissions.setDefault("autoplay", Permission.DENY_ACTION);
 | 
			
		||||
        if (permissions.default("flash") === undefined) permissions.setDefault("flash", Permission.ALLOW_ACTION);
 | 
			
		||||
        chrome.webNavigation.onCommitted.addListener(onCommitted, {url: [{schemes: ["http", "https", "about"]}]});
 | 
			
		||||
        if (!storage.data.uhandler)
 | 
			
		||||
            loadScript("uhandler", chrome.extension.getURL("script/userhandler.js"));
 | 
			
		||||
        if (!storage.data.handler)
 | 
			
		||||
            loadScript("handler", chrome.extension.getURL("script/handler.js"));
 | 
			
		||||
        if (!storage.data["selector-css"])
 | 
			
		||||
            loadScript("selector-css", chrome.extension.getURL("script/selector.css"));
 | 
			
		||||
        selector = storage.data["selector-css"].split("{")[0];
 | 
			
		||||
        js.forEach(function(a) { execScript(a, null, 0)});
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    chrome.browserAction.setBadgeBackgroundColor({color: badgeColor});
 | 
			
		||||
    chrome.tabs.onRemoved.addListener(function(tabid){ delete tabs[tabid]; });
 | 
			
		||||
    chrome.tabs.onActivated.addListener(resetMenuitem);
 | 
			
		||||
    chrome.runtime.onMessage.addListener(handleMessage);
 | 
			
		||||
    chrome.runtime.onInstalled.addListener(function(details) {
 | 
			
		||||
        if (details.reason == "update" && !storage.data.disableOverwrite) {
 | 
			
		||||
            loadScript("handler", chrome.extension.getURL("script/handler.js"));
 | 
			
		||||
            loadScript("selector-css", chrome.extension.getURL("script/selector.css"));
 | 
			
		||||
            selector = storage.data["selector-css"].split("{")[0];
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        get i18n() { return i18n; },
 | 
			
		||||
        get storage() { return storage; },
 | 
			
		||||
        get permissions() { return permissions; },
 | 
			
		||||
        openOptionsPage: function openOptionsPage(hash) {
 | 
			
		||||
            chrome.runtime.openOptionsPage();
 | 
			
		||||
            if (hash) addEventListener("message", function(e) {
 | 
			
		||||
                    if (location.origin == e.origin && e.data == "optionsPageActive")
 | 
			
		||||
                        e.source.location.hash = hash;
 | 
			
		||||
                }, { once: true});
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function resetMenuitem(){ if (menuitem) menuitem = chrome.contextMenus.remove("play-menuitem"); }
 | 
			
		||||
 | 
			
		||||
    function updateIcon() { chrome.browserAction.setIcon({ path: "/icons/" + (storage.data.disabled ? "icon32d.png" : "icon32.png")})};
 | 
			
		||||
 | 
			
		||||
    function handleMessage(request, sender, sendResponse)
 | 
			
		||||
    {
 | 
			
		||||
        if (!storage.data.handler) {
 | 
			
		||||
            console.log("handleMessage delayed -", request, sender);
 | 
			
		||||
            storage.ready.then(function() { handleMessage(request, sender, sendResponse)});
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (request == "permission") {
 | 
			
		||||
            var data = {debug: !!storage.data.debug};
 | 
			
		||||
            var allow = true, host = sender.tab && new URL(sender.tab.url).origin;
 | 
			
		||||
            if (host && !storage.data.disabled) {
 | 
			
		||||
                var permission = permsAutoplayCache[host] ||
 | 
			
		||||
                    (permsAutoplayCache[host] = permissions.testPermission("autoplay", sender.tab.url));
 | 
			
		||||
                allow = permission == Permission.ALLOW_ACTION ||
 | 
			
		||||
                    (permission == Permission.ACCESS_SESSION && tabs.get(sender.tab.id).last == host);
 | 
			
		||||
                data.strict = permission == Permission.PROMPT_ACTION;
 | 
			
		||||
            }
 | 
			
		||||
            var msg = {msg: "permission", data, allow, selector, handler: storage.data.handler, uhandler: storage.data.uhandler};
 | 
			
		||||
    //        console.log("background send:", msg, sender.url, sender.tab.url);
 | 
			
		||||
            sendResponse(msg);
 | 
			
		||||
        }
 | 
			
		||||
        if (request == "count")
 | 
			
		||||
            chrome.browserAction.setBadgeText({text: String(++tabs.get(sender.tab.id).count), tabId: sender.tab.id});
 | 
			
		||||
        if (request.msg == "contextmenu") {
 | 
			
		||||
            resetMenuitem();
 | 
			
		||||
            if (request.media)
 | 
			
		||||
                menuitem = chrome.contextMenus.create({ id: "play-menuitem", title: request.paused ? playMsg : pauseMsg,
 | 
			
		||||
                    contexts: ["all"], onclick: function onClick(info, tab) { if (info.menuItemId == "play-menuitem") sendResponse();}
 | 
			
		||||
                })
 | 
			
		||||
            return !!request.media;
 | 
			
		||||
        }
 | 
			
		||||
        if (request.msg == "select") {
 | 
			
		||||
            fetch(request.url, {cache: "no-store"}).then(function(res) {
 | 
			
		||||
                res.blob().then(function(file){ sendResponse({url: URL.createObjectURL(file), name: file.name}); });
 | 
			
		||||
            });
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (request.msg == "load") {
 | 
			
		||||
            var res = loadScript(request.script, request.file);
 | 
			
		||||
            sendResponse(res);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function onCommitted(details)
 | 
			
		||||
    {
 | 
			
		||||
        var allow = true, url = new URL(details.url);
 | 
			
		||||
        if (url.protocol.search("^chrome") != -1) return;
 | 
			
		||||
 | 
			
		||||
        var tab = tabs.get(details.tabId);
 | 
			
		||||
        if (details.frameId == 0) {
 | 
			
		||||
            tab.last = tab.host;
 | 
			
		||||
            tab.host = url.origin;
 | 
			
		||||
            tab.url = details.url;
 | 
			
		||||
            tab.count = 0;
 | 
			
		||||
            chrome.browserAction.setBadgeText({text:'', tabId: tab.id});
 | 
			
		||||
            chrome.tabs.query({ active: true, currentWindow: true}, function(tabs) {
 | 
			
		||||
                if (tabs[0] && tabs[0].id == tab.id) resetMenuitem();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        if (!storage.data.disabled && tab.url) {
 | 
			
		||||
            var permission = permsFlashCache[tab.host] ||
 | 
			
		||||
                (permsFlashCache[tab.host] = permissions.testPermission("flash", tab.url));
 | 
			
		||||
            if (permission == Permission.DENY_ACTION)
 | 
			
		||||
                execScript("content/navigator.js", details.tabId, details.frameId);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function execScript(file, tabId, frameId) {
 | 
			
		||||
        chrome.tabs.executeScript(tabId, {file, frameId, matchAboutBlank: true, runAt: "document_start"}, function() {
 | 
			
		||||
            if (chrome.runtime.lastError && storage.data.debug)
 | 
			
		||||
                console.error("chrome.tabs.executeScript - error", chrome.runtime.lastError, {tabId, frameId, file});
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function insertCSS(file, tabId, frameId) {
 | 
			
		||||
        chrome.tabs.insertCSS(tabId, {file, frameId, matchAboutBlank: true, runAt: "document_start"}, function() {
 | 
			
		||||
            if (chrome.runtime.lastError && storage.data.debug)
 | 
			
		||||
                console.error("chrome.tabs.insertCSS - error", chrome.runtime.lastError, {tabId, frameId, file});
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function loadScript(script, url){
 | 
			
		||||
        try {
 | 
			
		||||
            var request = new XMLHttpRequest();
 | 
			
		||||
            request.overrideMimeType("text/plain");
 | 
			
		||||
            request.open("GET", url, false);
 | 
			
		||||
            request.setRequestHeader("pragma", "no-cache");
 | 
			
		||||
            request.send();
 | 
			
		||||
            if (request.statusText == "Not Found" || !request.responseURL)
 | 
			
		||||
                 throw new DOMException(`Failed to load '${url}'.`, "NetworkError");
 | 
			
		||||
 | 
			
		||||
            storage.data[script] = request.responseText;
 | 
			
		||||
            storage.commit([script]);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            chrome.extension.isAllowedFileSchemeAccess(function(allowed) {
 | 
			
		||||
                if(!allowed && url.search(/^blob:/) == -1)
 | 
			
		||||
                    return alert(chrome.i18n.getMessage("allowFileUrls"));
 | 
			
		||||
                alert(`${chrome.i18n.getMessage("loadError")} ${e.name}\n  ${e.message}`);
 | 
			
		||||
            });
 | 
			
		||||
            return e;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//</>
 | 
			
		||||
							
								
								
									
										310
									
								
								AutoplayStopper/content/content.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								AutoplayStopper/content/content.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,310 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const ContentScript = new function() {
 | 
			
		||||
 | 
			
		||||
    "use strict";
 | 
			
		||||
 | 
			
		||||
    const start = Date.now();
 | 
			
		||||
    const any = (window.wrappedJSObject ? "-moz" : "-webkit") + "-any";
 | 
			
		||||
    const frameSelector = `iframe:${any}(:not([src]), [src^='javascript:' i], [src^='about:blank' i]):not([flashstopped])`;
 | 
			
		||||
    
 | 
			
		||||
    var data = {debug: false};
 | 
			
		||||
    const _trace = function TRACE(format, ...etc) {
 | 
			
		||||
        if (!data.debug) return TRACE._noop || (TRACE._noop = function(){});    
 | 
			
		||||
        return console.log.bind(console, "### " + format + " ###", ...etc);
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    var selector = null;
 | 
			
		||||
    var handler = null; //loadURL(chrome.extension.getURL("script/handler.js"));
 | 
			
		||||
    var href = frameElement !== null ? frameElement.src || "about:blank" : location.href;
 | 
			
		||||
    var ret = 0;
 | 
			
		||||
 | 
			
		||||
    _trace("ready(%s) content.js - iframe: %s href: %s loc: %s fs: %s")(start - Date.now(), 
 | 
			
		||||
        !!frameElement && frameElement.id, href == location.href || href, location.href, window.flashstopped);
 | 
			
		||||
 | 
			
		||||
    if (window.flashstopped) return;
 | 
			
		||||
    window.flashstopped = true;
 | 
			
		||||
 | 
			
		||||
    chrome.runtime.sendMessage("permission", handlePermission);
 | 
			
		||||
    function handlePermission(response) { 
 | 
			
		||||
        if (chrome.runtime.lastError && ret <= 3) {
 | 
			
		||||
            console.error(`handlePermission - error ret: ${ret} msg: ${chrome.runtime.lastError.message}`);
 | 
			
		||||
            window.setTimeout(function() { chrome.runtime.sendMessage("permission", handlePermission)}, ret++ * 250);
 | 
			
		||||
        };
 | 
			
		||||
        if (!response) return; 
 | 
			
		||||
        data = response.data;
 | 
			
		||||
        selector = response.selector;
 | 
			
		||||
        handler = `${response.uhandler}\n\n${response.handler}`;
 | 
			
		||||
        if (!response.allow) load(window); 
 | 
			
		||||
        addEventListener("message", function(e) {
 | 
			
		||||
            if (e.data && e.data.id == "userinput") e.stopImmediatePropagation();
 | 
			
		||||
        }, true);          
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (parent && parent != window)
 | 
			
		||||
        parent.postMessage({id: "userinput"}, "*");
 | 
			
		||||
 | 
			
		||||
    function load({window, frameElement, location}) 
 | 
			
		||||
    {    
 | 
			
		||||
        var href = frameElement !== null ? frameElement.src || "about:blank" : location.href;
 | 
			
		||||
        _trace("loading(%s) content.js - iframe: %s href: %s loc: %s")(start - Date.now(),
 | 
			
		||||
             !!frameElement && frameElement.id, href == location.href || href, location.href);
 | 
			
		||||
        
 | 
			
		||||
        var match = 0, query = 0;
 | 
			
		||||
        var injected = false;
 | 
			
		||||
        var body = window.document.body;
 | 
			
		||||
        var userInput = null;
 | 
			
		||||
       
 | 
			
		||||
        var n = handleDocument();
 | 
			
		||||
        _trace("body: %s n: %s")(!!body, n);
 | 
			
		||||
        
 | 
			
		||||
        var docObserver = new MutationObserver(function(mutations) {        
 | 
			
		||||
        
 | 
			
		||||
            _trace("!!! docObserver - body: %s neb: %s !!!")(!!body, body != window.document.body);
 | 
			
		||||
            if (window.document.body && body != window.document.body) {
 | 
			
		||||
                if (body) observer.observe(window.document.body, { subtree: true, childList: true});
 | 
			
		||||
                body = window.document.body;
 | 
			
		||||
                requestAnimationFrame(function() {
 | 
			
		||||
                    var n = handleDocument();
 | 
			
		||||
                    _trace(">>>>>>> requestAnimationFrame n: %s <<<<<<<")(n);
 | 
			
		||||
                });              
 | 
			
		||||
                window.setTimeout(function() {
 | 
			
		||||
                    var n = handleDocument();
 | 
			
		||||
                    _trace(">>>>>>> setting body observer - n: %s <<<<<<<<")(n);
 | 
			
		||||
                }, 500);
 | 
			
		||||
                var n = handleDocument();
 | 
			
		||||
                _trace("!!! docObserver - out n: %s !!!")(n);
 | 
			
		||||
            }
 | 
			
		||||
        });        
 | 
			
		||||
 | 
			
		||||
        var observer = new MutationObserver(function(mutations) {
 | 
			
		||||
            
 | 
			
		||||
            for (var i = 0; i < mutations.length; i++)
 | 
			
		||||
                for (var j = 0; j < mutations[i].addedNodes.length; j++) {
 | 
			
		||||
                    var addedNode = mutations[i].addedNodes[j];
 | 
			
		||||
                    if (addedNode.nodeType === 1){
 | 
			
		||||
                        match++;
 | 
			
		||||
                        if (addedNode.children.length) query++;
 | 
			
		||||
                        if (handleNodesDeep(addedNode, true)) {
 | 
			
		||||
                            _trace(">>>>>>> MutationObserver: tag: %s id: %s <<<<<<<")(addedNode.localName, addedNode.id);
 | 
			
		||||
                        }  
 | 
			
		||||
                        var frames = addedNode.matches(frameSelector) ? [addedNode] : [];
 | 
			
		||||
                        if (frames.push(...addedNode.querySelectorAll(frameSelector)))
 | 
			
		||||
                            handleFrames(frames);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        if (window.document.body) 
 | 
			
		||||
            observer.observe((href.search("^https?:") == -1) ? window.document : window.document.body
 | 
			
		||||
                , { subtree: true, childList: true});
 | 
			
		||||
        else
 | 
			
		||||
            docObserver.observe(window.document.documentElement, { childList: true});
 | 
			
		||||
        
 | 
			
		||||
                            // workaround for chrome no events on blank iframe ...
 | 
			
		||||
        setTimeout( function() { 
 | 
			
		||||
            window.addEventListener("mousedown", onContextMenu, true);
 | 
			
		||||
            ["mousedown","click"].forEach((a) => window.addEventListener(a, function(e) { 
 | 
			
		||||
                if (e.isTrusted && e.button == 0) {
 | 
			
		||||
                    userInput = {e: e, time: Date.now()};
 | 
			
		||||
                    if (injected) dispatchUserInput(userInput);
 | 
			
		||||
                }
 | 
			
		||||
            }, true));
 | 
			
		||||
            if (data.debug) chrome.storage.local.get(["selector-css"], function(data) {
 | 
			
		||||
                window.document.head.appendChild(document.createElement("style"))
 | 
			
		||||
                    .textContent = data["selector-css"];
 | 
			
		||||
            });
 | 
			
		||||
        }, 1000);
 | 
			
		||||
 | 
			
		||||
        window.addEventListener("DOMContentLoaded", function() {
 | 
			
		||||
            observer.observe(window.document.body, { subtree: true, childList: true});
 | 
			
		||||
            var n = handleDocument();       
 | 
			
		||||
            _trace(">>>>>>> DOMContentLoaded  n: %s match: %s query: %s iframe: %s loc: %s <<<<<<<")
 | 
			
		||||
                (n , match, query, !!frameElement && frameElement.id, location.href);
 | 
			
		||||
        }, true);
 | 
			
		||||
        
 | 
			
		||||
        window.addEventListener("message", function(e) {
 | 
			
		||||
            if (!e.data || e.data.id != "userinput") return;
 | 
			
		||||
            if (e.source == window.parent) {
 | 
			
		||||
                _trace("@@@ handleMessage(userinput) @@@@")();
 | 
			
		||||
                var si = new MouseEvent("siminput", Object.assign({view: window}, e.data));
 | 
			
		||||
                userInput = {e: Object.defineProperty(si, "target", {value: window}), time: e.data.time};
 | 
			
		||||
                if (injected) dispatchUserInput(userInput);
 | 
			
		||||
            }
 | 
			
		||||
            if (e.source && e.source.parent == window && userInput) {
 | 
			
		||||
                var iframe, iframes = [...window.document.querySelectorAll("iframe")];
 | 
			
		||||
                if (userInput.e.target.shadowRoot) iframes.push(...userInput.e.target.shadowRoot.querySelectorAll("iframe"));
 | 
			
		||||
                if (iframe = iframes.find((a) => a.contentWindow == e.source)) { 
 | 
			
		||||
                    var ue = userInput.e, time = userInput.time, r = iframe.getBoundingClientRect();
 | 
			
		||||
                    var data = {id: "userinput", clientX: ue.pageX - r.left - scrollX, clientY: ue.pageY - r.top - scrollY, time};
 | 
			
		||||
                    e.source.postMessage(data, "*");
 | 
			
		||||
                    _trace("@@@ iframe.postMessage(userinput) @@@")();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, true);
 | 
			
		||||
 | 
			
		||||
        function handleDocument()
 | 
			
		||||
        {
 | 
			
		||||
            var nodes = handleNodesDeep(window.document.body || window.document.documentElement);
 | 
			
		||||
            var frames = (window.document.body || window.document.documentElement).querySelectorAll(frameSelector);
 | 
			
		||||
            if (frames.length) handleFrames(frames);
 | 
			
		||||
            return nodes;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        function handleNodes(nodes, delayed)
 | 
			
		||||
        {
 | 
			
		||||
            if (!injected) {
 | 
			
		||||
                if (href.search("^https?:") == -1 && !delayed) 
 | 
			
		||||
                    return window.setTimeout(function(){ handleNodes(nodes, true)});
 | 
			
		||||
                injected = loadScript();
 | 
			
		||||
                if (userInput) dispatchUserInput(userInput);
 | 
			
		||||
            }
 | 
			
		||||
            nodes.forEach(function(node) { 
 | 
			
		||||
                node.setAttribute("flashstopped", true);
 | 
			
		||||
                try { node.parentNode.setAttribute("flashstopped_p", true)} catch(e){};
 | 
			
		||||
                if (!node.flashstopped) {
 | 
			
		||||
                    node.dispatchEvent(new Event("flashstop:bind", {bubbles: true, composed: true}));
 | 
			
		||||
                    chrome.runtime.sendMessage("count");
 | 
			
		||||
                    _trace("match: %s query: %s")(match, query);
 | 
			
		||||
                }
 | 
			
		||||
                node.flashstopped = true;
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        function handleFrames(frames)
 | 
			
		||||
        {
 | 
			
		||||
            if (!window.wrappedJSObject) frames.forEach(function(frame) {
 | 
			
		||||
                if (!frame.contentWindow) return;
 | 
			
		||||
                _trace("!!! iframe - id: %s src: %s fs: %s !!!")(frame.id, frame.src, frame.contentWindow.flashstopped);
 | 
			
		||||
                if (!frame.contentWindow.flashstopped) {
 | 
			
		||||
                    frame.setAttribute("flashstopped", true);
 | 
			
		||||
                    frame.contentWindow.flashstopped = true;
 | 
			
		||||
                    frame.contentWindow.Function('parent.postMessage({id: "userinput"}, "*")')();
 | 
			
		||||
                    window.setTimeout(function(){ load(frame.contentWindow)});
 | 
			
		||||
               };
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        function handleNodesDeep(node, match)
 | 
			
		||||
        {
 | 
			
		||||
            var nodes = match && (node.matches(selector) || node.shadowRoot) ? [node] : [];
 | 
			
		||||
            var count = nodes.push(...node.querySelectorAll(selector));
 | 
			
		||||
            for (var el of nodes.filter((a) => a.shadowRoot)) {
 | 
			
		||||
                nodes.splice(nodes.indexOf(el), 1)[0].setAttribute("flashstopped", true);
 | 
			
		||||
                count += handleNodesDeep(el.shadowRoot) - 1;
 | 
			
		||||
                observer.observe(el.shadowRoot, { subtree: true, childList: true});
 | 
			
		||||
            }
 | 
			
		||||
            if (nodes.length) handleNodes(nodes);
 | 
			
		||||
            return count;
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        function loadScript()
 | 
			
		||||
        {
 | 
			
		||||
            var code = `(function(data){ ${_trace} ${Handlers} ${handler} (${init})()})(${JSON.stringify(data)})`;
 | 
			
		||||
            var script = window.document.createElement("script");
 | 
			
		||||
            script.textContent = code;
 | 
			
		||||
            if (window.wrappedJSObject)
 | 
			
		||||
                script.textContent += "\ndocument.currentScript.dispatchEvent(new Event('load'));";
 | 
			
		||||
            script.onload = function() { this.executed = true};
 | 
			
		||||
            (window.document.head || window.document.documentElement).appendChild(script);
 | 
			
		||||
            script.remove();
 | 
			
		||||
            
 | 
			
		||||
            if (window.wrappedJSObject && !script.executed)   // fff
 | 
			
		||||
                try { window.eval(code); } catch(e) {};
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        };
 | 
			
		||||
                            // initilaizer & adapter for the injection code...
 | 
			
		||||
        function init()
 | 
			
		||||
        {
 | 
			
		||||
            var handlingUserInput = false
 | 
			
		||||
            var lastUserInput = null;
 | 
			
		||||
            var handlers = new Handlers(TRACE);
 | 
			
		||||
            function isHandlingUserInput() { return handlingUserInput = handlingUserInput && Date.now() - lastUserInput.time < 100 };
 | 
			
		||||
            
 | 
			
		||||
            registerUserHandlers(handlers, TRACE, isHandlingUserInput, () => TRACE("setHandlingUserInput")(), () => lastUserInput, data);
 | 
			
		||||
            registerHandlers(handlers, TRACE, isHandlingUserInput, () => TRACE("setHandlingUserInput")(), () => lastUserInput, data);
 | 
			
		||||
            
 | 
			
		||||
            window.addEventListener("userinput", function(e) { 
 | 
			
		||||
                handlingUserInput = true;
 | 
			
		||||
                setTimeout(function() { handlingUserInput = false;});
 | 
			
		||||
                lastUserInput = {e: Object.assign({target: e.target}, e.detail.e), time: e.detail.time};
 | 
			
		||||
            }, true);
 | 
			
		||||
            window.addEventListener("flashstop:bind", function onbind(e){
 | 
			
		||||
                var aElement = e.target, path = e.composedPath();
 | 
			
		||||
                if (path && path[0] != aElement) aElement = path[0];
 | 
			
		||||
                TRACE("onElementBinding - tag: %s id: %s loc: %s")(aElement.localName, aElement.id, window.location.href);
 | 
			
		||||
                window.wrappedJSObject = window;
 | 
			
		||||
                try { 
 | 
			
		||||
                    handlers.apply(wrapper(aElement));
 | 
			
		||||
                } catch(e) {
 | 
			
		||||
                    aElement.addEventListener("playing", () => {
 | 
			
		||||
                        if (!lastUserInput || Date.now() - lastUserInput.time > 1500) aElement.pause();
 | 
			
		||||
                })};
 | 
			
		||||
                delete window.wrappedJSObject;
 | 
			
		||||
            }, true);
 | 
			
		||||
                                    
 | 
			
		||||
            function wrapper(node)
 | 
			
		||||
            {
 | 
			
		||||
                var proxy = new Proxy(node, { get: function(target, prop, receiver) {
 | 
			
		||||
                        var proto = Object.getPrototypeOf(node);
 | 
			
		||||
                        var res = Reflect.get(proto, prop, node);
 | 
			
		||||
                        return typeof res == "function" && res.bind ? res.bind(node) : res;
 | 
			
		||||
                    }, set: function(target, prop, value, receiver) { 
 | 
			
		||||
                        var proto = Object.getPrototypeOf(node);
 | 
			
		||||
                        return Reflect.set(proto, prop, value, Reflect.has(proto, prop) ? node : receiver);
 | 
			
		||||
                    }});
 | 
			
		||||
                return Object.create(proxy, {wrappedJSObject: { value: node}});
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            TRACE("addEventListener - flashstop:bind")();
 | 
			
		||||
        };           
 | 
			
		||||
        
 | 
			
		||||
        function inRect(x, y, el){ var b = el.getBoundingClientRect(); return (x > b.left && x < b.right && y > b.top && y < b.bottom) ? el : null};
 | 
			
		||||
        function matchDeep(el, x, y, res) { 
 | 
			
		||||
            if (!el.shadowRoot) return el.matches("video, audio") ? el : null;
 | 
			
		||||
            for (var n of [...el.shadowRoot.elementsFromPoint(x, y)].filter((a) => a.getRootNode().host == el))
 | 
			
		||||
                 if (res = matchDeep(n, x, y)) return res;
 | 
			
		||||
        };
 | 
			
		||||
        function getMediaElement(aWin, aPrev, x, y)
 | 
			
		||||
        {
 | 
			
		||||
            try {aWin.document} catch(e) { _trace("getMediaElement - %s")(e); return };
 | 
			
		||||
            var res, sx = x + aWin.mozInnerScreenX, sy = y + aWin.mozInnerScreenY, round = Math.round;
 | 
			
		||||
            _trace("sc(%s,%s) win(%s,%s) win: %s prev: %s")(round(sx), round(sy), round(x), round(y), aWin.location.host, aPrev && aPrev.location.host);
 | 
			
		||||
            for (var node of aWin.document.elementsFromPoint(x, y))
 | 
			
		||||
                if (res = (node.localName != "iframe" || node.contentWindow == aPrev) ? matchDeep(node, x, y) :
 | 
			
		||||
                    getMediaElement(node.contentWindow, null, x - node.getBoundingClientRect().left, y - node.getBoundingClientRect().top))
 | 
			
		||||
                        return (res.localName != "iframe" && _trace("getMediaElement - success id: %s")(res.id), res);
 | 
			
		||||
            if (res = [...aWin.document.querySelectorAll("video:not([src^='data:'])")].find((node) => inRect(x, y, node)))
 | 
			
		||||
                return (_trace("getMediaElement - success id: %s")(res.id), res);
 | 
			
		||||
            return (aPrev && aWin != aWin.parent && aWin.frameElement) && getMediaElement(aWin.parent, aWin, x + 
 | 
			
		||||
                aWin.frameElement.getBoundingClientRect().left, y + aWin.frameElement.getBoundingClientRect().top);
 | 
			
		||||
        };                         
 | 
			
		||||
 | 
			
		||||
        function onContextMenu(e)
 | 
			
		||||
        {                               // before 
 | 
			
		||||
            if (e.isTrusted && e.button == 2){
 | 
			
		||||
                var media = e.target instanceof HTMLMediaElement ? e.target : getMediaElement(e.view, e.view, e.clientX, e.clientY);
 | 
			
		||||
                var paused = media && media.paused;
 | 
			
		||||
                if (media) {
 | 
			
		||||
                    chrome.runtime.sendMessage({ msg: "contextmenu", media: true, paused }, 
 | 
			
		||||
                        function(){ if (!chrome.runtime.lastError) paused ? media.play() : media.pause(); });
 | 
			
		||||
                    if (e.ctrlKey)
 | 
			
		||||
                        e.stopImmediatePropagation();
 | 
			
		||||
                } 
 | 
			
		||||
                else  
 | 
			
		||||
                    chrome.runtime.sendMessage({ msg: "contextmenu", media: false});
 | 
			
		||||
            }
 | 
			
		||||
        };          
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function dispatchUserInput({e, time, e: {view: window}})
 | 
			
		||||
{                                       // fff!
 | 
			
		||||
    with(e) var Obj = window.Object, data = Object.assign(new Obj, {clientX, clientY, pageX, pageY});
 | 
			
		||||
    var target = e.target != window && window.document.contains(e.target) ? e.target : window;
 | 
			
		||||
    target.dispatchEvent(new CustomEvent("userinput", {detail: Object.assign(new Obj,{e: data, time})}));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// </>
 | 
			
		||||
							
								
								
									
										49
									
								
								AutoplayStopper/content/handler-utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								AutoplayStopper/content/handler-utils.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
 | 
			
		||||
//      handler-utils.js See license.txt for terms of usage and credits
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
  
 | 
			
		||||
/**
 | 
			
		||||
*   Handlers - content handlers manager...
 | 
			
		||||
*   ----------------------------------------
 | 
			
		||||
*   @bYO!
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
function Handlers(TRACE){
 | 
			
		||||
 | 
			
		||||
    var _handlers = [], _mapRemoved = new Map();           
 | 
			
		||||
    return {
 | 
			
		||||
        unload: function unload(){ 
 | 
			
		||||
             for (var win of _mapRemoved.keys()) { 
 | 
			
		||||
                win.removeEventListener("unload", onUnload, false); 
 | 
			
		||||
                TRACE("Handlers.unload - remove wnd loc: %s")(win.location);
 | 
			
		||||
            }; 
 | 
			
		||||
            _handlers = [];
 | 
			
		||||
            _mapRemoved = new Map();
 | 
			
		||||
        },
 | 
			
		||||
        add: function add(handler) { _handlers.push(handler); },
 | 
			
		||||
        remove: function remove(win, handler) { 
 | 
			
		||||
            if (!_mapRemoved.has(win)){
 | 
			
		||||
                win.addEventListener("unload", onUnload, false);
 | 
			
		||||
                _mapRemoved.set(win, []);
 | 
			
		||||
            }
 | 
			
		||||
            _mapRemoved.get(win).push(handler);
 | 
			
		||||
            TRACE("Handlers.remove - handler: %s")(handler.name);    
 | 
			
		||||
        },
 | 
			
		||||
        apply: function apply(element){
 | 
			
		||||
            var removed = _mapRemoved.get(element.ownerDocument.defaultView);
 | 
			
		||||
            for (var handler, i = 0; i < _handlers.length; i++)
 | 
			
		||||
                if ((handler = _handlers[i]) && (!removed || removed.indexOf(handler) == -1))
 | 
			
		||||
                    try { 
 | 
			
		||||
                        if (handler(element)) break;
 | 
			
		||||
                    } catch (e) { TRACE("!!!!!!!!! handler: %s Exception: %s !!!!!!!!!")(handler.name, e); };
 | 
			
		||||
        },
 | 
			
		||||
        get length() { return _handlers.length; } 
 | 
			
		||||
    };      
 | 
			
		||||
    
 | 
			
		||||
    function onUnload(e){ 
 | 
			
		||||
        var win = e.target.defaultView;
 | 
			
		||||
        TRACE("Handlers.onUnload - remove wnd has: %s loc: %s")(_mapRemoved.has(win), win.location);
 | 
			
		||||
        _mapRemoved.delete(win);
 | 
			
		||||
    }        
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										39
									
								
								AutoplayStopper/content/navigator.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								AutoplayStopper/content/navigator.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
(function() {
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
//    setTimeout(function() {
 | 
			
		||||
        var script = document.createElement("script");
 | 
			
		||||
        script.textContent = `(${setNavigator})()`;
 | 
			
		||||
        (document.head || document.documentElement || document).appendChild(script);
 | 
			
		||||
        script.remove();
 | 
			
		||||
//    });
 | 
			
		||||
      
 | 
			
		||||
    function setNavigator(nav = { plugins: navigator.plugins, mimeTypes: navigator.mimeTypes}) {
 | 
			
		||||
        
 | 
			
		||||
        console.log("setNavigator - uri: " + location);
 | 
			
		||||
 | 
			
		||||
        var plugins = Object.assign(Object.create(PluginArray.prototype), [...nav.plugins]);
 | 
			
		||||
        Object.defineProperties(plugins, { item: {value: (a) => plugins[a]}, namedItem: {value: (a) => plugins[a]}, 
 | 
			
		||||
            refresh: {value: () => { nav.plugins.refresh(); setNavigator(nav)}}, 
 | 
			
		||||
            length: { writable: true, value: nav.plugins.length}});
 | 
			
		||||
        for (var a of plugins) { Object.defineProperty(plugins, a.name, {configurable: true, value: a}); };        
 | 
			
		||||
        [].splice.call(plugins, [].findIndex.call(plugins, (a) => a.name == "Shockwave Flash"), 1);
 | 
			
		||||
        delete plugins["Shockwave Flash"];
 | 
			
		||||
        Object.defineProperty(navigator, "plugins", {configurable: true, value: plugins});
 | 
			
		||||
                  
 | 
			
		||||
        var mimetypes = Object.assign(Object.create(MimeTypeArray.prototype), [...nav.mimeTypes]);
 | 
			
		||||
        Object.defineProperties(mimetypes, { item: {value: (a) => mimetypes[a]}, namedItem: {value: (a) => mimetypes[a]}, 
 | 
			
		||||
            refresh: {value: () => { plugins.refresh()}}, length: { writable: true, value: nav.mimeTypes.length}});            
 | 
			
		||||
        for (var a of mimetypes) { Object.defineProperty(mimetypes, a.type, {configurable: true, value: a}); };                    
 | 
			
		||||
        [].forEach.call(nav.plugins["Shockwave Flash"] || [], ({type}) => 
 | 
			
		||||
            delete mimetypes[[].splice.call(mimetypes, [].findIndex.call(mimetypes, (a) => a.type == type), 1)[0].type]);            
 | 
			
		||||
        Object.defineProperty(navigator, "mimeTypes", {configurable: true, value: mimetypes});
 | 
			
		||||
    };
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
// </>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										144
									
								
								AutoplayStopper/devtools.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								AutoplayStopper/devtools.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,144 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const DevTools = new function() {
 | 
			
		||||
 | 
			
		||||
    const sArea = "local";
 | 
			
		||||
    const sKeys = ["debug", "devtools", "codefile", "ucodefile", "codefilename", "ucodefilename", "disableOverwrite", "selector-css", "uhandler", "handler"];
 | 
			
		||||
 | 
			
		||||
    var storage = new Storage(sKeys, sArea); 
 | 
			
		||||
      
 | 
			
		||||
    storage.ready.then(function() { 
 | 
			
		||||
    
 | 
			
		||||
        if (!storage.data.devtools) 
 | 
			
		||||
            return; 
 | 
			
		||||
                                    //  devtools page - create panel ...
 | 
			
		||||
        if (location.search == "?view=page")
 | 
			
		||||
            return chrome.devtools.panels.create("AutoplayStopper", "/icons/icon48.png", "/skin/devtools.html?view=panel");
 | 
			
		||||
            
 | 
			
		||||
                                    //  devtools panel ...
 | 
			
		||||
        var fileinput = Object.assign(document.createElement("input"), {type: "file", hidden: true});
 | 
			
		||||
        document.body.appendChild(fileinput);        
 | 
			
		||||
        document.readyState == "complete" ? load() : addEventListener("load", load);
 | 
			
		||||
 | 
			
		||||
        function load() {
 | 
			
		||||
        
 | 
			
		||||
            i18n.process(document);
 | 
			
		||||
            document.getElementById("ver").textContent = chrome.runtime.getManifest().version;
 | 
			
		||||
            setCheckbox("overwrite", "disableOverwrite");
 | 
			
		||||
            setCheckbox("debug");
 | 
			
		||||
            setSelector();
 | 
			
		||||
            setup("");
 | 
			
		||||
            setup("u");
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        function setSelector() 
 | 
			
		||||
        {
 | 
			
		||||
            var selector = document.getElementById("selector");
 | 
			
		||||
            var apply = document.getElementById("apply");
 | 
			
		||||
            selector.value = storage.data["selector-css"];
 | 
			
		||||
            selector.oninput = function() { apply.disabled = selector.value == storage.data["selector-css"]; };
 | 
			
		||||
            apply.onclick = function() {
 | 
			
		||||
                storage.data["selector-css"] = selector.value;
 | 
			
		||||
                storage.commit(["selector-css"]);
 | 
			
		||||
                apply.disabled = true;
 | 
			
		||||
            };
 | 
			
		||||
            document.getElementById("reset").onclick = function() {
 | 
			
		||||
                var url = chrome.extension.getURL("script/selector.css");
 | 
			
		||||
                chrome.runtime.sendMessage({ msg: "load", script: "selector-css", file: url });
 | 
			
		||||
            };
 | 
			
		||||
            storage.addChangeListener(function(changes){
 | 
			
		||||
                if (changes.includes("selector-css")) selector.value = storage.data["selector-css"];
 | 
			
		||||
                apply.disabled = true;
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        function setup(pfx) 
 | 
			
		||||
        {
 | 
			
		||||
            var file = pfx + "codefile";
 | 
			
		||||
            var filename = file + "name";
 | 
			
		||||
                        
 | 
			
		||||
            document.getElementById(pfx + "path-input").textContent = storage.data[file];
 | 
			
		||||
            document.getElementById(pfx + "filename").textContent = storage.data[filename];
 | 
			
		||||
            updateState();
 | 
			
		||||
            
 | 
			
		||||
            document.getElementById(pfx + "load-button").onclick = function() {
 | 
			
		||||
                var url = storage.data[file] || chrome.extension.getURL("script/") + (pfx && "user") + "handler.js";
 | 
			
		||||
                chrome.runtime.sendMessage({ msg: "load", script: pfx + "handler", file: url});
 | 
			
		||||
            };
 | 
			
		||||
            document.getElementById(pfx + "export-button").onclick = function() {
 | 
			
		||||
                var a = document.getElementById("export-link");
 | 
			
		||||
                a.download = (pfx && "user") + "handler.js";
 | 
			
		||||
                a.href = "data:application/javascript," + encodeURIComponent(storage.data[pfx + "handler"]);
 | 
			
		||||
                a.click();
 | 
			
		||||
            };
 | 
			
		||||
            document.getElementById(pfx + "edit-button").onclick = function() { 
 | 
			
		||||
                var open = chrome.devtools.panels.openResource || function(){};
 | 
			
		||||
                open(getURL(file), null, function(res){
 | 
			
		||||
                    if (res.isError && res.code == "E_NOTFOUND")
 | 
			
		||||
                        alert(chrome.i18n.getMessage("fileNotFound"));
 | 
			
		||||
                });
 | 
			
		||||
            };
 | 
			
		||||
            var committed = chrome.devtools && chrome.devtools.inspectedWindow.onResourceContentCommitted;
 | 
			
		||||
            committed && committed.addListener(function(resource){
 | 
			
		||||
                if (resource.url == getURL(file))
 | 
			
		||||
                    resource.getContent(function(content, encoding) {
 | 
			
		||||
                        chrome.devtools.inspectedWindow.eval(content, function(result, isException) {
 | 
			
		||||
                            if (isException)
 | 
			
		||||
                                alert(chrome.i18n.getMessage("evalError") + isException.value);      
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
            });        
 | 
			
		||||
            document.getElementById(pfx + "path-input").oninput = updateState;
 | 
			
		||||
            document.getElementById(pfx + "path-button").onclick = function(e) {
 | 
			
		||||
                storage.data[filename] = document.getElementById(pfx + "filename").textContent = "";
 | 
			
		||||
                storage.data[file] = document.getElementById(pfx + "path-input").textContent;
 | 
			
		||||
                storage.commit([file, filename]);
 | 
			
		||||
                updateState();
 | 
			
		||||
            };
 | 
			
		||||
            document.getElementById(pfx + "select-button").onclick = function(e) {
 | 
			
		||||
                fileinput.onchange = function() {
 | 
			
		||||
                    if (!chrome.extension.getBackgroundPage) {    // fff...
 | 
			
		||||
                        var data = {msg: "select", url: URL.createObjectURL(this.files[0])};
 | 
			
		||||
                        chrome.runtime.sendMessage(data, function(res) { updateSelected(res.url, res.name); });
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        var url = chrome.extension.getBackgroundPage().URL.createObjectURL(this.files[0]);
 | 
			
		||||
                        updateSelected(url, this.files[0].name);
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                fileinput.click();
 | 
			
		||||
            };
 | 
			
		||||
            
 | 
			
		||||
            function updateSelected(url, name) {
 | 
			
		||||
                storage.data[file] = document.getElementById(pfx + "path-input").textContent = url;
 | 
			
		||||
                storage.data[filename] = document.getElementById(pfx + "filename").textContent = name;
 | 
			
		||||
                storage.commit([file, filename]);                    
 | 
			
		||||
                updateState();
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            function updateState() 
 | 
			
		||||
            {
 | 
			
		||||
                var a = document.getElementById(pfx + "path-input").textContent == (storage.data[file] || "");
 | 
			
		||||
                document.getElementById(pfx + "path-button").disabled = a;
 | 
			
		||||
                document.getElementById(pfx + "load-button").disabled = !a;
 | 
			
		||||
                document.getElementById(pfx + "edit-button").disabled =  !a || !storage.data[file];        
 | 
			
		||||
            };
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        function getURL(file) { try { return new URL(storage.data[file]).href } catch(e) {}; };
 | 
			
		||||
 | 
			
		||||
        function setCheckbox(id, key = id) 
 | 
			
		||||
        {
 | 
			
		||||
            var node = document.getElementById(id);
 | 
			
		||||
            node.checked = !!storage.data[key];
 | 
			
		||||
            node.onchange = function() {
 | 
			
		||||
                storage.data[key] = this.checked;
 | 
			
		||||
                storage.commit([key]);
 | 
			
		||||
            };                
 | 
			
		||||
        };
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//</>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								AutoplayStopper/icons/icon32.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								AutoplayStopper/icons/icon32.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								AutoplayStopper/icons/icon32d.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								AutoplayStopper/icons/icon32d.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								AutoplayStopper/icons/icon48.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								AutoplayStopper/icons/icon48.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.8 KiB  | 
							
								
								
									
										53
									
								
								AutoplayStopper/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								AutoplayStopper/manifest.json
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
{
 | 
			
		||||
	"description": "[MODIFIED BY ME] Stops video autoplay gracefully.",
 | 
			
		||||
	"manifest_version": 2,
 | 
			
		||||
	"name": "AutoplayStopper",
 | 
			
		||||
	"version": "1.8.7",
 | 
			
		||||
 | 
			
		||||
	"default_locale": "en",
 | 
			
		||||
 | 
			
		||||
	"icons": {
 | 
			
		||||
		"32": "icons/icon32.png",
 | 
			
		||||
		"48": "icons/icon48.png"
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"permissions": [
 | 
			
		||||
		"http://*/*", "https://*/*",
 | 
			
		||||
		"tabs",
 | 
			
		||||
		"contextMenus",
 | 
			
		||||
		"storage",
 | 
			
		||||
		"webNavigation"
 | 
			
		||||
	],
 | 
			
		||||
 | 
			
		||||
	"background": {
 | 
			
		||||
		"scripts": ["utils.js", "background.js"]
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"browser_action": {
 | 
			
		||||
		"default_icon": {
 | 
			
		||||
			"32": "icons/icon32.png"
 | 
			
		||||
		},
 | 
			
		||||
		"default_title": "AutoplayStopper",
 | 
			
		||||
		"default_popup": "skin/popup.html",
 | 
			
		||||
		"browser_style": true
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"content_scripts": [
 | 
			
		||||
		{
 | 
			
		||||
			"run_at": "document_start",
 | 
			
		||||
			"all_frames": true,
 | 
			
		||||
			"match_about_blank": true,
 | 
			
		||||
			"matches": ["http://*/*", "https://*/*"],
 | 
			
		||||
			"js": ["content/handler-utils.js", "content/content.js"]
 | 
			
		||||
		}],
 | 
			
		||||
 | 
			
		||||
	"options_ui": {
 | 
			
		||||
	  "chrome_style": true,
 | 
			
		||||
	  "browser_style": true,
 | 
			
		||||
	  "page": "skin/options.html"
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"devtools_page": "skin/devtools.html?view=page",
 | 
			
		||||
 | 
			
		||||
	"optional_permissions": ["file://*/*"]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										292
									
								
								AutoplayStopper/options.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								AutoplayStopper/options.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,292 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const Options = new function() {
 | 
			
		||||
 | 
			
		||||
    const {i18n, storage, permissions: perms} = chrome.extension.getBackgroundPage().Background;
 | 
			
		||||
    const permsAutoplayKey = perms.key("autoplay");
 | 
			
		||||
    const permsAutoplayDefaultKey = perms.defaultKey("autoplay");
 | 
			
		||||
    const permsFlashKey = perms.key("flash");
 | 
			
		||||
    const permsFlashDefaultKey = perms.defaultKey("flash");
 | 
			
		||||
    const data = { flash: { type: "flash", dirty: false}, autoplay: { type: "autoplay", dirty: false}};
 | 
			
		||||
    const { autoplay, flash } = data;
 | 
			
		||||
    
 | 
			
		||||
    var tabId = null;
 | 
			
		||||
    var selected = null;
 | 
			
		||||
    
 | 
			
		||||
//    chrome.tabs.getCurrent(function(tab) { tabId = tab.id; }); // chrome workaround ...
 | 
			
		||||
    chrome.tabs.query({ active: true, currentWindow: true}, function(tabs) { tabId = tabs[0].id; }); 
 | 
			
		||||
    chrome.tabs.onActivated.addListener(function(info){ if (tabId == info.tabId) postActive(); });
 | 
			
		||||
    addEventListener("load", init);
 | 
			
		||||
    addEventListener("hashchange", function() { updateState(location.hash.slice(1)); });
 | 
			
		||||
         
 | 
			
		||||
    function init()
 | 
			
		||||
    {
 | 
			
		||||
        i18n.process(document);
 | 
			
		||||
        var listener = storage.addChangeListener(function(changes){
 | 
			
		||||
            if (changes.indexOf(permsAutoplayKey) != -1) {
 | 
			
		||||
                autoplay.exceptions.init(perms.entries("autoplay"));
 | 
			
		||||
                autoplay.dirty = false;
 | 
			
		||||
                updateApply();            
 | 
			
		||||
            }
 | 
			
		||||
            if(changes.indexOf(permsAutoplayDefaultKey) != -1) {
 | 
			
		||||
                document.getElementById("autoplay-default").value = perms.default("autoplay");         
 | 
			
		||||
            }
 | 
			
		||||
            if (changes.indexOf(permsFlashKey) != -1) {
 | 
			
		||||
                flash.exceptions.init(perms.entries("flash"));
 | 
			
		||||
                flash.dirty = false;
 | 
			
		||||
                updateApply();            
 | 
			
		||||
            }
 | 
			
		||||
            if(changes.indexOf(permsFlashDefaultKey) != -1) {
 | 
			
		||||
                document.getElementById("flash-default").value = perms.default("flash");    
 | 
			
		||||
            }             
 | 
			
		||||
        });
 | 
			
		||||
        addEventListener("unload", function(){ storage.removeChangeListener(listener); });
 | 
			
		||||
        
 | 
			
		||||
        var manifest = chrome.runtime.getManifest();
 | 
			
		||||
        document.getElementById("extension-version").appendChild(document.createTextNode(manifest.version));
 | 
			
		||||
        document.getElementById("autoplay-default").value = perms.default("autoplay");
 | 
			
		||||
        document.getElementById("flash-default").value = perms.default("flash");
 | 
			
		||||
        document.getElementById("devtools").checked = storage.data.devtools;
 | 
			
		||||
        autoplay.exceptions = new ExceptionsList(document.getElementById("autoplay-list"));
 | 
			
		||||
        autoplay.exceptions.init(perms.entries("autoplay"));
 | 
			
		||||
        document.getElementById("autoplay-default").addEventListener("change", function(e) { 
 | 
			
		||||
            perms.setDefault("autoplay", e.target.value);
 | 
			
		||||
            storage.commit([permsAutoplayDefaultKey]);            
 | 
			
		||||
        });
 | 
			
		||||
        flash.exceptions = new ExceptionsList(document.getElementById("flash-list"));
 | 
			
		||||
        flash.exceptions.init(perms.entries("flash"));
 | 
			
		||||
        document.getElementById("flash-default").addEventListener("change", function(e) { 
 | 
			
		||||
            perms.setDefault("flash", e.target.value);
 | 
			
		||||
            storage.commit([permsFlashDefaultKey]);   
 | 
			
		||||
        });
 | 
			
		||||
        document.querySelectorAll(".exceptions-list-button").forEach(function(button) { 
 | 
			
		||||
            button.onclick = function(e) { location.hash = `${button.getAttribute("contenttype")}`; };
 | 
			
		||||
        });
 | 
			
		||||
        autoplay.exceptions.addDirtyListener(function(d) { autoplay.dirty = d; updateApply(); });
 | 
			
		||||
        flash.exceptions.addDirtyListener(function(d) { flash.dirty = d; updateApply(); });
 | 
			
		||||
        document.querySelector(".close-button").onclick = function() { location.hash = ""; };
 | 
			
		||||
        document.getElementById("exceptions-clear").onclick = function() { selected.exceptions.clear(); };        
 | 
			
		||||
        document.getElementById("exceptions-apply").onclick = apply;
 | 
			
		||||
        document.getElementById("exceptions-confirm").onclick = function() { apply(); location.hash = ""; };
 | 
			
		||||
        document.getElementById("devtools").onclick = function(e) {
 | 
			
		||||
            storage.data.devtools = this.checked;
 | 
			
		||||
            storage.commit(["devtools"]);
 | 
			
		||||
        };        
 | 
			
		||||
        if (location.hash) updateState(location.hash.slice(1));
 | 
			
		||||
        postActive();
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function postActive() { chrome.extension.getBackgroundPage().postMessage("optionsPageActive", "*"); };    
 | 
			
		||||
    function updateApply() { document.getElementById("exceptions-apply").disabled = !selected || !selected.dirty; };   
 | 
			
		||||
    
 | 
			
		||||
    function apply() 
 | 
			
		||||
    {
 | 
			
		||||
        if (selected.dirty) {
 | 
			
		||||
            perms.clear(selected.type);
 | 
			
		||||
            for (var [url, perm] of selected.exceptions.entries()) { perms.set(selected.type, url, perm); };
 | 
			
		||||
            storage.commit([perms.key(selected.type)], function(err){
 | 
			
		||||
                if (err) { selected.dirty = true; };
 | 
			
		||||
                updateApply();
 | 
			
		||||
            });
 | 
			
		||||
            selected.dirty = false;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function updateState(state)
 | 
			
		||||
    {
 | 
			
		||||
//        console.log(`updateState(${state})`);
 | 
			
		||||
        if (state) {
 | 
			
		||||
            document.querySelector("div[contenttype]:not([hidden])").hidden = true;
 | 
			
		||||
            document.querySelector("h2[contenttype]:not([hidden])").hidden = true;
 | 
			
		||||
            document.querySelector(`div[contenttype=${state}]`).hidden = false;
 | 
			
		||||
            document.querySelector(`h2[contenttype=${state}]`).hidden = false;
 | 
			
		||||
            var overlay = document.querySelector(".overlay");
 | 
			
		||||
            overlay.hidden = false;
 | 
			
		||||
            setTimeout(function() { overlay.classList.remove("transparent"); }, 20);
 | 
			
		||||
            selected = data[state];
 | 
			
		||||
            updateApply();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            var overlay = document.querySelector(".overlay");
 | 
			
		||||
            overlay.classList.add("transparent");
 | 
			
		||||
            setTimeout(function() { overlay.hidden = true; }, 500);        
 | 
			
		||||
        }            
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ExceptionsList = function ExceptionsList(list){
 | 
			
		||||
    
 | 
			
		||||
    var itemid    = 0;
 | 
			
		||||
    var baseitem  = list.querySelector("#listitem");
 | 
			
		||||
    var inputitem   = list.querySelector("#inputitem");
 | 
			
		||||
    var selected  = list.querySelector("[selected]");
 | 
			
		||||
    var listeners = [];
 | 
			
		||||
    var dirty     = false;
 | 
			
		||||
 | 
			
		||||
    baseitem.remove();
 | 
			
		||||
    list.addEventListener("mousedown", handleMousedown.bind(this));
 | 
			
		||||
    list.addEventListener("click",  handleClick.bind(this));
 | 
			
		||||
    list.addEventListener("keydown", handleKeyDown.bind(this));
 | 
			
		||||
    list.addEventListener("change", handleChange.bind(this));
 | 
			
		||||
    list.addEventListener("focus", function(e) {
 | 
			
		||||
        if (!e.target.classList.contains("row-delete-button")) {
 | 
			
		||||
            list.setAttribute("has-element-focus", "hasElementFocus");
 | 
			
		||||
            handleSelection(e.target.closest("[role=listitem]"));
 | 
			
		||||
            if (e.target.getAttribute("displaymode") == "static") e.target.nextSibling.focus();
 | 
			
		||||
        }
 | 
			
		||||
    }, true);
 | 
			
		||||
    list.addEventListener("blur", function(e) {
 | 
			
		||||
        if (!list.contains(e.relatedTarget) && !e.target.classList.contains("row-delete-button")) {
 | 
			
		||||
            list.removeAttribute("has-element-focus");
 | 
			
		||||
            handleSelection();
 | 
			
		||||
            if (!e.relatedTarget) list.parentNode.closest("[tabindex]").focus();
 | 
			
		||||
        } 
 | 
			
		||||
    }, true);
 | 
			
		||||
    
 | 
			
		||||
    return {
 | 
			
		||||
        init: function init(entries) {
 | 
			
		||||
            this.clear();
 | 
			
		||||
            entries.sort(function(a, b) { return a[0].localeCompare(b[0]); }); 
 | 
			
		||||
            for (var [key, type] of entries) { appendItem(key, type); };
 | 
			
		||||
            dirty = false;
 | 
			
		||||
        },
 | 
			
		||||
        entries: function * entries() 
 | 
			
		||||
        {             
 | 
			
		||||
            for (var node of list.children)
 | 
			
		||||
                if (node.id.search("listitem") == 0 && node != inputitem) 
 | 
			
		||||
                    yield [node.querySelector("#perms-host").textContent,  parseInt(node.querySelector("#perms-type-select").value)];
 | 
			
		||||
        },
 | 
			
		||||
        clear: function clear()
 | 
			
		||||
        {
 | 
			
		||||
            for (var node of [].slice.apply(list.children))
 | 
			
		||||
                if (node.id.search("listitem") == 0 && node != inputitem) node.remove();
 | 
			
		||||
            inputitem.querySelector("#perms-host-input").focus();
 | 
			
		||||
            fireDirty(true);
 | 
			
		||||
        },
 | 
			
		||||
        get dirty() { return dirty; },
 | 
			
		||||
        addDirtyListener: function(listener) { listeners.push(listener); },
 | 
			
		||||
        removeDirtyListener: function(listener) { var idx = listeners.indexOf(listener); if (idx != -1) listeners.splice(idx); }
 | 
			
		||||
    };    
 | 
			
		||||
        
 | 
			
		||||
    function appendItem(host, type, scroll)
 | 
			
		||||
    {
 | 
			
		||||
        var item = baseitem.cloneNode(true);
 | 
			
		||||
        item.id = item.id + "-" + (++itemid);        
 | 
			
		||||
        item.querySelector("#perms-host-input").value = item.querySelector("#perms-host").textContent = host;
 | 
			
		||||
        var select = item.querySelector("#perms-type-select");
 | 
			
		||||
        select.value = type;
 | 
			
		||||
        if (type != 0) item.querySelector("#perms-type").textContent = select[select.selectedIndex].text;
 | 
			
		||||
        list.insertBefore(item, inputitem);
 | 
			
		||||
        if (scroll) scrollToBottom(inputitem);
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function scrollToBottom(node) 
 | 
			
		||||
    {
 | 
			
		||||
        if (node.clientHeight < node.scrollHeight) 
 | 
			
		||||
            return node.scrollTop = node.scrollHeight - node.clientHeight;
 | 
			
		||||
        if (node.parentNode) scrollToBottom(node.parentNode);
 | 
			
		||||
    };    
 | 
			
		||||
    
 | 
			
		||||
    function handleMousedown(e) 
 | 
			
		||||
    {
 | 
			
		||||
        var target = e.target;
 | 
			
		||||
        var item = target.closest("[role=listitem]");
 | 
			
		||||
        if (target.classList.contains("row-delete-button")) return;
 | 
			
		||||
        if (target.id == "perms-host") {
 | 
			
		||||
            var x = e.clientX, y = e.clientY, offset = document.caretPositionFromPoint ? 
 | 
			
		||||
                document.caretPositionFromPoint(x, y).offset : document.caretRangeFromPoint(x, y).startOffset;
 | 
			
		||||
            var input = item.querySelector("#perms-host-input");
 | 
			
		||||
            var inside = x < inputitem.querySelector("#perms-host-input").getBoundingClientRect().right;
 | 
			
		||||
            input.selectionStart = input.selectionEnd = inside ? 0 : input.value.length;
 | 
			
		||||
            setTimeout(function() { input.selectionStart = input.selectionEnd = offset; }, 25);
 | 
			
		||||
        }
 | 
			
		||||
        if (item && !target.hasAttribute("tabindex") && !item.hasAttribute("editing")) { 
 | 
			
		||||
            item.querySelector("[id^=perms-host]").focus();
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function handleSelection(item)
 | 
			
		||||
    {
 | 
			
		||||
        if (selected && item != selected) {
 | 
			
		||||
            selected.removeAttribute("lead");
 | 
			
		||||
            selected.removeAttribute("editing");
 | 
			
		||||
            if (item) selected.removeAttribute("selected");
 | 
			
		||||
            if (selected == inputitem) handleInput(!item);
 | 
			
		||||
            selected.querySelectorAll("[id^=perms]").forEach(function(a) { a.tabIndex = item ? -1 : 0; });
 | 
			
		||||
        }
 | 
			
		||||
        if (item && !item.hasAttribute("editing")) {
 | 
			
		||||
            item.setAttribute("selected", "selected");
 | 
			
		||||
            item.setAttribute("lead", "lead");
 | 
			
		||||
            item.setAttribute("editing", "");
 | 
			
		||||
            item.querySelectorAll("[id^=perms]")
 | 
			
		||||
                .forEach(function(a) { a.tabIndex = a.getAttribute("displaymode") == "static" ? -1 : 0; });
 | 
			
		||||
            selected = item;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function handleClick(e) 
 | 
			
		||||
    {
 | 
			
		||||
        var target = e.target;
 | 
			
		||||
        if (target.classList.contains("row-delete-button")) {
 | 
			
		||||
            var item = target.closest("[role=listitem]");
 | 
			
		||||
            if (item == selected) handleSelection(inputitem);
 | 
			
		||||
            item.remove();
 | 
			
		||||
            list.focus({preventScroll: true});
 | 
			
		||||
            fireDirty(true);
 | 
			
		||||
            return;
 | 
			
		||||
        };
 | 
			
		||||
    };    
 | 
			
		||||
 | 
			
		||||
    function handleKeyDown(e) 
 | 
			
		||||
    {
 | 
			
		||||
        if (selected &&  selected != inputitem && e.target.id != "perms-host-input" && e.keyCode == 46)
 | 
			
		||||
            selected.querySelector(".row-delete-button").click();
 | 
			
		||||
        if (selected && e.key == "Enter") selected == inputitem ? handleInput(true) : list.focus({preventScroll: true});
 | 
			
		||||
        if (selected && e.key == "ArrowUp" && e.target.id != "perms-type-select" && selected != list.querySelector("[role=listitem]"))
 | 
			
		||||
            selected.previousSibling.querySelector("[id^=perms-host]").focus();
 | 
			
		||||
        if (selected && e.key == "ArrowDown" && e.target.id != "perms-type-select" && selected != inputitem)
 | 
			
		||||
            selected.nextSibling.querySelector("[id^=perms-host]").focus();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function handleChange(e)
 | 
			
		||||
    {
 | 
			
		||||
        var target = e.target;
 | 
			
		||||
        var item = target.closest("[role=listitem]");
 | 
			
		||||
        if (item != inputitem) {
 | 
			
		||||
            if (target.id == "perms-type-select") {
 | 
			
		||||
                item.querySelector("#perms-type").textContent = 
 | 
			
		||||
                    target.value != 0 ? target[target.selectedIndex].text : "";
 | 
			
		||||
                fireDirty(true);
 | 
			
		||||
            }
 | 
			
		||||
            if (target.id == "perms-host-input"){
 | 
			
		||||
                try { 
 | 
			
		||||
                    var url = new URL(target.value);
 | 
			
		||||
                    target.value = url.origin;
 | 
			
		||||
                    item.querySelector("#perms-host").textContent = target.value;
 | 
			
		||||
                    fireDirty(true);
 | 
			
		||||
                } 
 | 
			
		||||
                catch (e) { target.value = item.querySelector("#perms-host").textContent; };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function handleInput(scroll)
 | 
			
		||||
    {
 | 
			
		||||
        try { 
 | 
			
		||||
            var target = inputitem.querySelector("#perms-host-input")
 | 
			
		||||
            var url = new URL(target.value);
 | 
			
		||||
            target.value = url.origin;
 | 
			
		||||
            appendItem(target.value, inputitem.querySelector("#perms-type-select").value, scroll);
 | 
			
		||||
            target.value = null;
 | 
			
		||||
            fireDirty(true);
 | 
			
		||||
        } 
 | 
			
		||||
        catch (e) {};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function fireDirty(d) { dirty = d; for (var listener of listeners) listener(d); };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//    </>
 | 
			
		||||
							
								
								
									
										94
									
								
								AutoplayStopper/popup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								AutoplayStopper/popup.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const Popup = new function(){
 | 
			
		||||
 | 
			
		||||
    const start = Date.now();
 | 
			
		||||
    const {i18n, storage, permissions: perms, openOptionsPage} = chrome.extension.getBackgroundPage().Background;
 | 
			
		||||
 | 
			
		||||
    while (Date.now() - start < 50);
 | 
			
		||||
    setTimeout(function() {
 | 
			
		||||
        while (Date.now() - start < 150);
 | 
			
		||||
        addEventListener("unload", function() { 
 | 
			
		||||
            if (Date.now() - start < 250) {
 | 
			
		||||
                storage.data.disabled = !storage.data.disabled;
 | 
			
		||||
                storage.commit(["disabled"]);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    const permsAutoplayKey = perms.key("autoplay");
 | 
			
		||||
    const permsFlashKey = perms.key("flash");
 | 
			
		||||
 | 
			
		||||
    var url = null;
 | 
			
		||||
    var ready = new Promise( function(resolve) {
 | 
			
		||||
        chrome.tabs.query({ active: true, currentWindow: true}, function(tabs) {
 | 
			
		||||
            url = new URL(tabs[0].url);
 | 
			
		||||
            resolve();
 | 
			
		||||
        })
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    addEventListener("load", function() { ready.then(init); });
 | 
			
		||||
    
 | 
			
		||||
    function init()
 | 
			
		||||
    {
 | 
			
		||||
        i18n.process(document);
 | 
			
		||||
        var permission = perms.testPermission("autoplay", url);
 | 
			
		||||
        var permissionFlash = perms.testPermission("flash", url);
 | 
			
		||||
        initItem( document.getElementById("allow_site"), !!permission.origin && permission != perms.ACCESS_SESSION && permission, [url.origin]);
 | 
			
		||||
        initItem( document.getElementById("allow_session"), !!permission.origin && permission == perms.ACCESS_SESSION, [url.origin]);
 | 
			
		||||
        initItem( document.getElementById("disable_site"), !!permissionFlash.origin && permissionFlash, [url.origin]);
 | 
			
		||||
        initItem( document.getElementById("allow_all"), storage.data.disabled);
 | 
			
		||||
        initItem( document.getElementById("settings"));
 | 
			
		||||
        document.getElementById("popupmenu")
 | 
			
		||||
            .classList.toggle("restricted", url.protocol.search("^http") == -1 || !!storage.data.disabled); 
 | 
			
		||||
        
 | 
			
		||||
        window.onclick = function(e) {
 | 
			
		||||
 | 
			
		||||
            switch (e.target.id) {
 | 
			
		||||
                case "settings": 
 | 
			
		||||
                    openOptionsPage();
 | 
			
		||||
                    close();                    
 | 
			
		||||
                    break;
 | 
			
		||||
                case "allow_site":
 | 
			
		||||
                    if ( [undefined, perms.UNKNOWN_ACTION].indexOf(perms.get("autoplay", url)) != -1 
 | 
			
		||||
                        && permission != perms.default("autoplay")) { openOptionsPage("#autoplay"); close(); break; };
 | 
			
		||||
                    perms.set("autoplay", url, (permission == perms.ALLOW_ACTION) ? perms.DENY_ACTION : perms.ALLOW_ACTION);
 | 
			
		||||
                    storage.commit([permsAutoplayKey]);
 | 
			
		||||
                    init();
 | 
			
		||||
                    break;
 | 
			
		||||
                case "allow_session": 
 | 
			
		||||
                    if ( [undefined, perms.UNKNOWN_ACTION].indexOf(perms.get("autoplay", url)) != -1  
 | 
			
		||||
                        && permission != perms.default("autoplay")) { openOptionsPage("#autoplay"); close(); break; };
 | 
			
		||||
                    (permission == perms.ACCESS_SESSION) ? perms.remove("autoplay", url) :
 | 
			
		||||
                        perms.set("autoplay", url, perms.ACCESS_SESSION);
 | 
			
		||||
                    storage.commit([permsAutoplayKey]);
 | 
			
		||||
                    init();
 | 
			
		||||
                   break;       
 | 
			
		||||
                case "disable_site": 
 | 
			
		||||
                    if ( [undefined, perms.UNKNOWN_ACTION].indexOf(perms.get("flash", url)) != -1 
 | 
			
		||||
                        && permissionFlash != perms.default("flash")) { openOptionsPage("#flash"); close(); break; };
 | 
			
		||||
                    perms.set("flash", url, (permissionFlash == perms.ALLOW_ACTION) ? perms.DENY_ACTION : perms.ALLOW_ACTION);
 | 
			
		||||
                    storage.commit([permsFlashKey]);
 | 
			
		||||
                    init();
 | 
			
		||||
                   break;       
 | 
			
		||||
                case "allow_all":
 | 
			
		||||
                    storage.data.disabled = !storage.data.disabled;
 | 
			
		||||
                    storage.commit(["disabled"]);
 | 
			
		||||
                    init();
 | 
			
		||||
                   break;       
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function initItem(item, check, args) 
 | 
			
		||||
    { 
 | 
			
		||||
        if (check !== undefined) check ? item.setAttribute("checked", check) : item.removeAttribute("checked");         
 | 
			
		||||
        if (args) { var i = 0; item.textContent = item.textContent.replace(/%S/g, function () { return args[i++]; }); };
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//</>
 | 
			
		||||
							
								
								
									
										289
									
								
								AutoplayStopper/script/handler.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								AutoplayStopper/script/handler.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,289 @@
 | 
			
		|||
"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);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										24
									
								
								AutoplayStopper/script/selector.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								AutoplayStopper/script/selector.css
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
object[classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"]:not([flashstopped]),
 | 
			
		||||
object[classid*=":d27cdb6e-ae6d-11cf-96b8-444553540000"]:not([flashstopped]),
 | 
			
		||||
object[codebase*="swflash.cab"]:not([flashstopped]),
 | 
			
		||||
object[data*=".swf"]:not([flashstopped]),
 | 
			
		||||
object[type="application/x-shockwave-flash"]:not([flashstopped]),
 | 
			
		||||
object[src*=".swf"]:not([flashstopped]),
 | 
			
		||||
embed[type="application/x-shockwave-flash"]:not([flashstopped]),
 | 
			
		||||
embed[src*=".swf"]:not([flashstopped]),
 | 
			
		||||
embed[allowscriptaccess]:not([flashstopped]),
 | 
			
		||||
embed[flashvars]:not([flashstopped]),
 | 
			
		||||
embed[wmode]:not([flashstopped]),
 | 
			
		||||
lima-video:not([flashstopped]),
 | 
			
		||||
/*---------	!(html5media) ---------*/
 | 
			
		||||
*:not([flashstopped_p]) > video,
 | 
			
		||||
video:not([flashstopped]),
 | 
			
		||||
audio:not([flashstopped]) { 
 | 
			
		||||
	border: 5px red solid !important; 
 | 
			
		||||
	box-sizing: border-box;	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*[flashstopped] { 
 | 
			
		||||
	border: 3px blue solid !important;
 | 
			
		||||
	box-sizing: border-box;	
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								AutoplayStopper/script/userhandler.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								AutoplayStopper/script/userhandler.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
 | 
			
		||||
//      userhandler.js - handler that doesn't get overwritten by new versions 
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
function registerUserHandlers(handlers, TRACE)
 | 
			
		||||
{
 | 
			
		||||
    // add your handlers here...
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								AutoplayStopper/skin/IDR_CLOSE_DIALOG
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								AutoplayStopper/skin/IDR_CLOSE_DIALOG
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 139 B  | 
							
								
								
									
										
											BIN
										
									
								
								AutoplayStopper/skin/IDR_CLOSE_DIALOG_H
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								AutoplayStopper/skin/IDR_CLOSE_DIALOG_H
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 214 B  | 
							
								
								
									
										1
									
								
								AutoplayStopper/skin/arrow_down.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								AutoplayStopper/skin/arrow_down.svg
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="12px" viewBox="0 0 24 12" fill="#757575"><g><path d="M 0 0 L 24 0 L 12 12 z"/></g></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 150 B  | 
							
								
								
									
										157
									
								
								AutoplayStopper/skin/devtools.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								AutoplayStopper/skin/devtools.html
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,157 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <script src="/utils.js"></script>
 | 
			
		||||
    <script src="/devtools.js"></script>
 | 
			
		||||
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
        body {
 | 
			
		||||
            margin: 0.5% 10%; 
 | 
			
		||||
            font-family: "Segoe UI", Tahoma, sans-serif;
 | 
			
		||||
            color: #4c4c4c;                  
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        label.settings-label {
 | 
			
		||||
            min-width: 80px;
 | 
			
		||||
            font-size: initial;
 | 
			
		||||
            font-weight: lighter;            
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        div.settings-row {
 | 
			
		||||
            margin: 6px 18px;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        input.settings-checkbox {
 | 
			
		||||
            align-self: flex-end; 
 | 
			
		||||
            -webkit-margin-start: 0px;
 | 
			
		||||
            -webkit-margin-end: 10px;
 | 
			
		||||
            margin-inline-start: 0px;
 | 
			
		||||
            margin-inline-end: 10px;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        button {
 | 
			
		||||
            -webkit-margin-end: 3px;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        button:disabled {
 | 
			
		||||
            color: #a0a0a0;
 | 
			
		||||
        }        
 | 
			
		||||
        
 | 
			
		||||
        button:not([disabled]) {
 | 
			
		||||
            color: #4c4c4c;        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        span.input {
 | 
			
		||||
            min-width: 450px;
 | 
			
		||||
            max-width: 85%;
 | 
			
		||||
            border: 1px solid rgb(170, 170, 170);
 | 
			
		||||
            padding: 1px 2px;
 | 
			
		||||
            -webkit-appearance: textfield;
 | 
			
		||||
            font-size: 13.3333px;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            height: 17px; /* fff */
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        hr {
 | 
			
		||||
            border-color: rgb(210, 210, 210);
 | 
			
		||||
            border-top-width: 0px;
 | 
			
		||||
            margin-bottom: 1em;
 | 
			
		||||
            margin-top: .9em;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        h2 {
 | 
			
		||||
            font-weight: 400;
 | 
			
		||||
            margin-top: 15px; /* fff */
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #splitter {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            flex-flow: column nowrap;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            height: 0;
 | 
			
		||||
            min-height: calc(40px + 6.5em);
 | 
			
		||||
            max-height: calc(100vh - 10px);
 | 
			
		||||
            margin-bottom: 1px;
 | 
			
		||||
            resize: vertical;
 | 
			
		||||
            background: linear-gradient(to right bottom, transparent 50%,
 | 
			
		||||
                        rgba(0, 0, 0, 0.1) 50%) 100% 100% / 16px 15px no-repeat;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #selector {
 | 
			
		||||
            height: 100%;
 | 
			
		||||
            width: 800px;
 | 
			
		||||
            color: darkslateblue;
 | 
			
		||||
            border: 1px solid rgb(170, 170, 170);
 | 
			
		||||
            resize: none;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        :focus {
 | 
			
		||||
            outline: rgb(170, 170, 170) auto 1px;
 | 
			
		||||
        }     
 | 
			
		||||
    </style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <div id="splitter">
 | 
			
		||||
    <div class="settings-row" style="margin:0 0px;">
 | 
			
		||||
        <img src="../icons/icon48.png" style="margin: 10px; height: 32px;" />
 | 
			
		||||
        <h2>AutoplayStopper</h2>
 | 
			
		||||
        <h2 id="ver" style="font-weight: 200; -webkit-margin-start: 10px; margin-inline-start: 10px;">1.0.0</h2>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr style="width: calc(100% - 2px); margin-top: 6px; margin-bottom: 0px"/>
 | 
			
		||||
    <h2 i18n-content="selector">Selector</h2>
 | 
			
		||||
    <div class="settings-row" style="height: 100%;">
 | 
			
		||||
        <label class="settings-label" i18n-content="text" style="margin-bottom: auto;">Text</label>
 | 
			
		||||
        <textarea id="selector" spellcheck="false"></textarea>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="settings-row" style="margin-bottom: calc(.9em - 1px);">
 | 
			
		||||
        <label class="settings-label" i18n-content="actions">Actions</label>
 | 
			
		||||
        <button id="reset" i18n-content="reset">Reset</button>
 | 
			
		||||
        <button id="apply" disabled="" i18n-content="apply"></button>
 | 
			
		||||
    </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr style="margin-top:0px"/>
 | 
			
		||||
    <h2 i18n-content="script">Script</h2>
 | 
			
		||||
    <div class="settings-row">
 | 
			
		||||
        <label class="settings-label" i18n-content="path">Path:</label>
 | 
			
		||||
        <span id="path-input" class="input" contenteditable="true" spellcheck="false"></span>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="settings-row">
 | 
			
		||||
        <label class="settings-label" i18n-content="actions">Actions:</label>
 | 
			
		||||
        <button id="edit-button" i18n-content="edit">Edit</button>
 | 
			
		||||
        <button id="load-button" i18n-content="load">Load</button>
 | 
			
		||||
        <button id="export-button" i18n-content="export">Export...</button>
 | 
			
		||||
        <button id="path-button" i18n-content="setPath" disabled>Set Path</button>
 | 
			
		||||
        <button id="select-button" i18n-content="selectFile" >File...</button>
 | 
			
		||||
        <label id="filename" class="settings-label" style="-webkit-margin-start:10px;margin-inline-start:10px;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <h2 i18n-content="userScript">User Script</h2>
 | 
			
		||||
    <div class="settings-row">
 | 
			
		||||
        <label class="settings-label" i18n-content="path">Path:</label>
 | 
			
		||||
        <span id="upath-input" class="input" contenteditable="true" spellcheck="false"></span>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="settings-row">
 | 
			
		||||
        <label class="settings-label" i18n-content="actions">Actions:</label>
 | 
			
		||||
        <button id="uedit-button" i18n-content="edit">Edit</button>
 | 
			
		||||
        <button id="uload-button" i18n-content="load">Load</button>
 | 
			
		||||
        <button id="uexport-button" i18n-content="export">Export...</button>
 | 
			
		||||
        <button id="upath-button" i18n-content="setPath" disabled>Set Path</button>
 | 
			
		||||
        <button id="uselect-button" i18n-content="selectFile">File...</button>
 | 
			
		||||
        <label id="ufilename" class="settings-label" style="-webkit-margin-start:10px;margin-inline-start:10px;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <div class="settings-row">
 | 
			
		||||
        <input id="overwrite" class="settings-checkbox" type="checkbox" />
 | 
			
		||||
        <label class="settings-label" i18n-content="overwrite">Disable overwrite on update</label>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="settings-row">
 | 
			
		||||
        <input id="debug" class="settings-checkbox" type="checkbox" />
 | 
			
		||||
        <label class="settings-label" i18n-content="debug">Log debug info</label>
 | 
			
		||||
    </div>
 | 
			
		||||
    <a id="export-link" hidden="true"></a>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										615
									
								
								AutoplayStopper/skin/options.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										615
									
								
								AutoplayStopper/skin/options.css
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,615 @@
 | 
			
		|||
    
 | 
			
		||||
/*  chrome://resources/css/list.css     */
 | 
			
		||||
    
 | 
			
		||||
list,
 | 
			
		||||
grid {
 | 
			
		||||
  display: block;
 | 
			
		||||
  outline: none;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  position: relative; /* Make sure that item offsets are relative to the
 | 
			
		||||
                         list. */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > *,
 | 
			
		||||
grid > * {
 | 
			
		||||
  -webkit-user-select: none;
 | 
			
		||||
  background-color: rgba(255, 255, 255, 0);
 | 
			
		||||
  border: 1px solid rgba(255, 255, 255, 0); /* transparent white */
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
  cursor: default;
 | 
			
		||||
  line-height: 20px;
 | 
			
		||||
  margin: -1px 0;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  padding: 0 3px;
 | 
			
		||||
  position: relative; /* to allow overlap */
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  white-space: pre;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > * {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
grid > * {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > [lead],
 | 
			
		||||
grid > [lead] {
 | 
			
		||||
  border-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list:focus > [lead],
 | 
			
		||||
grid:focus > [lead] {
 | 
			
		||||
  border-color: hsl(214, 91%, 65%);
 | 
			
		||||
  z-index: 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > [anchor],
 | 
			
		||||
grid > [anchor] {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list:not([disabled]) > :hover,
 | 
			
		||||
grid:not([disabled]) > :hover {
 | 
			
		||||
  background-color: hsl(214, 91%, 97%);
 | 
			
		||||
  border-color: hsl(214, 91%, 85%);
 | 
			
		||||
  z-index: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > [selected],
 | 
			
		||||
grid > [selected] {
 | 
			
		||||
  background-color: hsl(0, 0%, 90%);
 | 
			
		||||
  background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.8),
 | 
			
		||||
                                            rgba(255, 255, 255, 0));
 | 
			
		||||
  border-color: hsl(0, 0%, 85%);
 | 
			
		||||
  z-index: 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list:focus > [selected],
 | 
			
		||||
grid:focus > [selected] {
 | 
			
		||||
  background-color: hsl(214, 91%, 89%);
 | 
			
		||||
  border-color: hsl(214, 91%, 65%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list:focus > [lead][selected],
 | 
			
		||||
list > [selected]:hover,
 | 
			
		||||
grid:focus > [lead][selected],
 | 
			
		||||
grid > [selected]:hover {
 | 
			
		||||
  background-color: hsl(214, 91%, 87%);
 | 
			
		||||
  border-color: hsl(214, 91%, 65%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > .spacer,
 | 
			
		||||
grid > .spacer {
 | 
			
		||||
  border: 0;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  display: block;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  visibility: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list :-webkit-any(
 | 
			
		||||
    input[type='input'],
 | 
			
		||||
    input[type='password'],
 | 
			
		||||
    input[type='search'],
 | 
			
		||||
    input[type='text'],
 | 
			
		||||
    input[type='url']),
 | 
			
		||||
list :-webkit-any(
 | 
			
		||||
    button,
 | 
			
		||||
    input[type='button'],
 | 
			
		||||
    input[type='submit'],
 | 
			
		||||
    select):not(.custom-appearance) {
 | 
			
		||||
  line-height: normal;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
}      
 | 
			
		||||
 | 
			
		||||
list input[type='text'] {
 | 
			
		||||
  margin-left: -4px;
 | 
			
		||||
  padding: 3px;
 | 
			
		||||
  width: 190px;	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*  chrome://resources/css/overlay.css     */
 | 
			
		||||
 | 
			
		||||
[hidden] {
 | 
			
		||||
    display: none !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay {
 | 
			
		||||
    -webkit-box-align: center;
 | 
			
		||||
    -webkit-box-orient: vertical;
 | 
			
		||||
    -webkit-box-pack: center;
 | 
			
		||||
    -webkit-perspective: 1px;
 | 
			
		||||
    -webkit-transition: 200ms opacity;   
 | 
			
		||||
    background-color: rgba(255, 255, 255, 0.75);
 | 
			
		||||
/*    bottom: 50px; */
 | 
			
		||||
    display: -webkit-box;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
    padding: 20px;
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    top: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay.transparent .page {
 | 
			
		||||
    transform: scale(0.99) translateY(-20px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.transparent {
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay .page {
 | 
			
		||||
    max-height: 335.5px;
 | 
			
		||||
/*    display: -webkit-box;
 | 
			
		||||
    -webkit-box-orient: vertical;
 | 
			
		||||
*/
 | 
			
		||||
    -webkit-border-radius: 3px;
 | 
			
		||||
    -webkit-box-orient: vertical;
 | 
			
		||||
    -webkit-transition: 200ms transform;
 | 
			
		||||
    background: white;
 | 
			
		||||
    box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);
 | 
			
		||||
    color: #333;
 | 
			
		||||
    display: -webkit-box;
 | 
			
		||||
    min-width: 400px;
 | 
			
		||||
    padding: 0px;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    z-index: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay .page .content-area {
 | 
			
		||||
    -webkit-box-flex: 1;
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
    overflow: overlay; /* auto */
 | 
			
		||||
    padding: 0px 20px 0px; /* 0px 17px 6px */
 | 
			
		||||
    position: relative;
 | 
			
		||||
    min-height: 226px;
 | 
			
		||||
    outline: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay .page > .close-button {
 | 
			
		||||
    background-image: url(IDR_CLOSE_DIALOG);
 | 
			
		||||
    background-position: center;
 | 
			
		||||
    background-repeat: no-repeat;
 | 
			
		||||
    height: 14px;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    right: 7px;
 | 
			
		||||
    top: 7px;
 | 
			
		||||
    width: 14px;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay .page > .close-button:hover {
 | 
			
		||||
    background-image: url(IDR_CLOSE_DIALOG_H);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay .page > .close-button:focus:not(:hover) {
 | 
			
		||||
    background-image: url(IDR_CLOSE_DIALOG_H);
 | 
			
		||||
    filter: opacity(75%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.settings-row {
 | 
			
		||||
    margin: 2px 18px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    padding: 2px 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
label.settings-label {
 | 
			
		||||
    width: 130px;
 | 
			
		||||
    display: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay .page h2 {
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* chrome://settings/contentExceptions#... */
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hbox {
 | 
			
		||||
  -webkit-box-orient: horizontal;
 | 
			
		||||
  display: -webkit-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.vbox {
 | 
			
		||||
  -webkit-box-orient: vertical;
 | 
			
		||||
  display: -webkit-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.box-align-center {
 | 
			
		||||
  -webkit-box-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.stretch {
 | 
			
		||||
  -webkit-box-flex: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.raw-button,
 | 
			
		||||
.raw-button:hover,
 | 
			
		||||
.raw-button:active {
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  background-repeat: no-repeat;
 | 
			
		||||
  border: none;
 | 
			
		||||
  box-shadow: none !important;
 | 
			
		||||
  min-width: 0;
 | 
			
		||||
  min-height: 0;
 | 
			
		||||
  padding: 1px 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.page list {
 | 
			
		||||
  /* Min height is a multiple of the list item height (32) */
 | 
			
		||||
  box-sizing: content-box;
 | 
			
		||||
  min-height: 192px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.option {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-list,
 | 
			
		||||
.settings-list-empty {
 | 
			
		||||
  border: 1px solid #d9d9d9;
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Editable List properties */
 | 
			
		||||
list > * {
 | 
			
		||||
  -webkit-box-align: center;
 | 
			
		||||
  -webkit-transition: 150ms background-color;
 | 
			
		||||
  border: none;
 | 
			
		||||
  border-radius: 0;  /* TODO(dbeam): Is this necessary? */
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  display: -webkit-box;
 | 
			
		||||
  height: 32px;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > .spacer {
 | 
			
		||||
  /* The above height rule should not apply to spacers. When redraw is called
 | 
			
		||||
     on the list they will be given an explicit element height but this ensures
 | 
			
		||||
     they have 0 height to begin with. */
 | 
			
		||||
  height: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list:not([disabled]) > :hover {
 | 
			
		||||
  background-color: rgb(228, 236, 247);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Note: If this becomes the list style for other WebUI pages these rules can be
 | 
			
		||||
 * simplified (since they wont need to override other rules). */
 | 
			
		||||
 | 
			
		||||
list:not([has-element-focus]) > [selected],
 | 
			
		||||
list:not([has-element-focus]) > [lead][selected] {
 | 
			
		||||
  background-color: #d0d0d0;
 | 
			
		||||
  background-image: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list[has-element-focus] > [selected],
 | 
			
		||||
list[has-element-focus] > [lead][selected],
 | 
			
		||||
list:not([has-element-focus]) > [selected]:hover,
 | 
			
		||||
list:not([has-element-focus]) > [selected][lead]:hover {
 | 
			
		||||
  background-color: rgb(187, 206, 233);
 | 
			
		||||
  background-image: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-list[has-element-focus] > [lead],
 | 
			
		||||
.settings-list[has-element-focus] > [lead][selected] {
 | 
			
		||||
  border-bottom: 1px solid rgb(120, 146, 180);
 | 
			
		||||
  border-top: 1px solid rgb(120, 146, 180); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-list[has-element-focus] > [lead]:nth-child(2),
 | 
			
		||||
.settings-list[has-element-focus] > [lead][selected]:nth-child(2) {
 | 
			
		||||
  border-top: 1px solid transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-list[has-element-focus] > [lead]:nth-last-child(2),
 | 
			
		||||
.settings-list[has-element-focus] > [lead][selected]:nth-last-child(2) {
 | 
			
		||||
  border-bottom: 1px solid transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-list[disabled] > [lead][selected],
 | 
			
		||||
.settings-list[disabled]:focus > [lead][selected] {
 | 
			
		||||
  border: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list .deletable-item {
 | 
			
		||||
  -webkit-box-align: center;
 | 
			
		||||
  outline: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list .deletable-item > :first-child {
 | 
			
		||||
  -webkit-box-align: center;
 | 
			
		||||
  -webkit-box-flex: 1;
 | 
			
		||||
  -webkit-padding-end: 5px;
 | 
			
		||||
  -moz-padding-end: 5px;  
 | 
			
		||||
  display: -webkit-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list .row-delete-button {
 | 
			
		||||
  -webkit-transition: 150ms opacity;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  background-image: 
 | 
			
		||||
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAiElEQVR42r2RsQrDMAxEBRdl8SDcX8lQPGg1GBI6lvz/h7QyRRXV0qUULwfvwZ1tenw5PxToRPWMC52eA9+WDnlh3HFQ/xBQl86NFYJqeGflkiogrOvVlIFhqURFVho3x1moGAa3deMs+LS30CAhBN5nNxeT5hbJ1zwmji2k+aF6NENIPf/hs54f0sZFUVAMigAAAABJRU5ErkJggg==);
 | 
			
		||||
  border: none;
 | 
			
		||||
  display: block;
 | 
			
		||||
  height: 16px;
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
  width: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > *:not(:hover):not([selected]):not([lead]) .row-delete-button,
 | 
			
		||||
list:not([has-element-focus]) > *:not(:hover):not([selected])
 | 
			
		||||
    .row-delete-button,
 | 
			
		||||
list[disabled] .row-delete-button,
 | 
			
		||||
list .row-delete-button[disabled] {
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list .row-delete-button:hover {
 | 
			
		||||
  background-image: 
 | 
			
		||||
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAqUlEQVR4XqWRMQqEMBBF/1E8Ra6x6V3FRnS9QbCxtJg6Z7CzE9lTiIXXyUb3C8EULixDIMM8Zt4kcDfxM5A45U+cgeXnC1tREgkzAgob3hiq3CUHvGLG4FTQoSgxQGDrzN8WTLBGnx2IVDksen9GH7Z9hA5E6uxABMJyCHDMCEGHzugLQPPlBCBNGq+5YtpnGw1Bv+te15ypljTpVzdak5Opy+z+qf//zQ+Lg+07ay5KsgAAAABJRU5ErkJggg==) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list .row-delete-button:active {
 | 
			
		||||
  background-image: 
 | 
			
		||||
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAQklEQVR4AWP4TwBSTQGDHcMZIIYAKA9VwRkwtINJgyCaCTAlCBaKAoQ+hFmoCqBKENKkK8C0gpAjCXuTyICiQ2QBAPSwyG3ByZlCAAAAAElFTkSuQmCC)
 | 
			
		||||
          ,
 | 
			
		||||
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAA/ElEQVR4Xu3UsWrCUBiG4efGlIBoIMFbcnYolYJ3pg4iKGrGYFTRwaUFhYAekiDt0EG++X2W83N8/3J/DbwBMJJSsdQItcDY1VlCOImzq3Ed8OmicHASB3ns5KBw8VUNpDJrW7uAiJ3sbK1l0mqArpmFTUlQ5jYWZrrUAUSmT0SZm4qoA56JvVhs/5g3A7RLolA85A1ASOTye65NMxASK6syfxGITMzvMxG9CvRkliWwlOm9AsSOcitzU1NzK7mjuBkQvHtLK7iLBiB5PhttJSGpB8I8vM6kDuiHeUjoVwMfYR4SRtUAw1veIZzOjRhSBzCoyKFjgH/3K7+BHzg+Cgw0eSW3AAAAAElFTkSuQmCC)
 | 
			
		||||
          ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list .static-text {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
/*    outline: none; bYO! inner rect on selection*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list[type='text'][inlineeditable] input {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > :not([editing]) [displaymode='edit'] {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > [editing] [displaymode='static'] {
 | 
			
		||||
  /* Don't use display:none or visibility:hidden because we need to keep an
 | 
			
		||||
   * element focusable.
 | 
			
		||||
   * We shrink only height.  We don't shrink width to avoid to change the size
 | 
			
		||||
   * of containing boxes. */
 | 
			
		||||
  border-bottom: 0 !important;
 | 
			
		||||
  border-top: 0 !important;
 | 
			
		||||
  height: 0 !important;
 | 
			
		||||
  width: auto;
 | 
			
		||||
  margin-bottom: 0 !important;
 | 
			
		||||
  margin-top: 0 !important;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list > [editing] input:invalid {
 | 
			
		||||
  background-color: pink;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* UI Controls */
 | 
			
		||||
 | 
			
		||||
/* LIST */	/* bYO! top level outline... */
 | 
			
		||||
.settings-list[has-element-focus]:after {
 | 
			
		||||
outline: 1px solid rgba(0, 128, 256, 0.5);
 | 
			
		||||
  outline-offset: -1px;
 | 
			
		||||
  content: "";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0px;
 | 
			
		||||
  left: 0px;
 | 
			
		||||
  bottom: 0px;
 | 
			
		||||
  right: 0px;
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
  z-index: 3;
 | 
			
		||||
}
 | 
			
		||||
   
 | 
			
		||||
/* chrome://settings/contentExceptions#... */
 | 
			
		||||
 | 
			
		||||
#content-settings-exceptions-area {
 | 
			
		||||
  min-width: 540px;
 | 
			
		||||
  width: 540px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.exception-pattern {
 | 
			
		||||
  -webkit-box-flex: 1;
 | 
			
		||||
  -webkit-margin-end: 10px;
 | 
			
		||||
  -moz-margin-end: 10px;
 | 
			
		||||
  -webkit-margin-start: 14px;
 | 
			
		||||
  -moz-margin-start: 14px;
 | 
			
		||||
  width: 200px;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.exception-setting {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  width: 120px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select.exception-setting {
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
  -webkit-padding-start: 3px;  
 | 
			
		||||
  width: calc(120px  + 4px); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overruled .exception-setting {
 | 
			
		||||
  width: calc(120px - 24px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overruled .overruleable:focus {
 | 
			
		||||
      outline:auto !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overruled .overruleable {
 | 
			
		||||
  text-decoration: line-through;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#exception-column-headers {
 | 
			
		||||
  margin-left: 17px;
 | 
			
		||||
  -webkit-margin-start: 17px;
 | 
			
		||||
  display: -webkit-box;
 | 
			
		||||
  margin-top: 10px;	/* bYO! 6 lines on FF */
 | 
			
		||||
  line-height: 16px;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#exception-column-headers > div {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#exception-pattern-column {
 | 
			
		||||
  -webkit-box-flex: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.exception-value-column-header {
 | 
			
		||||
  width: 145px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#content-settings-exceptions-area list {
 | 
			
		||||
  /*margin-bottom: 10px;  bYO!  keep list area consistent with scrolling */
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
}
 | 
			
		||||
					/******	new ui compat... ******/			   
 | 
			
		||||
button:not(.custom-appearance) {
 | 
			
		||||
    --google-blue-500: #528de0; /* #3b72ce #4285f4 #0a84ff */ 
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    line-height: 100%; /* 154% */
 | 
			
		||||
    padding: 8px 10px;
 | 
			
		||||
    color: white !important;
 | 
			
		||||
    border: 1px solid var(--google-blue-500);
 | 
			
		||||
    border-radius: 3px;
 | 
			
		||||
    box-shadow: none !important;
 | 
			
		||||
    font-family: inherit;
 | 
			
		||||
    font-size: inherit;
 | 
			
		||||
	text-shadow: none;    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:enabled:not(.custom-appearance) {
 | 
			
		||||
    background: var(--google-blue-500) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:enabled:not(.custom-appearance):focus {
 | 
			
		||||
    background: rgb(58, 117, 215) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select {
 | 
			
		||||
    --md-arrow-width: 0.9em;
 | 
			
		||||
    --md-arrow-offset: 0%;
 | 
			
		||||
    --md-select-side-padding: 3px;
 | 
			
		||||
    --md-select-width: 110px;
 | 
			
		||||
    -webkit-appearance: none;
 | 
			
		||||
    -moz-appearance: none;
 | 
			
		||||
/*    -webkit-margin-end: calc(-1 * var(--md-select-side-padding)); */
 | 
			
		||||
/*	-moz-margin-end: var(--md-select-side-padding); */
 | 
			
		||||
/*    -webkit-padding-end: calc(var(--md-select-side-padding) + var(--md-arrow-offset) + var(--md-arrow-width) + 3px); */
 | 
			
		||||
    -webkit-padding-start: var(--md-select-side-padding);
 | 
			
		||||
    -moz-padding-start: calc(var(--md-select-side-padding) - 1px);
 | 
			
		||||
    background: url(arrow_down.svg) calc(100% - var(--md-arrow-offset) - var(--md-select-side-padding)) center no-repeat !important;
 | 
			
		||||
    background-image: url(arrow_down.svg) !important;
 | 
			
		||||
    background-size: var(--md-arrow-width) !important;
 | 
			
		||||
    border: none;
 | 
			
		||||
    font-family: inherit;
 | 
			
		||||
    font-size: inherit;
 | 
			
		||||
    outline: none;
 | 
			
		||||
    padding-bottom: 2px;
 | 
			
		||||
    padding-top: 3px;
 | 
			
		||||
    border-bottom: 1px solid rgb(224, 224, 224);
 | 
			
		||||
    width: var(--md-select-width);
 | 
			
		||||
/*    width: calc(var(--md-select-width, 200px) + 2 * var(--md-select-side-padding)); */
 | 
			
		||||
    box-shadow: none !important;
 | 
			
		||||
    text-shadow: none;    
 | 
			
		||||
    margin: 3px 0;    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select:focus {
 | 
			
		||||
    border-color: rgb(77, 144, 254);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select.exception-setting {
 | 
			
		||||
    -webkit-padding-start: var(--md-select-side-padding);
 | 
			
		||||
    width: calc(120px + var(--md-select-side-padding));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html > body {
 | 
			
		||||
	height: 376px;
 | 
			
		||||
	width: 500px;
 | 
			
		||||
	margin: 16px 40px 14px 40px;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay {
 | 
			
		||||
    background-color: rgba(255, 255, 255,.5);
 | 
			
		||||
    bottom: 0px;
 | 
			
		||||
    padding-top: 30px;    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay .page {
 | 
			
		||||
    max-height: 341.5px;	
 | 
			
		||||
    box-shadow: 0 0px 1px 0px rgba(0, 0, 0, 0.2), 0 1px 6px rgba(0,0,0,0.15);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body > div:first-child {
 | 
			
		||||
	padding-bottom: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.action-area {
 | 
			
		||||
    padding-top: .3em !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
label.settings-label {
 | 
			
		||||
    width: 80px;
 | 
			
		||||
    margin: 7px 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input.settings-checkbox ~ label.settings-label {
 | 
			
		||||
    -webkit-margin-start: 3px;
 | 
			
		||||
    -moz-margin-start: 3px;   
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select ~ button.exceptions-list-button{
 | 
			
		||||
    -webkit-margin-start: auto;	
 | 
			
		||||
    -moz-margin-start: auto;	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input.settings-checkbox {
 | 
			
		||||
	display: -moz-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:enabled:not(.custom-appearance):not(:focus):hover {
 | 
			
		||||
    border: 1px solid rgba(0, 0, 0, 0.1); /* #3b72ce */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:disabled:not(.custom-appearance) {
 | 
			
		||||
    border-color: rgba(80, 80, 80, 0.1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
list input[type="text"] {
 | 
			
		||||
	font-size: inherit;
 | 
			
		||||
	font-family: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#perms-type {
 | 
			
		||||
    -moz-padding-start: 3px;
 | 
			
		||||
    height: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button::-moz-focus-inner {
 | 
			
		||||
	border: 0; 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select:-moz-focusring {
 | 
			
		||||
    color: transparent;
 | 
			
		||||
    text-shadow: 0 0 0 #000;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										124
									
								
								AutoplayStopper/skin/options.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								AutoplayStopper/skin/options.html
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
<!doctype html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="utf-8" />
 | 
			
		||||
        <link href="options.css" rel="stylesheet" type="text/css" />
 | 
			
		||||
        <script src="/options.js"></script>
 | 
			
		||||
        <style type="text/css">
 | 
			
		||||
        
 | 
			
		||||
        body {
 | 
			
		||||
            font-family: "Segoe UI", Tahoma, sans-serif;
 | 
			
		||||
            width: 560px;
 | 
			
		||||
            height: 400px; 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        h1 {
 | 
			
		||||
            font-size: 1.5em;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        h2 {
 | 
			
		||||
            margin: 1em 17px;
 | 
			
		||||
            font-size: 1.3em;            
 | 
			
		||||
        }        
 | 
			
		||||
 | 
			
		||||
        h1, h2, h3 {
 | 
			
		||||
            user-select: none;
 | 
			
		||||
            font-weight: normal;
 | 
			
		||||
            line-height: 1;
 | 
			
		||||
        }        
 | 
			
		||||
        
 | 
			
		||||
        hr {
 | 
			
		||||
            border-style: solid; 
 | 
			
		||||
            color: #dddddd; 
 | 
			
		||||
            border-top-width: 0px;
 | 
			
		||||
            margin-top: 1em;
 | 
			
		||||
            margin-bottom: 1.5em;
 | 
			
		||||
            margin-inline-start: initial;
 | 
			
		||||
            margin-inline-end: initial;            
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        input.settings-checkbox {
 | 
			
		||||
            margin: auto 1px;        
 | 
			
		||||
            -webkit-margin-start: 0px;
 | 
			
		||||
            margin-inline-start: 0px;
 | 
			
		||||
            position: static;
 | 
			
		||||
        }        
 | 
			
		||||
        </style>        
 | 
			
		||||
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <div style="text-align: center; display: block;">
 | 
			
		||||
            <span i18n-content="version">Version</span>
 | 
			
		||||
            <span id="extension-version"></span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <h1> <span i18n-content="settings" style="position: relative; top: -.7em">Settings</span></h1>
 | 
			
		||||
        <h2 i18n-content="autoplayTabLabel">Autoplay</h2>
 | 
			
		||||
 | 
			
		||||
        <div class="settings-row">
 | 
			
		||||
            <label for="autoplay-default" class="settings-label" i18n-content="defaultMode">Default Mode:</label>
 | 
			
		||||
            <select id="autoplay-default">
 | 
			
		||||
                <option i18n-content="disableAutoplay" value="2">Disable Autoplay</option>
 | 
			
		||||
                <option i18n-content="allowAutoplay" value="1">Allow Autoplay</option>
 | 
			
		||||
            </select>
 | 
			
		||||
            <button class="exceptions-list-button" contenttype="autoplay" i18n-content="manageExceptions">Exceptions...</button>
 | 
			
		||||
        </div>
 | 
			
		||||
        <hr />
 | 
			
		||||
        <h2 i18n-content="flashTabLabel">Flash</h2>
 | 
			
		||||
        <div class="settings-row">
 | 
			
		||||
            <label class="settings-label" for="flash-default" i18n-content="defaultMode">Default Mode:</label>
 | 
			
		||||
            <select id="flash-default">
 | 
			
		||||
                <option i18n-content="allowFlash" value="1">Allow Flash</option>
 | 
			
		||||
                <option i18n-content="disableFlash" value="2">Disable Flash</option>
 | 
			
		||||
            </select>
 | 
			
		||||
            <button class="exceptions-list-button" contenttype="flash" i18n-content="manageExceptions">Exceptions...</button>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="overlay transparent" hidden>   
 | 
			
		||||
        <div id="content-settings-exceptions-area" class="page">
 | 
			
		||||
            <button class="close-button raw-button custom-appearance"></button>
 | 
			
		||||
            <h2 contenttype="autoplay" i18n-content="autoplayExceptions">Autoplay exceptions</h2>
 | 
			
		||||
            <h2 contenttype="flash" i18n-content="flashExceptions" hidden>Flash exceptions</h2>
 | 
			
		||||
            <div class="content-area" tabindex="-1">
 | 
			
		||||
                <div id="exception-column-headers">
 | 
			
		||||
                    <div id="exception-pattern-column" i18n-content="exceptionHostnameHeader">
 | 
			
		||||
                        Hostname</div>
 | 
			
		||||
                    <div id="exception-behavior-column" class="exception-value-column-header" i18n-content="exceptionBehaviorHeader">
 | 
			
		||||
                        Behavior</div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div contenttype="autoplay">
 | 
			
		||||
                    <list id="autoplay-list" aria-activedescendant="listitem-27" class="settings-list" inlineeditable="" mode="normal" role="list" tabindex="-1">
 | 
			
		||||
                        <div class="spacer" style="height: 0px;"></div>
 | 
			
		||||
                        <div role="listitem" id="listitem" class="deletable-item" aria-posinset="1" aria-setsize="3"><div><div class="exception-pattern weakrtl"><div id="perms-host" class="static-text overruleable" displaymode="static" tabindex="-1"></div><input id="perms-host-input" type="text" displaymode="edit" tabindex="0"></div><span id="perms-type" class="exception-setting overruleable" displaymode="static" tabindex="-1"></span><select id="perms-type-select" tabindex="0" class="exception-setting" aria-labelledby="exception-behavior-column" displaymode="edit"><option value="1" i18n-content="exceptionAllow">Allow</option><option value="2" i18n-content="exceptionBlock">Block</option><option value="3" i18n-content="exceptionPrompt">Block (strict)</option><option value="8" i18n-content="exceptionSession">Session</option><option value="0" i18n-content="exceptionUndefined">Undefined</option></select></div><button class="raw-button row-delete-button custom-appearance" tabindex="-1" title="Delete this item"></button></div>
 | 
			
		||||
                        <div role="listitem" id="inputitem" selected="selected" lead="lead" class="deletable-item"><div><div class="exception-pattern weakrtl"><input id="perms-host-input" type="text" tabindex="0" placeholder="http://example.com"></div><select id="perms-type-select" tabindex="0" class="exception-setting" aria-labelledby="exception-behavior-column"><option value="1" i18n-content="exceptionAllow">Allow</option><option value="2" i18n-content="exceptionBlock">Block</option><option value="3" i18n-content="exceptionPrompt">Block (strict)</option><option value="8" i18n-content="exceptionSession">Session</option><option value="0" i18n-content="exceptionUndefined">Undefined</option></select></div><button class="raw-button row-delete-button custom-appearance" tabindex="-1" title="Delete this item" disabled=""></button></div>
 | 
			
		||||
                        <div class="spacer" style="height: 0px;"></div>
 | 
			
		||||
                    </list>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div contenttype="flash" hidden>
 | 
			
		||||
                    <list id="flash-list" aria-activedescendant="listitem-27" class="settings-list" inlineeditable="" mode="normal" role="list" tabindex="-1">
 | 
			
		||||
                        <div class="spacer" style="height: 0px;"></div>
 | 
			
		||||
                        <div role="listitem" id="listitem" class="deletable-item" aria-posinset="1" aria-setsize="3"><div><div class="exception-pattern weakrtl"><div id="perms-host" class="static-text overruleable" displaymode="static" tabindex="-1"></div><input id="perms-host-input" type="text" displaymode="edit" tabindex="0"></div><span id="perms-type" class="exception-setting overruleable" displaymode="static" tabindex="-1"></span><select id="perms-type-select" tabindex="0" class="exception-setting" aria-labelledby="exception-behavior-column" displaymode="edit"><option value="1" i18n-content="exceptionAllow">Allow</option><option value="2" i18n-content="exceptionBlock">Block</option><option value="0" i18n-content="exceptionUndefined">Undefined</option></select></div><button class="raw-button row-delete-button custom-appearance" tabindex="-1" title="Delete this item"></button></div>
 | 
			
		||||
                        <div role="listitem" id="inputitem" selected="selected" lead="lead" class="deletable-item"><div><div class="exception-pattern weakrtl"><input id="perms-host-input" type="text" tabindex="0" placeholder="http://example.com"></div><select id="perms-type-select" tabindex="0" class="exception-setting" aria-labelledby="exception-behavior-column"><option value="1" i18n-content="exceptionAllow">Allow</option><option value="2" i18n-content="exceptionBlock">Block</option><option value="0" i18n-content="exceptionUndefined">Undefined</option></select></div><button class="raw-button row-delete-button custom-appearance" tabindex="-1" title="Delete this item" disabled=""></button></div>
 | 
			
		||||
                        <div class="spacer" style="height: 0px;"></div>
 | 
			
		||||
                    </list>
 | 
			
		||||
                </div>                
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="action-area" style="padding-top: .5em">
 | 
			
		||||
                <div class="hbox stretch">
 | 
			
		||||
                </div>
 | 
			
		||||
                <button id="exceptions-clear" style="margin-left: 20px;" i18n-content="removeAll">Remove All</button>
 | 
			
		||||
                <div class="action-area-right" style="-webkit-box-pack: end; display: -webkit-box;">
 | 
			
		||||
                    <div class="button-strip" reversed="" style="position:relative; top: -1.5em; right: 19px">
 | 
			
		||||
                        <button id="exceptions-apply"  disabled i18n-content="apply">Apply</button>
 | 
			
		||||
                        <button id="exceptions-confirm" class="default-button" i18n-content="done">Done</button>                        
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <hr />
 | 
			
		||||
        <h2 i18n-content="advanced">Advanced</h2>
 | 
			
		||||
        <div class="settings-row">
 | 
			
		||||
            <input id="devtools" class="settings-checkbox" type="checkbox" />
 | 
			
		||||
            <label class="settings-label" i18n-content="devtools">Devtools Panel</label>
 | 
			
		||||
        </div>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										53
									
								
								AutoplayStopper/skin/popup.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								AutoplayStopper/skin/popup.css
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
body {
 | 
			
		||||
	margin: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    color: #303942;
 | 
			
		||||
    background: #f9fafb;
 | 
			
		||||
    -webkit-user-select: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu .popupitem {
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    display: block;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu .popupitem:hover {
 | 
			
		||||
    background: rgb(235, 235, 235); /*#565a63; 
 | 
			
		||||
    color: white;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu .popupitem.separator {
 | 
			
		||||
    background-color: rgba(0,0,0,0.15);
 | 
			
		||||
    height: 1px;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
    margin: 2px 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu .popupitem:not(.separator) {
 | 
			
		||||
    padding: 7px 10px;
 | 
			
		||||
    border-radius: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu .popupitem[checked] {
 | 
			
		||||
    background: rgb(80, 135, 90); /*#54975f;*/
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu .popupitem[checked="2"], .popupmenu .popupitem[checked="3"] {
 | 
			
		||||
    background: rgb(135, 80, 90); /*#54975f;*/
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu.restricted #allow_site, .popupmenu.restricted #allow_session, .popupmenu.restricted #disable_site {
 | 
			
		||||
    opacity: 0.5;
 | 
			
		||||
    pointer-events: none;    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popupmenu #allow_all[checked] {
 | 
			
		||||
    background: darkgray;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								AutoplayStopper/skin/popup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								AutoplayStopper/skin/popup.html
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8" />
 | 
			
		||||
    <link href="popup.css" rel="stylesheet" />
 | 
			
		||||
    <script src="/popup.js"></script>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <div id="popupmenu" class="popupmenu">
 | 
			
		||||
            <section>
 | 
			
		||||
                <div id="disable_site" class="popupitem" i18n-content="disableSite" >Disable flash for %S</div>
 | 
			
		||||
                <div id="allow_site" class="popupitem" i18n-content="allowSite" >Allow autoplay for %S</div>
 | 
			
		||||
                <div id="allow_session" class="popupitem" i18n-content="allowSession" >Allow session autoplay for %S</div>
 | 
			
		||||
            </section>
 | 
			
		||||
            <div class="popupitem separator"></div>
 | 
			
		||||
            <section>
 | 
			
		||||
    <!--        <popup-item id="script">Edit script...</popup-item> -->
 | 
			
		||||
                <div id="allow_all" class="popupitem" i18n-content="allowAll" >Allow everywhere</div>
 | 
			
		||||
                <div id="settings"  class="popupitem" i18n-content="settings" >Settings</div>
 | 
			
		||||
            </section>
 | 
			
		||||
        </div>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										103
									
								
								AutoplayStopper/utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								AutoplayStopper/utils.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const i18n = new function(){
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        process: function (doc) {
 | 
			
		||||
            var elements = doc.querySelectorAll("[i18n-content]");
 | 
			
		||||
            for (var i = 0; i < elements.length; ++i) {
 | 
			
		||||
                var element = elements[i];
 | 
			
		||||
                var message = chrome.i18n.getMessage(element.getAttribute("i18n-content"));
 | 
			
		||||
                if (message) element.textContent = message;
 | 
			
		||||
                else
 | 
			
		||||
                    console.warn("i18n: no message for " + element.getAttribute("i18n-content"));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Storage = function Storage(keys, areaname){
 | 
			
		||||
 | 
			
		||||
    var listeners = [];
 | 
			
		||||
    var data = {};
 | 
			
		||||
    var ready = new Promise(function (resolve, reject) { 
 | 
			
		||||
        chrome.storage[areaname].get(keys, function(items){
 | 
			
		||||
            Object.assign(data, items);
 | 
			
		||||
            if (!chrome.runtime.lastError) resolve();
 | 
			
		||||
        })
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    chrome.storage.onChanged.addListener(function(changes, area) {
 | 
			
		||||
        if (area == areaname) {
 | 
			
		||||
            var updated = [];
 | 
			
		||||
            for (var key of Object.keys(changes)) 
 | 
			
		||||
                if (keys.indexOf(key) != -1) { data[key] = changes[key].newValue; updated.push(key); };
 | 
			
		||||
            fireChanged(updated);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
        
 | 
			
		||||
    return {
 | 
			
		||||
        get ready() { return ready; },
 | 
			
		||||
        get data() { return data; },
 | 
			
		||||
        addChangeListener: function(listener) { listeners.push(listener); return listener; },
 | 
			
		||||
        removeChangeListener: function(listener) { var idx = listeners.indexOf(listener); if (idx != -1) listeners.splice(idx); },        
 | 
			
		||||
        commit: function commit(keys, callback) {
 | 
			
		||||
            var items = {};
 | 
			
		||||
            for (var key of keys) items[key] = data[key];
 | 
			
		||||
            chrome.storage[areaname].set(items, function(){
 | 
			
		||||
                if (callback) callback(chrome.runtime.lastError);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    function fireChanged(updated) { for (var listener of listeners) listener(updated); };    
 | 
			
		||||
}; 
 | 
			
		||||
 | 
			
		||||
const Permission = {
 | 
			
		||||
    UNKNOWN_ACTION: 0,
 | 
			
		||||
    ALLOW_ACTION:	1, 	
 | 
			
		||||
    DENY_ACTION: 	2, 	
 | 
			
		||||
    PROMPT_ACTION:  3,
 | 
			
		||||
    ACCESS_SESSION: 8
 | 
			
		||||
};   
 | 
			
		||||
 | 
			
		||||
const Permissions = class Permissions {
 | 
			
		||||
  
 | 
			
		||||
   constructor(data) {
 | 
			
		||||
     
 | 
			
		||||
      function getData(type){ return data[Permissions.key(type)] || (data[Permissions.key(type)] = {}); };
 | 
			
		||||
      function getDefault(type){ return data[Permissions.defaultKey(type)]; };     
 | 
			
		||||
     
 | 
			
		||||
      Object.assign(this, {
 | 
			
		||||
          testPermission: function testPermission(type, uri) {
 | 
			
		||||
              var origin, url = new window.URL(uri);
 | 
			
		||||
              var hostTokens = url.host.split(".");
 | 
			
		||||
              do {
 | 
			
		||||
                  var permission = getData(type)[origin = url.protocol + "//" + hostTokens.join(".")];
 | 
			
		||||
                  if (permission != undefined && permission != Permission.UNKNOWN_ACTION)
 | 
			
		||||
                      return Object.assign(Number(permission), {origin});
 | 
			
		||||
              } while (hostTokens.shift());
 | 
			
		||||
              return getDefault(type);
 | 
			
		||||
          },
 | 
			
		||||
          clear: function clear(type) { data[Permissions.key(type)] = {}; },
 | 
			
		||||
          set: function set(type, url, perm) { getData(type)[new window.URL(url).origin] = perm; },
 | 
			
		||||
          remove: function remove(type, url) { delete getData(type)[new window.URL(url).origin]; },
 | 
			
		||||
          get: function get(type, url) { return getData(type)[new window.URL(url).origin]; },
 | 
			
		||||
          setDefault: function setDefault(type, perm) { data[Permissions.defaultKey(type)] = perm; },
 | 
			
		||||
          default: function _default(type) { return getDefault(type); },
 | 
			
		||||
          entries: function entries(type) { return Object.entries(getData(type)); },
 | 
			
		||||
      });     
 | 
			
		||||
   };
 | 
			
		||||
  
 | 
			
		||||
   key(type) { return Permissions.key(type); };
 | 
			
		||||
   defaultKey(type) { return Permissions.defaultKey(type); };
 | 
			
		||||
  
 | 
			
		||||
   static key(type) { return `perms:${type}`; };
 | 
			
		||||
   static defaultKey(type) { return `perms:${type}Default`; };  
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Object.assign(Permissions.prototype, Permission);
 | 
			
		||||
 | 
			
		||||
//</>
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user