Skip to content
Snippets Groups Projects
Commit 4ae8a457 authored by mpcomplete@chromium.org's avatar mpcomplete@chromium.org
Browse files

Clean up extension message port data in the renderer.

BUG=26262

Review URL: http://codereview.chromium.org/344044

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30884 0039d316-1c4b-4281-b951-d872f2087c98
parent 28dbc657
No related merge requests found
......@@ -147,72 +147,3 @@ TEST_F(RenderViewTest, ExtensionMessagesOnConnect) {
ASSERT_TRUE(IPC::ReadParam(alert_msg, &iter, &alert_param));
EXPECT_EQ(L"disconnected: 24", alert_param.a);
}
// Tests that we don't send the disconnect message until all ports have
// disconnected.
TEST_F(RenderViewTest, ExtensionMessagesDisconnect) {
LoadHTML("<body></body>");
ExecuteJavaScript(
"chrome.extension.onConnect.addListener(function (port) {"
" port.onMessage.addListener(function(msg, p) {"
" if (msg.disconnect) port.disconnect();"
" });"
"});"
"var iframe1 = document.createElement('iframe');"
"var iframe2 = document.createElement('iframe');"
"var src = 'javascript:"
" chrome.extension.onConnect.addListener(function(port) {"
" port.postMessage(\"onconnect\");"
" port.onMessage.addListener(function(p) { alert(\"NOTREACHED\"); });"
" port.disconnect();"
" });';"
"iframe1.src = src;"
"iframe2.src = src;"
"document.body.appendChild(iframe1);"
"document.body.appendChild(iframe2);");
render_thread_.sink().ClearMessages();
// Simulate a new connection being opened. The two child frames should
// disconnect immediately, but we shouldn't get a disconnect message until
// all 3 frames disconnect.
const int kPortId = 0;
const std::string kPortName = "testName";
DispatchOnConnect(kPortId, kPortName, "null");
// Verify that we handled the new connection by posting a message.
const IPC::Message* post_msg =
render_thread_.sink().GetFirstMessageMatching(
ViewHostMsg_ExtensionPostMessage::ID);
ASSERT_TRUE(post_msg);
ViewHostMsg_ExtensionPostMessage::Param post_params;
ViewHostMsg_ExtensionPostMessage::Read(post_msg, &post_params);
EXPECT_EQ("\"onconnect\"", post_params.b);
// Simulate sending a message.
render_thread_.sink().ClearMessages();
DispatchOnMessage("{\"val\": 42}", kPortId);
// If we get an alert box, then the iframes failed to disconnect properly.
const IPC::Message* alert_msg =
render_thread_.sink().GetFirstMessageMatching(
ViewHostMsg_RunJavaScriptMessage::ID);
ASSERT_FALSE(alert_msg);
// We should not get a disconnect message yet, since the toplevel frame didn't
// disconnect.
const IPC::Message* disconnect_msg =
render_thread_.sink().GetFirstMessageMatching(
ViewHostMsg_ExtensionCloseChannel::ID);
ASSERT_FALSE(disconnect_msg);
// Disconnect the port in the top frame.
render_thread_.sink().ClearMessages();
DispatchOnMessage("{\"disconnect\": true}", kPortId);
// Now we should have a disconnect message.
disconnect_msg =
render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_ExtensionCloseChannel::ID);
ASSERT_TRUE(disconnect_msg);
}
......@@ -37,10 +37,18 @@ struct ExtensionData {
};
std::map<int, PortData> ports; // port ID -> data
};
bool HasPortData(int port_id) {
return Singleton<ExtensionData>::get()->ports.find(port_id) !=
Singleton<ExtensionData>::get()->ports.end();
}
ExtensionData::PortData& GetPortData(int port_id) {
return Singleton<ExtensionData>::get()->ports[port_id];
}
void ClearPortData(int port_id) {
Singleton<ExtensionData>::get()->ports.erase(port_id);
}
const char kPortClosedError[] = "Attempting to use a disconnected port object";
const char* kExtensionDeps[] = { EventBindings::kName };
class ExtensionImpl : public ExtensionBase {
......@@ -99,6 +107,10 @@ class ExtensionImpl : public ExtensionBase {
if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) {
int port_id = args[0]->Int32Value();
if (!HasPortData(port_id)) {
return v8::ThrowException(v8::Exception::Error(
v8::String::New(kPortClosedError)));
}
std::string message = *v8::String::Utf8Value(args[1]->ToString());
renderview->Send(new ViewHostMsg_ExtensionPostMessage(
renderview->routing_id(), port_id, message));
......@@ -110,10 +122,13 @@ class ExtensionImpl : public ExtensionBase {
static v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) {
if (args.Length() >= 1 && args[0]->IsInt32()) {
int port_id = args[0]->Int32Value();
if (!HasPortData(port_id)) {
return v8::Undefined();
}
// Send via the RenderThread because the RenderView might be closing.
EventBindings::GetRenderThread()->Send(
new ViewHostMsg_ExtensionCloseChannel(port_id));
GetPortData(port_id).disconnected = true;
ClearPortData(port_id);
}
return v8::Undefined();
}
......@@ -134,11 +149,11 @@ class ExtensionImpl : public ExtensionBase {
static v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) {
if (args.Length() >= 1 && args[0]->IsInt32()) {
int port_id = args[0]->Int32Value();
if (!GetPortData(port_id).disconnected &&
--GetPortData(port_id).ref_count == 0) {
if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) {
// Send via the RenderThread because the RenderView might be closing.
EventBindings::GetRenderThread()->Send(
new ViewHostMsg_ExtensionCloseChannel(port_id));
ClearPortData(port_id);
}
}
return v8::Undefined();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment