diff options
author | jstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-14 16:07:27 +0000 |
---|---|---|
committer | jstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-14 16:07:27 +0000 |
commit | d3b94c23bfd798c2fa9c72e1da23e9dfa7834862 (patch) | |
tree | 4846c7fd6287d592ccac3c4619cf9c900c813d5c /chrome | |
parent | e6850c99467f8747125a378cf80108fc2f57e95f (diff) | |
download | chromium_src-d3b94c23bfd798c2fa9c72e1da23e9dfa7834862.zip chromium_src-d3b94c23bfd798c2fa9c72e1da23e9dfa7834862.tar.gz chromium_src-d3b94c23bfd798c2fa9c72e1da23e9dfa7834862.tar.bz2 |
Fix Port and Event leaking.
BUG=67344
TEST=See bug.
Review URL: http://codereview.chromium.org/6670001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78036 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/renderer/resources/event_bindings.js | 16 | ||||
-rw-r--r-- | chrome/renderer/resources/extension_process_bindings.js | 10 | ||||
-rw-r--r-- | chrome/renderer/resources/renderer_extension_bindings.js | 46 |
3 files changed, 54 insertions, 18 deletions
diff --git a/chrome/renderer/resources/event_bindings.js b/chrome/renderer/resources/event_bindings.js index 05ed65d..3410686 100644 --- a/chrome/renderer/resources/event_bindings.js +++ b/chrome/renderer/resources/event_bindings.js @@ -69,7 +69,7 @@ var chrome = chrome || {}; return "Event validation error during " + opt_eventName + " -- " + exception; } - } + }; } }; @@ -106,7 +106,7 @@ var chrome = chrome || {}; chromeHidden.Event.hasListener = function(name) { return (attachedNamedEvents[name] && attachedNamedEvents[name].listeners_.length > 0); - } + }; // Registers a callback to be called when this event is dispatched. chrome.Event.prototype.addListener = function(cb) { @@ -204,6 +204,12 @@ var chrome = chrome || {}; delete attachedNamedEvents[this.eventName_]; }; + chrome.Event.prototype.destroy_ = function() { + this.listeners_ = []; + this.validate_ = []; + this.detach_(); + }; + // Special load events: we don't use the DOM unload because that slows // down tab shutdown. On the other hand, onUnload might not always fire, // since Chrome will terminate renderers on shutdown (SuddenTermination). @@ -212,7 +218,7 @@ var chrome = chrome || {}; chromeHidden.dispatchOnLoad = function(extensionId) { chromeHidden.onLoad.dispatch(extensionId); - } + }; chromeHidden.dispatchOnUnload = function() { chromeHidden.onUnload.dispatch(); @@ -221,9 +227,9 @@ var chrome = chrome || {}; if (event) event.detach_(); } - } + }; chromeHidden.dispatchError = function(msg) { console.error(msg); - } + }; })(); diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js index 6588c70..7b4ce83 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -652,9 +652,13 @@ var chrome = chrome || {}; responseCallback(); }); port.onMessage.addListener(function(response) { - if (responseCallback) - responseCallback(response); - port.disconnect(); + try { + if (responseCallback) + responseCallback(response); + } finally { + port.disconnect(); + port = null; + } }); }; diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js index 9f6ecb3..422b794 100644 --- a/chrome/renderer/resources/renderer_extension_bindings.js +++ b/chrome/renderer/resources/renderer_extension_bindings.js @@ -27,6 +27,10 @@ var chrome = chrome || {}; // Map of port IDs to port object. var ports = {}; + // Map of port IDs to chromeHidden.onUnload listeners. Keep track of these + // to free the onUnload listeners when ports are closed. + var portReleasers = {}; + // Change even to odd and vice versa, to get the other side of a given // channel. function getOppositePortId(portId) { return portId ^ 1; } @@ -50,9 +54,9 @@ var chrome = chrome || {}; } var port = new chrome.Port(portId, opt_name); ports[portId] = port; - chromeHidden.onUnload.addListener(function() { - PortRelease(portId); - }); + portReleasers[portId] = PortRelease.partial(portId); + chromeHidden.onUnload.addListener(portReleasers[portId]); + PortAddRef(portId); return port; }; @@ -87,6 +91,7 @@ var chrome = chrome || {}; port.onMessage.addListener(function(request) { requestEvent.dispatch(request, sender, function(response) { port.postMessage(response); + port = null; }); }); } @@ -121,8 +126,8 @@ var chrome = chrome || {}; try { port.onDisconnect.dispatch(port); } finally { + port.destroy_(); delete chrome.extension.lastError; - delete ports[portId]; } } }; @@ -149,8 +154,21 @@ var chrome = chrome || {}; // Disconnects the port from the other end. chrome.Port.prototype.disconnect = function() { - delete ports[this.portId_]; CloseChannel(this.portId_, true); + this.destroy_(); + }; + + chrome.Port.prototype.destroy_ = function() { + var portId = this.portId_; + + this.onDisconnect.destroy_(); + this.onMessage.destroy_(); + + PortRelease(portId); + chromeHidden.onUnload.removeListener(portReleasers[portId]); + + delete ports[portId]; + delete portReleasers[portId]; }; // This function is called on context initialization for both content scripts @@ -209,13 +227,21 @@ var chrome = chrome || {}; port.postMessage(request); port.onDisconnect.addListener(function() { // For onDisconnects, we only notify the callback if there was an error - if (chrome.extension.lastError && responseCallback) - responseCallback(); + try { + if (chrome.extension.lastError && responseCallback) + responseCallback(); + } finally { + port = null; + } }); port.onMessage.addListener(function(response) { - if (responseCallback) - responseCallback(response); - port.disconnect(); + try { + if (responseCallback) + responseCallback(response); + } finally { + port.disconnect(); + port = null; + } }); }; |