aboutsummaryrefslogtreecommitdiffstats
path: root/platform/firefox/vapi-client.js
diff options
context:
space:
mode:
authorgorhill <rhill@raymondhill.net>2015-06-26 00:08:41 -0400
committergorhill <rhill@raymondhill.net>2015-06-26 00:08:41 -0400
commit631443768f2359e6fdb0bc6a3e457a0951e0a9e9 (patch)
treeff3d746cce63b7b964de5e2f2b5b4a2daaa0f8f7 /platform/firefox/vapi-client.js
parent2fd7a73c628113e1cffab8bc15f1ce8cbbf393bc (diff)
downloaduBlock-631443768f2359e6fdb0bc6a3e457a0951e0a9e9.zip
uBlock-631443768f2359e6fdb0bc6a3e457a0951e0a9e9.tar.gz
uBlock-631443768f2359e6fdb0bc6a3e457a0951e0a9e9.tar.bz2
dom inspector: ébauche
Diffstat (limited to 'platform/firefox/vapi-client.js')
-rw-r--r--platform/firefox/vapi-client.js188
1 files changed, 130 insertions, 58 deletions
diff --git a/platform/firefox/vapi-client.js b/platform/firefox/vapi-client.js
index 88b11da..44bbec0 100644
--- a/platform/firefox/vapi-client.js
+++ b/platform/firefox/vapi-client.js
@@ -67,66 +67,158 @@ vAPI.shutdown = (function() {
/******************************************************************************/
+var MessagingListeners = function(callback) {
+ this.listeners = [];
+ if ( typeof callback === 'function' ) {
+ this.listeners.push(callback);
+ }
+};
+
+MessagingListeners.prototype.add = function(callback) {
+ if ( typeof callback !== 'function' ) {
+ return;
+ }
+ if ( this.listeners.indexOf(callback) !== -1 ) {
+ throw new Error('Duplicate listener.');
+ }
+ this.listeners.push(callback);
+};
+
+MessagingListeners.prototype.remove = function(callback) {
+ if ( typeof callback !== 'function' ) {
+ return;
+ }
+ if ( this.listeners.indexOf(callback) === -1 ) {
+ throw new Error('Listener not found.');
+ }
+ this.listeners.splice(this.listeners.indexOf(callback), 1);
+};
+
+MessagingListeners.prototype.process = function(msg) {
+ var listeners = this.listeners;
+ var n = listeners.length;
+ for ( var i = 0; i < n; i++ ) {
+ listeners[i](msg);
+ }
+};
+
+/******************************************************************************/
+
var messagingConnector = function(response) {
if ( !response ) {
return;
}
- var channels = vAPI.messaging.channels;
- var channel, listener;
+ var messaging = vAPI.messaging;
+ var channels = messaging.channels;
+ var channel;
+ // Sent to all channels
if ( response.broadcast === true && !response.channelName ) {
for ( channel in channels ) {
- if ( channels.hasOwnProperty(channel) === false ) {
+ if ( channels[channel] instanceof MessagingChannel === false ) {
continue;
}
- listener = channels[channel].listener;
- if ( typeof listener === 'function' ) {
- listener(response.msg);
- }
+ channels[channel].listeners.process(response.msg);
}
return;
}
+ // Response to specific message previously sent
if ( response.requestId ) {
- listener = vAPI.messaging.listeners[response.requestId];
- delete vAPI.messaging.listeners[response.requestId];
- delete response.requestId;
+ var listener = messaging.pending[response.requestId];
+ delete messaging.pending[response.requestId];
+ delete response.requestId; // TODO: why?
+ if ( listener ) {
+ listener(response.msg);
+ return;
+ }
+ }
+
+ // Sent to a specific channel
+ channel = channels[response.channelName];
+ if ( channel instanceof MessagingChannel ) {
+ channel.listeners.process(response.msg);
}
+};
+
+/******************************************************************************/
- if ( !listener ) {
- channel = channels[response.channelName];
- listener = channel && channel.listener;
+var MessagingChannel = function(name, callback) {
+ this.channelName = name;
+ this.listeners = new MessagingListeners(callback);
+ this.refCount = 1;
+ if ( typeof callback === 'function' ) {
+ var messaging = vAPI.messaging;
+ if ( !messaging.connected ) {
+ messaging.setup();
+ }
}
+};
- if ( typeof listener === 'function' ) {
- listener(response.msg);
+MessagingChannel.prototype.send = function(message, callback) {
+ var messaging = vAPI.messaging;
+ if ( !messaging.connected ) {
+ messaging.setup();
+ }
+ var requestId;
+ if ( callback ) {
+ requestId = messaging.requestId++;
+ messaging.pending[requestId] = callback;
}
+ sendAsyncMessage('ublock0:background', {
+ channelName: self._sandboxId_ + '|' + this.channelName,
+ requestId: requestId,
+ msg: message
+ });
+};
+
+MessagingChannel.prototype.close = function() {
+ this.refCount -= 1;
+ if ( this.refCount !== 0 ) {
+ return;
+ }
+ delete vAPI.messaging.channels[this.channelName];
+};
+
+MessagingChannel.prototype.addListener = function(callback) {
+ if ( typeof callback !== 'function' ) {
+ return;
+ }
+ this.listeners.add(callback);
+ var messaging = vAPI.messaging;
+ if ( !messaging.connected ) {
+ messaging.setup();
+ }
+};
+
+MessagingChannel.prototype.removeListener = function(callback) {
+ if ( typeof callback !== 'function' ) {
+ return;
+ }
+ this.listeners.remove(callback);
};
/******************************************************************************/
vAPI.messaging = {
channels: {},
- listeners: {},
+ pending: {},
requestId: 1,
+ connected: false,
+ connector: function(msg) {
+ messagingConnector(JSON.parse(msg));
+ },
setup: function() {
- this.connector = function(msg) {
- messagingConnector(JSON.parse(msg));
- };
-
addMessageListener(this.connector);
-
- this.channels['vAPI'] = {};
- this.channels['vAPI'].listener = function(msg) {
+ this.connected = true;
+ this.channels['vAPI'] = new MessagingChannel('vAPI', function(msg) {
if ( msg.cmd === 'injectScript' ) {
var details = msg.details;
-
if ( !details.allFrames && window !== window.top ) {
return;
}
-
// TODO: investigate why this happens, and if this happens
// legitimately (content scripts not injected I suspect, so
// that would make this legitimate).
@@ -135,55 +227,35 @@ vAPI.messaging = {
self.injectScript(details.file);
}
}
- };
+ });
},
close: function() {
- if ( !this.connector ) {
+ if ( !this.connected ) {
return;
}
-
removeMessageListener();
- this.connector = null;
+ this.connected = false;
this.channels = {};
- this.listeners = {};
+ this.pending = {};
},
channel: function(channelName, callback) {
if ( !channelName ) {
return;
}
-
- this.channels[channelName] = {
- channelName: channelName,
- listener: typeof callback === 'function' ? callback : null,
- send: function(message, callback) {
- if ( !vAPI.messaging.connector ) {
- vAPI.messaging.setup();
- }
-
- message = {
- channelName: self._sandboxId_ + '|' + this.channelName,
- msg: message
- };
-
- if ( callback ) {
- message.requestId = vAPI.messaging.requestId++;
- vAPI.messaging.listeners[message.requestId] = callback;
- }
-
- sendAsyncMessage('ublock0:background', message);
- },
- close: function() {
- delete vAPI.messaging.channels[this.channelName];
- }
- };
-
- return this.channels[channelName];
+ var channel = this.channels[channelName];
+ if ( channel instanceof MessagingChannel ) {
+ channel.addListener(callback);
+ channel.refCount += 1;
+ } else {
+ channel = this.channels[channelName] = new MessagingChannel(channelName, callback);
+ }
+ return channel;
},
toggleListener: function({type, persisted}) {
- if ( !vAPI.messaging.connector ) {
+ if ( !vAPI.messaging.connected ) {
return;
}