Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Side by Side Diff: chrome/renderer/extensions/miscellaneous_bindings.cc

Issue 16226004: Replace JSON (de)serialization of extension messages with direct Value pickling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) { 98 // Arguments are (int32 port_id, object message).
99 int port_id = args[0]->Int32Value(); 99 CHECK_EQ(2, args.Length());
100 if (!HasPortData(port_id)) { 100 CHECK(args[0]->IsInt32());
101 return v8::ThrowException(v8::Exception::Error( 101
102 v8::String::New(kPortClosedError))); 102 int port_id = args[0]->Int32Value();
103 } 103 if (!HasPortData(port_id)) {
104 std::string message = *v8::String::Utf8Value(args[1]->ToString()); 104 return v8::ThrowException(v8::Exception::Error(
105 renderview->Send(new ExtensionHostMsg_PostMessage( 105 v8::String::New(kPortClosedError)));
106 renderview->GetRoutingID(), port_id, message));
107 } 106 }
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], context()->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
108 return v8::Undefined(); 121 return v8::Undefined();
109 } 122 }
110 123
111 // Forcefully disconnects a port. 124 // Forcefully disconnects a port.
112 v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) { 125 v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) {
113 if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsBoolean()) { 126 // Arguments are (int32 port_id, boolean notify_browser).
114 int port_id = args[0]->Int32Value(); 127 CHECK_EQ(2, args.Length());
115 if (!HasPortData(port_id)) { 128 CHECK(args[0]->IsInt32());
116 return v8::Undefined(); 129 CHECK(args[1]->IsBoolean());
117 } 130
118 // Send via the RenderThread because the RenderView might be closing. 131 int port_id = args[0]->Int32Value();
119 bool notify_browser = args[1]->BooleanValue(); 132 if (!HasPortData(port_id))
120 if (notify_browser) 133 return v8::Undefined();
121 content::RenderThread::Get()->Send( 134
122 new ExtensionHostMsg_CloseChannel(port_id, std::string())); 135 // Send via the RenderThread because the RenderView might be closing.
123 ClearPortData(port_id); 136 bool notify_browser = args[1]->BooleanValue();
137 if (notify_browser) {
138 content::RenderThread::Get()->Send(
139 new ExtensionHostMsg_CloseChannel(port_id, std::string()));
124 } 140 }
141
142 ClearPortData(port_id);
143
125 return v8::Undefined(); 144 return v8::Undefined();
126 } 145 }
127 146
128 // A new port has been created for a context. This occurs both when script 147 // A new port has been created for a context. This occurs both when script
129 // opens a connection, and when a connection is opened to this script. 148 // opens a connection, and when a connection is opened to this script.
130 v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) { 149 v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) {
131 if (args.Length() >= 1 && args[0]->IsInt32()) { 150 // Arguments are (int32 port_id).
132 int port_id = args[0]->Int32Value(); 151 CHECK_EQ(1, args.Length());
133 ++GetPortData(port_id).ref_count; 152 CHECK(args[0]->IsInt32());
134 } 153
154 int port_id = args[0]->Int32Value();
155 ++GetPortData(port_id).ref_count;
156
135 return v8::Undefined(); 157 return v8::Undefined();
136 } 158 }
137 159
138 // The frame a port lived in has been destroyed. When there are no more 160 // The frame a port lived in has been destroyed. When there are no more
139 // frames with a reference to a given port, we will disconnect it and notify 161 // frames with a reference to a given port, we will disconnect it and notify
140 // the other end of the channel. 162 // the other end of the channel.
141 v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) { 163 v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) {
142 if (args.Length() >= 1 && args[0]->IsInt32()) { 164 // Arguments are (int32 port_id).
143 int port_id = args[0]->Int32Value(); 165 CHECK_EQ(1, args.Length());
144 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { 166 CHECK(args[0]->IsInt32());
145 // Send via the RenderThread because the RenderView might be closing. 167
146 content::RenderThread::Get()->Send( 168 int port_id = args[0]->Int32Value();
147 new ExtensionHostMsg_CloseChannel(port_id, std::string())); 169 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) {
148 ClearPortData(port_id); 170 // Send via the RenderThread because the RenderView might be closing.
149 } 171 content::RenderThread::Get()->Send(
172 new ExtensionHostMsg_CloseChannel(port_id, std::string()));
173 ClearPortData(port_id);
150 } 174 }
175
151 return v8::Undefined(); 176 return v8::Undefined();
152 } 177 }
153 178
154 struct GCCallbackArgs { 179 struct GCCallbackArgs {
155 GCCallbackArgs(v8::Handle<v8::Object> object, 180 GCCallbackArgs(v8::Handle<v8::Object> object,
156 v8::Handle<v8::Function> callback) 181 v8::Handle<v8::Function> callback)
157 : object(object), callback(callback) {} 182 : object(object), callback(callback) {}
158 183
159 extensions::ScopedPersistent<v8::Object> object; 184 extensions::ScopedPersistent<v8::Object> object;
160 extensions::ScopedPersistent<v8::Function> callback; 185 extensions::ScopedPersistent<v8::Function> callback;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 bool port_created = false; 240 bool port_created = false;
216 std::string source_url_spec = source_url.spec(); 241 std::string source_url_spec = source_url.spec();
217 242
218 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin(); 243 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
219 it != contexts.end(); ++it) { 244 it != contexts.end(); ++it) {
220 if (restrict_to_render_view && 245 if (restrict_to_render_view &&
221 restrict_to_render_view != (*it)->GetRenderView()) { 246 restrict_to_render_view != (*it)->GetRenderView()) {
222 continue; 247 continue;
223 } 248 }
224 249
250 // TODO(kalman): remove when ContextSet::ForEach is available.
251 if ((*it)->v8_context().IsEmpty())
252 continue;
253
225 v8::Handle<v8::Value> tab = v8::Null(); 254 v8::Handle<v8::Value> tab = v8::Null();
226 if (!source_tab.empty()) 255 if (!source_tab.empty())
227 tab = converter->ToV8Value(&source_tab, (*it)->v8_context()); 256 tab = converter->ToV8Value(&source_tab, (*it)->v8_context());
228 257
229 v8::Handle<v8::Value> arguments[] = { 258 v8::Handle<v8::Value> arguments[] = {
230 v8::Integer::New(target_port_id), 259 v8::Integer::New(target_port_id),
231 v8::String::New(channel_name.c_str(), channel_name.size()), 260 v8::String::New(channel_name.c_str(), channel_name.size()),
232 tab, 261 tab,
233 v8::String::New(source_extension_id.c_str(), source_extension_id.size()), 262 v8::String::New(source_extension_id.c_str(), source_extension_id.size()),
234 v8::String::New(target_extension_id.c_str(), target_extension_id.size()), 263 v8::String::New(target_extension_id.c_str(), target_extension_id.size()),
(...skipping 29 matching lines...) Expand all
264 content::RenderThread::Get()->Send( 293 content::RenderThread::Get()->Send(
265 new ExtensionHostMsg_CloseChannel( 294 new ExtensionHostMsg_CloseChannel(
266 target_port_id, kReceivingEndDoesntExistError)); 295 target_port_id, kReceivingEndDoesntExistError));
267 } 296 }
268 } 297 }
269 298
270 // static 299 // static
271 void MiscellaneousBindings::DeliverMessage( 300 void MiscellaneousBindings::DeliverMessage(
272 const ChromeV8ContextSet::ContextSet& contexts, 301 const ChromeV8ContextSet::ContextSet& contexts,
273 int target_port_id, 302 int target_port_id,
274 const std::string& message, 303 const base::ListValue& message,
275 content::RenderView* restrict_to_render_view) { 304 content::RenderView* restrict_to_render_view) {
276 v8::HandleScope handle_scope; 305 v8::HandleScope handle_scope;
277 306
278 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin(); 307 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
279 it != contexts.end(); ++it) { 308 it != contexts.end(); ++it) {
280 if (restrict_to_render_view && 309 if (restrict_to_render_view &&
281 restrict_to_render_view != (*it)->GetRenderView()) { 310 restrict_to_render_view != (*it)->GetRenderView()) {
282 continue; 311 continue;
283 } 312 }
284 313
314 // TODO(kalman): remove when ContextSet::ForEach is available.
315 if ((*it)->v8_context().IsEmpty())
316 continue;
317
318 v8::Handle<v8::Context> context = (*it)->v8_context();
319 v8::Context::Scope context_scope(context);
320
285 // Check to see whether the context has this port before bothering to create 321 // Check to see whether the context has this port before bothering to create
286 // the message. 322 // the message.
287 v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id); 323 v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id);
288 v8::Handle<v8::Value> has_port; 324 v8::Handle<v8::Value> has_port;
289 v8::TryCatch try_catch; 325 v8::TryCatch try_catch;
290 if (!(*it)->CallChromeHiddenMethod("Port.hasPort", 1, &port_id_handle, 326 if (!(*it)->CallChromeHiddenMethod("Port.hasPort", 1, &port_id_handle,
291 &has_port)) { 327 &has_port)) {
292 continue; 328 continue;
293 } 329 }
294 330
295 if (try_catch.HasCaught()) { 331 if (try_catch.HasCaught()) {
296 LOG(ERROR) << "Exception caught when calling Port.hasPort."; 332 LOG(ERROR) << "Exception caught when calling Port.hasPort.";
297 continue; 333 continue;
298 } 334 }
299 335
300 CHECK(!has_port.IsEmpty()); 336 CHECK(!has_port.IsEmpty());
301 if (!has_port->BooleanValue()) 337 if (!has_port->BooleanValue())
302 continue; 338 continue;
303 339
304 std::vector<v8::Handle<v8::Value> > arguments; 340 std::vector<v8::Handle<v8::Value> > arguments;
305 arguments.push_back(v8::String::New(message.c_str(), message.size())); 341
342 // Convert the message to a v8 object; either a value or undefined.
343 // See PostMessage for more details.
344 if (message.empty()) {
345 arguments.push_back(v8::Undefined());
346 } else {
347 CHECK_EQ(1u, message.GetSize());
348 const base::Value* message_value = NULL;
349 message.Get(0, &message_value);
350 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
351 arguments.push_back(converter->ToV8Value(message_value, context));
352 }
353
306 arguments.push_back(port_id_handle); 354 arguments.push_back(port_id_handle);
307 CHECK((*it)->CallChromeHiddenMethod("Port.dispatchOnMessage", 355 CHECK((*it)->CallChromeHiddenMethod("Port.dispatchOnMessage",
308 arguments.size(), 356 arguments.size(),
309 &arguments[0], 357 &arguments[0],
310 NULL)); 358 NULL));
311 } 359 }
312 } 360 }
313 361
314 // static 362 // static
315 void MiscellaneousBindings::DispatchOnDisconnect( 363 void MiscellaneousBindings::DispatchOnDisconnect(
316 const ChromeV8ContextSet::ContextSet& contexts, 364 const ChromeV8ContextSet::ContextSet& contexts,
317 int port_id, 365 int port_id,
318 const std::string& error_message, 366 const std::string& error_message,
319 content::RenderView* restrict_to_render_view) { 367 content::RenderView* restrict_to_render_view) {
320 v8::HandleScope handle_scope; 368 v8::HandleScope handle_scope;
321 369
322 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin(); 370 for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
323 it != contexts.end(); ++it) { 371 it != contexts.end(); ++it) {
324 if (restrict_to_render_view && 372 if (restrict_to_render_view &&
325 restrict_to_render_view != (*it)->GetRenderView()) { 373 restrict_to_render_view != (*it)->GetRenderView()) {
326 continue; 374 continue;
327 } 375 }
328 376
377 // TODO(kalman): remove when ContextSet::ForEach is available.
378 if ((*it)->v8_context().IsEmpty())
379 continue;
380
329 std::vector<v8::Handle<v8::Value> > arguments; 381 std::vector<v8::Handle<v8::Value> > arguments;
330 arguments.push_back(v8::Integer::New(port_id)); 382 arguments.push_back(v8::Integer::New(port_id));
331 if (!error_message.empty()) { 383 if (!error_message.empty()) {
332 arguments.push_back(v8::String::New(error_message.c_str())); 384 arguments.push_back(v8::String::New(error_message.c_str()));
333 } else { 385 } else {
334 arguments.push_back(v8::Null()); 386 arguments.push_back(v8::Null());
335 } 387 }
336 (*it)->CallChromeHiddenMethod("Port.dispatchOnDisconnect", 388 (*it)->CallChromeHiddenMethod("Port.dispatchOnDisconnect",
337 arguments.size(), &arguments[0], 389 arguments.size(), &arguments[0],
338 NULL); 390 NULL);
339 } 391 }
340 } 392 }
341 393
342 } // namespace extensions 394 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/miscellaneous_bindings.h ('k') | chrome/renderer/resources/extensions/miscellaneous_bindings.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698