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 --- .../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 +++ 15 files changed, 802 insertions(+) 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/resources/html5-video-everywhere') 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