271 lines
6.4 KiB
JavaScript
271 lines
6.4 KiB
JavaScript
var browser = (function() {
|
|
var ua = navigator.userAgent.toLowerCase();
|
|
var browser = {
|
|
id: null,
|
|
chrome: false,
|
|
safari: false,
|
|
yandex: false,
|
|
firefox: false,
|
|
opera: false
|
|
};
|
|
|
|
if (/opr/i.test(ua) && /chrome/i.test(ua)) {
|
|
browser.opera = true;
|
|
browser.id = 3;
|
|
} else if (/yabrowser/i.test(ua) && /chrome/i.test(ua)) {
|
|
browser.yandex = true;
|
|
browser.id = 4;
|
|
} else if (/firefox|iceweasel/i.test(ua)) {
|
|
browser.firefox = true;
|
|
browser.id = 1;
|
|
} else if (!(/chrome/i.test(ua)) && /webkit|safari|khtml/i.test(ua)) {
|
|
browser.safari = true;
|
|
browser.id = 2;
|
|
} else if (/chrome/i.test(ua)) {
|
|
browser.chrome = true;
|
|
browser.id = 0;
|
|
}
|
|
|
|
return browser;
|
|
})();
|
|
|
|
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 extend(dest, source) {
|
|
for (var i in source) {
|
|
dest[i] = source[i];
|
|
}
|
|
return dest;
|
|
}
|
|
function log() {
|
|
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 intval(value) {
|
|
if (value === true) return 1;
|
|
return parseInt(value) || 0;
|
|
}
|
|
function str(v) {
|
|
var str;
|
|
if (v && v.toString)
|
|
str = v.toString();
|
|
else
|
|
str = v + '';
|
|
if (str == '[object Object]') {
|
|
str = JSON.stringify(v);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
var WSC_STATE_NONE = 'NONE',
|
|
WSC_STATE_OK = 'OK',
|
|
WSC_STATE_CLOSED = 'CLOSED',
|
|
WSC_STATE_ERR = 'ERR';
|
|
function WSClient(address, protocol, opts) {
|
|
this.state = WSC_STATE_NONE;
|
|
this._ws = null;
|
|
|
|
this.address = address;
|
|
this.protocol = protocol;
|
|
|
|
this._onmessage = opts.onmessage;
|
|
this._onclose = opts.onclose;
|
|
this._onerror = opts.onerror;
|
|
this._onopen = opts.onopen;
|
|
|
|
this._pingTimer = null;
|
|
this._reconnectTimer = null;
|
|
}
|
|
extend(WSClient.prototype, {
|
|
connect: function() {
|
|
this.state = WSC_STATE_NONE;
|
|
var self = this;
|
|
|
|
var _websocket = window.WebSocket || window.MozWebSocket;
|
|
if (!_websocket) {
|
|
log('[WSClient connect] websockets are not supported');
|
|
return;
|
|
}
|
|
|
|
this._ws = new _websocket(this.address, this.protocol);
|
|
this._ws.onopen = function() {
|
|
self.state = WSC_STATE_OK;
|
|
self._setTimers();
|
|
self._onopen && self._onopen.apply(self);
|
|
};
|
|
this._ws.onerror = function() {
|
|
self._unsetTimers();
|
|
if (self.state != WSC_STATE_ERR) {
|
|
self.state = WSC_STATE_ERR;
|
|
}
|
|
self._onerror && self._onerror.apply(self);
|
|
};
|
|
this._ws.onclose = function() {
|
|
self._unsetTimers();
|
|
if (self.state != WSC_STATE_ERR) {
|
|
self.state = WSC_STATE_ERR;
|
|
}
|
|
self._onclose && self._onclose.apply(self);
|
|
};
|
|
this._ws.onmessage = function(e) {
|
|
self._onmessage && self._onmessage.apply(self, [e.data]);
|
|
};
|
|
},
|
|
close: function() {
|
|
this._unsetTimers();
|
|
this._ws.close();
|
|
},
|
|
reconnect: function() {
|
|
var self = this;
|
|
if (this.state == WSC_STATE_OK) {
|
|
log('[WSClient reconnect] state = '+this.state+', why reconnect?');
|
|
return;
|
|
}
|
|
clearTimeout(this._reconnectTimer);
|
|
this._reconnectTimer = setTimeout(function() {
|
|
self.connect();
|
|
}, 3000);
|
|
},
|
|
send: function(obj) {
|
|
obj._browser = browser.id;
|
|
var self = this;
|
|
this._waitForConnection(function() {
|
|
self._ws.send(JSON.stringify(obj));
|
|
}, 200);
|
|
},
|
|
_setTimers: function() {
|
|
var self = this;
|
|
this._pingTimer = setInterval(function() {
|
|
try {
|
|
self._ws.send("PING");
|
|
} catch (e) {
|
|
log('[WSClient _pingTimer]', e);
|
|
}
|
|
}, 30000);
|
|
},
|
|
_unsetTimers: function() {
|
|
clearInterval(this._pingTimer);
|
|
},
|
|
_waitForConnection: function(callback, interval) {
|
|
if (this._ws.readyState === 1) {
|
|
callback();
|
|
} else {
|
|
var self = this;
|
|
setTimeout(function() {
|
|
self._waitForConnection(callback, interval);
|
|
}, interval);
|
|
}
|
|
}
|
|
});
|
|
|
|
(function(window, document) {
|
|
var queue = [], done = false, _top = true, root = document.documentElement, eventsAdded = false;
|
|
|
|
function init(e) {
|
|
if (e.type == 'readystatechange' && document.readyState != 'complete') return;
|
|
(e.type == 'load' ? window : document).removeEventListener(e.type, init);
|
|
if (!done) {
|
|
done = true;
|
|
while (queue.length) {
|
|
queue.shift().call(window);
|
|
}
|
|
}
|
|
}
|
|
function poll() {
|
|
try {
|
|
root.doScroll('left');
|
|
} catch (e) {
|
|
setTimeout(poll, 50);
|
|
return;
|
|
}
|
|
init('poll');
|
|
}
|
|
|
|
window.DOMContentLoaded = function(fn) {
|
|
if (document.readyState == 'complete' || done) {
|
|
fn.call(window);
|
|
} else {
|
|
queue.push(fn);
|
|
|
|
if (!eventsAdded) {
|
|
if (document.createEventObject && root.doScroll) {
|
|
try {
|
|
_top = !window.frameElement;
|
|
} catch (e) {}
|
|
if (_top) poll();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
document.addEventListener('readystatechange', init);
|
|
window.addEventListener('load', init);
|
|
eventsAdded = true;
|
|
}
|
|
}
|
|
}
|
|
})(window, document);
|
|
|
|
var Injections = {
|
|
id: 0,
|
|
objs: {},
|
|
getNextId: function() {
|
|
if (this.id == Number.MAX_VALUE) {
|
|
this.id = -1;
|
|
}
|
|
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];
|
|
}
|
|
};
|
|
|
|
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);
|
|
}
|
|
});
|