[Pkg-mozext-commits] [video-without-flash] 01/01: Imported Upstream version 2.0.2

Dmitry Smirnov onlyjob at moszumanska.debian.org
Thu Jan 1 07:24:19 UTC 2015


This is an automated email from the git hooks/post-receive script.

onlyjob pushed a commit to branch upstream
in repository video-without-flash.

commit b0819e1 (upstream)
Author: Dmitry Smirnov <onlyjob at member.fsf.org>
Date:   Thu Jan 1 07:24:08 2015

    Imported Upstream version 2.0.2
---
 README.md                                    | 139 +++++++++++++++++++++++
 bootstrap.js                                 |  73 ++++++++++++
 chrome.manifest                              |  10 +-
 chrome/#blip.js#                             |  85 ++++++++++++++
 chrome/#list_modules.js#                     |  31 +++++
 chrome/#vwof.js#                             |  93 +++++++++++++++
 chrome/blip.js                               |  85 ++++++++++++++
 chrome/content/browserOverlay.js             | 164 ---------------------------
 chrome/content/browserOverlay.xul            |  36 ------
 chrome/content/onload.js                     |  18 ---
 chrome/content/prefs.xul                     |  62 ----------
 chrome/{content => }/list_modules.js         |   7 +-
 chrome/listener.js                           | 156 +++++++++++++++++++++++++
 chrome/locale/en-US/browserOverlay.dtd       |   3 -
 {modules => chrome/modules}/FC2.jsm          |   6 +-
 {modules => chrome/modules}/HTML5.jsm        |   0
 chrome/modules/Makefile.in                   |   2 +
 chrome/modules/SWM.jsm                       | 105 +++++++++++++++++
 chrome/modules/ScreenWaveMedia.jsm           |  57 ++++++++++
 chrome/modules/blip.jsm                      | 118 +++++++++++++++++++
 {modules => chrome/modules}/dailymotion.jsm  |   0
 chrome/modules/dew.jsm                       |  20 ++++
 {modules => chrome/modules}/niconico.jsm     |   4 +-
 chrome/modules/springboard.jsm               |  25 ++++
 chrome/modules/twitch.jsm                    |  39 +++++++
 chrome/modules/ustream.jsm                   |  48 ++++++++
 {modules => chrome/modules}/youtube.jsm      |  10 +-
 chrome/{content => }/player.js               |   6 +-
 chrome/prefs.js                              |  47 ++++++++
 chrome/prefs.xul                             |  79 +++++++++++++
 chrome/skin/toolbar-button.css               |  14 ---
 chrome/skin/video-icon_14.png                | Bin 1587 -> 0 bytes
 chrome/skin/video-icon_24.png                | Bin 2318 -> 0 bytes
 chrome/{content => }/utils.js                |  11 +-
 chrome/vwof.js                               |  89 +++++++++++++++
 chrome/{content => }/youtube_utils.js        |   7 +-
 {chrome/content => content}/list_modules.js  |   7 +-
 content/listener.js                          | 144 +++++++++++++++++++++++
 {modules => content/modules}/FC2.jsm         |   6 +-
 {modules => content/modules}/HTML5.jsm       |   0
 content/modules/Makefile.in                  |   2 +
 content/modules/ScreenWaveMedia.jsm          |  57 ++++++++++
 content/modules/blip.jsm                     | 118 +++++++++++++++++++
 {modules => content/modules}/dailymotion.jsm |   0
 {modules => content/modules}/niconico.jsm    |   4 +-
 {modules => content/modules}/youtube.jsm     |  10 +-
 {chrome/content => content}/player.js        |   6 +-
 content/prefs.js                             |  47 ++++++++
 content/prefs.xul                            |  79 +++++++++++++
 {chrome/content => content}/utils.js         |  11 +-
 content/vwof.js                              |  89 +++++++++++++++
 {chrome/content => content}/youtube_utils.js |   7 +-
 defaults/preferences/vwof.js                 |   3 +-
 install.rdf                                  |  38 +++++--
 locale/en-US/strings.dtd                     |   1 +
 locale/en-US/strings.properties              |   3 +
 modules/blip.jsm                             | 111 ------------------
 {chrome/content => skin}/player.css          |   2 +-
 {chrome/skin => skin}/video-icon.png         | Bin
 59 files changed, 1905 insertions(+), 489 deletions(-)

