diff options
author | gorhill <rhill@raymondhill.net> | 2015-06-26 00:08:41 -0400 |
---|---|---|
committer | gorhill <rhill@raymondhill.net> | 2015-06-26 00:08:41 -0400 |
commit | 631443768f2359e6fdb0bc6a3e457a0951e0a9e9 (patch) | |
tree | ff3d746cce63b7b964de5e2f2b5b4a2daaa0f8f7 /platform/firefox/vapi-client.js | |
parent | 2fd7a73c628113e1cffab8bc15f1ce8cbbf393bc (diff) | |
download | uBlock-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.js | 188 |
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; } |