Index: chrome/renderer/extensions/miscellaneous_bindings.cc |
diff --git a/chrome/renderer/extensions/miscellaneous_bindings.cc b/chrome/renderer/extensions/miscellaneous_bindings.cc |
index 0f376539edbc371458034631877955dace21dc2f..b5c670999426a28f38d9457298c60cddb176b94b 100644 |
--- a/chrome/renderer/extensions/miscellaneous_bindings.cc |
+++ b/chrome/renderer/extensions/miscellaneous_bindings.cc |
@@ -95,43 +95,65 @@ class ExtensionImpl : public extensions::ChromeV8Extension { |
if (!renderview) |
return v8::Undefined(); |
- 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 ExtensionHostMsg_PostMessage( |
- renderview->GetRoutingID(), port_id, message)); |
+ // Arguments are (int32 port_id, object message). |
+ CHECK_EQ(2, args.Length()); |
+ CHECK(args[0]->IsInt32()); |
+ |
+ int port_id = args[0]->Int32Value(); |
+ if (!HasPortData(port_id)) { |
+ return v8::ThrowException(v8::Exception::Error( |
+ v8::String::New(kPortClosedError))); |
} |
+ |
+ // The message can be any base::Value but IPC can't serialize that, so we |
+ // give it a singleton base::ListValue instead, or an empty list if the |
+ // argument was undefined (v8 value converter will return NULL for this). |
+ scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); |
+ scoped_ptr<base::Value> message( |
+ converter->FromV8Value(args[1], context()->v8_context())); |
+ ListValue message_as_list; |
+ if (message) |
+ message_as_list.Append(message.release()); |
+ |
+ renderview->Send(new ExtensionHostMsg_PostMessage( |
+ renderview->GetRoutingID(), port_id, message_as_list)); |
+ |
return v8::Undefined(); |
} |
// Forcefully disconnects a port. |
v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) { |
- if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsBoolean()) { |
- int port_id = args[0]->Int32Value(); |
- if (!HasPortData(port_id)) { |
- return v8::Undefined(); |
- } |
- // Send via the RenderThread because the RenderView might be closing. |
- bool notify_browser = args[1]->BooleanValue(); |
- if (notify_browser) |
- content::RenderThread::Get()->Send( |
- new ExtensionHostMsg_CloseChannel(port_id, std::string())); |
- ClearPortData(port_id); |
+ // Arguments are (int32 port_id, boolean notify_browser). |
+ CHECK_EQ(2, args.Length()); |
+ CHECK(args[0]->IsInt32()); |
+ CHECK(args[1]->IsBoolean()); |
+ |
+ int port_id = args[0]->Int32Value(); |
+ if (!HasPortData(port_id)) |
+ return v8::Undefined(); |
+ |
+ // Send via the RenderThread because the RenderView might be closing. |
+ bool notify_browser = args[1]->BooleanValue(); |
+ if (notify_browser) { |
+ content::RenderThread::Get()->Send( |
+ new ExtensionHostMsg_CloseChannel(port_id, std::string())); |
} |
+ |
+ ClearPortData(port_id); |
+ |
return v8::Undefined(); |
} |
// A new port has been created for a context. This occurs both when script |
// opens a connection, and when a connection is opened to this script. |
v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) { |
- if (args.Length() >= 1 && args[0]->IsInt32()) { |
- int port_id = args[0]->Int32Value(); |
- ++GetPortData(port_id).ref_count; |
- } |
+ // Arguments are (int32 port_id). |
+ CHECK_EQ(1, args.Length()); |
+ CHECK(args[0]->IsInt32()); |
+ |
+ int port_id = args[0]->Int32Value(); |
+ ++GetPortData(port_id).ref_count; |
+ |
return v8::Undefined(); |
} |
@@ -139,15 +161,18 @@ class ExtensionImpl : public extensions::ChromeV8Extension { |
// frames with a reference to a given port, we will disconnect it and notify |
// the other end of the channel. |
v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) { |
- if (args.Length() >= 1 && args[0]->IsInt32()) { |
- int port_id = args[0]->Int32Value(); |
- if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { |
- // Send via the RenderThread because the RenderView might be closing. |
- content::RenderThread::Get()->Send( |
- new ExtensionHostMsg_CloseChannel(port_id, std::string())); |
- ClearPortData(port_id); |
- } |
+ // Arguments are (int32 port_id). |
+ CHECK_EQ(1, args.Length()); |
+ CHECK(args[0]->IsInt32()); |
+ |
+ int port_id = args[0]->Int32Value(); |
+ if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { |
+ // Send via the RenderThread because the RenderView might be closing. |
+ content::RenderThread::Get()->Send( |
+ new ExtensionHostMsg_CloseChannel(port_id, std::string())); |
+ ClearPortData(port_id); |
} |
+ |
return v8::Undefined(); |
} |
@@ -222,6 +247,10 @@ void MiscellaneousBindings::DispatchOnConnect( |
continue; |
} |
+ // TODO(kalman): remove when ContextSet::ForEach is available. |
+ if ((*it)->v8_context().IsEmpty()) |
+ continue; |
+ |
v8::Handle<v8::Value> tab = v8::Null(); |
if (!source_tab.empty()) |
tab = converter->ToV8Value(&source_tab, (*it)->v8_context()); |
@@ -271,7 +300,7 @@ void MiscellaneousBindings::DispatchOnConnect( |
void MiscellaneousBindings::DeliverMessage( |
const ChromeV8ContextSet::ContextSet& contexts, |
int target_port_id, |
- const std::string& message, |
+ const base::ListValue& message, |
content::RenderView* restrict_to_render_view) { |
v8::HandleScope handle_scope; |
@@ -282,6 +311,13 @@ void MiscellaneousBindings::DeliverMessage( |
continue; |
} |
+ // TODO(kalman): remove when ContextSet::ForEach is available. |
+ if ((*it)->v8_context().IsEmpty()) |
+ continue; |
+ |
+ v8::Handle<v8::Context> context = (*it)->v8_context(); |
+ v8::Context::Scope context_scope(context); |
+ |
// Check to see whether the context has this port before bothering to create |
// the message. |
v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id); |
@@ -302,7 +338,19 @@ void MiscellaneousBindings::DeliverMessage( |
continue; |
std::vector<v8::Handle<v8::Value> > arguments; |
- arguments.push_back(v8::String::New(message.c_str(), message.size())); |
+ |
+ // Convert the message to a v8 object; either a value or undefined. |
+ // See PostMessage for more details. |
+ if (message.empty()) { |
+ arguments.push_back(v8::Undefined()); |
+ } else { |
+ CHECK_EQ(1u, message.GetSize()); |
+ const base::Value* message_value = NULL; |
+ message.Get(0, &message_value); |
+ scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); |
+ arguments.push_back(converter->ToV8Value(message_value, context)); |
+ } |
+ |
arguments.push_back(port_id_handle); |
CHECK((*it)->CallChromeHiddenMethod("Port.dispatchOnMessage", |
arguments.size(), |
@@ -326,6 +374,10 @@ void MiscellaneousBindings::DispatchOnDisconnect( |
continue; |
} |
+ // TODO(kalman): remove when ContextSet::ForEach is available. |
+ if ((*it)->v8_context().IsEmpty()) |
+ continue; |
+ |
std::vector<v8::Handle<v8::Value> > arguments; |
arguments.push_back(v8::Integer::New(port_id)); |
if (!error_message.empty()) { |