diff --git a/README.md b/README.md
new file mode 100755
index 0000000..8e2f2dc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,139 @@
+video-without-flash
+===================
+
+Firefox extension for watching videos without the flash plugin
+
+
+<i>Fetch video source of flash based media and play the video directly with Firefox, without the use of the flash plug-in. </i>
+
+<b> Supported sites/embed video player </b>
+<ul>
+<li>Youtube</li>
+<li>Blip</li>
+<li>ScreenWaveMedia</li>
+<li>Dew</li>
+<li>HTML5</li>
+<li>Springboard</li>
+<li>Dailymotion</li>
+<li>UStream </li>
+</ul>
+
+Due to some minor variations of providing the video by a same media provider (different version of there player, use of the embed tag) a few videos may not be detected. 
+
+<b> Usage </b>
+By default the video are detected when a page load, you can disable this behavior in the preference pane and manually try to detect video by pressing 
+ ALT-W or Right Click and "Watch video without flash". 
+
+<b>Why you  may want to use this extension</b>
+<ul>
+<li>You experienced some lag or bad CPU performance using flash </li>
+<li>You only use flash to watch videos, and do not want to install a non-free packages on your linux station (this extension is released under the GPL)</li>
+</ul>
+
+<b> Pro tips </b>
+*To read MP4 videos you must install a media plugin like vlc-web-plugin or gecko-mplayer. Under Windows the vlc web plugin can be install when running the vlc install exe. 
+
+* The video can be save with a "right click / save as" on the "open in a new tab"  link.
+
+* Numerous options in the preference pane : select preferred format / quality when available, disable modules. 
+
+<b> Known bugs </b> 
+(unfortunately these are upstream bugs, nothing I can do about it)
+
+* YouTube : The video area is not reloading when clicking on a suggested video link. After clicking on such a link, please use the ALT-w command to refresh the player area
+
+* VLC plugin : The video crashes when a video is paused when played with the vlc web plugin.
+
+<b> How does it works </b> 
+This extension fetch the direct link to videos using regular expression, XPath, and DOM. When available,  a picture and a select control are displayed to read the video with firefox, using the firefox internal HTML5 compliant media player or a plugin like vlc or mplayer if the user had installed it. 
+
+Each media provider is handled by a "parser". Javascript modules (.jsm) that are loaded at startup. The extension can fairly easy be extended due to it modular approache, as new media provider can be added by implementing a new jsm file. 
+
+<b>Why a HTML5 parser ? </b>
+For licensing reasons firefox do not support at the moment the H264 codec, although  it may change in the future. If a site uses HTML5 to display a video, but the video itself is encoded with H264 or a variant you normally wont be able to play it. By using the HTML5 parser, you can read the video if a media player plugin is installed as stated previously.
+
+
+= Technical documentation for developers =
+
+== How to write a new parser == 
+
+<i>Do not esitate to fork and add your own parser</i>
+
+* Step 1 : Add the name of your parser without the .jsm extension in the browser variable "extensions.vwof.modules" you can do it with about:config for test purposes or do it permanently in src/defaults/preferenes/vwof.js
+The boolean value (parsername:1) is eather if your parser is activated or not. 
+
+
+* Step 2 : Create a jsm file in the modules directory
+
+The parser must respect the following API  : 
+
+```javascript
+var parser = {
+    BASE_URI: '',
+    parse_embed: function(cw) {
+        var video_info = [];
+	return video_info;
+    },
+
+    parse_site: function(cw) {
+	var video_info = [];
+	var player = cw.document.getElementById('');
+	if(!player)return;
+
+	return video_info;
+    }
+};
+```
+
+=== video_info variable ===
+
+video player is an array of an hash
+
+each video is an entry in the array and the hash contains video information
+
+If the videos array contains more than one element a combo box (select tag)
+will be added in the player displaying the format and quality
+
+```javascript
+video_info = 
+[
+{
+'player':,              //DOM where the video player will be embed, replacing all child nodes, if undefined, the video open in a new tab
+
+'video_img':,           //string link to the picture displayed as a preview, if undefined the background is black
+
+'videos': []            //array of video informations, see below
+}
+];
+
+videos = 
+[
+{
+'quality':,              //quality of the video (low, medium, hd720, hd1080)
+
+'format':,               //format of the video (webm, mp4, flv, ...)
+
+'url':                   //direct link to the video, this is the only mandatory variable
+}
+];
+
+
+== How to build ==
+
+This plugin comes with a home made makefile based on mozilla school xul example.
+
+Targets are : 
+
+* make
+  Create an .xpi in the ../bin directory (manually create ../bin if necessary)
+
+* make install
+  install the plugin in the profil directory. By default the profil name is "devel"
+  you can change this behaviour by passing the profile_dir variable (example : make install profile_dir default)
+
+* you need to restart firefox to apply the changes, it can be done with the make target
+  make rerun
+
+  which will run the following command : killall firefox ; firefox -purgecaches -P &
+
+
diff --git a/bootstrap.js b/bootstrap.js
new file mode 100755
index 0000000..ce07dc4
--- /dev/null
+++ b/bootstrap.js
@@ -0,0 +1,73 @@
+const {interfaces: Ci, utils: Cu} = Components;
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/NetUtil.jsm');
+
+const PREF_BRANCH = "extensions.vwof.";
+
+function listenPageLoad(event) {
+    var cw = event.originalTarget.defaultView;
+    if (cw.frameElement && windowListener.ignoreFrames) {
+	return;  //dont want to watch frames
+    }
+    
+    var prefManager = Components.classes["@mozilla.org/preferences-service;1"].
+                      getService(Components.interfaces.nsIPrefBranch);
+    var activate_onload = prefManager.getBoolPref(PREF_BRANCH+"activate_onload");
+    if(activate_onload){vwof.detectVideo(cw);}
+}
+
+function oncommand_detect_video(window){
+    //window is browser.xul. Pass the contentWindow of the document
+    vwof.detectVideo(window.gBrowser.contentDocument.defaultView);
+}
+
+function init(window){
+    let doc = window.document;
+    keyset = doc.getElementById('mainKeyset');
+
+    //keyboard shortcut
+    let key = doc.createElement('key');
+    key.setAttribute('id', 'vwof-key');
+    key.addEventListener("command", function (){oncommand_detect_video(window);});
+    key.setAttribute("oncommand", "//");
+    key.setAttribute('key', 'w');
+    key.setAttribute('modifiers', 'alt');
+    keyset.appendChild(key);
+    keyset.parentElement.appendChild(keyset);
+}
+
+function startup(aData, aReason) {
+    Services.scriptloader.loadSubScript("chrome://vwof/content/prefs.js")
+    Services.scriptloader.loadSubScript('chrome://vwof/content/vwof.js');    
+    Services.scriptloader.loadSubScript('chrome://vwof/content/player.js');
+    Services.scriptloader.loadSubScript('chrome://vwof/content/utils.js');
+    Services.scriptloader.loadSubScript('chrome://vwof/content/youtube_utils.js');    
+    Services.scriptloader.loadSubScript('chrome://vwof/content/listener.js');
+    windowListener.register();
+    PrefObserver.register();
+
+    setDefaultPref(PREF_BRANCH, "modules", '{"HTML5":1, "blip":1, "youtube":1, "dailymotion":1, "niconico":1, "FC2":1, "ScreenWaveMedia":1}');
+    setDefaultPref(PREF_BRANCH, "prefered_quality", 'medium');
+    setDefaultPref(PREF_BRANCH, "prefered_format", 'webm');
+    setDefaultPref(PREF_BRANCH, "activate_onload", true);
+
+    // Load into any existing windows
+    let wm = Services.wm,
+    enumerator = wm.getEnumerator('navigator:browser');
+    while (enumerator.hasMoreElements()) {
+        init(enumerator.getNext().QueryInterface(Ci.nsIDOMWindow));
+    }
+
+    vwof.load_modules();
+    vwof.set_parsers_activation();
+}
+
+function shutdown(aData, aReason) {
+    if (aReason == APP_SHUTDOWN) return;
+    windowListener.unregister();
+    PrefObserver.unregister();
+}
+
+function install() {}
+
+function uninstall() {}
diff --git a/chrome.manifest b/chrome.manifest
index 5c6f57d..9032b42 100755
--- a/chrome.manifest
+++ b/chrome.manifest
@@ -1,7 +1,3 @@
-content   vwof              chrome/content/  contentaccessible=yes
-skin      vwof  classic/1.0 chrome/skin/
-locale    vwof  en-US       chrome/locale/en-US/
-resource  vwof              modules/
-
-overlay chrome://browser/content/browser.xul  chrome://vwof/content/browserOverlay.xul
-style chrome://global/content/customizeToolbar.xul chrome://vwof/skin/toolbar-button.css
\ No newline at end of file
+content vwof content/ contentaccessible=yes
+locale  vwof en-US locale/en-US/
+skin    vwof classic/1.0 skin/
diff --git a/chrome/#blip.js# b/chrome/#blip.js#
new file mode 100644
index 0000000..b556232
--- /dev/null
+++ b/chrome/#blip.js#
@@ -0,0 +1,85 @@
+var parser = {
+    BASE_URI: 'blip.tv',
+    URL_PARAM_JSON: '?skin=json&no_wrap=1',
+    parse_embed: function(cw) {
+	const XPATH_PLAYER = "//iframe[starts-with(@src, 'http://blip.tv/play')]";
+	var video_info = [];
+	var player;
+	var video_img;
+
+	var xp_res_player = cw.document.evaluate(XPATH_PLAYER, cw.document, null, cw.XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );
+	while (player = xp_res_player.iterateNext()) {
+    	    var videos = [];
+	    var player_doc = player.contentDocument;
+	    var episode_info = player_doc.getElementById('EpisodeInfo');
+	    if(episode_info){
+		//megaplaya method
+		var data_episode_page = episode_info.getAttribute('data-episode-page');
+		var json_string = utils.get(data_episode_page+this.URL_PARAM_JSON);
+		var parse_data = this.parse_json_data(json_string);
+		video_img = parse_data[0];
+		videos = parse_data[1];		
+	    }
+	    else{
+		//embed method		
+		var encoded_file = player_doc.body.textContent.match(/"file":"(.+?)",/)[1];
+		var file = decodeURIComponent(encoded_file);
+		file = file.replace('rss/flash', 'posts/view');
+		var json_string = utils.get(file+this.URL_PARAM_JSON);
+		var parse_data = this.parse_json_data(json_string);
+		video_img = parse_data[0];
+		videos = parse_data[1];
+		cw.oalert(videos[0].url);
+	    }
+	    cw.alert(player);
+	    video_info.push({
+		'player': player,
+		'video_img':video_img,
+		'videos': videos
+	    });
+	}
+
+	return video_info;
+    },
+
+    parse_site: function(cw) {
+	var video_info = [];
+	var player = cw.document.getElementById('PlayeriFrame');
+	if(!player)return;
+	
+	var json_string = utils.get(cw.document.URL+this.URL_PARAM_JSON);
+	var parse_data = this.parse_json_data(json_string);
+	var video_img = parse_data[0];
+	var videos = parse_data[1];
+	
+	video_info.push({
+	    'player': player,
+	    'video_img': video_img,
+	    'videos': videos
+	});
+
+	return video_info;
+    },
+
+    parse_json_data: function(json_string){
+	var post = JSON.parse(json_string).Post;
+	
+	var videos = [];
+	for(var i=0;i<post.additionalMedia.length;i++){
+	    var format = post.additionalMedia[i].primary_mime_type;
+	    if(format == 'text/plain')continue;
+	    
+	    //remove video part of the mime type for a prettier display
+	    format=format.replace('video/', '');
+
+	    videos.push({'format': format,
+			 'quality': post.additionalMedia[i].media_width + '/' + post.additionalMedia[i].media_height,
+			 'url':post.additionalMedia[i].url}
+		       );
+	}
+
+	var video_img = post.thumbnailUrl;
+
+	return [video_img, videos];
+    }
+};
diff --git a/chrome/#list_modules.js# b/chrome/#list_modules.js#
new file mode 100644
index 0000000..3948543
--- /dev/null
+++ b/chrome/#list_modules.js#
@@ -0,0 +1,31 @@
+var checkbox_wide = document.getElementById("vwof_yt_wide");
+var wide = youtubeUtils.yt_is_wide();
+checkbox_wide.setAttribute("checked", wide);
+
+var prefPane = document.getElementById('vwof_pref_modules');
+var s_modules = document.getElementById('extensions.vwof.modules').value;
+modules = JSON.parse(s_modules);
+
+var element_label = document.createElement('label');
+element_label.setAttribute('value', ' -- Enable/disable modules -- ');
+dprefPane.appendChild(element_label);
+
+for(var key_module in modules){
+    var element_checkbox = document.createElement('checkbox');
+    element_checkbox.setAttribute('label', key_module);
+    element_checkbox.setAttribute('checked', modules[key_module]?'true':'false');
+    element_checkbox.setAttribute('oncommand', "update_module(event)");
+    prefPane.appendChild(element_checkbox);
+}
+
+function update_module(event){
+    var l = event.target.getAttribute('label');
+    var c = event.target.hasAttribute('checked')?1:0;
+
+    modules[l] = c;
+    var s_modules = JSON.stringify(modules);
+
+    var prefManager = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
+    prefManager.setCharPref("extensions.vwof.modules", s_modules);
+}
+
diff --git a/chrome/#vwof.js# b/chrome/#vwof.js#
new file mode 100644
index 0000000..ae9e0f4
--- /dev/null
+++ b/chrome/#vwof.js#
@@ -0,0 +1,93 @@
+var vwof= {
+    parsers:{},   //hash of the parsers (loaded from jsm modules)
+    parser_name:["blip", "dailymotion", "FC2", "HTML5", "niconico", "youtube", "ScreenWaveMedia"],
+
+    /**
+       Load modules listed in the extensions.vwof.modules pref variable to this.parsers hash
+    */
+    load_modules:function(){
+	//check in the preferences : activated a parser on page load or not
+	Components.utils.import("resource://gre/modules/Services.jsm");
+	var prefManager = Components.classes["@mozilla.org/preferences-service;1"]
+	    .getService(Components.interfaces.nsIPrefBranch);
+
+	var modules_list = prefManager.getCharPref("extensions.vwof.modules");
+	var modules = JSON.parse(modules_list);  //parser / value from the preferences
+
+	for(var i=0;i<this.parser_name.length;i++){
+            let key_parser = this.parser_name[i];
+	    if(modules[key_parser]){
+
+	        let context = {};
+	        let res = 'chrome://vwof/content/modules/'+key_parser+'.jsm';
+	        Services.scriptloader.loadSubScript(res, context, "UTF-8");
+	        this.parsers[key_parser] = context;
+            }
+	}
+    },
+    reload_modules:function(){
+	try{	    
+	    // clear the previously loaded parsers
+	    delete this.parsers;
+	    this.parsers = {};
+
+	    //finally load the modules
+	    this.load_modules();
+	}
+	catch(err){
+	    Components.utils.reportError("vwof exception: "+err);
+	};	
+    },    
+    getVideoInfo:function (cw) {
+	var video_info = [];	// array of video_data
+	var has_parsed_site = false;
+	
+	for(var key_parser in this.parsers){
+  	    try{
+		var parser = this.parsers[key_parser].parser;
+		var video_data = [];  //array of video links with quality
+
+		//if the parser has a URI and it's the current location
+		if(parser.BASE_URI && cw.location.hostname == parser.BASE_URI){
+		    video_data = parser.parse_site(cw);
+		    has_parsed_site = true;
+		}
+		else if(parser.parse_embed){
+		    video_data = parser.parse_embed(cw);
+		}
+
+		//if there is at least a video url retreived from the parser
+		if(video_data.length >= 1){		    
+		    //set the source (name of the parser)
+		    for(var i=0;i < video_data.length;i++){
+			video_data[i]['source'] = this.parsers[key_parser].name;
+		    }
+		    
+                    //concat the chunks of video(s) from this parser
+		    video_info = video_info.concat(video_data);
+		}
+	    }
+	    catch(err){
+		Components.utils.reportError("vwof plugin, exception in "+key_parser+": "+err);
+	    };
+
+	    //official web sites do not embed several videos, so don't use other parsers
+	    if(has_parsed_site){break;}
+	}
+
+	return video_info;
+    },
+    
+    detectVideo:function(cw) {
+	var video_info = this.getVideoInfo(cw);
+
+	for (var i = 0; i < video_info.length; i++) {
+	    if(video_info[i]['player']){
+    		var replace_location = video_info[i]['player'];
+		var player = vwofPlayer.create_video_selector(video_info[i], cw);
+		var replace_parent = replace_location.parentNode;
+		replace_parent.replaceChild(player, replace_location);
+	    }
+	}
+    }    
+};
diff --git a/chrome/blip.js b/chrome/blip.js
new file mode 100644
index 0000000..03dbc11
--- /dev/null
+++ b/chrome/blip.js
@@ -0,0 +1,85 @@
+var parser = {
+    BASE_URI: 'blip.tv',
+    URL_PARAM_JSON: '?skin=json&no_wrap=1',
+    parse_embed: function(cw) {
+	const XPATH_PLAYER = "//iframe[starts-with(@src, 'http://blip.tv/play')]";
+	var video_info = [];
+	var player;
+	var video_img;
+
+	var xp_res_player = cw.document.evaluate(XPATH_PLAYER, cw.document, null, cw.XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );
+	while (player = xp_res_player.iterateNext()) {
+    	    var videos = [];
+	    var player_doc = player.contentDocument;
+	    var episode_info = player_doc.getElementById('EpisodeInfo');
+	    if(episode_info){
+		//megaplaya method
+		var data_episode_page = episode_info.getAttribute('data-episode-page');
+		var json_string = utils.get(data_episode_page+this.URL_PARAM_JSON);
+		var parse_data = this.parse_json_data(json_string);
+		video_img = parse_data[0];
+		videos = parse_data[1];		
+	    }
+	    else{
+		//embed method		
+		var encoded_file = player_doc.body.textContent.match(/"file":"(.+?)",/)[1];
+		var file = decodeURIComponent(encoded_file);
+		file = file.replace('rss/flash', 'posts/view');
+		var json_string = utils.get(file+this.URL_PARAM_JSON);
+		var parse_data = this.parse_json_data(json_string);
+		video_img = parse_data[0];
+		videos = parse_data[1];
+		cw.alert(videos[0].url);
+	    }
+	    cw.alert(player);
+	    video_info.push({
+		'player': player,
+		'video_img':video_img,
+		'videos': videos
+	    });
+	}
+
+	return video_info;
+    },
+
+    parse_site: function(cw) {
+	var video_info = [];
+	var player = cw.document.getElementById('PlayeriFrame');
+	if(!player)return;
+	
+	var json_string = utils.get(cw.document.URL+this.URL_PARAM_JSON);
+	var parse_data = this.parse_json_data(json_string);
+	var video_img = parse_data[0];
+	var videos = parse_data[1];
+	
+	video_info.push({
+	    'player': player,
+	    'video_img': video_img,
+	    'videos': videos
+	});
+
+	return video_info;
+    },
+
+    parse_json_data: function(json_string){
+	var post = JSON.parse(json_string).Post;
+	
+	var videos = [];
+	for(var i=0;i<post.additionalMedia.length;i++){
+	    var format = post.additionalMedia[i].primary_mime_type;
+	    if(format == 'text/plain')continue;
+	    
+	    //remove video part of the mime type for a prettier display
+	    format=format.replace('video/', '');
+
+	    videos.push({'format': format,
+			 'quality': post.additionalMedia[i].media_width + '/' + post.additionalMedia[i].media_height,
+			 'url':post.additionalMedia[i].url}
+		       );
+	}
+
+	var video_img = post.thumbnailUrl;
+
+	return [video_img, videos];
+    }
+};
diff --git a/chrome/content/browserOverlay.js b/chrome/content/browserOverlay.js
deleted file mode 100755
index 904bda1..0000000
--- a/chrome/content/browserOverlay.js
+++ /dev/null
@@ -1,164 +0,0 @@
-if("undefined" == typeof(vwofChrome)){
-    var vwofChrome = {};
-}
-
-vwofChrome.BrowserOverlay = {
-    parser_name:["blip", "dailymotion", "FC2", "HTML5", "niconico", "youtube"],
-    parsers:{},   //hash of the parsers (loaded from jsm modules)
-
-    /**
-       function called at startup
-    */
-    startup:function() {
-	this.load_modules();
-	this.set_parsers_activation();
-    },
-    set_parsers_activation:function(){
-	//check in the preferences : activated a parser on page load or not
-	Components.utils.import("resource://gre/modules/Services.jsm");
-	var prefManager = Components.classes["@mozilla.org/preferences-service;1"]
-	    .getService(Components.interfaces.nsIPrefBranch);
-
-	var modules_list = prefManager.getCharPref("extensions.vwof.modules");
-	var modules = JSON.parse(modules_list);  //parser / value from the preferences
-
-	for(var key_parser in this.parsers){
- 	    var parser = this.parsers[key_parser].parser;
-
-	    //if a pref is defined for this parser
-	    if(modules[key_parser])
-		parser['activated'] = modules[key_parser]?true:false;
-	    else 
-		parser['activated'] = false;
-	}
-    },
-    /**
-       Load modules listed in the extensions.vwof.modules pref variable to this.parsers hash
-    */
-    load_modules:function(){
-	try{
-	    Components.utils.import("resource://gre/modules/Services.jsm");
-	    var prefManager = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-	    var modules_list = prefManager.getCharPref("extensions.vwof.modules");
-	    var modules = JSON.parse(modules_list);
-
-	    for(var i=0;i<this.parser_name.length;i++){
-		let key_parser = this.parser_name[i];
-		let context = {};
-		let res = 'resource://vwof/'+key_parser+'.jsm';
-		Services.scriptloader.loadSubScript(res, context, "UTF-8");
-		this.parsers[key_parser] = context;
-	    }
-	}
-	catch(err){
-	    alert(err);
-	};
-	
-    },    
-    /**
-       call every parse function from loaded parsers
-    */
-    getVideoInfo:function (cw) {
-	var video_info = [];	// array of video_data
-	var has_parsed_site = false;
-	
-	for(var key_parser in this.parsers){
-	    
-  	    try{
-		var parser = this.parsers[key_parser].parser;
-		var video_data = [];  //array of video links with quality
-
-		if(parser['activated'] != true)continue;
-
-		//if the parser has a URI and it's the current location
-		if(parser.BASE_URI && cw.location.hostname == parser.BASE_URI){
-		    video_data = parser.parse_site(cw);
-		    has_parsed_site = true;
-		}
-		else if(parser.parse_embed){
-		    video_data = parser.parse_embed(cw);
-		}
-
-		//if there is at least a video url retreived from the parser
-		if(video_data.length >= 1){		    
-		    //set the source (name of the parser)
-		    for(var i=0;i < video_data.length;i++){
-			video_data[i]['source'] = key_parser;
-		    }
-		    
-		    //concat the chunks of video(s) from this parser
-		    video_info = video_info.concat(video_data);    
-		}
-	    }
-	    catch(err){
-		console.error("vwof plugin, exception in parser "+key_parser+": "+err);
-	    };
-
-	    //video web sites never have several videos on a same page, 
-	    //stop the search if a hit was found
-	    if(has_parsed_site){break;}
-	}
-
-	return video_info;
-    },
-
-    /**
-       get the video source and add a link in the document 
-    */
-    detectVideo:function(cw) {
-
-	//check if the content window is defined
-	if (!cw ||
-	    !cw.document
-	   ){
-	    return;
-	}
-
-	var video_info = this.getVideoInfo(cw);
-
-	for (var i = 0; i < video_info.length; i++) {
-	    if(video_info[i]['player']){
-    		var replace_location = video_info[i]['player'];
-		var player = vwofPlayer.create_video_selector(video_info[i], cw);
-		var replace_parent = replace_location.parentNode;
-		replace_parent.replaceChild(player, replace_location);
-	    }
-	}
-    }
-};
-
-
-/**
-   Listeners
-
-   initialize the application on startup
-*/
-window.addEventListener("load", function() { vwofChrome.BrowserOverlay.startup(); }, false);
-
-/**
-   Listener that observe the prefs variables
-
-   If the module list changes (new module, module deactivated/activated), the parser list is reloaded
-*/
-var myPrefObserver = {
-    register: function() {
-	// load preference service
-	var prefService = Components.classes["@mozilla.org/preferences-service;1"]
-	    .getService(Components.interfaces.nsIPrefService);
-	this.branch = prefService.getBranch("extensions.vwof.");
-	this.branch.addObserver("", this, false);
-    },
-
-    unregister: function() {
-	this.branch.removeObserver("", this);
-    },
-
-    observe: function(aSubject, aTopic, aData) {
-	switch (aData) {
-	case "modules":
-	    vwofChrome.BrowserOverlay.set_parsers_activation();
-	    break;
-	}
-    }
-}
-myPrefObserver.register();
diff --git a/chrome/content/browserOverlay.xul b/chrome/content/browserOverlay.xul
deleted file mode 100755
index cbaeea7..0000000
--- a/chrome/content/browserOverlay.xul
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://vwof/skin/toolbar-button.css" type="text/css"?>
-
-<overlay id="vwof-browser-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <script type="application/x-javascript" src="chrome://vwof/content/browserOverlay.js" />
-  <script type="application/x-javascript" src="chrome://vwof/content/utils.js" />  
-  <script type="application/x-javascript" src="chrome://vwof/content/youtube_utils.js" />
-  <script type="application/x-javascript" src="chrome://vwof/content/player.js" />
-  <script type="application/x-javascript" src="chrome://vwof/content/onload.js" />
-
-  <script type="application/x-javascript">
-    function oncommand_detectvideo(){
-      var cw = getBrowser().contentWindow;
-      vwofChrome.BrowserOverlay.detectVideo(cw);
-    }
-
-    function vwof_toggle(event){
-      var c = event.target.hasAttribute('checked')?1:0;
-      var prefManager = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-      prefManager.setBoolPref("extensions.vwof.activate_onload", c);
-    }
-
-  </script>
-  
-  <keyset>
-    <key id="vwof-key-detect-video" modifiers="alt" key="w" oncommand="oncommand_detectvideo();"/>
-  </keyset>
-
-  <popup id="contentAreaContextMenu">
-    <menuitem id="vwof-detect-video" key="vwof-key-detect-video" label="Watch video without flash" oncommand="oncommand_detectvideo();"/>
-  </popup>
-
-  <toolbarpalette id="BrowserToolbarPalette">
-    <toolbarbutton id="vwof-button" class="vwof-button" tooltiptext="Video WithOut Flash" oncommand="vwof_toggle(event);" type="checkbox"></toolbarbutton>
-  </toolbarpalette>
-</overlay>
diff --git a/chrome/content/onload.js b/chrome/content/onload.js
deleted file mode 100755
index 8d4672e..0000000
--- a/chrome/content/onload.js
+++ /dev/null
@@ -1,18 +0,0 @@
-function pageLoad(event) {
-    var prefManager = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-    var activate_onload = prefManager.getBoolPref("extensions.vwof.activate_onload");
-    
-    if (activate_onload
-	&& event.originalTarget instanceof HTMLDocument
-       ){
-	var cw = event.originalTarget.defaultView;
-	vwofChrome.BrowserOverlay.detectVideo(cw);
-    }
-}
-
-window.addEventListener("DOMContentLoaded", function () {
-    gBrowser.addEventListener("load", pageLoad, true);
-}, false);
-
-// When no longer needed
-gBrowser.removeEventListener("load", pageLoad, true);
diff --git a/chrome/content/prefs.xul b/chrome/content/prefs.xul
deleted file mode 100755
index 05fe9a4..0000000
--- a/chrome/content/prefs.xul
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<prefwindow id="vwofPrefWindow" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <prefpane id="vwof_pref_general" label="General">
-  
-    <preferences>
-      <preference id="extensions.vwof.activate_onload" name="extensions.vwof.activate_onload" type="bool"/>
-      <preference id="plugins.notifyMissingFlash" name="plugins.notifyMissingFlash" type="bool"/>
-      <preference id="full-screen-api.approval-required" name="full-screen-api.approval-required" type="bool"/>
-    </preferences>
-
-    <checkbox label="Activate on page load" preference="extensions.vwof.activate_onload"/>
-    <checkbox label="Enable missing flash plugin warnings" preference="plugins.notifyMissingFlash"/>
-    <checkbox label="Enable approval message when fullscreen" preference="full-screen-api.approval-required"/>
-    
-  </prefpane>
-
-  <prefpane id="vwof_pref_prefered_format" label="Prefered format">
-    <preferences>
-      <preference id="extensions.vwof.prefered_quality" name="extensions.vwof.prefered_quality" type="string" />
-      <preference id="extensions.vwof.prefered_format" name="extensions.vwof.prefered_format" type="string" />
-    </preferences>
-    
-    <label value="Prefered format" control="prefered_format" />
-    <menulist id="prefered_format" preference="extensions.vwof.prefered_format" preference-editable="true">
-      <menupopup>
-	<menuitem label="webm" value="webm"/>
-	<menuitem label="mp4" value="mp4"/>
-	<menuitem label="avi" value="avi"/>
-	<menuitem label="flv" value="flv"/>	
-      </menupopup>
-    </menulist>
-
-    <label value="Prefered quality" control="prefered_quality" />    
-    <menulist id="prefered_quality" preference="extensions.vwof.prefered_quality" preference-editable="true">
-      <menupopup>
-	<menuitem label="hd1080" value="hd1080"/>
-	<menuitem label="hd720" value="hd720"/>
-	<menuitem label="medium" value="medium"/>
-	<menuitem label="low" value="low"/>	
-      </menupopup>
-    </menulist>
-    
-  </prefpane>
-  
-  <prefpane id="vwof_pref_modules" label="modules">
-    <script type="application/x-javascript" src="chrome://vwof/content/browserOverlay.js" />
-    <script type="application/x-javascript" src="chrome://vwof/content/youtube_utils.js" />
-
-    <preferences>
-      <preference id="extensions.vwof.modules" name="extensions.vwof.modules" type="string"/>
-    </preferences>
- 
-    <checkbox id="vwof_yt_wide" label="YouTube theater mode" oncommand="vwofChrome.youtubeUtils.toggle_yt_wide(event)"/>
-    <!--button label="Reload modules" oncommand="vwofChrome.BrowserOverlay.reload_modules()"/-->     
-  </prefpane>
-  
-  <script src="youtube_utils.js"/> 
-  <script src="list_modules.js"/>
-
-</prefwindow>
-
diff --git a/chrome/content/list_modules.js b/chrome/list_modules.js
old mode 100755
new mode 100644
similarity index 91%
copy from chrome/content/list_modules.js
copy to chrome/list_modules.js
index 89c55aa..9bda604
--- a/chrome/content/list_modules.js
+++ b/chrome/list_modules.js
@@ -1,5 +1,5 @@
 var checkbox_wide = document.getElementById("vwof_yt_wide");
-var wide = vwofChrome.youtubeUtils.yt_is_wide();
+var wide = youtubeUtils.yt_is_wide();
 checkbox_wide.setAttribute("checked", wide);
 
 var prefPane = document.getElementById('vwof_pref_modules');
@@ -21,10 +21,10 @@ element_columns.appendChild(element_column_embed);
 element_grid.appendChild(element_columns);
 element_grid.appendChild(element_rows);
 
-for(var i=0;i<vwofChrome.BrowserOverlay.parser_name.length;i++){
+for(var i=0;i<vwof.parser_name.length;i++){
     var element_row = document.createElement('row');
 
-    let key_module = vwofChrome.BrowserOverlay.parser_name[i];
+    let key_module = vwof.parser_name[i];
 
     var element_label_key = document.createElement('label');
     element_label_key.setAttribute('value', key_module);
@@ -53,3 +53,4 @@ function update_module(event){
 
     prefManager.setCharPref("extensions.vwof.modules", s_modules);
 }
+
diff --git a/chrome/listener.js b/chrome/listener.js
new file mode 100644
index 0000000..fbb98d5
--- /dev/null
+++ b/chrome/listener.js
@@ -0,0 +1,156 @@
+var windowListener = {
+    ignoreFrames:true,
+    onOpenWindow: function (aXULWindow) {
+	let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
+	aDOMWindow.addEventListener("load", function () {
+	    aDOMWindow.removeEventListener("load", arguments.callee, false);
+	    windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
+	}, false);
+    },
+    register: function () {
+	let XULWindows = Services.wm.getXULWindowEnumerator(null);
+	while (XULWindows.hasMoreElements()) {
+	    let aXULWindow = XULWindows.getNext();
+	    let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
+	    windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
+	}
+	// Listen to new windows
+	Services.wm.addListener(windowListener);
+    },
+    unregister: function () {
+	// Unload from any existing windows
+	let XULWindows = Services.wm.getXULWindowEnumerator(null);
+	while (XULWindows.hasMoreElements()) {
+	    let aXULWindow = XULWindows.getNext();
+	    let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
+	    windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
+	}
+	//Stop listening so future added windows dont get this attached
+	Services.wm.removeListener(windowListener);
+    },
+    loadIntoWindow: function (aDOMWindow, aXULWindow) {
+	if (!aDOMWindow) {
+	    return;
+	}
+	if (aDOMWindow.gBrowser) {
+	    aDOMWindow.gBrowser.addEventListener('DOMContentLoaded', listenPageLoad, false);
+	    if (aDOMWindow.gBrowser.tabContainer) {
+		//start - go through all tabs in this window we just added to
+		var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
+		for (var i = 0; i < tabs.length; i++) {
+		    var tabBrowser = tabs[i].linkedBrowser;
+		    var win = tabBrowser.contentWindow;
+		    loadIntoContentWindowAndItsFrames(win);
+		}
+		//end - go through all tabs in this window we just added to
+	    } else {
+		//does not have tabContainer
+		var win = aDOMWindow.gBrowser.contentWindow;
+		loadIntoContentWindowAndItsFrames(win);
+	    }
+	}
+    },
+    unloadFromWindow: function (aDOMWindow, aXULWindow) {
+	if (!aDOMWindow) {
+	    return;
+	}
+	if (aDOMWindow.gBrowser) {
+	    aDOMWindow.gBrowser.removeEventListener('DOMContentLoaded', listenPageLoad, false);
+	    if (aDOMWindow.gBrowser.tabContainer) {
+		//has tabContainer
+		//start - go through all tabs in this window we just added to
+		var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
+		for (var i = 0; i < tabs.length; i++) {
+		    Cu.reportError('DOING tab: ' + i);
+		    var tabBrowser = tabs[i].linkedBrowser;
+		    var win = tabBrowser.contentWindow;
+		    unloadFromContentWindowAndItsFrames(win);
+		}
+		//end - go through all tabs in this window we just added to
+	    } else {
+		//does not have tabContainer
+		var win = aDOMWindow.gBrowser.contentWindow;
+		unloadFromContentWindowAndItsFrames(win);
+	    }
+	} else {
+	    //window does not have gBrowser
+	}
+    }
+};
+/*end - windowlistener*/
+
+function loadIntoContentWindowAndItsFrames(theWin) {
+    var frames = theWin.frames;
+    var winArr = [theWin];
+    for (var j = 0; j < frames.length; j++) {
+	winArr.push(frames[j].window);
+    }
+    Cu.reportError('# of frames in tab: ' + frames.length);
+    for (var j = 0; j < winArr.length; j++) {
+	if (j == 0) {
+	    Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
+	} else {
+	    Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
+	}
+	var doc = winArr[j].document;
+	//START - edit below here
+
+	if (this.ignoreFrames) {
+	    break;
+	}
+	//END - edit above here
+    }
+}
+
+function unloadFromContentWindowAndItsFrames(theWin) {
+    var frames = theWin.frames;
+    var winArr = [theWin];
+    for (var j = 0; j < frames.length; j++) {
+	winArr.push(frames[j].window);
+    }
+    Cu.reportError('# of frames in tab: ' + frames.length);
+    for (var j = 0; j < winArr.length; j++) {
+	if (j == 0) {
+	    Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
+	} else {
+	    Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
+	}
+	var doc = winArr[j].document;
+	//START - edit below here
+	if (this.ignoreFrames) {
+	    break;
+	}
+	//END - edit above here
+    }
+}
+
+/**
+   Listener that observe the prefs variables
+
+   If the module list changes (new module, module deactivated/activated), the parser list is reloaded
+*/
+var PrefObserver = {
+    register: function() {
+	// First we'll need the preference services to look for preferences.
+	var prefService = Components.classes["@mozilla.org/preferences-service;1"]
+	    .getService(Components.interfaces.nsIPrefService);
+
+	// For this.branch we ask for the preferences
+	this.branch = prefService.getBranch("extensions.vwof.");
+
+	// Finally add the observer.
+	this.branch.addObserver("", this, false);
+    },
+
+    unregister: function() {
+	this.branch.removeObserver("", this);
+    },
+
+    observe: function(aSubject, aTopic, aData) {
+	switch (aData) {
+	case "modules":
+	    vwof.set_parsers_activation();
+	    break;
+	}
+    }
+}
diff --git a/chrome/locale/en-US/browserOverlay.dtd b/chrome/locale/en-US/browserOverlay.dtd
deleted file mode 100755
index 9b759db..0000000
--- a/chrome/locale/en-US/browserOverlay.dtd
+++ /dev/null
@@ -1,3 +0,0 @@
-<!ENTITY vwof.open.label            "Open Video WithOut Flash">
-<!ENTITY vwof.openMenu.accesskey    "O">
-<!ENTITY vwof.openItem.accesskey    "V">
diff --git a/modules/FC2.jsm b/chrome/modules/FC2.jsm
old mode 100755
new mode 100644
similarity index 91%
copy from modules/FC2.jsm
copy to chrome/modules/FC2.jsm
index 1018e14..cc218b5
--- a/modules/FC2.jsm
+++ b/chrome/modules/FC2.jsm
@@ -20,7 +20,7 @@ var parser = {
 
 	//get MD5 from video id and salt
 	var id_salt = id+this.SALT;
-	var md5sum = vwofChrome.utils.md5(id_salt);
+	var md5sum = utils.md5(id_salt);
 
 	//get gk (signature generated by JS)
 	var gk = [];
@@ -38,9 +38,9 @@ var parser = {
 	api_video_uri = api_video_uri.replace('MIMI', md5sum);
 	api_video_uri = api_video_uri.replace('GK', gk.join(''));
 	
-	var data = vwofChrome.utils.get(api_video_uri).responseText;
+	var data = utils.get(api_video_uri);
 	//extract the video url (filepath) from the data
-	var assoc_data = vwofChrome.utils.url_vars_to_array(data);
+	var assoc_data = utils.url_vars_to_array(data);
 	var filepath = assoc_data['filepath'];
 	if(!filepath)return;
 
diff --git a/modules/HTML5.jsm b/chrome/modules/HTML5.jsm
old mode 100755
new mode 100644
similarity index 100%
copy from modules/HTML5.jsm
copy to chrome/modules/HTML5.jsm
diff --git a/chrome/modules/Makefile.in b/chrome/modules/Makefile.in
new file mode 100644
index 0000000..23f8111
--- /dev/null
+++ b/chrome/modules/Makefile.in
@@ -0,0 +1,2 @@
+# The sources for the module files.
+modules_sources := $(wildcard $(modules_dir)/*.jsm)
diff --git a/chrome/modules/SWM.jsm b/chrome/modules/SWM.jsm
new file mode 100644
index 0000000..9b23f80
--- /dev/null
+++ b/chrome/modules/SWM.jsm
@@ -0,0 +1,105 @@
+/**
+ScreenWaveMedia module
+
+The only site where I go that uses this media provider is cinemassacre.com
+
+The video are all in RMTP format and there is only one format for each video
+
+Since it is all RMTP, the link is open in a vlc instance outside of firefox, but it's no big deal as long
+as the video can be played.
+
+There are two html layout, the "old" layout (http://cinemassacre.com/2013/07/01/avgn-bill-teds-excellent-adventure/)
+
+<div id="SWMPlayer_25823" class="SWMPlayer" style="width:640px;height:320px;">Loading Video...</div>
+<script type="text/javascript" src="http://player.screenwavemedia.com/play/jwplayer/jwplayer.js"></script>
+<script type="text/javascript" src="http://player.screenwavemedia.com/play/embed.php?id=25823"></script>   <-- video data are here
+
+and the "new" layout since september 2013 (http://cinemassacre.com/2013/09/06/avgn-tiger-electronic/)
+
+<iframe src="http://player.screenwavemedia.com/play/player.php?id=Cinemassacre-52273484b87b2" frameborder="0" height="540" width="960">
+<html> ...
+
+	<div id="SWMPlayer" class="SWMPlayer">Loading Video...</div>
+	<script>
+	   ...
+	  jwplayer('SWMPlayer').setup({
+		'id': 'videoPlayer',
+		'width': '100%', 'height': '100%',
+		'provider': 'rtmp',
+		'streamer': 'rtmp://174.127.86.16/Cinemassacre',
+		'flashplayer': 'http://player.screenwavemedia.com/play/jwplayer/player.swf',
+		'file': 'Cinemassacre-52273484b87b2_high.mp4',
+		'image': 'http://image.screenwavemedia.com/Cinemassacre-52273484b87b2_thumb_640x360.jpg', 'stretching': 'uniform',
+	</script>  
+</body></html>
+</iframe>
+
+
+For both layout, the video data are in the same format, only the way to get the script content differ
+*/
+
+var parser = {
+    parse_embed: function(cw) {
+	const REGEX_IMG = /'image': '(.*\.jpg)'/;
+	var video_info = [];   //player DOM element, preview image and array of videos
+	
+	//for the "old" layout, outside of a frame, script tag with src
+	const XPATH_PLAYER = "//div[starts-with(@id, 'SWMPlayer')]";
+	const XPATH_SCRIPT = "//script[starts-with(@src, 'http://player.screenwavemedia.com/play/embed.php')]";
+
+	var xp_res_player = cw.document.evaluate(XPATH_PLAYER, cw.document, null, cw.XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
+       	var xp_res_script = cw.document.evaluate(XPATH_SCRIPT, cw.document, null, cw.XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
+
+	while (player = xp_res_player.iterateNext()) {
+	    var script = xp_res_script.iterateNext();
+	    var script_content = utils.get(script.src);
+
+	    var video_img = script_content.match(REGEX_IMG)[1];
+	    var videos = this.parse_data(script_content);  //get format, type and uri of videos
+	    
+	    video_info.push({
+		'player':player,
+		'video_img':video_img,
+		'videos': videos
+	    });
+	}
+
+	//for the "new" layout, inside a frame, simple script markup
+	const XPATH_PLAYER_FRAME = "//iframe[starts-with(@src, 'http://player.screenwavemedia.com/play/player.php')]";
+	var xp_res_player_frame = cw.document.evaluate(XPATH_PLAYER_FRAME, cw.document, null, cw.XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
+	
+	while (player = xp_res_player_frame.iterateNext()) {
+	    var script_content = player.contentDocument.body.innerHTML;
+
+	    var video_img_match = script_content.match(REGEX_IMG);
+	    if(video_img_match)video_img = video_img_match[1];
+	    else video_img = undefined;
+	    
+	    var videos = this.parse_data(script_content);  //get format, type and uri of videos
+	    
+	    video_info.push({
+		'player':player,
+		'video_img':video_img,
+		'videos': videos
+	    });
+	}
+
+	return video_info;
+    },
+
+    /**
+       the video data are written in a script markup
+    */
+    parse_data: function(data){
+	const REGEX_STREAMER = /'streamer': '(.*)'/;
+	const REGEX_FILE = /'file': '(.*)'/;
+	
+	var streamer = data.match(REGEX_STREAMER)[1];
+	var file = data.match(REGEX_FILE)[1];
+	var video_uri = streamer + '/' + file;
+
+	//only one element in the array for this module
+	var videos = [ {'quality':'medium', 'format':'rtmp', 'url':video_uri} ];
+	return videos;
+    }
+};
diff --git a/chrome/modules/ScreenWaveMedia.jsm b/chrome/modules/ScreenWaveMedia.jsm
new file mode 100644
index 0000000..71d935a
--- /dev/null
+++ b/chrome/modules/ScreenWaveMedia.jsm
@@ -0,0 +1,57 @@
+var parser = {
+    parse_embed: function(cw) {
+	var player;
+	var videos = [];
+	var video_info = [];	
+	const doc = cw.document;
+	const REGEX_ID = /id=(.+)/;
+	const URL_VIDEO = 'http://video2.screenwavemedia.com/vod/VIDEO_ID_QUALITY.mp4';
+	const URL_IMAGE = 'http://image.screenwavemedia.com/VIDEO_ID_thumb_640x360.jpg';
+	const video_quality = ['audio', 'low', 'med', 'high', 'hd1'];
+	const URL_PLAYER_FRAME = 'http://player.screenwavemedia.com/play/player.php';
+	const XPATH_PLAYER_FRAME = "//iframe[starts-with(@src, '"+URL_PLAYER_FRAME+"')]"
+	const URL_PLAYER_SCRIPT = 'http://player.screenwavemedia.com/play/play.php';
+	const XPATH_PLAYER_SCRIPT = "//script[starts-with(@src, '"+URL_PLAYER_SCRIPT+"')]";
+	
+	var xp_res_player_frame = doc.evaluate(XPATH_PLAYER_FRAME, doc, null, 
+					       cw.XPathResult.FIRST_ORDERED_NODE_TYPE, 
+					       null);
+
+	var node = xp_res_player_frame.singleNodeValue;
+
+	if(node){
+	   player = node;
+	}
+	else{
+	    var xp_res_player_script = doc.evaluate(XPATH_PLAYER_SCRIPT, doc, null, 
+					       cw.XPathResult.FIRST_ORDERED_NODE_TYPE, 
+					       null);
+
+	    node = xp_res_player_script.singleNodeValue;
+	    if(!node)return;
+
+	    player = doc.getElementById('videoarea');
+	    player.id = "swmvwof_player";
+	}
+
+	if(!node)return;
+
+	var video_id = node.src.match(REGEX_ID)[1];
+
+	for (var i=0;i<video_quality.length;i++) {
+	    var url = URL_VIDEO.replace('VIDEO_ID', video_id);
+	    url = url.replace("QUALITY", video_quality[i]);
+	    videos.push( {'quality': video_quality[i], 'format':'mp4', 'url':url} );
+	}
+
+	var video_img = URL_IMAGE.replace('VIDEO_ID', video_id);
+	
+	video_info.push({
+	    'player': player,
+	    'video_img':video_img,
+	    'videos': videos
+	});
+
+	return video_info;
+    }
+};
diff --git a/chrome/modules/blip.jsm b/chrome/modules/blip.jsm
new file mode 100644
index 0000000..b776df9
--- /dev/null
+++ b/chrome/modules/blip.jsm
@@ -0,0 +1,118 @@
+var parser = {
+    BASE_URI: 'blip.tv',
+    URL_PARAM_JSON: '?skin=json&no_wrap=1',
+
+    parse_embed: function(cw) {
+	const doc = cw.document;
+	const XPATH_PLAYER = "//iframe[starts-with(@src, 'http://blip.tv/play')]";
+	var video_info = [];
+	var player;
+	var video_img;
+	
+	var xp_res_player = doc.evaluate(XPATH_PLAYER, doc,
+					 null, cw.XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+					 null );
+
+        try{
+	    while (player = xp_res_player.iterateNext()) {
+    	        var videos = [];
+	        var encoded_file;
+	        var player_doc = utils.get(player.src);
+
+	        if((encoded_file = player_doc.match(/"file":"(.+?)",/)) !== null){
+		    var file = decodeURIComponent(encoded_file[1]);
+		    file = file.replace('rss/flash', 'posts/view');
+		    var json_string = utils.get(file+this.URL_PARAM_JSON);
+		    var parse_data = this.parse_json_data(json_string);
+		    video_img = parse_data[0];
+		    videos = parse_data[1];
+	        }
+	        else{
+		    const URL_BASE = 'http://blip.tv/file/get/';
+
+		    const REGEX_VIDEO_URI_HD = 'bliphd720 : "(.*)"';
+		    const REGEX_VIDEO_URI_SD = 'blipsd : "(.*)"';
+		    const REGEX_VIDEO_URI_LD = 'blipld : "(.*)"';
+		    const REGEX_VIDEO_IMG = 'config\.video\.thumbnail = "(.*)"';
+
+		    var video_uri_hd = player_doc.match(REGEX_VIDEO_URI_HD);
+		    var video_uri_sd = player_doc.match(REGEX_VIDEO_URI_SD);
+		    var video_uri_ld = player_doc.match(REGEX_VIDEO_URI_LD);
+		    var video_uri_img = player_doc.match(REGEX_VIDEO_IMG);
+
+		    if(video_uri_hd[1] != ""){
+		        videos.push({'quality':'hd720' , 'url':URL_BASE+video_uri_hd[1]});
+		    }
+		    if(video_uri_sd[1] != ""){
+		        videos.push({'quality':'medium', 'url':URL_BASE+video_uri_sd[1]});
+		    }
+		    if(video_uri_ld[1] != ""){
+		        videos.push({'quality':'low' , 'url':URL_BASE+video_uri_ld[1]});
+		    }
+	            
+		    if(video_uri_img){
+		        video_img = 'http:'+video_uri_img[1];
+		        video_img = video_img.replace('THUMB_WIDTH', player.width);
+		        video_img = video_img.replace('THUMB_HEIGHT', player.height);
+		    }
+	        }
+
+	        video_info.push({
+		    'player': player,
+		    'video_img':video_img,
+		    'videos': videos
+	        });
+	    }
+        }
+        finally{
+            //in case iterateNext() throw invalidStateException 
+            //because of a DOM alteration, return what was fetched
+            return video_info;
+        }
+
+	return video_info;
+    },
+
+    parse_site: function(cw) {
+	var doc = cw.document;
+	var video_info = [];
+	var player = doc.getElementById('PlayeriFrame');
+	if(!player)return;
+	
+	var json_string = utils.get(doc.URL+this.URL_PARAM_JSON);
+	var parse_data = this.parse_json_data(json_string);
+	var video_img = parse_data[0];
+	var videos = parse_data[1];
+	
+	video_info.push({
+	    'player': player,
+	    'video_img': video_img,
+	    'videos': videos
+	});
+
+	return video_info;
+    },
+
+    parse_json_data: function(json_string){
+	var post = JSON.parse(json_string).Post;
+	
+	var videos = [];
+	for(var i=0;i<post.additionalMedia.length;i++){
+	    var format = post.additionalMedia[i].primary_mime_type;
+	    if(format == 'text/plain')continue;
+	    
+	    //remove video part of the mime type for a prettier display
+	    format=format.replace('video/', '');
+
+	    videos.push({'format': format,
+			 'quality': post.additionalMedia[i].media_width + '/' + 
+			 post.additionalMedia[i].media_height,
+			 'url':post.additionalMedia[i].url}
+		       );
+	}
+
+	var video_img = post.thumbnailUrl;
+
+	return [video_img, videos];
+    }
+};
diff --git a/modules/dailymotion.jsm b/chrome/modules/dailymotion.jsm
old mode 100755
new mode 100644
similarity index 100%
copy from modules/dailymotion.jsm
copy to chrome/modules/dailymotion.jsm
diff --git a/chrome/modules/dew.jsm b/chrome/modules/dew.jsm
new file mode 100644
index 0000000..b09ea55
--- /dev/null
+++ b/chrome/modules/dew.jsm
@@ -0,0 +1,20 @@
+var parser = {
+    parse_embed: function(cw) {
+	const XPATH_PLAYER = "//embed[contains(@src, 'dewplayer')]";
+	const REGEX_SOURCE = /[&\?]?son=([^&?]+)/;
+	var video_info = [];
+	var xp_res_player = cw.document.evaluate(XPATH_PLAYER, cw.document, null, cw.XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
+	
+	while (player = xp_res_player.iterateNext()) {
+	    var video_uri = player.src.match(REGEX_SOURCE)[1];
+	    
+	    if(!video_uri)continue;
+	    video_info.push({
+		'player':player,
+		'videos': [ {'quality':'medium', 'url':video_uri} ]
+	    });
+	}
+	
+	return video_info;
+    }
+};
diff --git a/modules/niconico.jsm b/chrome/modules/niconico.jsm
old mode 100755
new mode 100644
similarity index 92%
copy from modules/niconico.jsm
copy to chrome/modules/niconico.jsm
index 61bb763..5e3eb8b
--- a/modules/niconico.jsm
+++ b/chrome/modules/niconico.jsm
@@ -33,8 +33,8 @@ var parser = {
 	////get the video link from the flapi
 	const video_id = json_data.flashvars.videoId;
 	const flapi_url = 'http://flapi.nicovideo.jp/api/getflv?v='+video_id;
-	const data = vwofChrome.utils.get(flapi_url).responseText;
-	const assoc_data = vwofChrome.utils.url_vars_to_array(data);
+	const data = utils.get(flapi_url);
+	const assoc_data = utils.url_vars_to_array(data);
 	const url = decodeURIComponent(assoc_data['url']);
 	
 	var videos = [ {
diff --git a/chrome/modules/springboard.jsm b/chrome/modules/springboard.jsm
new file mode 100644
index 0000000..f881418
--- /dev/null
+++ b/chrome/modules/springboard.jsm
@@ -0,0 +1,25 @@
+var parser = {
+    parse_embed: function(cw) {
+	const XPATH_PLAYER = "//iframe[starts-with(@src, 'http://cms.springboardplatform.com/embed_iframe')]";
+	const XPATH_VIDEO_URI = '/html/head/meta[@property="og:video"]/@content';
+	const XPATH_VIDEO_IMG = '/html/head/meta[@property="og:image"]/@content';
+	var video_info = [];
+	var xp_res_player = cw.document.evaluate(XPATH_PLAYER, cw.document, null, cw.XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
+
+	while (player = xp_res_player.iterateNext()) {
+	    var player_doc = player.contentDocument;
+
+       	    var video_uri = player_doc.evaluate(XPATH_VIDEO_URI, player_doc, null, cw.XPathResult.STRING_TYPE, null).stringValue;
+	    var video_img = player_doc.evaluate(XPATH_VIDEO_IMG, player_doc, null, cw.XPathResult.STRING_TYPE, null).stringValue;
+
+	    if(!video_uri)continue;
+	    
+	    video_info.push({
+		'player':player,
+		'video_img':video_img,
+		'videos': [ {'quality':'medium', 'url':video_uri} ]
+	    });
+	}
+	return video_info;
+    }
+};
diff --git a/chrome/modules/twitch.jsm b/chrome/modules/twitch.jsm
new file mode 100644
index 0000000..b0277d6
--- /dev/null
+++ b/chrome/modules/twitch.jsm
@@ -0,0 +1,39 @@
+var parser = {
+    BASE_URI : 'www.twitch.tv',
+    API_GET_VIDEO:'http://usher.twitch.tv/select/CHANNEL.json?allow_source=true&nauthsig=SIG&nauth=TOKEN&type=any',
+    API_GET_TOKEN:'http://api.twitch.tv/api/channels/CHANNEL/access_token',
+    
+    parse_site:function(cw) {
+	const REGEX_CHANNEL = /twitch.tv\/(\w+)/;
+	var doc = cw.document;
+	var video_info = [];
+	var channel;
+
+	//get the channel name
+	if(url_match = doc.URL.match(REGEX_CHANNEL)){
+	    channel = url_match[1];
+	}
+	else{
+	    throw('cannot retreive channel name of a '+this.BASE_URI+' video on '+doc.URL);
+	}
+
+	//get sig and token
+	var api_token_uri = this.API_GET_TOKEN.replace('CHANNEL', channel);
+	var str_token = vwofChrome.utils.get(api_token_uri);
+	var json_token = JSON.parse(str_token);
+	
+	var sig = json_token['sig'];
+	var token = json_token['token'];
+	//token = token.replace(/"/g, '\\"');
+	token = encodeURIComponent(token);
+
+	//get video info with sig and token values
+	var api_video_uri = this.API_GET_VIDEO.replace('CHANNEL', channel);
+	api_video_uri = api_video_uri.replace('SIG', sig);
+	api_video_uri = api_video_uri.replace('TOKEN', token);
+
+	var str_video = vwofChrome.utils.get(api_video_uri);
+	alert(str_video);
+	return video_info;
+    }
+};
diff --git a/chrome/modules/ustream.jsm b/chrome/modules/ustream.jsm
new file mode 100644
index 0000000..a43b93c
--- /dev/null
+++ b/chrome/modules/ustream.jsm
@@ -0,0 +1,48 @@
+/**
+   ustream parser
+   inspired from https://github.com/piscui/ustream-to-ffmpeg
+*/
+
+var parser = {
+    BASE_URI:'www.ustream.tv',
+    
+    parse_site : function(cw){
+	const XPATH_CHANNEL_ID = '/html/head/meta[@name="ustream:channel_id"]/@content';
+	const XPATH_VIDEO_IMG = '/html/head/meta[@property="og:image"]/@content';
+	const URL_AMF = 'http://cgw.ustream.tv/Viewer/getStream/1/CHANNEL_ID.amf';
+
+	var video_info = [];
+	
+       	var channel_id = cw.document.evaluate(XPATH_CHANNEL_ID, cw.document, null, cw.XPathResult.STRING_TYPE, null).stringValue;
+	var video_img = cw.document.evaluate(XPATH_VIDEO_IMG, cw.document, null, cw.XPathResult.STRING_TYPE, null).stringValue;
+	var video_uri = URL_AMF.replace('CHANNEL_ID', channel_id);
+
+	var data = utils.get(video_uri);
+	var videos = this.parse_data(data);
+	
+	var player = cw.document.getElementsByClassName("player")[0];
+
+	video_info.push({
+	    'player':player,
+	    'video_img':video_img,
+	    'videos': videos
+	});
+
+
+	return video_info;
+    },
+
+    parse_data : function(data){
+	//const REGEX_CDNURL = /cdnUrl\W\W\S(.+?)\x00/;
+	const REGEX_LIVEHTTP = /liveHttpUrl\W\W\S(.+?)\x00/;	
+
+	//var url_rtmp = data.match(REGEX_CDNURL)[1];
+	var url_http = data.match(REGEX_LIVEHTTP)[1];
+
+	var videos = [];       
+	//videos.push({'format': 'rtmp', 'url': url_rtmp });
+	videos.push({'format': 'm3u8', 'url': url_http });
+
+	return videos;
+    }
+};
diff --git a/modules/youtube.jsm b/chrome/modules/youtube.jsm
old mode 100755
new mode 100644
similarity index 90%
copy from modules/youtube.jsm
copy to chrome/modules/youtube.jsm
index ad7910b..c521f21
--- a/modules/youtube.jsm
+++ b/chrome/modules/youtube.jsm
@@ -22,7 +22,7 @@ var parser = {
 	var player_api = doc.getElementById('player-api');
 	if(player_api){
 	    player_api.setAttribute('id', 'vwof_player-api');  //prevent the player-api div to be erased by the missing plugin tv-static message
-	    if(vwofChrome.youtubeUtils.yt_is_wide()){
+	    if(youtubeUtils.yt_is_wide()){
 		player_api.setAttribute("style", "margin:auto;");  //center the player
 	    }
 	}
@@ -39,7 +39,7 @@ var parser = {
 	player_api.appendChild(player);
 	
 	var api_video_uri = this.API_GET_VIDEO.replace('VIDEO_ID', id);
-	var data = vwofChrome.utils.get(api_video_uri).responseText;
+	var data = utils.get(api_video_uri);
 	var video_data = this.parse_data(data);
 	video_data['player'] = player;
 	
@@ -67,7 +67,7 @@ var parser = {
 
 	    var id = player.src.match(REGEX_VIDEO_ID_IFRAME)[1];
 	    var api_video_uri = this.API_GET_VIDEO.replace('VIDEO_ID', id);
-	    var data = vwofChrome.utils.get(api_video_uri).responseText;
+	    var data = utils.get(api_video_uri);
 
 	    var parsed_array = this.parse_data(data);
 	    parsed_array['player'] = player;
@@ -84,7 +84,7 @@ var parser = {
     */
     parse_data: function(data){
 	var videos = [];
-	var assoc_data = vwofChrome.utils.url_vars_to_array(data);
+	var assoc_data = utils.url_vars_to_array(data);
 
 	var url_encoded_fmt_stream_map = assoc_data['url_encoded_fmt_stream_map'];
 	var url_decoded_fmt_stream_map = decodeURIComponent(url_encoded_fmt_stream_map);
@@ -92,7 +92,7 @@ var parser = {
 	var i;
 	
 	for(i=0;i<arr_url_decoded_fmt_stream_map.length;i++){
-	    var assoc_url_decoded_fmt_stream = vwofChrome.utils.url_vars_to_array(arr_url_decoded_fmt_stream_map[i]);
+	    var assoc_url_decoded_fmt_stream = utils.url_vars_to_array(arr_url_decoded_fmt_stream_map[i]);
 	    var encoded_uri = assoc_url_decoded_fmt_stream['url'];
 	    var decoded_uri = decodeURIComponent(encoded_uri);
 	    decoded_uri += '&signature='+assoc_url_decoded_fmt_stream['sig'];    //add the signature to the decoded url
diff --git a/chrome/content/player.js b/chrome/player.js
old mode 100755
new mode 100644
similarity index 98%
copy from chrome/content/player.js
copy to chrome/player.js
index 80e2958..809768b
--- a/chrome/content/player.js
+++ b/chrome/player.js
@@ -1,7 +1,3 @@
-if ("undefined" == typeof(vwofPlayer)) {
-    var vwofPlayer = {};
-};
-
 vwofPlayer = {
     /**
        add the player stylecheet link to the head of the document
@@ -10,7 +6,7 @@ vwofPlayer = {
 	var style = doc.createElement('link');
 	style.setAttribute('type', 'text/css');
 	style.setAttribute('rel', 'stylesheet');
-	style.setAttribute('href', 'chrome://vwof/content/player.css');
+	style.setAttribute('href', 'chrome://vwof/skin/player.css');
 	style.setAttribute('id', style_id);
 	doc.head.appendChild(style);
     },
diff --git a/chrome/prefs.js b/chrome/prefs.js
new file mode 100644
index 0000000..2764774
--- /dev/null
+++ b/chrome/prefs.js
@@ -0,0 +1,47 @@
+function getGenericPref(branch,prefName)
+{
+    switch (branch.getPrefType(prefName))
+    {
+        default:
+        case 0:   return undefined;                      // PREF_INVALID
+        case 32:  return getUCharPref(prefName,branch);  // PREF_STRING
+        case 64:  return branch.getIntPref(prefName);    // PREF_INT
+        case 128: return branch.getBoolPref(prefName);   // PREF_BOOL
+    }
+}
+
+function setGenericPref(branch,prefName,prefValue)
+{
+    switch (typeof prefValue)
+    {
+      case "string":
+          setUCharPref(prefName,prefValue,branch);
+          return;
+      case "number":
+          branch.setIntPref(prefName,prefValue);
+          return;
+      case "boolean":
+          branch.setBoolPref(prefName,prefValue);
+          return;
+    }
+}
+
+function setDefaultPref(prefBranch, prefName, prefValue)
+{
+    var defaultBranch = Services.prefs.getDefaultBranch(prefBranch);
+    setGenericPref(defaultBranch,prefName,prefValue);
+}
+
+function getUCharPref(prefName,branch)  // Unicode getCharPref
+{
+    branch = branch ? branch : Services.prefs;
+    return branch.getComplexValue(prefName, Components.interfaces.nsISupportsString).data;
+}
+function setUCharPref(prefName,text,branch)  // Unicode setCharPref
+{
+    var string = Components.classes["@mozilla.org/supports-string;1"]
+                           .createInstance(Components.interfaces.nsISupportsString);
+    string.data = text;
+    branch = branch ? branch : Services.prefs;
+    branch.setComplexValue(prefName, Components.interfaces.nsISupportsString, string);
+}
diff --git a/chrome/prefs.xul b/chrome/prefs.xul
new file mode 100644
index 0000000..fcef025
--- /dev/null
+++ b/chrome/prefs.xul
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<prefwindow id="vwofPrefWindow" 
+            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <prefpane id="vwof_pref_general" label="General">
+  
+    <preferences>
+      <preference id="extensions.vwof.activate_onload" 
+                  name="extensions.vwof.activate_onload"
+                  type="bool"/>
+      <preference id="plugins.notifyMissingFlash" 
+                  name="plugins.notifyMissingFlash" 
+                  type="bool"/>
+      <preference id="full-screen-api.approval-required"
+                  name="full-screen-api.approval-required" 
+                  type="bool"/>
+    </preferences>
+
+    <checkbox label="Detect videos on page load" 
+              preference="extensions.vwof.activate_onload"/>
+    <checkbox label="Enable missing flash plugin warnings" 
+              preference="plugins.notifyMissingFlash"/>
+    <checkbox label="Enable approval message when fullscreen" 
+              preference="full-screen-api.approval-required"/>
+    
+  </prefpane>
+
+  <prefpane id="vwof_pref_prefered_format" label="Prefered format">
+    <preferences>
+      <preference id="extensions.vwof.prefered_quality" 
+                  name="extensions.vwof.prefered_quality" 
+                  type="string" />
+      <preference id="extensions.vwof.prefered_format" 
+                  name="extensions.vwof.prefered_format" 
+                  type="string" />
+    </preferences>
+    
+    <label value="Prefered format" control="prefered_format" />
+    <menulist id="prefered_format" preference="extensions.vwof.prefered_format" 
+              preference-editable="true">
+      <menupopup>
+	<menuitem label="webm" value="webm"/>
+	<menuitem label="mp4" value="mp4"/>
+	<menuitem label="avi" value="avi"/>
+	<menuitem label="flv" value="flv"/>	
+      </menupopup>
+    </menulist>
+
+    <label value="Prefered quality" control="prefered_quality" />    
+    <menulist id="prefered_quality" preference="extensions.vwof.prefered_quality"
+              preference-editable="true">
+      <menupopup>
+	<menuitem label="hd1080" value="hd1080"/>
+	<menuitem label="hd720" value="hd720"/>
+	<menuitem label="medium" value="medium"/>
+	<menuitem label="low" value="low"/>	
+      </menupopup>
+    </menulist>
+    
+  </prefpane>
+  
+  <prefpane id="vwof_pref_modules" label="modules">
+    <script type="application/x-javascript" src="chrome://vwof/content/browserOverlay.js" />
+    <script type="application/x-javascript" src="chrome://vwof/content/youtube_utils.js" />
+
+    <preferences>
+      <preference id="extensions.vwof.modules" name="extensions.vwof.modules" type="string"/>
+    </preferences>
+ 
+    <checkbox id="vwof_yt_wide" label="YouTube theater mode" 
+              oncommand="vwofChrome.youtubeUtils.toggle_yt_wide(event)"/>
+  </prefpane>
+  
+  <script src="youtube_utils.js"/>
+  <script src="vwof.js"/> 
+  <script src="list_modules.js"/>
+
+</prefwindow>
+
diff --git a/chrome/skin/toolbar-button.css b/chrome/skin/toolbar-button.css
deleted file mode 100755
index a475ebb..0000000
--- a/chrome/skin/toolbar-button.css
+++ /dev/null
@@ -1,14 +0,0 @@
-/*  skin/toolbar-button.css  */
-
-#vwof-button {
-  list-style-image: url("chrome://vwof/skin/video-icon_24.png");
-}
-
-toolbar[iconsize="small"] #vwof-button {
-  list-style-image: url("chrome://vwof/skin/video-icon_14.png");
-}
-
-#vwof-button:checked{
-    background-color:#FF0000;
-}
-
diff --git a/chrome/skin/video-icon_14.png b/chrome/skin/video-icon_14.png
deleted file mode 100755
index d4150b6..0000000
Binary files a/chrome/skin/video-icon_14.png and /dev/null differ
diff --git a/chrome/skin/video-icon_24.png b/chrome/skin/video-icon_24.png
deleted file mode 100755
index bf273fa..0000000
Binary files a/chrome/skin/video-icon_24.png and /dev/null differ
diff --git a/chrome/content/utils.js b/chrome/utils.js
old mode 100755
new mode 100644
similarity index 89%
copy from chrome/content/utils.js
copy to chrome/utils.js
index 5d1025e..cdc8dc6
--- a/chrome/content/utils.js
+++ b/chrome/utils.js
@@ -1,7 +1,5 @@
-vwofChrome.utils = {
-    /**
-       needed by some parser to get the video source
-    */
+var utils = {
+
     get:function(uri){
 	const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1",
 						      "nsIXMLHttpRequest",
@@ -9,12 +7,9 @@ vwofChrome.utils = {
 	
 	let xmlhttp = XMLHttpRequest("GET", uri, false);
 	xmlhttp.send();
-	return xmlhttp;
+	return xmlhttp.responseText;
     },
     
-    /**
-       converts url vars into a js associative array
-    */
     url_vars_to_array: function(url){
 	var arr_variable = url.split('&');
 	var arr_assoc = {};
diff --git a/chrome/vwof.js b/chrome/vwof.js
new file mode 100644
index 0000000..e251ec4
--- /dev/null
+++ b/chrome/vwof.js
@@ -0,0 +1,89 @@
+var vwof= {
+    parsers:{},   //hash of the parsers (loaded from jsm modules)
+    parser_name:["blip", "dailymotion", "FC2", "HTML5", "niconico", "youtube", "ScreenWaveMedia"],
+
+    /**
+       Load modules listed in the extensions.vwof.modules pref variable to this.parsers hash
+    */
+    load_modules:function(){
+	for(var i=0;i<this.parser_name.length;i++){
+            let key_parser = this.parser_name[i];
+	    let context = {};
+	    let res = 'chrome://vwof/content/modules/'+key_parser+'.jsm';
+	    Services.scriptloader.loadSubScript(res, context, "UTF-8");
+	    this.parsers[key_parser] = context;
+	}
+    },
+    set_parsers_activation:function(){
+	//check in the preferences : activated a parser on page load or not
+	Components.utils.import("resource://gre/modules/Services.jsm");
+	var prefManager = Components.classes["@mozilla.org/preferences-service;1"]
+	    .getService(Components.interfaces.nsIPrefBranch);
+
+	var modules_list = prefManager.getCharPref("extensions.vwof.modules");
+	var modules = JSON.parse(modules_list);  //parser / value from the preferences
+
+	for(var key_parser in this.parsers){
+ 	    var parser = this.parsers[key_parser].parser;
+
+	    //if a pref is defined for this parser
+	    if(modules[key_parser])
+		parser['activated'] = modules[key_parser]?true:false;
+	    else 
+		parser['activated'] = false;
+	}
+    },    
+    getVideoInfo:function (cw) {
+	var video_info = [];	// array of video_data
+	var has_parsed_site = false;
+	
+	for(var key_parser in this.parsers){
+  	    try{
+		var parser = this.parsers[key_parser].parser;
+		if(parser['activated'] != true)continue;
+		var video_data = [];  //array of video links with quality
+
+		//if the parser has a URI and it's the current location
+		if(parser.BASE_URI && cw.location.hostname == parser.BASE_URI){
+		    video_data = parser.parse_site(cw);
+		    has_parsed_site = true;
+		}
+		else if(parser.parse_embed){
+		    video_data = parser.parse_embed(cw);
+		}
+
+		//if there is at least a video url retreived from the parser
+		if(video_data.length >= 1){		    
+		    //set the source (name of the parser)
+		    for(var i=0;i < video_data.length;i++){
+			video_data[i]['source'] = this.parsers[key_parser].name;
+		    }
+		    
+                    //concat the chunks of video(s) from this parser
+		    video_info = video_info.concat(video_data);
+		}
+	    }
+	    catch(err){
+		Components.utils.reportError("vwof plugin, exception in "+key_parser+": "+err);
+	    };
+
+	    //official web sites do not embed several videos, so don't use other parsers
+	    if(has_parsed_site){break;}
+	}
+
+	return video_info;
+    },
+    
+    detectVideo:function(cw) {
+	var video_info = this.getVideoInfo(cw);
+
+	for (var i = 0; i < video_info.length; i++) {
+	    if(video_info[i]['player']){
+    		var replace_location = video_info[i]['player'];
+		var player = vwofPlayer.create_video_selector(video_info[i], cw);
+		var replace_parent = replace_location.parentNode;
+		replace_parent.replaceChild(player, replace_location);
+	    }
+	}
+    }    
+};
diff --git a/chrome/content/youtube_utils.js b/chrome/youtube_utils.js
old mode 100755
new mode 100644
similarity index 90%
copy from chrome/content/youtube_utils.js
copy to chrome/youtube_utils.js
index 7842b7c..c0e1f0c
--- a/chrome/content/youtube_utils.js
+++ b/chrome/youtube_utils.js
@@ -1,7 +1,4 @@
-if("undefined" == typeof(vwofChrome)){
-    var vwofChrome = {};
-}
-vwofChrome.youtubeUtils = {
+var youtubeUtils = {
     toggle_yt_wide:function (event){
 	var c = event.target.hasAttribute('checked')?1:0;
 	var wide;
@@ -36,7 +33,7 @@ vwofChrome.youtubeUtils = {
 	}
 	catch (errorInfo)
 	{
-	    console.error(errorInfo);
+	    Components.utils.reportError(errorInfo);
 	}
 	return wide;
     }
diff --git a/chrome/content/list_modules.js b/content/list_modules.js
old mode 100755
new mode 100644
similarity index 91%
rename from chrome/content/list_modules.js
rename to content/list_modules.js
index 89c55aa..9bda604
--- a/chrome/content/list_modules.js
+++ b/content/list_modules.js
@@ -1,5 +1,5 @@
 var checkbox_wide = document.getElementById("vwof_yt_wide");
-var wide = vwofChrome.youtubeUtils.yt_is_wide();
+var wide = youtubeUtils.yt_is_wide();
 checkbox_wide.setAttribute("checked", wide);
 
 var prefPane = document.getElementById('vwof_pref_modules');
@@ -21,10 +21,10 @@ element_columns.appendChild(element_column_embed);
 element_grid.appendChild(element_columns);
 element_grid.appendChild(element_rows);
 
-for(var i=0;i<vwofChrome.BrowserOverlay.parser_name.length;i++){
+for(var i=0;i<vwof.parser_name.length;i++){
     var element_row = document.createElement('row');
 
-    let key_module = vwofChrome.BrowserOverlay.parser_name[i];
+    let key_module = vwof.parser_name[i];
 
     var element_label_key = document.createElement('label');
     element_label_key.setAttribute('value', key_module);
@@ -53,3 +53,4 @@ function update_module(event){
 
     prefManager.setCharPref("extensions.vwof.modules", s_modules);
 }
+
diff --git a/content/listener.js b/content/listener.js
new file mode 100644
index 0000000..4c54182
--- /dev/null
+++ b/content/listener.js
@@ -0,0 +1,144 @@
+var windowListener = {
+    ignoreFrames:true,
+    onOpenWindow: function (aXULWindow) {
+	let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
+	aDOMWindow.addEventListener("load", function () {
+	    aDOMWindow.removeEventListener("load", arguments.callee, false);
+	    windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
+	}, false);
+    },
+    register: function () {
+	let XULWindows = Services.wm.getXULWindowEnumerator(null);
+	while (XULWindows.hasMoreElements()) {
+	    let aXULWindow = XULWindows.getNext();
+	    let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
+	    windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
+	}
+	// Listen to new windows
+	Services.wm.addListener(windowListener);
+    },
+    unregister: function () {
+	// Unload from any existing windows
+	let XULWindows = Services.wm.getXULWindowEnumerator(null);
+	while (XULWindows.hasMoreElements()) {
+	    let aXULWindow = XULWindows.getNext();
+	    let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
+	    windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
+	}
+	//Stop listening so future added windows dont get this attached
+	Services.wm.removeListener(windowListener);
+    },
+    loadIntoWindow: function (aDOMWindow, aXULWindow) {
+	if (!aDOMWindow) {
+	    return;
+	}
+	if (aDOMWindow.gBrowser) {
+	    aDOMWindow.gBrowser.addEventListener('DOMContentLoaded', listenPageLoad, false);
+	    if (aDOMWindow.gBrowser.tabContainer) {
+		//start - go through all tabs in this window we just added to
+		var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
+		for (var i = 0; i < tabs.length; i++) {
+		    var tabBrowser = tabs[i].linkedBrowser;
+		    var win = tabBrowser.contentWindow;
+		    loadIntoContentWindowAndItsFrames(win);
+		}
+		//end - go through all tabs in this window we just added to
+	    } else {
+		//does not have tabContainer
+		var win = aDOMWindow.gBrowser.contentWindow;
+		loadIntoContentWindowAndItsFrames(win);
+	    }
+	}
+    },
+    unloadFromWindow: function (aDOMWindow, aXULWindow) {
+	if (!aDOMWindow) {
+	    return;
+	}
+	if (aDOMWindow.gBrowser) {
+	    aDOMWindow.gBrowser.removeEventListener('DOMContentLoaded', listenPageLoad, false);
+	    if (aDOMWindow.gBrowser.tabContainer) {
+		//has tabContainer
+		//start - go through all tabs in this window we just added to
+		var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
+		for (var i = 0; i < tabs.length; i++) {
+		    var tabBrowser = tabs[i].linkedBrowser;
+		    var win = tabBrowser.contentWindow;
+		    unloadFromContentWindowAndItsFrames(win);
+		}
+		//end - go through all tabs in this window we just added to
+	    } else {
+		//does not have tabContainer
+		var win = aDOMWindow.gBrowser.contentWindow;
+		unloadFromContentWindowAndItsFrames(win);
+	    }
+	} else {
+	    //window does not have gBrowser
+	}
+    }
+};
+/*end - windowlistener*/
+
+function loadIntoContentWindowAndItsFrames(theWin) {
+    var frames = theWin.frames;
+    var winArr = [theWin];
+    for (var j = 0; j < frames.length; j++) {
+	winArr.push(frames[j].window);
+    }
+    for (var j = 0; j < winArr.length; j++) {
+	var doc = winArr[j].document;
+	//START - edit below here
+
+	if (this.ignoreFrames) {
+	    break;
+	}
+	//END - edit above here
+    }
+}
+
+function unloadFromContentWindowAndItsFrames(theWin) {
+    var frames = theWin.frames;
+    var winArr = [theWin];
+    for (var j = 0; j < frames.length; j++) {
+	winArr.push(frames[j].window);
+    }
+
+    for (var j = 0; j < winArr.length; j++) {
+	var doc = winArr[j].document;
+	//START - edit below here
+	if (this.ignoreFrames) {
+	    break;
+	}
+	//END - edit above here
+    }
+}
+
+/**
+   Listener that observe the prefs variables
+
+   If the module list changes (new module, module deactivated/activated), the parser list is reloaded
+*/
+var PrefObserver = {
+    register: function() {
+	// First we'll need the preference services to look for preferences.
+	var prefService = Components.classes["@mozilla.org/preferences-service;1"]
+	    .getService(Components.interfaces.nsIPrefService);
+
+	// For this.branch we ask for the preferences
+	this.branch = prefService.getBranch("extensions.vwof.");
+
+	// Finally add the observer.
+	this.branch.addObserver("", this, false);
+    },
+
+    unregister: function() {
+	this.branch.removeObserver("", this);
+    },
+
+    observe: function(aSubject, aTopic, aData) {
+	switch (aData) {
+	case "modules":
+	    vwof.set_parsers_activation();
+	    break;
+	}
+    }
+}
diff --git a/modules/FC2.jsm b/content/modules/FC2.jsm
old mode 100755
new mode 100644
similarity index 91%
rename from modules/FC2.jsm
rename to content/modules/FC2.jsm
index 1018e14..cc218b5
--- a/modules/FC2.jsm
+++ b/content/modules/FC2.jsm
@@ -20,7 +20,7 @@ var parser = {
 
 	//get MD5 from video id and salt
 	var id_salt = id+this.SALT;
-	var md5sum = vwofChrome.utils.md5(id_salt);
+	var md5sum = utils.md5(id_salt);
 
 	//get gk (signature generated by JS)
 	var gk = [];
@@ -38,9 +38,9 @@ var parser = {
 	api_video_uri = api_video_uri.replace('MIMI', md5sum);
 	api_video_uri = api_video_uri.replace('GK', gk.join(''));
 	
-	var data = vwofChrome.utils.get(api_video_uri).responseText;
+	var data = utils.get(api_video_uri);
 	//extract the video url (filepath) from the data
-	var assoc_data = vwofChrome.utils.url_vars_to_array(data);
+	var assoc_data = utils.url_vars_to_array(data);
 	var filepath = assoc_data['filepath'];
 	if(!filepath)return;
 
diff --git a/modules/HTML5.jsm b/content/modules/HTML5.jsm
old mode 100755
new mode 100644
similarity index 100%
rename from modules/HTML5.jsm
rename to content/modules/HTML5.jsm
diff --git a/content/modules/Makefile.in b/content/modules/Makefile.in
new file mode 100644
index 0000000..23f8111
--- /dev/null
+++ b/content/modules/Makefile.in
@@ -0,0 +1,2 @@
+# The sources for the module files.
+modules_sources := $(wildcard $(modules_dir)/*.jsm)
diff --git a/content/modules/ScreenWaveMedia.jsm b/content/modules/ScreenWaveMedia.jsm
new file mode 100644
index 0000000..71d935a
--- /dev/null
+++ b/content/modules/ScreenWaveMedia.jsm
@@ -0,0 +1,57 @@
+var parser = {
+    parse_embed: function(cw) {
+	var player;
+	var videos = [];
+	var video_info = [];	
+	const doc = cw.document;
+	const REGEX_ID = /id=(.+)/;
+	const URL_VIDEO = 'http://video2.screenwavemedia.com/vod/VIDEO_ID_QUALITY.mp4';
+	const URL_IMAGE = 'http://image.screenwavemedia.com/VIDEO_ID_thumb_640x360.jpg';
+	const video_quality = ['audio', 'low', 'med', 'high', 'hd1'];
+	const URL_PLAYER_FRAME = 'http://player.screenwavemedia.com/play/player.php';
+	const XPATH_PLAYER_FRAME = "//iframe[starts-with(@src, '"+URL_PLAYER_FRAME+"')]"
+	const URL_PLAYER_SCRIPT = 'http://player.screenwavemedia.com/play/play.php';
+	const XPATH_PLAYER_SCRIPT = "//script[starts-with(@src, '"+URL_PLAYER_SCRIPT+"')]";
+	
+	var xp_res_player_frame = doc.evaluate(XPATH_PLAYER_FRAME, doc, null, 
+					       cw.XPathResult.FIRST_ORDERED_NODE_TYPE, 
+					       null);
+
+	var node = xp_res_player_frame.singleNodeValue;
+
+	if(node){
+	   player = node;
+	}
+	else{
+	    var xp_res_player_script = doc.evaluate(XPATH_PLAYER_SCRIPT, doc, null, 
+					       cw.XPathResult.FIRST_ORDERED_NODE_TYPE, 
+					       null);
+
+	    node = xp_res_player_script.singleNodeValue;
+	    if(!node)return;
+
+	    player = doc.getElementById('videoarea');
+	    player.id = "swmvwof_player";
+	}
+
+	if(!node)return;
+
+	var video_id = node.src.match(REGEX_ID)[1];
+
+	for (var i=0;i<video_quality.length;i++) {
+	    var url = URL_VIDEO.replace('VIDEO_ID', video_id);
+	    url = url.replace("QUALITY", video_quality[i]);
+	    videos.push( {'quality': video_quality[i], 'format':'mp4', 'url':url} );
+	}
+
+	var video_img = URL_IMAGE.replace('VIDEO_ID', video_id);
+	
+	video_info.push({
+	    'player': player,
+	    'video_img':video_img,
+	    'videos': videos
+	});
+
+	return video_info;
+    }
+};
diff --git a/content/modules/blip.jsm b/content/modules/blip.jsm
new file mode 100644
index 0000000..b776df9
--- /dev/null
+++ b/content/modules/blip.jsm
@@ -0,0 +1,118 @@
+var parser = {
+    BASE_URI: 'blip.tv',
+    URL_PARAM_JSON: '?skin=json&no_wrap=1',
+
+    parse_embed: function(cw) {
+	const doc = cw.document;
+	const XPATH_PLAYER = "//iframe[starts-with(@src, 'http://blip.tv/play')]";
+	var video_info = [];
+	var player;
+	var video_img;
+	
+	var xp_res_player = doc.evaluate(XPATH_PLAYER, doc,
+					 null, cw.XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+					 null );
+
+        try{
+	    while (player = xp_res_player.iterateNext()) {
+    	        var videos = [];
+	        var encoded_file;
+	        var player_doc = utils.get(player.src);
+
+	        if((encoded_file = player_doc.match(/"file":"(.+?)",/)) !== null){
+		    var file = decodeURIComponent(encoded_file[1]);
+		    file = file.replace('rss/flash', 'posts/view');
+		    var json_string = utils.get(file+this.URL_PARAM_JSON);
+		    var parse_data = this.parse_json_data(json_string);
+		    video_img = parse_data[0];
+		    videos = parse_data[1];
+	        }
+	        else{
+		    const URL_BASE = 'http://blip.tv/file/get/';
+
+		    const REGEX_VIDEO_URI_HD = 'bliphd720 : "(.*)"';
+		    const REGEX_VIDEO_URI_SD = 'blipsd : "(.*)"';
+		    const REGEX_VIDEO_URI_LD = 'blipld : "(.*)"';
+		    const REGEX_VIDEO_IMG = 'config\.video\.thumbnail = "(.*)"';
+
+		    var video_uri_hd = player_doc.match(REGEX_VIDEO_URI_HD);
+		    var video_uri_sd = player_doc.match(REGEX_VIDEO_URI_SD);
+		    var video_uri_ld = player_doc.match(REGEX_VIDEO_URI_LD);
+		    var video_uri_img = player_doc.match(REGEX_VIDEO_IMG);
+
+		    if(video_uri_hd[1] != ""){
+		        videos.push({'quality':'hd720' , 'url':URL_BASE+video_uri_hd[1]});
+		    }
+		    if(video_uri_sd[1] != ""){
+		        videos.push({'quality':'medium', 'url':URL_BASE+video_uri_sd[1]});
+		    }
+		    if(video_uri_ld[1] != ""){
+		        videos.push({'quality':'low' , 'url':URL_BASE+video_uri_ld[1]});
+		    }
+	            
+		    if(video_uri_img){
+		        video_img = 'http:'+video_uri_img[1];
+		        video_img = video_img.replace('THUMB_WIDTH', player.width);
+		        video_img = video_img.replace('THUMB_HEIGHT', player.height);
+		    }
+	        }
+
+	        video_info.push({
+		    'player': player,
+		    'video_img':video_img,
+		    'videos': videos
+	        });
+	    }
+        }
+        finally{
+            //in case iterateNext() throw invalidStateException 
+            //because of a DOM alteration, return what was fetched
+            return video_info;
+        }
+
+	return video_info;
+    },
+
+    parse_site: function(cw) {
+	var doc = cw.document;
+	var video_info = [];
+	var player = doc.getElementById('PlayeriFrame');
+	if(!player)return;
+	
+	var json_string = utils.get(doc.URL+this.URL_PARAM_JSON);
+	var parse_data = this.parse_json_data(json_string);
+	var video_img = parse_data[0];
+	var videos = parse_data[1];
+	
+	video_info.push({
+	    'player': player,
+	    'video_img': video_img,
+	    'videos': videos
+	});
+
+	return video_info;
+    },
+
+    parse_json_data: function(json_string){
+	var post = JSON.parse(json_string).Post;
+	
+	var videos = [];
+	for(var i=0;i<post.additionalMedia.length;i++){
+	    var format = post.additionalMedia[i].primary_mime_type;
+	    if(format == 'text/plain')continue;
+	    
+	    //remove video part of the mime type for a prettier display
+	    format=format.replace('video/', '');
+
+	    videos.push({'format': format,
+			 'quality': post.additionalMedia[i].media_width + '/' + 
+			 post.additionalMedia[i].media_height,
+			 'url':post.additionalMedia[i].url}
+		       );
+	}
+
+	var video_img = post.thumbnailUrl;
+
+	return [video_img, videos];
+    }
+};
diff --git a/modules/dailymotion.jsm b/content/modules/dailymotion.jsm
old mode 100755
new mode 100644
similarity index 100%
rename from modules/dailymotion.jsm
rename to content/modules/dailymotion.jsm
diff --git a/modules/niconico.jsm b/content/modules/niconico.jsm
old mode 100755
new mode 100644
similarity index 92%
rename from modules/niconico.jsm
rename to content/modules/niconico.jsm
index 61bb763..5e3eb8b
--- a/modules/niconico.jsm
+++ b/content/modules/niconico.jsm
@@ -33,8 +33,8 @@ var parser = {
 	////get the video link from the flapi
 	const video_id = json_data.flashvars.videoId;
 	const flapi_url = 'http://flapi.nicovideo.jp/api/getflv?v='+video_id;
-	const data = vwofChrome.utils.get(flapi_url).responseText;
-	const assoc_data = vwofChrome.utils.url_vars_to_array(data);
+	const data = utils.get(flapi_url);
+	const assoc_data = utils.url_vars_to_array(data);
 	const url = decodeURIComponent(assoc_data['url']);
 	
 	var videos = [ {
diff --git a/modules/youtube.jsm b/content/modules/youtube.jsm
old mode 100755
new mode 100644
similarity index 90%
rename from modules/youtube.jsm
rename to content/modules/youtube.jsm
index ad7910b..c521f21
--- a/modules/youtube.jsm
+++ b/content/modules/youtube.jsm
@@ -22,7 +22,7 @@ var parser = {
 	var player_api = doc.getElementById('player-api');
 	if(player_api){
 	    player_api.setAttribute('id', 'vwof_player-api');  //prevent the player-api div to be erased by the missing plugin tv-static message
-	    if(vwofChrome.youtubeUtils.yt_is_wide()){
+	    if(youtubeUtils.yt_is_wide()){
 		player_api.setAttribute("style", "margin:auto;");  //center the player
 	    }
 	}
@@ -39,7 +39,7 @@ var parser = {
 	player_api.appendChild(player);
 	
 	var api_video_uri = this.API_GET_VIDEO.replace('VIDEO_ID', id);
-	var data = vwofChrome.utils.get(api_video_uri).responseText;
+	var data = utils.get(api_video_uri);
 	var video_data = this.parse_data(data);
 	video_data['player'] = player;
 	
@@ -67,7 +67,7 @@ var parser = {
 
 	    var id = player.src.match(REGEX_VIDEO_ID_IFRAME)[1];
 	    var api_video_uri = this.API_GET_VIDEO.replace('VIDEO_ID', id);
-	    var data = vwofChrome.utils.get(api_video_uri).responseText;
+	    var data = utils.get(api_video_uri);
 
 	    var parsed_array = this.parse_data(data);
 	    parsed_array['player'] = player;
@@ -84,7 +84,7 @@ var parser = {
     */
     parse_data: function(data){
 	var videos = [];
-	var assoc_data = vwofChrome.utils.url_vars_to_array(data);
+	var assoc_data = utils.url_vars_to_array(data);
 
 	var url_encoded_fmt_stream_map = assoc_data['url_encoded_fmt_stream_map'];
 	var url_decoded_fmt_stream_map = decodeURIComponent(url_encoded_fmt_stream_map);
@@ -92,7 +92,7 @@ var parser = {
 	var i;
 	
 	for(i=0;i<arr_url_decoded_fmt_stream_map.length;i++){
-	    var assoc_url_decoded_fmt_stream = vwofChrome.utils.url_vars_to_array(arr_url_decoded_fmt_stream_map[i]);
+	    var assoc_url_decoded_fmt_stream = utils.url_vars_to_array(arr_url_decoded_fmt_stream_map[i]);
 	    var encoded_uri = assoc_url_decoded_fmt_stream['url'];
 	    var decoded_uri = decodeURIComponent(encoded_uri);
 	    decoded_uri += '&signature='+assoc_url_decoded_fmt_stream['sig'];    //add the signature to the decoded url
diff --git a/chrome/content/player.js b/content/player.js
old mode 100755
new mode 100644
similarity index 98%
rename from chrome/content/player.js
rename to content/player.js
index 80e2958..809768b
--- a/chrome/content/player.js
+++ b/content/player.js
@@ -1,7 +1,3 @@
-if ("undefined" == typeof(vwofPlayer)) {
-    var vwofPlayer = {};
-};
-
 vwofPlayer = {
     /**
        add the player stylecheet link to the head of the document
@@ -10,7 +6,7 @@ vwofPlayer = {
 	var style = doc.createElement('link');
 	style.setAttribute('type', 'text/css');
 	style.setAttribute('rel', 'stylesheet');
-	style.setAttribute('href', 'chrome://vwof/content/player.css');
+	style.setAttribute('href', 'chrome://vwof/skin/player.css');
 	style.setAttribute('id', style_id);
 	doc.head.appendChild(style);
     },
diff --git a/content/prefs.js b/content/prefs.js
new file mode 100644
index 0000000..2764774
--- /dev/null
+++ b/content/prefs.js
@@ -0,0 +1,47 @@
+function getGenericPref(branch,prefName)
+{
+    switch (branch.getPrefType(prefName))
+    {
+        default:
+        case 0:   return undefined;                      // PREF_INVALID
+        case 32:  return getUCharPref(prefName,branch);  // PREF_STRING
+        case 64:  return branch.getIntPref(prefName);    // PREF_INT
+        case 128: return branch.getBoolPref(prefName);   // PREF_BOOL
+    }
+}
+
+function setGenericPref(branch,prefName,prefValue)
+{
+    switch (typeof prefValue)
+    {
+      case "string":
+          setUCharPref(prefName,prefValue,branch);
+          return;
+      case "number":
+          branch.setIntPref(prefName,prefValue);
+          return;
+      case "boolean":
+          branch.setBoolPref(prefName,prefValue);
+          return;
+    }
+}
+
+function setDefaultPref(prefBranch, prefName, prefValue)
+{
+    var defaultBranch = Services.prefs.getDefaultBranch(prefBranch);
+    setGenericPref(defaultBranch,prefName,prefValue);
+}
+
+function getUCharPref(prefName,branch)  // Unicode getCharPref
+{
+    branch = branch ? branch : Services.prefs;
+    return branch.getComplexValue(prefName, Components.interfaces.nsISupportsString).data;
+}
+function setUCharPref(prefName,text,branch)  // Unicode setCharPref
+{
+    var string = Components.classes["@mozilla.org/supports-string;1"]
+                           .createInstance(Components.interfaces.nsISupportsString);
+    string.data = text;
+    branch = branch ? branch : Services.prefs;
+    branch.setComplexValue(prefName, Components.interfaces.nsISupportsString, string);
+}
diff --git a/content/prefs.xul b/content/prefs.xul
new file mode 100644
index 0000000..fcef025
--- /dev/null
+++ b/content/prefs.xul
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<prefwindow id="vwofPrefWindow" 
+            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <prefpane id="vwof_pref_general" label="General">
+  
+    <preferences>
+      <preference id="extensions.vwof.activate_onload" 
+                  name="extensions.vwof.activate_onload"
+                  type="bool"/>
+      <preference id="plugins.notifyMissingFlash" 
+                  name="plugins.notifyMissingFlash" 
+                  type="bool"/>
+      <preference id="full-screen-api.approval-required"
+                  name="full-screen-api.approval-required" 
+                  type="bool"/>
+    </preferences>
+
+    <checkbox label="Detect videos on page load" 
+              preference="extensions.vwof.activate_onload"/>
+    <checkbox label="Enable missing flash plugin warnings" 
+              preference="plugins.notifyMissingFlash"/>
+    <checkbox label="Enable approval message when fullscreen" 
+              preference="full-screen-api.approval-required"/>
+    
+  </prefpane>
+
+  <prefpane id="vwof_pref_prefered_format" label="Prefered format">
+    <preferences>
+      <preference id="extensions.vwof.prefered_quality" 
+                  name="extensions.vwof.prefered_quality" 
+                  type="string" />
+      <preference id="extensions.vwof.prefered_format" 
+                  name="extensions.vwof.prefered_format" 
+                  type="string" />
+    </preferences>
+    
+    <label value="Prefered format" control="prefered_format" />
+    <menulist id="prefered_format" preference="extensions.vwof.prefered_format" 
+              preference-editable="true">
+      <menupopup>
+	<menuitem label="webm" value="webm"/>
+	<menuitem label="mp4" value="mp4"/>
+	<menuitem label="avi" value="avi"/>
+	<menuitem label="flv" value="flv"/>	
+      </menupopup>
+    </menulist>
+
+    <label value="Prefered quality" control="prefered_quality" />    
+    <menulist id="prefered_quality" preference="extensions.vwof.prefered_quality"
+              preference-editable="true">
+      <menupopup>
+	<menuitem label="hd1080" value="hd1080"/>
+	<menuitem label="hd720" value="hd720"/>
+	<menuitem label="medium" value="medium"/>
+	<menuitem label="low" value="low"/>	
+      </menupopup>
+    </menulist>
+    
+  </prefpane>
+  
+  <prefpane id="vwof_pref_modules" label="modules">
+    <script type="application/x-javascript" src="chrome://vwof/content/browserOverlay.js" />
+    <script type="application/x-javascript" src="chrome://vwof/content/youtube_utils.js" />
+
+    <preferences>
+      <preference id="extensions.vwof.modules" name="extensions.vwof.modules" type="string"/>
+    </preferences>
+ 
+    <checkbox id="vwof_yt_wide" label="YouTube theater mode" 
+              oncommand="vwofChrome.youtubeUtils.toggle_yt_wide(event)"/>
+  </prefpane>
+  
+  <script src="youtube_utils.js"/>
+  <script src="vwof.js"/> 
+  <script src="list_modules.js"/>
+
+</prefwindow>
+
diff --git a/chrome/content/utils.js b/content/utils.js
old mode 100755
new mode 100644
similarity index 89%
rename from chrome/content/utils.js
rename to content/utils.js
index 5d1025e..cdc8dc6
--- a/chrome/content/utils.js
+++ b/content/utils.js
@@ -1,7 +1,5 @@
-vwofChrome.utils = {
-    /**
-       needed by some parser to get the video source
-    */
+var utils = {
+
     get:function(uri){
 	const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1",
 						      "nsIXMLHttpRequest",
@@ -9,12 +7,9 @@ vwofChrome.utils = {
 	
 	let xmlhttp = XMLHttpRequest("GET", uri, false);
 	xmlhttp.send();
-	return xmlhttp;
+	return xmlhttp.responseText;
     },
     
-    /**
-       converts url vars into a js associative array
-    */
     url_vars_to_array: function(url){
 	var arr_variable = url.split('&');
 	var arr_assoc = {};
diff --git a/content/vwof.js b/content/vwof.js
new file mode 100644
index 0000000..e251ec4
--- /dev/null
+++ b/content/vwof.js
@@ -0,0 +1,89 @@
+var vwof= {
+    parsers:{},   //hash of the parsers (loaded from jsm modules)
+    parser_name:["blip", "dailymotion", "FC2", "HTML5", "niconico", "youtube", "ScreenWaveMedia"],
+
+    /**
+       Load modules listed in the extensions.vwof.modules pref variable to this.parsers hash
+    */
+    load_modules:function(){
+	for(var i=0;i<this.parser_name.length;i++){
+            let key_parser = this.parser_name[i];
+	    let context = {};
+	    let res = 'chrome://vwof/content/modules/'+key_parser+'.jsm';
+	    Services.scriptloader.loadSubScript(res, context, "UTF-8");
+	    this.parsers[key_parser] = context;
+	}
+    },
+    set_parsers_activation:function(){
+	//check in the preferences : activated a parser on page load or not
+	Components.utils.import("resource://gre/modules/Services.jsm");
+	var prefManager = Components.classes["@mozilla.org/preferences-service;1"]
+	    .getService(Components.interfaces.nsIPrefBranch);
+
+	var modules_list = prefManager.getCharPref("extensions.vwof.modules");
+	var modules = JSON.parse(modules_list);  //parser / value from the preferences
+
+	for(var key_parser in this.parsers){
+ 	    var parser = this.parsers[key_parser].parser;
+
+	    //if a pref is defined for this parser
+	    if(modules[key_parser])
+		parser['activated'] = modules[key_parser]?true:false;
+	    else 
+		parser['activated'] = false;
+	}
+    },    
+    getVideoInfo:function (cw) {
+	var video_info = [];	// array of video_data
+	var has_parsed_site = false;
+	
+	for(var key_parser in this.parsers){
+  	    try{
+		var parser = this.parsers[key_parser].parser;
+		if(parser['activated'] != true)continue;
+		var video_data = [];  //array of video links with quality
+
+		//if the parser has a URI and it's the current location
+		if(parser.BASE_URI && cw.location.hostname == parser.BASE_URI){
+		    video_data = parser.parse_site(cw);
+		    has_parsed_site = true;
+		}
+		else if(parser.parse_embed){
+		    video_data = parser.parse_embed(cw);
+		}
+
+		//if there is at least a video url retreived from the parser
+		if(video_data.length >= 1){		    
+		    //set the source (name of the parser)
+		    for(var i=0;i < video_data.length;i++){
+			video_data[i]['source'] = this.parsers[key_parser].name;
+		    }
+		    
+                    //concat the chunks of video(s) from this parser
+		    video_info = video_info.concat(video_data);
+		}
+	    }
+	    catch(err){
+		Components.utils.reportError("vwof plugin, exception in "+key_parser+": "+err);
+	    };
+
+	    //official web sites do not embed several videos, so don't use other parsers
+	    if(has_parsed_site){break;}
+	}
+
+	return video_info;
+    },
+    
+    detectVideo:function(cw) {
+	var video_info = this.getVideoInfo(cw);
+
+	for (var i = 0; i < video_info.length; i++) {
+	    if(video_info[i]['player']){
+    		var replace_location = video_info[i]['player'];
+		var player = vwofPlayer.create_video_selector(video_info[i], cw);
+		var replace_parent = replace_location.parentNode;
+		replace_parent.replaceChild(player, replace_location);
+	    }
+	}
+    }    
+};
diff --git a/chrome/content/youtube_utils.js b/content/youtube_utils.js
old mode 100755
new mode 100644
similarity index 90%
rename from chrome/content/youtube_utils.js
rename to content/youtube_utils.js
index 7842b7c..c0e1f0c
--- a/chrome/content/youtube_utils.js
+++ b/content/youtube_utils.js
@@ -1,7 +1,4 @@
-if("undefined" == typeof(vwofChrome)){
-    var vwofChrome = {};
-}
-vwofChrome.youtubeUtils = {
+var youtubeUtils = {
     toggle_yt_wide:function (event){
 	var c = event.target.hasAttribute('checked')?1:0;
 	var wide;
@@ -36,7 +33,7 @@ vwofChrome.youtubeUtils = {
 	}
 	catch (errorInfo)
 	{
-	    console.error(errorInfo);
+	    Components.utils.reportError(errorInfo);
 	}
 	return wide;
     }
diff --git a/defaults/preferences/vwof.js b/defaults/preferences/vwof.js
old mode 100755
new mode 100644
index ab25570..4090ad2
--- a/defaults/preferences/vwof.js
+++ b/defaults/preferences/vwof.js
@@ -1,4 +1,3 @@
-pref("extensions.vwof.activate_onload", true);
 pref("extensions.vwof.prefered_quality", 'medium');
 pref("extensions.vwof.prefered_format", 'webm');
-pref("extensions.vwof.modules", '{"HTML5":1, "blip":1, "youtube":1, "dailymotion":1, "niconico":1, "FC2":1}');
+pref("extensions.vwof.modules", '{"HTML5":1, "springboard":1, "blip":1, "youtube":1, "dew":1, "SWM":1, "dailymotion":1, "ustream":1, "niconico":1, "FC2":1}');
diff --git a/install.rdf b/install.rdf
index fa36e99..6de29d7 100755
--- a/install.rdf
+++ b/install.rdf
@@ -1,25 +1,45 @@
 <?xml version="1.0"?>
 
 <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-  xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
 
   <Description about="urn:mozilla:install-manifest">
+
+    <!-- The id of the extension. -->
     <em:id>vwof at drev.com</em:id>
+
+    <!-- A version string identifying the version of the add-on. -->
+    <em:version>2.0.2</em:version>
+
+    <!-- The name of the add-on; intended for display in the UI. -->
     <em:name>Video WithOut Flash</em:name>
+
+    <!-- A short description to display in the user interface. -->
     <em:description>Watch videos without flash</em:description>
-    <em:version>1.5.1</em:version>
-    <em:creator>Drevet Olivier</em:creator>
-    <em:homepageURL>http://olivier.drevet.free.fr</em:homepageURL>
-    <em:type>2</em:type>
-    <em:optionsURL>chrome://vwof/content/prefs.xul</em:optionsURL>
 
-    <!-- Mozilla Firefox -->
+    <!-- The name of the developer to display in the user interface. -->
+    <em:creator>DREVET Olivier</em:creator>
+
+    <!-- A link to the add-on home page to display in the user interface. -->
+    <em:homepageURL>http://mozilla.org</em:homepageURL>
+
+    <!-- Target Application this extension can install into,
+         with minimum and maximum supported versions. -->
     <em:targetApplication>
       <Description>
+        <!-- Mozilla Firefox -->
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>3.0</em:minVersion>
-        <em:maxVersion>33.0</em:maxVersion>
+        <em:minVersion>27.0</em:minVersion>
+        <em:maxVersion>34.0</em:maxVersion>
       </Description>
     </em:targetApplication>
+
+    <!-- An integer value representing the type of add-on. -->
+    <em:type>2</em:type> <!-- Extensions -->
+
+    <!-- Tells the application whether the extension is boot-strappable. -->
+    <em:bootstrap>true</em:bootstrap>
+
+    <em:optionsURL>chrome://vwof/content/prefs.xul</em:optionsURL>    
   </Description>
 </RDF>
diff --git a/locale/en-US/strings.dtd b/locale/en-US/strings.dtd
new file mode 100644
index 0000000..83ebffb
--- /dev/null
+++ b/locale/en-US/strings.dtd
@@ -0,0 +1 @@
+<!ENTITY VideoUI.label "Open in a new tab">
diff --git a/locale/en-US/strings.properties b/locale/en-US/strings.properties
new file mode 100644
index 0000000..139c356
--- /dev/null
+++ b/locale/en-US/strings.properties
@@ -0,0 +1,3 @@
+Video.label=vwof
+Video.tooltip=Watch videos without flash
+Video.commandkey=W
diff --git a/modules/blip.jsm b/modules/blip.jsm
deleted file mode 100755
index f1d3137..0000000
--- a/modules/blip.jsm
+++ /dev/null
@@ -1,111 +0,0 @@
-var parser = {
-    BASE_URI: 'blip.tv',
-    URL_PARAM_JSON: '?skin=json&no_wrap=1',
-
-    parse_embed: function(cw) {
-	var doc = cw.document;
-	const XPATH_PLAYER = "//iframe[starts-with(@src, 'http://blip.tv/play')]";
-	var video_info = [];
-	var player;
-	var video_img;
-	
-	var xp_res_player = doc.evaluate(XPATH_PLAYER, doc,
-					 null, cw.XPathResult.UNORDERED_NODE_ITERATOR_TYPE, 
-					 null );
-
-	while (player = xp_res_player.iterateNext()) {
-    	    var videos = [];
-	    var encoded_file;
-	    var player_doc = vwofChrome.utils.get(player.src).responseText;
-
-	    if((encoded_file = player_doc.match(/"file":"(.+?)",/)) !== null){
-		var file = decodeURIComponent(encoded_file[1]);
-		file = file.replace('rss/flash', 'posts/view');
-		var json_string = vwofChrome.utils.get(file+this.URL_PARAM_JSON).responseText;
-		var parse_data = this.parse_json_data(json_string);
-		video_img = parse_data[0];
-		videos = parse_data[1];
-	    }
-	    else{
-		const URL_BASE = 'http://blip.tv/file/get/';
-
-		const REGEX_VIDEO_URI_HD = 'bliphd720 : "(.*)"';
-		const REGEX_VIDEO_URI_SD = 'blipsd : "(.*)"';
-		const REGEX_VIDEO_URI_LD = 'blipld : "(.*)"';
-		const REGEX_VIDEO_IMG = 'config\.video\.thumbnail = "(.*)"';
-
-		var video_uri_hd = player_doc.match(REGEX_VIDEO_URI_HD);
-		var video_uri_sd = player_doc.match(REGEX_VIDEO_URI_SD);
-		var video_uri_ld = player_doc.match(REGEX_VIDEO_URI_LD);
-		var video_uri_img = player_doc.match(REGEX_VIDEO_IMG);
-
-		if(video_uri_hd[1] != ""){
-		    videos.push({'quality':'hd720' , 'url':URL_BASE+video_uri_hd[1]});
-		}
-		if(video_uri_sd[1] != ""){
-		    videos.push({'quality':'medium', 'url':URL_BASE+video_uri_sd[1]});
-		}
-		if(video_uri_ld[1] != ""){
-		    videos.push({'quality':'low' , 'url':URL_BASE+video_uri_ld[1]});
-		}
-	
-		if(video_uri_img){
-		    video_img = 'http:'+video_uri_img[1];
-		    video_img = video_img.replace('THUMB_WIDTH', player.width);
-		    video_img = video_img.replace('THUMB_HEIGHT', player.height);
-		}
-	    }
-
-	    video_info.push({
-		'player': player,
-		'video_img':video_img,
-		'videos': videos
-	    });
-	}
-
-	return video_info;
-    },
-
-    parse_site: function(cw) {
-	var doc = cw.document;
-	var video_info = [];
-	var player = doc.getElementById('PlayeriFrame');
-	if(!player)return;
-	
-	var json_string = vwofChrome.utils.get(doc.URL+this.URL_PARAM_JSON).responseText;
-	var parse_data = this.parse_json_data(json_string);
-	var video_img = parse_data[0];
-	var videos = parse_data[1];
-	
-	video_info.push({
-	    'player': player,
-	    'video_img': video_img,
-	    'videos': videos
-	});
-
-	return video_info;
-    },
-
-    parse_json_data: function(json_string){
-	var post = JSON.parse(json_string).Post;
-	
-	var videos = [];
-	for(var i=0;i<post.additionalMedia.length;i++){
-	    var format = post.additionalMedia[i].primary_mime_type;
-	    if(format == 'text/plain')continue;
-	    
-	    //remove video part of the mime type for a prettier display
-	    format=format.replace('video/', '');
-
-	    videos.push({'format': format,
-			 'quality': post.additionalMedia[i].media_width + '/' + 
-			 post.additionalMedia[i].media_height,
-			 'url':post.additionalMedia[i].url}
-		       );
-	}
-
-	var video_img = post.thumbnailUrl;
-
-	return [video_img, videos];
-    }
-};
diff --git a/chrome/content/player.css b/skin/player.css
old mode 100755
new mode 100644
similarity index 96%
rename from chrome/content/player.css
rename to skin/player.css
index 41d2ae3..0135922
--- a/chrome/content/player.css
+++ b/skin/player.css
@@ -7,7 +7,7 @@
     background-size: 100%;
     background-repeat: no-repeat;
     background-size: contain;
-    background-position: center top;    
+    background-position: center top;
     display:block;
     cursor:pointer;
     z-index:1;
diff --git a/chrome/skin/video-icon.png b/skin/video-icon.png
old mode 100755
new mode 100644
similarity index 100%
rename from chrome/skin/video-icon.png
rename to skin/video-icon.png

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/video-without-flash.git



More information about the Pkg-mozext-commits mailing list