aboutsummaryrefslogtreecommitdiff
path: root/extensions/firefox/chrome/background.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/firefox/chrome/background.js')
-rw-r--r--extensions/firefox/chrome/background.js258
1 files changed, 258 insertions, 0 deletions
diff --git a/extensions/firefox/chrome/background.js b/extensions/firefox/chrome/background.js
new file mode 100644
index 0000000..2795a8c
--- /dev/null
+++ b/extensions/firefox/chrome/background.js
@@ -0,0 +1,258 @@
+var VKPC = new function() {
+
+function init() {
+ window.addEventListener("load", function load(event) {
+ window.removeEventListener("load", load, false);
+ injectOnLoad();
+ }, false);
+
+ WSClient.go();
+}
+function extend(dest, source) {
+ for (var i in source) {
+ dest[i] = source[i];
+ }
+}
+function remove(element) {
+ element.parentNode.removeChild(element);
+}
+function createCData(data) {
+ var docu = new DOMParser().parseFromString('<xml></xml>', "application/xml");
+ var cdata = docu.createCDATASection(data);
+ docu.getElementsByTagName('xml')[0].appendChild(cdata);
+ return cdata;
+}
+function getWebSocket() {
+ return window.WebSocket || window.MozWebSocket;
+}
+function print() {
+ var msgs = [], i, tmp;
+ for (i = 0; i < arguments.length; i++) {
+ if (arguments[i] instanceof Error) tmp = [arguments[i], arguments[i].stack];
+ else tmp = arguments[i];
+ msgs.push(tmp);
+ }
+
+ try {
+ console.log.apply(console, msgs);
+ } catch(e) {}
+}
+function injectOnLoad() {
+ function onPageLoaded(e) {
+ var doc = e.originalTarget, loc = doc.location;
+ if (!loc.href.match(/^https?:\/\/vk.com\/.*$/)) return;
+
+ doc.addEventListener("VKPCInjectedMessage", function(e) {
+ var target = e.target, json = JSON.parse(target.data || "{}"), doc = target.ownerDocument;
+ receiveMessage(json, doc, target);
+ }, false);
+
+ var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
+ loader.loadSubScript("chrome://vkpc/content/inject_on_load.js", doc);
+ }
+
+ var appcontent = document.getElementById("appcontent");
+ if (appcontent) {
+ appcontent.addEventListener("DOMContentLoaded", onPageLoaded, true);
+ }
+}
+function receiveMessage(json, doc, target) {
+ switch (json.cmd) {
+ case "register":
+ Documents.add(doc);
+ break;
+
+ case "params":
+ var id = json.id;
+ var obj = Injections.get(id);
+ if (obj) {
+ obj.addResponse(doc, json.data);
+ }
+ break;
+ }
+
+ try {
+ remove(target);
+ } catch (e) {}
+}
+function executeCommand(cmd) {
+ var injId = Injections.getNextId();
+
+ var tabsCount = Documents.getCount();
+ if (!tabsCount) return;
+
+ var injResponses;
+ var onDone = function() {
+ var ok = {nowPlaying: null, lsSource: null, recentlyPlayed: null, active: null, last: null};
+ var results = injResponses.results, lsSource = injResponses.lsSource;
+
+ for (var i = 0; i < results.length; i++) {
+ var data = results[i].data, doc = results[i].tab;
+ ok.last = doc;
+
+ if (data.havePlayer && (data.isPlaying || typeof data.trackId == 'string')) {
+ ok.recentlyPlayed = doc;
+ }
+ if (data.isPlaying) {
+ ok.nowPlaying = doc;
+ }
+ if (lsSource && lsSource == data.instanceId) {
+ ok.lsSource = doc;
+ }
+ if (data.isFocused) {
+ ok.active = doc;
+ }
+ }
+ injResponses.unregister();
+
+ var rightDoc = ok.nowPlaying || ok.lsSource || ok.recentlyPlayed || ok.active || ok.last;
+ if (rightDoc) {
+ Documents.sendToDoc(rightDoc, {
+ cmd: "audioCommand",
+ command: cmd
+ });
+ }
+ };
+
+ injResponses = new InjectionResponses(injId, tabsCount, onDone);
+
+ Documents.send({
+ cmd: "getParams",
+ id: injId
+ });
+}
+
+var Injections = {
+ id: 0,
+ objs: {},
+ getNextId: function() {
+ return ++this.id;
+ },
+ get: function(id) {
+ return this.objs[id] || false;
+ },
+ register: function(id, obj) {
+ this.objs[id] = obj;
+ },
+ unregister: function(id) {
+ if (this.objs[id] !== undefined) delete this.objs[id];
+ }
+};
+
+var Documents = {
+ list: [],
+ add: function(doc) {
+ this.cleanup();
+ this.list.push(doc);
+ },
+ cleanup: function() {
+ this.list = this.list.filter(function(t) {
+ return Object.prototype.toString.call(t) != '[object DeadObject]';
+ });
+ },
+ send: function(json) {
+ var self = this;
+ this.cleanup();
+
+ this.list.forEach(function(doc) {
+ self.sendToDoc(doc, json);
+ });
+ },
+ sendToDoc: function(doc, json) {
+ var cdata = createCData(JSON.stringify(json));
+ doc.getElementById('utils').appendChild(cdata);
+
+ var evt = doc.createEvent("Events");
+ evt.initEvent("VKPCBgMessage", true, false);
+ cdata.dispatchEvent(evt);
+ },
+ getCount: function() {
+ this.cleanup();
+ return this.list.length;
+ }
+};
+
+var WSClient = new function() {
+ var STATUS_NONE = 0, STATUS_OK = 1, STATUS_ERR = 2;
+ var _ws = getWebSocket(), ws;
+ var _status = STATUS_NONE;
+ var ping_timer, reconnect_timer;
+
+ if (!_ws) return;
+
+ function setTimers() {
+ ping_timer = setInterval(function() {
+ if (ws) ws.send("PING");
+ }, 30000);
+ }
+ function unsetTimers() {
+ clearInterval(ping_timer);
+ }
+
+ function connect() {
+ _status = STATUS_NONE;
+
+ print("[connect]");
+ ws = new _ws("ws://localhost:52178", "signaling-protocol");
+ ws.onopen = function() {
+ _status = STATUS_OK;
+ setTimers();
+ };
+ ws.onerror = function() {
+ unsetTimers();
+ if (_status != STATUS_ERR) {
+ _status = STATUS_ERR;
+ tryToReconnect();
+ }
+ }
+ ws.onclose = function() {
+ unsetTimers();
+ if (_status != STATUS_ERR) {
+ _status = STATUS_ERR;
+ tryToReconnect();
+ }
+ };
+ ws.onmessage = function(e) {
+ onCommand(e.data);
+ };
+ }
+ function tryToReconnect() {
+ print("[tryToReconnect]");
+
+ clearTimeout(reconnect_timer);
+ reconnect_timer = setTimeout(connect, 5000);
+ }
+ function onCommand(msg) {
+ executeCommand(msg);
+ }
+
+ this.go = function() {
+ connect();
+ }
+};
+
+function InjectionResponses(id, count, callback) {
+ this.id = id;
+ this.results = [];
+ this.lsSource = null;
+ this.maxCount = count;
+ this.callback = callback || function() {};
+
+ Injections.register(this.id, this);
+}
+extend(InjectionResponses.prototype, {
+ addResponse: function(doc, response) {
+ this.results.push({tab: doc, data: response});
+ if (!this.lsSource && response && response.lastInstanceId) this.lsSource = response.lastInstanceId;
+ if (this.results.length == this.maxCount) {
+ this.callback();
+ }
+ },
+ unregister: function() {
+ Injections.unregister(this.id);
+ }
+});
+
+init();
+
+};