summaryrefslogtreecommitdiff
path: root/extensions/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/chrome')
-rw-r--r--extensions/chrome/_locales/en/messages.json8
-rw-r--r--extensions/chrome/common.js187
-rw-r--r--extensions/chrome/inject_and_return.js28
-rw-r--r--extensions/chrome/inject_exec.js74
-rw-r--r--extensions/chrome/manifest.json23
5 files changed, 320 insertions, 0 deletions
diff --git a/extensions/chrome/_locales/en/messages.json b/extensions/chrome/_locales/en/messages.json
new file mode 100644
index 0000000..eebbc14
--- /dev/null
+++ b/extensions/chrome/_locales/en/messages.json
@@ -0,0 +1,8 @@
+{
+ "title": {
+ "message": "VK Player Controller Client"
+ },
+ "description_short": {
+ "message": "Chrome client for VK Player Controller app."
+ }
+}
diff --git a/extensions/chrome/common.js b/extensions/chrome/common.js
new file mode 100644
index 0000000..30dc55a
--- /dev/null
+++ b/extensions/chrome/common.js
@@ -0,0 +1,187 @@
+function init() {
+ // receive messages from webpage
+ chrome.runtime.onMessageExternal.addListener(receiveMessage);
+}
+function receiveMessage(msg, sender, sendResponse) {
+ if (msg.cmd == "injection_result") {
+ var obj = Injections.get(msg.id);
+ if (obj) obj.addResponse(sender.tab.id, msg.data);
+ }
+}
+function extend(dest, source) {
+ for (var i in source) {
+ dest[i] = source[i];
+ }
+}
+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 getExtensionId() {
+ return chrome.i18n.getMessage("@@extension_id");
+}
+function getVKTabs(callback) {
+ var vkTabs = [];
+ chrome.tabs.query({}, function(tabs) {
+ for (var i = 0; i < tabs.length; i++) {
+ var tab = tabs[i];
+ if (tab.url.match(new RegExp('https?://vk.com/.*', 'gi'))) {
+ vkTabs.push(tab);
+ }
+ }
+ callback(vkTabs);
+ });
+}
+function executeCommand(cmd) {
+ var injId = Injections.getNextId();
+ var code_inj = "var el = document.createElement('script'); el.src = chrome.extension.getURL('inject_and_return.js'); document.body.appendChild(el); var el1 = document.createElement('script'); el1.textContent = 'window.__vkpc_extid=\""+getExtensionId()+"\"; window.__vkpc_injid="+injId+"'; document.body.appendChild(el1)";
+ var code_exec = "var el = document.createElement('script'); el.src = chrome.extension.getURL('inject_exec.js'); document.body.appendChild(el); var el1 = document.createElement('script'); el1.textContent = 'window.__vkpc_cmd=\""+cmd+"\"'; document.body.appendChild(el1)";
+
+ getVKTabs(function(tabs) {
+ if (!tabs.length) return;
+
+ var injResponses, activeTabId = null;
+ var onDone = function() {
+ var ok = {nowPlaying: null, lsSource: null, recentlyPlayed: null, active: activeTabId, last: null};
+ var results = injResponses.results, lsSource = injResponses.lsSource;
+
+ for (var i = 0; i < results.length; i++) {
+ var data = results[i].data, id = results[i].tab;
+ ok.last = id;
+
+ if (data.havePlayer && (data.isPlaying || typeof data.trackId == 'string')) {
+ ok.recentlyPlayed = id;
+ }
+ if (data.isPlaying) {
+ ok.nowPlaying = id;
+ }
+ if (lsSource && lsSource == data.instanceId) {
+ ok.lsSource = id;
+ }
+ }
+ injResponses.unregister();
+
+ var rightId = ok.nowPlaying || ok.lsSource || ok.recentlyPlayed || ok.active || ok.last;
+ if (rightId) {
+ chrome.tabs.executeScript(rightId, {code: code_exec});
+ }
+ };
+ injResponses = new InjectionResponses(injId, tabs.length, onDone);
+
+ for (var i = 0; i < tabs.length; i++) {
+ if (tabs[i].active) activeTabId = tabs[i].id;
+ chrome.tabs.executeScript(tabs[i].id, {
+ code: code_inj
+ });
+ }
+ });
+}
+
+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 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);
+ }
+
+ 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(id, response) {
+ this.results.push({tab: id, 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();
diff --git a/extensions/chrome/inject_and_return.js b/extensions/chrome/inject_and_return.js
new file mode 100644
index 0000000..ebb2827
--- /dev/null
+++ b/extensions/chrome/inject_and_return.js
@@ -0,0 +1,28 @@
+(function() {
+ function getLastInstanceId() {
+ var id = null, pp = ls.get('pad_playlist');
+ if (pp && pp.source) id = pp.source;
+ return id;
+ }
+
+ var data = {};
+ try {
+ var havePlayer = window.audioPlayer !== undefined;
+ var havePlaylist = havePlayer && !!padAudioPlaylist();
+
+ data = {
+ havePlayer: havePlayer,
+ havePlaylist: havePlaylist,
+ isPlaying: havePlayer && window.audioPlayer.player && !window.audioPlayer.player.paused(),
+ instanceId: window.curNotifier && curNotifier.instance_id,
+ trackId: havePlayer && audioPlayer.id,
+ lastInstanceId: getLastInstanceId()
+ };
+ } catch(e) {}
+
+ chrome.runtime.sendMessage(window.__vkpc_extid, {
+ cmd: "injection_result",
+ id: parseInt(window.__vkpc_injid, 10),
+ data: data
+ });
+})();
diff --git a/extensions/chrome/inject_exec.js b/extensions/chrome/inject_exec.js
new file mode 100644
index 0000000..c1df18f
--- /dev/null
+++ b/extensions/chrome/inject_exec.js
@@ -0,0 +1,74 @@
+(function() {
+ function vkAudio__getPlayFirstId() {
+ var id = currentAudioId() || ls.get('audio_id') || (window.audioPlaylist && audioPlaylist.start);
+ return id || null;
+ }
+ function vkAudio__executeAfterPadLoading(f) {
+ Pads.show('mus');
+ window.onPlaylistLoaded = function() {
+ if (f) {
+ try {
+ f();
+ } catch(e) {}
+ }
+ setTimeout(function() {
+ Pads.show('mus');
+ }, 10);
+ }
+ }
+ function vkAudio__next() {
+ console.log("Next");
+ window.audioPlayer && audioPlayer.nextTrack(true, !window.audioPlaylist);
+ }
+ function vkAudio__prev() {
+ console.log("Prev");
+ window.audioPlayer && audioPlayer.prevTrack(true, !window.audioPlaylist);
+ }
+ function vkAudio__playPause() {
+ console.log("PlayPause");
+ if (!window.audioPlayer || !padAudioPlaylist()) {
+ stManager.add(['audioplayer.js'], function() {
+ vkAudio__executeAfterPadLoading(function() {
+ var plist = padAudioPlaylist(), id = vkAudio__getPlayFirstId();
+ if (id) {
+ playAudioNew(id);
+ } else if (plist && plist.start) {
+ playAudioNew(plist.start);
+ }
+ });
+ });
+ } else {
+ if (window.audioPlayer && audioPlayer.player) {
+ if (audioPlayer.player.paused()) {
+ audioPlayer.playTrack();
+ } else {
+ audioPlayer.pauseTrack();
+ }
+ }
+ }
+ }
+
+ try {
+ var data = window.__vkpc_cmd;
+ if (data) {
+ switch (data) {
+ case "next":
+ vkAudio__next();
+ break;
+
+ case "prev":
+ vkAudio__prev();
+ break;
+
+ case "play":
+ case "pause":
+ vkAudio__playPause();
+ break;
+ }
+
+ delete window.__vkpc_cmd;
+ }
+ } catch (e) {
+ console.log('[VKPC]', e, e.stack);
+ }
+})();
diff --git a/extensions/chrome/manifest.json b/extensions/chrome/manifest.json
new file mode 100644
index 0000000..f7b29d7
--- /dev/null
+++ b/extensions/chrome/manifest.json
@@ -0,0 +1,23 @@
+{
+ "manifest_version": 2,
+ "name": "__MSG_title__",
+ "description": "__MSG_description_short__",
+ "version": "0.1",
+ "default_locale": "en",
+ "permissions": [
+ "background",
+ "tabs",
+ "https://vk.com/*",
+ "http://vk.com/*",
+ "https://*.vk.com/*",
+ "http://*.vk.com/*"
+ ],
+ "background": {
+ "scripts": ["common.js"]
+ },
+ "externally_connectable": {
+ "matches": ["https://vk.com/*", "http://vk.com/*", "https://*.vk.com/*", "http://*.vk.com/*"]
+ },
+ "content_security_policy": "script-src 'self' 'unsafe-eval' https://vk.com; object-src 'self' 'unsafe-eval'",
+ "web_accessible_resources": ["inject_and_return.js", "inject_exec.js"]
+}