OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/extensions/miscellaneous_bindings.h" | 5 #include "chrome/renderer/extensions/miscellaneous_bindings.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 } | 88 } |
89 | 89 |
90 virtual ~ExtensionImpl() {} | 90 virtual ~ExtensionImpl() {} |
91 | 91 |
92 // Sends a message along the given channel. | 92 // Sends a message along the given channel. |
93 v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) { | 93 v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) { |
94 content::RenderView* renderview = GetRenderView(); | 94 content::RenderView* renderview = GetRenderView(); |
95 if (!renderview) | 95 if (!renderview) |
96 return v8::Undefined(); | 96 return v8::Undefined(); |
97 | 97 |
98 // Arguments are (int32 port_id, object message). | 98 if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) { |
99 CHECK_EQ(2, args.Length()); | 99 int port_id = args[0]->Int32Value(); |
100 CHECK(args[0]->IsInt32()); | 100 if (!HasPortData(port_id)) { |
101 | 101 return v8::ThrowException(v8::Exception::Error( |
102 int port_id = args[0]->Int32Value(); | 102 v8::String::New(kPortClosedError))); |
103 if (!HasPortData(port_id)) { | 103 } |
104 return v8::ThrowException(v8::Exception::Error( | 104 std::string message = *v8::String::Utf8Value(args[1]->ToString()); |
105 v8::String::New(kPortClosedError))); | 105 renderview->Send(new ExtensionHostMsg_PostMessage( |
| 106 renderview->GetRoutingID(), port_id, message)); |
106 } | 107 } |
107 | |
108 // The message can be any base::Value but IPC can't serialize that, so we | |
109 // give it a singleton base::ListValue instead, or an empty list if the | |
110 // argument was undefined (v8 value converter will return NULL for this). | |
111 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); | |
112 scoped_ptr<base::Value> message( | |
113 converter->FromV8Value(args[1], v8_context())); | |
114 ListValue message_as_list; | |
115 if (message) | |
116 message_as_list.Append(message.release()); | |
117 | |
118 renderview->Send(new ExtensionHostMsg_PostMessage( | |
119 renderview->GetRoutingID(), port_id, message_as_list)); | |
120 | |
121 return v8::Undefined(); | 108 return v8::Undefined(); |
122 } | 109 } |
123 | 110 |
124 // Forcefully disconnects a port. | 111 // Forcefully disconnects a port. |
125 v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) { | 112 v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) { |
126 // Arguments are (int32 port_id, boolean notify_browser). | 113 if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsBoolean()) { |
127 CHECK_EQ(2, args.Length()); | 114 int port_id = args[0]->Int32Value(); |
128 CHECK(args[0]->IsInt32()); | 115 if (!HasPortData(port_id)) { |
129 CHECK(args[1]->IsBoolean()); | 116 return v8::Undefined(); |
130 | 117 } |
131 int port_id = args[0]->Int32Value(); | 118 // Send via the RenderThread because the RenderView might be closing. |
132 if (!HasPortData(port_id)) | 119 bool notify_browser = args[1]->BooleanValue(); |
133 return v8::Undefined(); | 120 if (notify_browser) |
134 | 121 content::RenderThread::Get()->Send( |
135 // Send via the RenderThread because the RenderView might be closing. | 122 new ExtensionHostMsg_CloseChannel(port_id, std::string())); |
136 bool notify_browser = args[1]->BooleanValue(); | 123 ClearPortData(port_id); |
137 if (notify_browser) { | |
138 content::RenderThread::Get()->Send( | |
139 new ExtensionHostMsg_CloseChannel(port_id, std::string())); | |
140 } | 124 } |
141 | |
142 ClearPortData(port_id); | |
143 | |
144 return v8::Undefined(); | 125 return v8::Undefined(); |
145 } | 126 } |
146 | 127 |
147 // A new port has been created for a context. This occurs both when script | 128 // A new port has been created for a context. This occurs both when script |
148 // opens a connection, and when a connection is opened to this script. | 129 // opens a connection, and when a connection is opened to this script. |
149 v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) { | 130 v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) { |
150 // Arguments are (int32 port_id). | 131 if (args.Length() >= 1 && args[0]->IsInt32()) { |
151 CHECK_EQ(1, args.Length()); | 132 int port_id = args[0]->Int32Value(); |
152 CHECK(args[0]->IsInt32()); | 133 ++GetPortData(port_id).ref_count; |
153 | 134 } |
154 int port_id = args[0]->Int32Value(); | |
155 ++GetPortData(port_id).ref_count; | |
156 | |
157 return v8::Undefined(); | 135 return v8::Undefined(); |
158 } | 136 } |
159 | 137 |
160 // The frame a port lived in has been destroyed. When there are no more | 138 // The frame a port lived in has been destroyed. When there are no more |
161 // frames with a reference to a given port, we will disconnect it and notify | 139 // frames with a reference to a given port, we will disconnect it and notify |
162 // the other end of the channel. | 140 // the other end of the channel. |
163 v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) { | 141 v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) { |
164 // Arguments are (int32 port_id). | 142 if (args.Length() >= 1 && args[0]->IsInt32()) { |
165 CHECK_EQ(1, args.Length()); | 143 int port_id = args[0]->Int32Value(); |
166 CHECK(args[0]->IsInt32()); | 144 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { |
167 | 145 // Send via the RenderThread because the RenderView might be closing. |
168 int port_id = args[0]->Int32Value(); | 146 content::RenderThread::Get()->Send( |
169 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { | 147 new ExtensionHostMsg_CloseChannel(port_id, std::string())); |
170 // Send via the RenderThread because the RenderView might be closing. | 148 ClearPortData(port_id); |
171 content::RenderThread::Get()->Send( | 149 } |
172 new ExtensionHostMsg_CloseChannel(port_id, std::string())); | |
173 ClearPortData(port_id); | |
174 } | 150 } |
175 | |
176 return v8::Undefined(); | 151 return v8::Undefined(); |
177 } | 152 } |
178 | 153 |
179 struct GCCallbackArgs { | 154 struct GCCallbackArgs { |
180 GCCallbackArgs(v8::Handle<v8::Object> object, | 155 GCCallbackArgs(v8::Handle<v8::Object> object, |
181 v8::Handle<v8::Function> callback) | 156 v8::Handle<v8::Function> callback) |
182 : object(object), callback(callback) {} | 157 : object(object), callback(callback) {} |
183 | 158 |
184 extensions::ScopedPersistent<v8::Object> object; | 159 extensions::ScopedPersistent<v8::Object> object; |
185 extensions::ScopedPersistent<v8::Function> callback; | 160 extensions::ScopedPersistent<v8::Function> callback; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 content::RenderThread::Get()->Send( | 264 content::RenderThread::Get()->Send( |
290 new ExtensionHostMsg_CloseChannel( | 265 new ExtensionHostMsg_CloseChannel( |
291 target_port_id, kReceivingEndDoesntExistError)); | 266 target_port_id, kReceivingEndDoesntExistError)); |
292 } | 267 } |
293 } | 268 } |
294 | 269 |
295 // static | 270 // static |
296 void MiscellaneousBindings::DeliverMessage( | 271 void MiscellaneousBindings::DeliverMessage( |
297 const ChromeV8ContextSet::ContextSet& contexts, | 272 const ChromeV8ContextSet::ContextSet& contexts, |
298 int target_port_id, | 273 int target_port_id, |
299 const base::ListValue& message, | 274 const std::string& message, |
300 content::RenderView* restrict_to_render_view) { | 275 content::RenderView* restrict_to_render_view) { |
301 v8::HandleScope handle_scope; | 276 v8::HandleScope handle_scope; |
302 | 277 |
303 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin(); | 278 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin(); |
304 it != contexts.end(); ++it) { | 279 it != contexts.end(); ++it) { |
305 if (restrict_to_render_view && | 280 if (restrict_to_render_view && |
306 restrict_to_render_view != (*it)->GetRenderView()) { | 281 restrict_to_render_view != (*it)->GetRenderView()) { |
307 continue; | 282 continue; |
308 } | 283 } |
309 | 284 |
310 v8::Handle<v8::Context> context = (*it)->v8_context(); | |
311 v8::Context::Scope context_scope(context); | |
312 | |
313 // Check to see whether the context has this port before bothering to create | 285 // Check to see whether the context has this port before bothering to create |
314 // the message. | 286 // the message. |
315 v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id); | 287 v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id); |
316 v8::Handle<v8::Value> has_port; | 288 v8::Handle<v8::Value> has_port; |
317 v8::TryCatch try_catch; | 289 v8::TryCatch try_catch; |
318 if (!(*it)->CallChromeHiddenMethod("Port.hasPort", 1, &port_id_handle, | 290 if (!(*it)->CallChromeHiddenMethod("Port.hasPort", 1, &port_id_handle, |
319 &has_port)) { | 291 &has_port)) { |
320 continue; | 292 continue; |
321 } | 293 } |
322 | 294 |
323 if (try_catch.HasCaught()) { | 295 if (try_catch.HasCaught()) { |
324 LOG(ERROR) << "Exception caught when calling Port.hasPort."; | 296 LOG(ERROR) << "Exception caught when calling Port.hasPort."; |
325 continue; | 297 continue; |
326 } | 298 } |
327 | 299 |
328 CHECK(!has_port.IsEmpty()); | 300 CHECK(!has_port.IsEmpty()); |
329 if (!has_port->BooleanValue()) | 301 if (!has_port->BooleanValue()) |
330 continue; | 302 continue; |
331 | 303 |
332 std::vector<v8::Handle<v8::Value> > arguments; | 304 std::vector<v8::Handle<v8::Value> > arguments; |
333 | 305 arguments.push_back(v8::String::New(message.c_str(), message.size())); |
334 // Convert the message to a v8 object; either a value or undefined. | |
335 // See PostMessage for more details. | |
336 if (message.empty()) { | |
337 arguments.push_back(v8::Undefined()); | |
338 } else { | |
339 CHECK_EQ(1u, message.GetSize()); | |
340 const base::Value* message_value = NULL; | |
341 message.Get(0, &message_value); | |
342 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); | |
343 arguments.push_back(converter->ToV8Value(message_value, context)); | |
344 } | |
345 | |
346 arguments.push_back(port_id_handle); | 306 arguments.push_back(port_id_handle); |
347 CHECK((*it)->CallChromeHiddenMethod("Port.dispatchOnMessage", | 307 CHECK((*it)->CallChromeHiddenMethod("Port.dispatchOnMessage", |
348 arguments.size(), | 308 arguments.size(), |
349 &arguments[0], | 309 &arguments[0], |
350 NULL)); | 310 NULL)); |
351 } | 311 } |
352 } | 312 } |
353 | 313 |
354 // static | 314 // static |
355 void MiscellaneousBindings::DispatchOnDisconnect( | 315 void MiscellaneousBindings::DispatchOnDisconnect( |
(...skipping 17 matching lines...) Expand all Loading... |
373 } else { | 333 } else { |
374 arguments.push_back(v8::Null()); | 334 arguments.push_back(v8::Null()); |
375 } | 335 } |
376 (*it)->CallChromeHiddenMethod("Port.dispatchOnDisconnect", | 336 (*it)->CallChromeHiddenMethod("Port.dispatchOnDisconnect", |
377 arguments.size(), &arguments[0], | 337 arguments.size(), &arguments[0], |
378 NULL); | 338 NULL); |
379 } | 339 } |
380 } | 340 } |
381 | 341 |
382 } // namespace extensions | 342 } // namespace extensions |
OLD | NEW |