From 16f2defa530b36cae7da5e28b5eafef9138adba5 Mon Sep 17 00:00:00 2001 From: Ruben Rodriguez Date: Wed, 28 Jan 2015 22:16:14 +0100 Subject: Updated to v31.4.0ESR * Search form in about:icecat now searches in default search engine * Disabled accessibility.blockautorefresh * Replaced references to Open Source with Free Software where applicable * Added html5-video-everywhere v0.1.1 extension: https://github.com/lejenome/html5-video-everywhere * Updated LibreJS to 6.0.8 Build scripts updated to use pbuilder --- .../bootstrap.js | 350 +++++++++++++++++++++ .../defaults/preferences/prefs.js | 7 + .../harness-options.json | 222 +++++++++++++ .../html5-video-everywhere@lejenome.me/install.rdf | 28 ++ .../locales.json | 1 + .../html5-video-everywhere@lejenome.me/options.xul | 42 +++ .../resources/html5-video-everywhere/data/break.js | 49 +++ .../html5-video-everywhere/data/common.js | 123 ++++++++ .../html5-video-everywhere/data/dailymotion.js | 42 +++ .../html5-video-everywhere/data/facebook.js | 31 ++ .../html5-video-everywhere/data/metacafe.js | 57 ++++ .../resources/html5-video-everywhere/data/vimeo.js | 98 ++++++ .../html5-video-everywhere/data/youtube-formats.js | 33 ++ .../html5-video-everywhere/data/youtube.js | 200 ++++++++++++ .../resources/html5-video-everywhere/lib/break.js | 10 + .../html5-video-everywhere/lib/dailymotion.js | 10 + .../html5-video-everywhere/lib/facebook.js | 8 + .../resources/html5-video-everywhere/lib/main.js | 96 ++++++ .../html5-video-everywhere/lib/metacafe.js | 12 + .../resources/html5-video-everywhere/lib/vimeo.js | 12 + .../html5-video-everywhere/lib/youtube.js | 21 ++ 21 files changed, 1452 insertions(+) create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/bootstrap.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/defaults/preferences/prefs.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/harness-options.json create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/install.rdf create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/locales.json create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/options.xul create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/break.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/common.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/dailymotion.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/facebook.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/metacafe.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/vimeo.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube-formats.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/break.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/dailymotion.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/facebook.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/main.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/metacafe.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/vimeo.js create mode 100644 data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/youtube.js (limited to 'data/extensions/html5-video-everywhere@lejenome.me') diff --git a/data/extensions/html5-video-everywhere@lejenome.me/bootstrap.js b/data/extensions/html5-video-everywhere@lejenome.me/bootstrap.js new file mode 100644 index 0000000..840103a --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/bootstrap.js @@ -0,0 +1,350 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// @see http://mxr.mozilla.org/mozilla-central/source/js/src/xpconnect/loader/mozJSComponentLoader.cpp + +'use strict'; + +// IMPORTANT: Avoid adding any initialization tasks here, if you need to do +// something before add-on is loaded consider addon/runner module instead! + +const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu, + results: Cr, manager: Cm } = Components; +const ioService = Cc['@mozilla.org/network/io-service;1']. + getService(Ci.nsIIOService); +const resourceHandler = ioService.getProtocolHandler('resource'). + QueryInterface(Ci.nsIResProtocolHandler); +const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(); +const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1']. + getService(Ci.mozIJSSubScriptLoader); +const prefService = Cc['@mozilla.org/preferences-service;1']. + getService(Ci.nsIPrefService). + QueryInterface(Ci.nsIPrefBranch); +const appInfo = Cc["@mozilla.org/xre/app-info;1"]. + getService(Ci.nsIXULAppInfo); +const vc = Cc["@mozilla.org/xpcom/version-comparator;1"]. + getService(Ci.nsIVersionComparator); + + +const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable', + 'install', 'uninstall', 'upgrade', 'downgrade' ]; + +const bind = Function.call.bind(Function.bind); + +let loader = null; +let unload = null; +let cuddlefishSandbox = null; +let nukeTimer = null; + +let resourceDomains = []; +function setResourceSubstitution(domain, uri) { + resourceDomains.push(domain); + resourceHandler.setSubstitution(domain, uri); +} + +// Utility function that synchronously reads local resource from the given +// `uri` and returns content string. +function readURI(uri) { + let ioservice = Cc['@mozilla.org/network/io-service;1']. + getService(Ci.nsIIOService); + let channel = ioservice.newChannel(uri, 'UTF-8', null); + let stream = channel.open(); + + let cstream = Cc['@mozilla.org/intl/converter-input-stream;1']. + createInstance(Ci.nsIConverterInputStream); + cstream.init(stream, 'UTF-8', 0, 0); + + let str = {}; + let data = ''; + let read = 0; + do { + read = cstream.readString(0xffffffff, str); + data += str.value; + } while (read != 0); + + cstream.close(); + + return data; +} + +// We don't do anything on install & uninstall yet, but in a future +// we should allow add-ons to cleanup after uninstall. +function install(data, reason) {} +function uninstall(data, reason) {} + +function startup(data, reasonCode) { + try { + let reason = REASON[reasonCode]; + // URI for the root of the XPI file. + // 'jar:' URI if the addon is packed, 'file:' URI otherwise. + // (Used by l10n module in order to fetch `locale` folder) + let rootURI = data.resourceURI.spec; + + // TODO: Maybe we should perform read harness-options.json asynchronously, + // since we can't do anything until 'sessionstore-windows-restored' anyway. + let options = JSON.parse(readURI(rootURI + './harness-options.json')); + + let id = options.jetpackID; + let name = options.name; + + // Clean the metadata + options.metadata[name]['permissions'] = options.metadata[name]['permissions'] || {}; + + // freeze the permissionss + Object.freeze(options.metadata[name]['permissions']); + // freeze the metadata + Object.freeze(options.metadata[name]); + + // Register a new resource 'domain' for this addon which is mapping to + // XPI's `resources` folder. + // Generate the domain name by using jetpack ID, which is the extension ID + // by stripping common characters that doesn't work as a domain name: + let uuidRe = + /^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/; + + let domain = id. + toLowerCase(). + replace(/@/g, '-at-'). + replace(/\./g, '-dot-'). + replace(uuidRe, '$1'); + + let prefixURI = 'resource://' + domain + '/'; + let resourcesURI = ioService.newURI(rootURI + '/resources/', null, null); + setResourceSubstitution(domain, resourcesURI); + + // Create path to URLs mapping supported by loader. + let paths = { + // Relative modules resolve to add-on package lib + './': prefixURI + name + '/lib/', + './tests/': prefixURI + name + '/tests/', + '': 'resource://gre/modules/commonjs/' + }; + + // Maps addon lib and tests ressource folders for each package + paths = Object.keys(options.metadata).reduce(function(result, name) { + result[name + '/'] = prefixURI + name + '/lib/' + result[name + '/tests/'] = prefixURI + name + '/tests/' + return result; + }, paths); + + // We need to map tests folder when we run sdk tests whose package name + // is stripped + if (name == 'addon-sdk') + paths['tests/'] = prefixURI + name + '/tests/'; + + let useBundledSDK = options['force-use-bundled-sdk']; + if (!useBundledSDK) { + try { + useBundledSDK = prefService.getBoolPref("extensions.addon-sdk.useBundledSDK"); + } + catch (e) { + // Pref doesn't exist, allow using Firefox shipped SDK + } + } + + // Starting with Firefox 21.0a1, we start using modules shipped into firefox + // Still allow using modules from the xpi if the manifest tell us to do so. + // And only try to look for sdk modules in xpi if the xpi actually ship them + if (options['is-sdk-bundled'] && + (vc.compare(appInfo.version, '21.0a1') < 0 || useBundledSDK)) { + // Maps sdk module folders to their resource folder + paths[''] = prefixURI + 'addon-sdk/lib/'; + // test.js is usually found in root commonjs or SDK_ROOT/lib/ folder, + // so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder + // until we no longer support SDK modules in XPI: + paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js'; + } + + // Retrieve list of module folder overloads based on preferences in order to + // eventually used a local modules instead of files shipped into Firefox. + let branch = prefService.getBranch('extensions.modules.' + id + '.path'); + paths = branch.getChildList('', {}).reduce(function (result, name) { + // Allows overloading of any sub folder by replacing . by / in pref name + let path = name.substr(1).split('.').join('/'); + // Only accept overloading folder by ensuring always ending with `/` + if (path) path += '/'; + let fileURI = branch.getCharPref(name); + + // On mobile, file URI has to end with a `/` otherwise, setSubstitution + // takes the parent folder instead. + if (fileURI[fileURI.length-1] !== '/') + fileURI += '/'; + + // Maps the given file:// URI to a resource:// in order to avoid various + // failure that happens with file:// URI and be close to production env + let resourcesURI = ioService.newURI(fileURI, null, null); + let resName = 'extensions.modules.' + domain + '.commonjs.path' + name; + setResourceSubstitution(resName, resourcesURI); + + result[path] = 'resource://' + resName + '/'; + return result; + }, paths); + + // Make version 2 of the manifest + let manifest = options.manifest; + + // Import `cuddlefish.js` module using a Sandbox and bootstrap loader. + let cuddlefishPath = 'loader/cuddlefish.js'; + let cuddlefishURI = 'resource://gre/modules/commonjs/sdk/' + cuddlefishPath; + if (paths['sdk/']) { // sdk folder has been overloaded + // (from pref, or cuddlefish is still in the xpi) + cuddlefishURI = paths['sdk/'] + cuddlefishPath; + } + else if (paths['']) { // root modules folder has been overloaded + cuddlefishURI = paths[''] + 'sdk/' + cuddlefishPath; + } + + cuddlefishSandbox = loadSandbox(cuddlefishURI); + let cuddlefish = cuddlefishSandbox.exports; + + // Normalize `options.mainPath` so that it looks like one that will come + // in a new version of linker. + let main = options.mainPath; + + unload = cuddlefish.unload; + loader = cuddlefish.Loader({ + paths: paths, + // modules manifest. + manifest: manifest, + + // Add-on ID used by different APIs as a unique identifier. + id: id, + // Add-on name. + name: name, + // Add-on version. + version: options.metadata[name].version, + // Add-on package descriptor. + metadata: options.metadata[name], + // Add-on load reason. + loadReason: reason, + + prefixURI: prefixURI, + // Add-on URI. + rootURI: rootURI, + // options used by system module. + // File to write 'OK' or 'FAIL' (exit code emulation). + resultFile: options.resultFile, + // Arguments passed as --static-args + staticArgs: options.staticArgs, + // Add-on preferences branch name + preferencesBranch: options.preferencesBranch, + + // Arguments related to test runner. + modules: { + '@test/options': { + allTestModules: options.allTestModules, + iterations: options.iterations, + filter: options.filter, + profileMemory: options.profileMemory, + stopOnError: options.stopOnError, + verbose: options.verbose, + parseable: options.parseable, + checkMemory: options.check_memory, + } + } + }); + + let module = cuddlefish.Module('sdk/loader/cuddlefish', cuddlefishURI); + let require = cuddlefish.Require(loader, module); + + require('sdk/addon/runner').startup(reason, { + loader: loader, + main: main, + prefsURI: rootURI + 'defaults/preferences/prefs.js' + }); + } catch (error) { + dump('Bootstrap error: ' + + (error.message ? error.message : String(error)) + '\n' + + (error.stack || error.fileName + ': ' + error.lineNumber) + '\n'); + throw error; + } +}; + +function loadSandbox(uri) { + let proto = { + sandboxPrototype: { + loadSandbox: loadSandbox, + ChromeWorker: ChromeWorker + } + }; + let sandbox = Cu.Sandbox(systemPrincipal, proto); + // Create a fake commonjs environnement just to enable loading loader.js + // correctly + sandbox.exports = {}; + sandbox.module = { uri: uri, exports: sandbox.exports }; + sandbox.require = function (id) { + if (id !== "chrome") + throw new Error("Bootstrap sandbox `require` method isn't implemented."); + + return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm, + CC: bind(CC, Components), components: Components, + ChromeWorker: ChromeWorker }); + }; + scriptLoader.loadSubScript(uri, sandbox, 'UTF-8'); + return sandbox; +} + +function unloadSandbox(sandbox) { + if ("nukeSandbox" in Cu) + Cu.nukeSandbox(sandbox); +} + +function setTimeout(callback, delay) { + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.initWithCallback({ notify: callback }, delay, + Ci.nsITimer.TYPE_ONE_SHOT); + return timer; +} + +function shutdown(data, reasonCode) { + let reason = REASON[reasonCode]; + if (loader) { + unload(loader, reason); + unload = null; + + // Don't waste time cleaning up if the application is shutting down + if (reason != "shutdown") { + // Avoid leaking all modules when something goes wrong with one particular + // module. Do not clean it up immediatly in order to allow executing some + // actions on addon disabling. + // We need to keep a reference to the timer, otherwise it is collected + // and won't ever fire. + nukeTimer = setTimeout(nukeModules, 1000); + + // Bug 944951 - bootstrap.js must remove the added resource: URIs on unload + resourceDomains.forEach(domain => { + resourceHandler.setSubstitution(domain, null); + }) + } + } +}; + +function nukeModules() { + nukeTimer = null; + // module objects store `exports` which comes from sandboxes + // We should avoid keeping link to these object to avoid leaking sandboxes + for (let key in loader.modules) { + delete loader.modules[key]; + } + // Direct links to sandboxes should be removed too + for (let key in loader.sandboxes) { + let sandbox = loader.sandboxes[key]; + delete loader.sandboxes[key]; + // Bug 775067: From FF17 we can kill all CCW from a given sandbox + unloadSandbox(sandbox); + } + loader = null; + + // both `toolkit/loader` and `system/xul-app` are loaded as JSM's via + // `cuddlefish.js`, and needs to be unloaded to avoid memory leaks, when + // the addon is unload. + + unloadSandbox(cuddlefishSandbox.loaderSandbox); + unloadSandbox(cuddlefishSandbox.xulappSandbox); + + // Bug 764840: We need to unload cuddlefish otherwise it will stay alive + // and keep a reference to this compartment. + unloadSandbox(cuddlefishSandbox); + cuddlefishSandbox = null; +} diff --git a/data/extensions/html5-video-everywhere@lejenome.me/defaults/preferences/prefs.js b/data/extensions/html5-video-everywhere@lejenome.me/defaults/preferences/prefs.js new file mode 100644 index 0000000..e3d6b4d --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/defaults/preferences/prefs.js @@ -0,0 +1,7 @@ +pref("extensions.html5-video-everywhere@lejenome.me.prefCdc", 0); +pref("extensions.html5-video-everywhere@lejenome.me.prefQlt", 2); +pref("extensions.html5-video-everywhere@lejenome.me.autoplay", 2); +pref("extensions.html5-video-everywhere@lejenome.me.preload", 2); +pref("extensions.html5-video-everywhere@lejenome.me.volume", 100); +pref("extensions.html5-video-everywhere@lejenome.me.disableEmbed", false); +pref("extensions.html5-video-everywhere@lejenome.me.dontPlayNext", false); diff --git a/data/extensions/html5-video-everywhere@lejenome.me/harness-options.json b/data/extensions/html5-video-everywhere@lejenome.me/harness-options.json new file mode 100644 index 0000000..fc1992b --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/harness-options.json @@ -0,0 +1,222 @@ +{ + "abort_on_missing": false, + "check_memory": false, + "enable_e10s": false, + "is-sdk-bundled": false, + "jetpackID": "html5-video-everywhere@lejenome.me", + "loader": "addon-sdk/lib/sdk/loader/cuddlefish.js", + "main": "main", + "mainPath": "html5-video-everywhere/main", + "manifest": { + "html5-video-everywhere/break": { + "docsSHA256": null, + "jsSHA256": "44287333a482842991e2acfd6d4446f1f31c8759349eca1ca94d5a21a570f2e1", + "moduleName": "break.js", + "packageName": "html5-video-everywhere", + "requirements": {}, + "sectionName": "lib" + }, + "html5-video-everywhere/dailymotion": { + "docsSHA256": null, + "jsSHA256": "e4107011ad40fcd3741b7d4bf3216aa80126490889ca70264eb7a8a93405e72b", + "moduleName": "dailymotion.js", + "packageName": "html5-video-everywhere", + "requirements": {}, + "sectionName": "lib" + }, + "html5-video-everywhere/facebook": { + "docsSHA256": null, + "jsSHA256": "ed4075b7c113a2c869cc7aff028973a4e8f3779361d2d1b3a8468d4ec1cdd6f1", + "moduleName": "facebook.js", + "packageName": "html5-video-everywhere", + "requirements": {}, + "sectionName": "lib" + }, + "html5-video-everywhere/main": { + "docsSHA256": "2600330609036287c5d48070ba591543183b0f1619d06d2c61f016088f81d2ec", + "jsSHA256": "9b53c709d2869db49baadc00c3a5cb6bef31ccccd9595be4e851a513b5de34e7", + "moduleName": "main", + "packageName": "html5-video-everywhere", + "requirements": { + "./break.js": "html5-video-everywhere/break", + "./dailymotion.js": "html5-video-everywhere/dailymotion", + "./facebook.js": "html5-video-everywhere/facebook", + "./metacafe.js": "html5-video-everywhere/metacafe", + "./vimeo.js": "html5-video-everywhere/vimeo", + "./youtube.js": "html5-video-everywhere/youtube", + "chrome": "chrome", + "sdk/page-mod": "sdk/page-mod", + "sdk/self": "sdk/self", + "sdk/simple-prefs": "sdk/simple-prefs", + "sdk/system/events": "sdk/system/events", + "sdk/util/array": "sdk/util/array", + "sdk/window/utils": "sdk/window/utils" + }, + "sectionName": "lib" + }, + "html5-video-everywhere/metacafe": { + "docsSHA256": null, + "jsSHA256": "3c14cc0f0915d2f5966f6592c7ece0afc1229f783b8ae78a14acf2ea8408fcb8", + "moduleName": "metacafe.js", + "packageName": "html5-video-everywhere", + "requirements": {}, + "sectionName": "lib" + }, + "html5-video-everywhere/vimeo": { + "docsSHA256": null, + "jsSHA256": "f44444a72857e73b2b1cad2526aad121e5b96da6f6e201760e6cb6f7d19efa59", + "moduleName": "vimeo.js", + "packageName": "html5-video-everywhere", + "requirements": {}, + "sectionName": "lib" + }, + "html5-video-everywhere/youtube": { + "docsSHA256": null, + "jsSHA256": "e0446c651e43306ffe9872354463bcbc0380f050088c1ba19ea85bfbb36ba625", + "moduleName": "youtube.js", + "packageName": "html5-video-everywhere", + "requirements": {}, + "sectionName": "lib" + } + }, + "metadata": { + "addon-sdk": { + "description": "Add-on development made easy.", + "keywords": [ + "javascript", + "engine", + "addon", + "extension", + "xulrunner", + "firefox", + "browser" + ], + "license": "MPL 2.0", + "name": "addon-sdk" + }, + "html5-video-everywhere": { + "author": "Moez Bouhlel (http://lejenome.github.io/", + "description": "Replace video player with Firefox native video player", + "homepage": "https://github.com/lejenome/html5-video-everywhere", + "license": "MPL 2.0", + "main": "main", + "name": "html5-video-everywhere", + "permissions": { + "private-browsing": true + }, + "version": "0.1.1" + } + }, + "name": "html5-video-everywhere", + "parseable": false, + "preferences": [ + { + "name": "prefCdc", + "options": [ + { + "label": "WebM", + "value": "0" + }, + { + "label": "Mp4", + "value": "1" + } + ], + "title": "Preferred Codec", + "type": "menulist", + "value": 0 + }, + { + "name": "prefQlt", + "options": [ + { + "label": "Higher", + "value": "0" + }, + { + "label": "High", + "value": "1" + }, + { + "label": "Medium", + "value": "2" + }, + { + "label": "Low", + "value": "3" + } + ], + "title": "Preferred Quality", + "type": "menulist", + "value": 2 + }, + { + "description": "Change default behaviour of the video player of the website", + "name": "autoplay", + "options": [ + { + "label": "Default", + "value": "2" + }, + { + "label": "Enabled", + "value": "1" + }, + { + "label": "Disabled", + "value": "0" + } + ], + "title": "Auto Play Video", + "type": "menulist", + "value": 2 + }, + { + "description": "Change default behaviour of the video player of the website in case it does not auto play the video", + "name": "preload", + "options": [ + { + "label": "Default", + "value": "2" + }, + { + "label": "Enabled", + "value": "1" + }, + { + "label": "Disabled", + "value": "0" + } + ], + "title": "Preload Video", + "type": "menulist", + "value": 2 + }, + { + "name": "volume", + "title": "Volume", + "type": "integer", + "value": 100 + }, + { + "description": "Use default youtube video player for embed videos", + "hidden": true, + "name": "disableEmbed", + "title": "Disable for Embed Youtube", + "type": "bool", + "value": false + }, + { + "description": "Do not tell youtube that video reached the end, so it will no play the next Video on playlist mode", + "hidden": true, + "name": "dontPlayNext", + "title": "Do not play next Item", + "type": "bool", + "value": false + } + ], + "preferencesBranch": "html5-video-everywhere@lejenome.me", + "sdkVersion": "1.17", + "staticArgs": {}, + "verbose": false +} \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/install.rdf b/data/extensions/html5-video-everywhere@lejenome.me/install.rdf new file mode 100644 index 0000000..24db335 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/install.rdf @@ -0,0 +1,28 @@ + + + html5-video-everywhere@lejenome.me + 0.1.1 + 2 + true + false + + + + + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} + 26.0 + 30.0 + + + + + HTML5 Video Everywhere! + Replace video player with Firefox native video player + Moez Bouhlel <bmoez.j@gmail.com> (http://lejenome.github.io/ + https://github.com/lejenome/html5-video-everywhere + 2 + + + \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/locales.json b/data/extensions/html5-video-everywhere@lejenome.me/locales.json new file mode 100644 index 0000000..303e186 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/locales.json @@ -0,0 +1 @@ +{"locales": []} diff --git a/data/extensions/html5-video-everywhere@lejenome.me/options.xul b/data/extensions/html5-video-everywhere@lejenome.me/options.xul new file mode 100644 index 0000000..e6a70e2 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/options.xul @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + Change default behaviour of the video player of the website + + + + + + + + + + Change default behaviour of the video player of the website in case it does not auto play the video + + + + + + + + + + diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/break.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/break.js new file mode 100644 index 0000000..207dc00 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/break.js @@ -0,0 +1,49 @@ +(function() { + "use strict"; + + onReady(() => { + var url_r = /"uri":\s*"([^"]*)"/; + var width_r = /"width":\s*([^\s,]*),/; + var height_r = /"height":\s*([^\s,]*),/; + var fmts = {}; + var data = document.head.innerHTML.match(/"media": \[\s[^\]]*\s\],/); + if (!data) + return; + data = data[0].match(/\{[^}]*\}/g); + data.forEach(it => + fmts[it.match(width_r)[1] + "x" + it.match(height_r)[1]] = it.match(url_r)[1] + ); + var url = getPreferredFmt(fmts, { + "higher/mp4": "1280x720", + "high/mp4": "848x480", + "medium/mp4": "640x360", + "low/mp4": "301x232" // there is 300x220 too which is audio only + }); + if (url === undefined && !(url = fallback())) + return; + injectPlayer(url); + }); + + function injectPlayer(url) { + var player = createNode("video", { + controls: true, + autoplay: autoPlay(true), + preload: preLoad(), + src: url + }, { + width: "100%", + heigth: "100%" + }); + + document.body.innerHTML = ""; + document.head.innerHTML = ""; + document.body.appendChild(player); + } + + function fallback() { + // Just fallback method if the first one didn't work + var url_r = /"videoUri":\s*"([^"]*)"/; + var url = (document.head.innerHTML.match(url_r) || ["", ""])[1]; + return url; + } +}()); \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/common.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/common.js new file mode 100644 index 0000000..637cc00 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/common.js @@ -0,0 +1,123 @@ +/* global OPTIONS:true, onPrefChange:true, getPreferredFmt:true */ +/* global createNode:true, asyncGet:true, onReady:true, onInit:true, logify:true */ +/* global preLoad:true, autoPlay:true, HANDLE_VOL_PREF_CHANGE:true */ +// the following jshint global rule is only because jshint support for ES6 arrow +// functions is limited +/* global wrapper:true, args:true, auto:true */ +"use strict"; + +//This Addons Preferences +var OPTIONS = {}; +// push your prefernces change listner function to this table, yah the old way +const onPrefChange = []; +const Qlt = [ + "higher", + "high", + "medium", + "low" +]; +// set it to false if the module uses custom listener +var HANDLE_VOL_PREF_CHANGE = true; +const Cdc = ["webm", "mp4"]; +self.port.on("preferences", function(prefs) { + OPTIONS = prefs; + onPrefChange.forEach(f => f()); +}); + +self.port.on("prefChanged", function(pref) { + OPTIONS[pref.name] = pref.value; + if (pref.name === "volume" && HANDLE_VOL_PREF_CHANGE === true) + Array.forEach(document.getElementsByTagName("video"), el => { + el.volume = OPTIONS.volume / 100; + }); + onPrefChange.forEach(f => f(pref.name)); +}); + +const getPreferredFmt = (fmts, wrapper = {}) => { + // for example of the optional wrapper, see data/youtube-formats.js + var i, j, slct; + var _cdc = [ + Cdc[OPTIONS.prefCdc], + Cdc[(OPTIONS.prefCdc + 1 % 2)] + ]; + i = OPTIONS.prefQlt; + while (i > -1) { + for (j = 0; j < 2; j++) { + slct = Qlt[i] + "/" + _cdc[j]; + slct = wrapper[slct] || slct; + if (fmts[slct]) + return fmts[slct]; + } + i = (i >= OPTIONS.prefQlt) ? i + 1 : i - 1; + if (i > 3) + i = OPTIONS.prefQlt - 1; + } + logify("Error on getPreferredFmt", fmts, wrapper); +}; + +const createNode = (type, prprt, style, data) => { + logify("createNode", type, prprt); + var node = document.createElement(type); + if (prprt) + Object.keys(prprt).forEach(p => node[p] = prprt[p]); + if (style) + Object.keys(style).forEach(s => node.style[s] = style[s]); + if (data) + Object.keys(data).forEach(d => node.dataset[d] = data[d]); + return node; +}; + +const asyncGet = (url, headers, mimetype) => { + logify("asyncGet", url); + return new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + if (headers) + Object.keys(headers).forEach(h => xhr.setRequestHeader(h, headers[h])); + if (mimetype && xhr.overrideMimeType) + xhr.overrideMimeType(mimetype); + xhr.onload = function() { + if (this.status !== 200) { + reject(this.status); + logify("Error on asyncGet", url, headers, this.status); + return; + } + resolve(this.responseText); + }; + xhr.onerror = function() { + reject(); + }; + xhr.send(); + }); +}; + +const logify = (...args) => + console.log.apply(console, args.map(s => JSON.stringify(s, null, 2))); + +const onReady = f => { + //TODO: document readyState is "loading" (and DOMECotentLoaded) even DOM elements are + //accessible + try { + if (document.readyState !== "loading") { + f(); + } else { + document.addEventListener("DOMContentLoaded", f); + } + } catch (e) { + console.error("Exception", e.lineNumber, e.columnNumber, e.message, e.stack); + } +}; + +const onInit = f => { + // code running on when="ready" mode or does not need until onReady + // execc but depend on preferences, need to wrapped to this funct. + // need + document.onafterscriptexecute = function() { + document.onafterscriptexecute = undefined; + f(); + }; +}; +const autoPlay = (auto = false) => ((OPTIONS.autoplay === 1 || auto === true) && + OPTIONS.autoplay !== 0); +const preLoad = (auto = false) => ((OPTIONS.preload === 1 || auto === true) && + OPTIONS.preload !== 0) ? "auto" : "metadata"; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/dailymotion.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/dailymotion.js new file mode 100644 index 0000000..7732ec4 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/dailymotion.js @@ -0,0 +1,42 @@ +(function() { + "use strict"; + + onReady(() => { + + // VIDEO_ID = location.pathname.match(/\/embed\/video\/([^_]+)/)[1]; + // asyncGet http://www.dailymotion.com/json/video/?fields=stream_audio_url,stream_h264_hd1080_url,stream_h264_hd_url,stream_h264_hq_url,stream_h264_ld_url,stream_h264_url,stream_hls_url,stream_live_hls_url,thumbnail_120_url,thumbnail_240_url,thumbnail_url + // returns a json + var streams_r = /"stream_h264[^"]*_url":"[^"]*"/g; + var url_r = /"(stream_h264[^"]*_url)":"([^"]*)"/; + var streams = document.body.innerHTML.match(streams_r); + var url, urls = {}; + streams.forEach(u => { + var r = u.match(url_r); + urls[r[1]] = r[2].replace("\\/", "/", "g"); + }); + var types = []; + url = getPreferredFmt(urls, { + // stream_h264_hd1080_url + "higher/mp4": "stream_h264_hd_url", // H264 1280x720 + "high/mp4": "stream_h264_hq_url", // H264 848x480 + "medium/mp4": "stream_h264_url", // H264 512x384 + "low/mp4": "stream_h264_ld_url" // H264 320x240 + }); + if (url === undefined) + return; + var poster = (document.body.innerHTML.match(/"thumbnail_url":"([^"]*)"/) || ["", ""])[1].replace("\\/", "/", "g"); + var player = createNode("video", { + controls: true, + autoplay: autoPlay(), + preload: preLoad(), + poster: poster, + src: url + }, { + width: "100%", + heigth: "100%" + }); + + document.body.innerHTML = ""; + document.body.appendChild(player); + }); +}()); \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/facebook.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/facebook.js new file mode 100644 index 0000000..136b1b9 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/facebook.js @@ -0,0 +1,31 @@ +(function() { + "use strict"; + // Facebook module is injected when page is "ready", so onReady() will exec + // the code directly, even before addon preferences are fetched. Because + // they are needed by the following code, we use onInit() instead of + // onReady() so our code get Executed after the prefernces get fetched. + // Waw! seems the longest code documentation I ever wrote o.0 + onInit(() => { + var params = document.body.innerHTML.match(/\"params\",(\"[^\"]*\")/)[1]; + params = JSON.parse(decodeURIComponent(JSON.parse(params))); + var url = getPreferredFmt({ + "medium/mp4": params.video_data[0].sd_src, + "high/mp4": params.video_data[0].hd_src + }); + if (url === undefined) + return; + var player = createNode("video", { + // preload: true, + controls: true, + autoplay: autoPlay(true), + preload: preLoad(), + src: url + }, { + width: "100%", + heigth: "100%" + }); + + document.getElementsByClassName("_53j5")[0].innerHTML = ""; + document.getElementsByClassName("_53j5")[0].appendChild(player); + }); +}()); \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/metacafe.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/metacafe.js new file mode 100644 index 0000000..022d811 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/metacafe.js @@ -0,0 +1,57 @@ +(function() { + "use strict"; + + onReady(() => { + if (/watch\/\d+\/.*/.test(location.pathname)) + watchPage(); + else if (/[^\/]+\/?$/.test(location.pathname)) + channelPage(); + }); + + function watchPage() { + var ob = document.getElementById("flashVars"); + if (!ob) + return; + var url = getURL(ob.value); + var player = createNode("video", { + autoplay: autoPlay(true), + preload: preLoad(), + controls: true, + src: url + }); + + var container = document.getElementById("ItemContainer"); + if (!container) + return; + container.innerHTML = ""; + container.appendChild(player); + } + + function channelPage() { + var embed = document.getElementsByTagName("embed"); + if (!embed) + return; + embed = embed[0]; + var page = embed.src; + page = page.replace("/fplayer/", "/watch/").replace(/.swf$/, ""); + asyncGet(page).then((data) => { + var url = getURL(data); + var player = createNode("video", { + autoplay: autoPlay(false), + preload: preLoad(), + controls: true, + src: url + }); + var container = embed.parentElement; + container.innerHTML = ""; + container.appendChild(player); + + }); + } + + function getURL(e) { + var data = decodeURIComponent(e.match(/&mediaData=([^&]*)&/)[1]); + return JSON.parse(data).MP4.mediaURL; + } + +}()); \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/vimeo.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/vimeo.js new file mode 100644 index 0000000..b3d3e43 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/vimeo.js @@ -0,0 +1,98 @@ +(function() { + "use strict"; + + onReady(() => + getConfig().then(getVideoInfo) + ); + + function injectPlayer(conf) { + try { + let player_container, player; + if (conf.isEmbed) { + player_container = document.body; + player_container.innerHTML = ""; + } else if (conf.isWatch) { + player_container = document.getElementById("video"); + player_container.children[1].remove(); + } else { + player_container = document.getElementById("clip_" + conf.id); + player_container.innerHTML = ""; + } + if (!player_container) + return; + player = createNode("video", { + className: conf.className, + autoplay: autoPlay(), + preload: preLoad(), + controls: true, + poster: conf.poster, + volume: OPTIONS.volume / 100 + }); + player.appendChild(createNode("source", { + src: conf.url + })); + player_container.appendChild(player); + } catch (e) { + console.error("Exception on changePlayer()", e.lineNumber, e.columnNumber, e.message, e.stack); + } + } + + function getConfig() { + return new Promise((resolve, reject) => { + var isWatch = /https?:\/\/vimeo.com\/[\d]+/.test(location.href); + var isEmbed = /https?:\/\/player.vimeo.com\/video/.test(location.href); + var isChannel = /https?:\/\/vimeo.com\/(channels\/|)\w+/.test(location.href); + if (!isWatch && !isChannel && !isEmbed) + reject(); + var player_id, player_class; + if (isWatch) { + player_id = location.pathname.match(/^\/([\d]+)/)[1]; + player_class = "player"; + } else if (isEmbed) { + player_id = location.pathname.match(/video\/([\d]+)/)[1]; + player_class = "fallback"; + } else if (isChannel) { + player_class = "player"; + } + if (!player_id && !isChannel) + reject(); + resolve({ + isWatch: isWatch, + isEmbed: isEmbed, + isChannel: isChannel, + id: player_id, + className: player_class + }); + }); + } + + function getVideoInfo(conf) { + const processData = (conf) => (data) => { + data = JSON.parse(data); + var fmt = getPreferredFmt(data.request.files.h264, { + "high/mp4": "hd", + "medium/mp4": "sd", + "low/mp4": "mobile" + }); + if (fmt === undefined) + return Promise.reject(); + conf.poster = data.video.thumbs.base; + conf.url = fmt.url; + return Promise.resolve(conf); + }; + const INFO_URL = "https://player.vimeo.com/video/"; + if (conf.isChannel) { + return Array.map(document.getElementsByClassName("player_container"), (el) => { + var _conf = {}; + for (var va in conf) + _conf[va] = conf[va]; + _conf.id = el.id.replace("clip_", ""); + return asyncGet(INFO_URL + _conf.id + "/config").then(processData(_conf)) + .then(injectPlayer); + }); + } else { + return asyncGet(INFO_URL + conf.id + "/config").then(processData(conf)) + .then(injectPlayer); + } + } +}()); \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube-formats.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube-formats.js new file mode 100644 index 0000000..e23cf83 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube-formats.js @@ -0,0 +1,33 @@ +// wrap getPreferedFmt selector to YT itag eq, as we the passed fmts object +// later has itags as keys not getPreferredFmt known keys +var FMT_WRAPPER = { + "high/mp4": "22", + "medium/mp4": "18", + "medium/webm": "43" +}; +/* ++----+-----------+------------+---------+------------------------------------------- +|FMT | container | resolution | profile | type ++----+-----------+------------+---------+------------------------------------------- +| 18 | mp4 | 360p | normal | "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"" +| 22 | mp4 | 720p | normal | "video/mp4; codecs=\"avc1.64001F, mp4a.40.2\"" +| 43 | webm | 360p | normal | "video/webm; codecs=\"vp8.0, vorbis\"" ++----+-----------+------------+---------+------------------------------------------ +| 82 | mp4 | 360p | 3D | +| 83 | mp4 | 240p | 3D | +| 84 | mp4 | 720p | 3D | +| 85 | mp4 | 1080p | 3D | +|100 | webm | 360p | 3D | +|101 | webm | 360p | 3D | +|102 | webm | 700p | 3D | +|133 | mp4 | 240p | DASH V | +|134 | mp4 | 360p | DASH V | +|135 | mp4 | 480p | DASH V | +|136 | mp4 | 720p | DASH V | +|137 | mp4 | 1080p | DASH V | +|160 | mp4 | 144p | DASH V | +|264 | mp4 | 1440p | DASH V | +|. | . | . | . | ++----+-----------+------------+---------+---------------------------------------- +MORE FROM: http://en.wikipedia.org/wiki/YouTube +*/ \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube.js new file mode 100644 index 0000000..431ad9d --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/data/youtube.js @@ -0,0 +1,200 @@ +/*globals FMT_WRAPPER*/ +(function() { + "use strict"; + var player, player_container; + + onReady(() => { + player = createNode("video"); + changePlayer(); + window.addEventListener("spfrequest", function() { + if (player) + player.src = ""; + }); + window.addEventListener("spfdone", function() { + changePlayer(); + }); + }); + + function changePlayer() { + getConfig() + .then(getVideoInfo) + .then((conf) => { + try { + if (player_container) + player_container.innerHTML = ""; + player_container = getPlayerContainer(conf); + if (!player_container) + return; + player_container.innerHTML = ""; + player_container.className = conf.className || ""; + player = createNode("video", { + id: "video_player", + className: conf.className || "", + autoplay: autoPlay(!conf.isEmbed), + preload: preLoad(), + controls: true, + poster: conf.poster || "", + volume: OPTIONS.volume / 100 + }, { + position: "relative" + }); + player.appendChild(createNode("source", { + src: conf.url, + type: conf.type + })); + player_container.appendChild(player); + } catch (e) { + console.error("Exception on changePlayer()", e.lineNumber, e.columnNumber, e.message, e.stack); + } + }) + .catch((rej) => { + if (rej === undefined) + return; + switch (rej.error) { + case "VIDEO_URL_UNACCESSIBLE": + var error = rej.data.match(/reason=([^&]*)&/); + if (error) + errorMessage("Failed to load video url with the following error message: " + + error[1].replace("+", " ", "g")); + break; + case "NO_SUPPORTED_VIDEO_FOUND": + errorMessage("Failed to find any playable video url." + + (rej.unsig ? " All urls are not signed" : ""), rej.conf); + break; + } + }); + } + + function errorMessage(msg, conf) { + logify("errorMessage", msg, conf); + var error_container; + if (conf) + error_container = getPlayerContainer(conf); + if (!error_container) + error_container = document.getElementById("player-unavailable") || document.getElementById("player"); + if (!error_container) + return; + if (conf && conf.isWatch) + error_container.className += " player-height player-width"; + if (conf && conf.isChannel) + error_container.className += " html5-main-video"; + if (conf && conf.isEmbed) { + error_container.className += " full-frame"; + } + error_container.style.background = "linear-gradient(to bottom, #383838 0px, #131313 100%) repeat scroll 0% 0% #262626"; + error_container.innerHTML = ""; + error_container.appendChild(createNode("p", { + textContent: "Ooops! :(" + }, { + padding: "15px", + fontSize: "20px" + })); + error_container.appendChild(createNode("p", { + textContent: msg + }, { + fontSize: "20px" + })); + } + + function getPlayerContainer(conf) { + if (conf.isWatch) + return document.getElementById("player-mole-container"); + if (conf.isEmbed) + return document.body; + if (conf.isChannel) + return document.getElementsByClassName("c4-player-container")[0]; + } + + function getConfig() { + return new Promise((resolve, reject) => { + var isEmbed = location.href.search("youtube.com/embed/") > -1; + var isWatch = location.href.search("youtube.com/watch?") > -1; + var isChannel = location.href.search("youtube.com/channel/") > -1 || location.href.search("youtube.com/user/") > -1; + if (!isEmbed && !isWatch && !isChannel) + reject(); + var player_id, player_class; + if (isEmbed) { + player_id = location.pathname.match(/^\/embed\/([^?#/]*)/)[1]; + player_class = "full-frame"; + } else if (isChannel) { + var upsell = document.getElementById("upsell-video"); + if (!upsell) + reject(); + player_id = upsell.dataset["videoId"]; + player_class = "html5-main-video"; + } else { + player_id = location.search.slice(1).match(/v=([^/?#]*)/)[1]; + player_class = "player-width player-height"; + } + if (!player_id) + reject({ + error: "PLAYER_ID_NOT_FOUND" + }); + resolve({ + isEmbed: isEmbed, + isWatch: isWatch, + isChannel: isChannel, + id: player_id, + className: player_class + }); + }); + } + + function getVideoInfo(conf) { + var INFO_URL = "https://www.youtube.com/get_video_info?html5=1&hl=en_US&el=detailpage&video_id="; + return asyncGet(INFO_URL + conf.id, {}, "text/plain").then((data) => { + if (data.endsWith("=")) + try { + data = atob(data); + } catch (_) {} + if (/status=fail/.test(data)) { + return Promise.reject({ + error: "VIDEO_URL_UNACCESSIBLE", + data: data + }); + } + // get the poster url + var poster = data.match(/iurlhq=([^&]*)/); + if (poster) + conf.poster = decodeURIComponent(poster[1]); + // extract avalable formats to fmts object + var info = data.match(/url_encoded_fmt_stream_map=([^&]*)/)[1]; + info = decodeURIComponent(info); + var fmt, fmts = {}, + unsignedVideos; + info.split(",") + .map(it1 => { + var oo = {}; + it1.split("&") + .map(it2 => it2.split("=")) + .map(it3 => [it3[0], decodeURIComponent(it3[1])]) + .forEach(it4 => oo[it4[0]] = it4[1]); + return oo; + }) + .filter(it5 => (player.canPlayType( + (it5.type = it5.type.replace("+", " ", "g")) + ) === "probably")) + .filter(it6 => { + if (it6.url.search("signature=") > 0) + return true; + unsignedVideos = true; + logify("Url without signature!!", it6.itag); + return false; + }) + .forEach(fmt => fmts[fmt.itag] = fmt); + // choose best format from fmts onject + fmt = getPreferredFmt(fmts, FMT_WRAPPER); + if (fmt === undefined) { + return Promise.reject({ + error: "NO_SUPPORTED_VIDEO_FOUND", + unsig: unsignedVideos, + conf: conf + }); + } else { + conf.url = fmt.url; + conf.type = fmt.type; + return Promise.resolve(conf); + } + }); + } +}()); \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/break.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/break.js new file mode 100644 index 0000000..79f1a8b --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/break.js @@ -0,0 +1,10 @@ +"use strict"; +var match = [/https?:\/\/www.break.com\/embed\/.*/]; +var inject = [ + "common.js", + "break.js" +]; +var when = "start"; +exports.when = when; +exports.match = match; +exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/dailymotion.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/dailymotion.js new file mode 100644 index 0000000..e2c5761 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/dailymotion.js @@ -0,0 +1,10 @@ +"use strict"; +var match = [/https?:\/\/(www.)dailymotion.com\/embed\/video\/.*/]; +var inject = [ + "common.js", + "dailymotion.js" +]; +var when = "start"; +exports.when = when; +exports.match = match; +exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/facebook.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/facebook.js new file mode 100644 index 0000000..a229268 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/facebook.js @@ -0,0 +1,8 @@ +"use strict"; +var match = [/https?:\/\/(www\.|beta\.)?facebook.com\/video.php\?.*/]; +var inject = [ + "common.js", + "facebook.js" +]; +exports.match = match; +exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/main.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/main.js new file mode 100644 index 0000000..8240ede --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/main.js @@ -0,0 +1,96 @@ +/* jshint esnext:true, node:true*/ +"use strict"; +const { + Cc, Ci, Cr +} = require("chrome"); +const { + add, remove +} = require("sdk/util/array"); +const data = require("sdk/self").data; +const pageMod = require("sdk/page-mod"); +const events = require("sdk/system/events"); +const utils = require("sdk/window/utils"); +var prefs = require("sdk/simple-prefs").prefs; +// list of current workers +const workers = []; +const drivers = [ + require("./youtube.js"), + require("./vimeo.js"), + require("./dailymotion.js"), + require("./break.js"), + require("./metacafe.js"), + require("./facebook.js") +]; + +for (let driver of drivers) { + if (driver.match === void(0)) + continue; + pageMod.PageMod({ + include: driver.match, + contentScriptFile: driver.inject.map(i => data.url(i)), + contentScriptWhen: driver.when || "ready", + onAttach: onWorkerAttach + }); +} + +function listener(event) { + var channel = event.subject.QueryInterface(Ci.nsIHttpChannel); + var url = event.subject.URI.spec; + for (let driver of drivers) { + for (let redirect of(driver.redirect || [])) { + if (redirect.src.test(url)) { + channel.redirectTo(Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService).newURI( + String.replace(url, redirect.src, redirect.funct), + null, + null)); + console.log("Redirect:", url); + return; + } + } + for (let block of(driver.block || [])) { + if (block.test(url)) { + channel.cancel(Cr.NS_BINDING_ABORTED); + console.log("Block:", url); + return; + } + } + } +} + +//on Addon prefernces change, send the changes to content-script +require("sdk/simple-prefs").on("", function prefChangeHandler(pref) { + if (pref === "volume" && prefs.volume > 100) + prefs.volume = 100; + else if (pref === "volume" && prefs.volume < 0) + prefs.volume = 0; + else + workersPrefHandler(pref); +}); + +function workersPrefHandler(pref) { + for (let worker of workers) + worker.port.emit("prefChanged", { + name: pref, + value: prefs[pref] + }); +} + +function onWorkerAttach(worker) { + console.log("onAttach", worker); + //send current Addon preferences to content-script + let _prefs = {}; + for (let pref in prefs) + _prefs[pref] = prefs[pref]; + worker.port.emit("preferences", _prefs); + add(workers, worker); + worker.on("detach", function(e) { + remove(workers, this); + + }); +} +exports.main = function() { + events.on("http-on-modify-request", listener); +}; +exports.onUnload = function(reason) { + events.off("http-on-modify-request", listener); +}; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/metacafe.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/metacafe.js new file mode 100644 index 0000000..ca6d179 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/metacafe.js @@ -0,0 +1,12 @@ +"use strict"; +var match = [/https?:\/\/www.metacafe.com\/watch\/.*/, + /https?:\/\/www.metacafe.com\/[^\/]+\/?/ +]; +var inject = [ + "common.js", + "metacafe.js" +]; +var when = "start"; +exports.when = when; +exports.match = match; +exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/vimeo.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/vimeo.js new file mode 100644 index 0000000..1475d1d --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/vimeo.js @@ -0,0 +1,12 @@ +"use strict"; +var when = "start"; +var match = [/https?:\/\/vimeo.com\/.+/, + /https?:\/\/player.vimeo.com\/video.*/ +]; +var inject = [ + "common.js", + "vimeo.js" +]; +exports.when = when; +exports.match = match; +exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/youtube.js b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/youtube.js new file mode 100644 index 0000000..e054233 --- /dev/null +++ b/data/extensions/html5-video-everywhere@lejenome.me/resources/html5-video-everywhere/lib/youtube.js @@ -0,0 +1,21 @@ +"use strict"; +var YOUTUBE_FLASH_REGEX = /https?:\/\/(www.)?youtube.com\/v\/([^#?\/]*)/; +var YT_BIN_REGEX = /https:\/\/s.ytimg.com\/yts\/jsbin\/[^\/]*\/base.js/; +var YT_PLAYER_REGEX = /https?:\/\/s.ytimg.com\/yts\/jsbin\/[^\/]*\/html5player.js/; +var when = "start"; +var match = ["*.www.youtube.com"]; +var inject = [ + "common.js", + "youtube-formats.js", + "youtube.js" +]; +var redirect = [{ + src: /https?:\/\/(www.)?youtube.com\/v\/([^#?\/]*)/, + funct: (_1, _2, v) => "https://www.youtube.com/embed/" + v +}]; +var block = [/https?:\/\/s.ytimg.com\/yts\/jsbin\/[^\/]*\/html5player.js/]; +exports.when = when; +exports.match = match; +exports.inject = inject; +exports.redirect = redirect; +exports.block = block; \ No newline at end of file -- cgit v1.2.3