| Index: chrome/ext/common.js | 
| =================================================================== | 
| --- a/chrome/ext/common.js | 
| +++ b/chrome/ext/common.js | 
| @@ -19,42 +19,54 @@ | 
| { | 
| /* Events */ | 
|  | 
| +  SimpleEventTarget = function() | 
| +  { | 
| +    this._listeners = []; | 
| +  }; | 
| +  SimpleEventTarget.prototype = { | 
| +    _onListenerAdded: function(listener, idx) {}, | 
| +    _onListenerRemoved: function(listener, idx) {}, | 
| + | 
| +    addListener: function(listener) | 
| +    { | 
| +      var idx = this._listeners.push(listener) - 1; | 
| +      this._onListenerAdded(listener, idx); | 
| +    }, | 
| +    removeListener: function(listener) | 
| +    { | 
| +      var idx = this._listeners.indexOf(listener); | 
| +      if (idx != -1) | 
| +      { | 
| +        this._listeners.splice(idx, 1); | 
| +        this._onListenerRemoved(listener, idx); | 
| +      } | 
| +    } | 
| +  }; | 
| + | 
| WrappedEventTarget = function(target) | 
| { | 
| -    this._listeners = []; | 
| +    SimpleEventTarget.call(this); | 
| + | 
| this._wrappedListeners = []; | 
| this._target = target; | 
| }; | 
| WrappedEventTarget.prototype = { | 
| -    _prepareExtraArguments: function() | 
| +    __proto__: SimpleEventTarget.prototype, | 
| +    _onListenerAdded: function(listener, idx) | 
| { | 
| -      return []; | 
| +      var wrappedListener = this._wrapListener(listener); | 
| + | 
| +      this._wrappedListeners[idx] = wrappedListener; | 
| +      this._target.addListener.call(this._target, wrappedListener); | 
| }, | 
| -    addListener: function(listener) | 
| +    _onListenerRemoved: function(listener, idx) | 
| { | 
| -      var extraArgs = Array.prototype.slice.call(arguments, 1); | 
| -      extraArgs = this._prepareExtraArguments.apply(this, extraArgs); | 
| - | 
| -      var wrappedListener = this._wrapListener(listener); | 
| -      this._listeners.push(listener); | 
| -      this._wrappedListeners.push(wrappedListener); | 
| - | 
| -      this._target.addListener.apply(this._target, [wrappedListener].concat(extraArgs)); | 
| -    }, | 
| -    removeListener: function(listener) | 
| -    { | 
| -      var idx = this._listeners.indexOf(listener); | 
| - | 
| -      if (idx != -1) { | 
| -        this._target.removeListener(this._wrappedListeners[idx]); | 
| - | 
| -        this._listeners.splice(idx, 1); | 
| -        this._wrappedListeners.splice(idx, 1); | 
| -      } | 
| +      this._target.removeListener(this._wrappedListeners[idx]); | 
| +      this._wrappedListeners.splice(idx, 1); | 
| } | 
| }; | 
|  | 
| -  var MessageEventTarget = function() | 
| +  MessageEventTarget = function() | 
| { | 
| var target; | 
| if ("runtime" in chrome && "onMessage" in chrome.runtime) | 
| @@ -67,13 +79,16 @@ | 
| }; | 
| MessageEventTarget.prototype = { | 
| __proto__: WrappedEventTarget.prototype, | 
| -    _wrapListener: function(listener) { | 
| +    _wrapSender: function(sender) | 
| +    { | 
| +      return {}; | 
| +    }, | 
| +    _wrapListener: function(listener) | 
| +    { | 
| return function(message, sender, sendResponse) | 
| { | 
| -        if (sender.tab && sender.tab.id >= 0) | 
| -          sender.tab = new Tab(sender.tab); | 
| -        return listener(message, sender, sendResponse); | 
| -      }; | 
| +        return listener(message, this._wrapSender(sender), sendResponse); | 
| +      }.bind(this); | 
| } | 
| }; | 
|  | 
| @@ -88,7 +103,6 @@ | 
| } | 
| }, | 
| getURL: chrome.extension.getURL, | 
| -    onMessage: new MessageEventTarget(), | 
| i18n: chrome.i18n | 
| }; | 
|  | 
|  |