summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-14 16:07:27 +0000
committerjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-14 16:07:27 +0000
commitd3b94c23bfd798c2fa9c72e1da23e9dfa7834862 (patch)
tree4846c7fd6287d592ccac3c4619cf9c900c813d5c /chrome
parente6850c99467f8747125a378cf80108fc2f57e95f (diff)
downloadchromium_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.js16
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js10
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js46
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;
+ }
});
};