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 "webkit/plugins/ppapi/message_channel.h" | 5 #include "webkit/plugins/ppapi/message_channel.h" |
6 | 6 |
7 #include <cstdlib> | 7 #include <cstdlib> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 using WebKit::WebPluginContainer; | 38 using WebKit::WebPluginContainer; |
39 using WebKit::WebSerializedScriptValue; | 39 using WebKit::WebSerializedScriptValue; |
40 | 40 |
41 namespace webkit { | 41 namespace webkit { |
42 | 42 |
43 namespace ppapi { | 43 namespace ppapi { |
44 | 44 |
45 namespace { | 45 namespace { |
46 | 46 |
47 const char kPostMessage[] = "postMessage"; | 47 const char kPostMessage[] = "postMessage"; |
48 const char kV8ToVarConversionError[] = "Failed to convert a PostMessage " | |
49 "argument from a JavaScript value to a PP_Var. It may have cycles or be of " | |
50 "an unsupported type: "; | |
51 const char kVarToV8ConversionError[] = "Failed to convert a PostMessage " | |
52 "argument from a PP_Var to a Javascript value. It may have cycles or be of " | |
53 "an unsupported type: "; | |
54 | |
55 std::string MakeV8ConversionError(v8::Handle<v8::Value> v8_value) { | |
56 v8::String::Utf8Value utf8(v8_value->ToString()); | |
57 return kV8ToVarConversionError + std::string(*utf8, utf8.length()); | |
dmichael (off chromium)
2013/06/04 16:59:10
Are you actually converting the v8_value to a stri
raymes
2013/06/04 19:36:06
That's ok with me.
| |
58 } | |
59 | |
60 std::string MakePPVarConversionError(PP_Var var) { | |
61 return kVarToV8ConversionError + ::ppapi::Var::PPVarToLogString(var); | |
62 } | |
48 | 63 |
49 // Helper function to get the MessageChannel that is associated with an | 64 // Helper function to get the MessageChannel that is associated with an |
50 // NPObject*. | 65 // NPObject*. |
51 MessageChannel* ToMessageChannel(NPObject* object) { | 66 MessageChannel* ToMessageChannel(NPObject* object) { |
52 return static_cast<MessageChannel::MessageChannelNPObject*>(object)-> | 67 return static_cast<MessageChannel::MessageChannelNPObject*>(object)-> |
53 message_channel; | 68 message_channel; |
54 } | 69 } |
55 | 70 |
56 NPObject* ToPassThroughObject(NPObject* object) { | 71 NPObject* ToPassThroughObject(NPObject* object) { |
57 MessageChannel* channel = ToMessageChannel(object); | 72 MessageChannel* channel = ToMessageChannel(object); |
58 return channel ? channel->passthrough_object() : NULL; | 73 return channel ? channel->passthrough_object() : NULL; |
59 } | 74 } |
60 | 75 |
61 // Helper function to determine if a given identifier is equal to kPostMessage. | 76 // Helper function to determine if a given identifier is equal to kPostMessage. |
62 bool IdentifierIsPostMessage(NPIdentifier identifier) { | 77 bool IdentifierIsPostMessage(NPIdentifier identifier) { |
63 return WebBindings::getStringIdentifier(kPostMessage) == identifier; | 78 return WebBindings::getStringIdentifier(kPostMessage) == identifier; |
64 } | 79 } |
65 | 80 |
66 bool NPVariantToPPVar(const NPVariant* variant, PP_Var* result) { | 81 bool NPVariantToPPVar(const NPVariant* variant, |
82 PP_Var* result, | |
83 std::string* error) { | |
67 switch (variant->type) { | 84 switch (variant->type) { |
68 case NPVariantType_Void: | 85 case NPVariantType_Void: |
69 *result = PP_MakeUndefined(); | 86 *result = PP_MakeUndefined(); |
70 return true; | 87 return true; |
71 case NPVariantType_Null: | 88 case NPVariantType_Null: |
72 *result = PP_MakeNull(); | 89 *result = PP_MakeNull(); |
73 return true; | 90 return true; |
74 case NPVariantType_Bool: | 91 case NPVariantType_Bool: |
75 *result = PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant))); | 92 *result = PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant))); |
76 return true; | 93 return true; |
77 case NPVariantType_Int32: | 94 case NPVariantType_Int32: |
78 *result = PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); | 95 *result = PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); |
79 return true; | 96 return true; |
80 case NPVariantType_Double: | 97 case NPVariantType_Double: |
81 *result = PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); | 98 *result = PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); |
82 return true; | 99 return true; |
83 case NPVariantType_String: | 100 case NPVariantType_String: |
84 *result = StringVar::StringToPPVar( | 101 *result = StringVar::StringToPPVar( |
85 NPVARIANT_TO_STRING(*variant).UTF8Characters, | 102 NPVARIANT_TO_STRING(*variant).UTF8Characters, |
86 NPVARIANT_TO_STRING(*variant).UTF8Length); | 103 NPVARIANT_TO_STRING(*variant).UTF8Length); |
87 return true; | 104 return true; |
88 case NPVariantType_Object: | 105 case NPVariantType_Object: { |
89 V8VarConverter converter; | 106 V8VarConverter converter(false); |
90 // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it | 107 // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it |
91 // shouldn't result in a deep copy. | 108 // shouldn't result in a deep copy. |
92 return converter.FromV8Value(WebBindings::toV8Value(variant), | 109 v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant); |
93 v8::Context::GetCurrent(), result); | 110 if (!converter.FromV8Value(v8_value, v8::Context::GetCurrent(), result)) { |
111 *error = MakeV8ConversionError(v8_value); | |
112 return false; | |
113 } | |
114 return true; | |
115 } | |
94 } | 116 } |
117 *error = MakeV8ConversionError(WebBindings::toV8Value(variant)); | |
95 return false; | 118 return false; |
96 } | 119 } |
97 | 120 |
98 // Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage. | 121 // Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage. |
99 // This currently just copies the value. For a string Var, the result is a | 122 // This currently just copies the value. For a string Var, the result is a |
100 // PP_Var with the a copy of |var|'s string contents and a reference count of 1. | 123 // PP_Var with the a copy of |var|'s string contents and a reference count of 1. |
101 PP_Var CopyPPVar(const PP_Var& var) { | 124 PP_Var CopyPPVar(const PP_Var& var) { |
102 switch (var.type) { | 125 switch (var.type) { |
103 case PP_VARTYPE_UNDEFINED: | 126 case PP_VARTYPE_UNDEFINED: |
104 case PP_VARTYPE_NULL: | 127 case PP_VARTYPE_NULL: |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 const NPVariant* args, uint32 arg_count, | 197 const NPVariant* args, uint32 arg_count, |
175 NPVariant* result) { | 198 NPVariant* result) { |
176 if (!np_obj) | 199 if (!np_obj) |
177 return false; | 200 return false; |
178 | 201 |
179 // We only handle a function called postMessage. | 202 // We only handle a function called postMessage. |
180 if (IdentifierIsPostMessage(name) && (arg_count == 1)) { | 203 if (IdentifierIsPostMessage(name) && (arg_count == 1)) { |
181 MessageChannel* message_channel = ToMessageChannel(np_obj); | 204 MessageChannel* message_channel = ToMessageChannel(np_obj); |
182 if (message_channel) { | 205 if (message_channel) { |
183 PP_Var argument = PP_MakeUndefined(); | 206 PP_Var argument = PP_MakeUndefined(); |
184 if (!NPVariantToPPVar(&args[0], &argument)) { | 207 std::string error; |
185 NOTREACHED(); | 208 bool success = NPVariantToPPVar(&args[0], &argument, &error); |
186 return false; | 209 message_channel->PostMessageToNative(argument, success, error); |
187 } | |
188 message_channel->PostMessageToNative(argument); | |
189 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument); | 210 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument); |
190 return true; | 211 return success; |
191 } else { | 212 } else { |
192 return false; | 213 return false; |
193 } | 214 } |
194 } | 215 } |
195 // Other method calls we will pass to the passthrough object, if we have one. | 216 // Other method calls we will pass to the passthrough object, if we have one. |
196 NPObject* passthrough = ToPassThroughObject(np_obj); | 217 NPObject* passthrough = ToPassThroughObject(np_obj); |
197 if (passthrough) { | 218 if (passthrough) { |
198 return WebBindings::invoke(NULL, passthrough, name, args, arg_count, | 219 return WebBindings::invoke(NULL, passthrough, name, args, arg_count, |
199 result); | 220 result); |
200 } | 221 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 WebPluginContainer* container = instance_->container(); | 360 WebPluginContainer* container = instance_->container(); |
340 // It's possible that container() is NULL if the plugin has been removed from | 361 // It's possible that container() is NULL if the plugin has been removed from |
341 // the DOM (but the PluginInstance is not destroyed yet). | 362 // the DOM (but the PluginInstance is not destroyed yet). |
342 if (!container) | 363 if (!container) |
343 return; | 364 return; |
344 | 365 |
345 v8::Local<v8::Context> context = | 366 v8::Local<v8::Context> context = |
346 container->element().document().frame()->mainWorldScriptContext(); | 367 container->element().document().frame()->mainWorldScriptContext(); |
347 v8::Context::Scope context_scope(context); | 368 v8::Context::Scope context_scope(context); |
348 | 369 |
349 v8::Local<v8::Value> v8_val; | 370 v8::Handle<v8::Value> v8_val; |
350 V8VarConverter converter; | 371 V8VarConverter converter(false); |
351 if (!converter.ToV8Value(message_data, context, &v8_val)) { | 372 if (!converter.ToV8Value(message_data, context, &v8_val)) { |
352 NOTREACHED(); | 373 PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(), |
353 return; | 374 PP_LOGLEVEL_ERROR, std::string(), |
375 MakePPVarConversionError(message_data)); | |
376 v8_val = v8::Undefined(); | |
354 } | 377 } |
355 | 378 |
356 // This is for backward compatibility. It usually makes sense for us to return | 379 // This is for backward compatibility. It usually makes sense for us to return |
357 // a string object rather than a string primitive because it allows multiple | 380 // a string object rather than a string primitive because it allows multiple |
358 // references to the same string (as with PP_Var strings). However, prior to | 381 // references to the same string (as with PP_Var strings). However, prior to |
359 // implementing dictionary and array, vars we would return a string primitive | 382 // implementing dictionary and array, vars we would return a string primitive |
360 // here. Changing it to an object now will break existing code that uses | 383 // here. Changing it to an object now will break existing code that uses |
361 // strict comparisons for strings returned from PostMessage. e.g. x === "123" | 384 // strict comparisons for strings returned from PostMessage. e.g. x === "123" |
362 // will no longer return true. So if the only value to return is a string | 385 // will no longer return true. So if the only value to return is a string |
363 // object, just return the string primitive. | 386 // object, just return the string primitive. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 // messages: | 473 // messages: |
451 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html | 474 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html |
452 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari | 475 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari |
453 // at least, postMessage on Workers does not provide the origin or source. | 476 // at least, postMessage on Workers does not provide the origin or source. |
454 // TODO(dmichael): Add origin if we change to a more iframe-like origin | 477 // TODO(dmichael): Add origin if we change to a more iframe-like origin |
455 // policy (see crbug.com/81537) | 478 // policy (see crbug.com/81537) |
456 | 479 |
457 container->element().dispatchEvent(msg_event); | 480 container->element().dispatchEvent(msg_event); |
458 } | 481 } |
459 | 482 |
460 void MessageChannel::PostMessageToNative(PP_Var message_data) { | 483 void MessageChannel::PostMessageToNative(PP_Var message_data, |
484 bool success, | |
485 const std::string& error_msg) { | |
486 if (!success) { | |
487 PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(), | |
488 PP_LOGLEVEL_ERROR, std::string(), error_msg); | |
489 message_data = PP_MakeUndefined(); | |
dmichael (off chromium)
2013/06/04 16:59:10
This feels kind of klugy to me. My first choice is
raymes
2013/06/04 19:36:06
This was kludgy. Hopefully my change seems nicer.
| |
490 } | |
461 if (instance_->module()->IsProxied()) { | 491 if (instance_->module()->IsProxied()) { |
462 // In the proxied case, the copy will happen via serializiation, and the | 492 // In the proxied case, the copy will happen via serializiation, and the |
463 // message is asynchronous. Therefore there's no need to copy the Var, nor | 493 // message is asynchronous. Therefore there's no need to copy the Var, nor |
464 // to PostTask. | 494 // to PostTask. |
465 PostMessageToNativeImpl(message_data); | 495 PostMessageToNativeImpl(message_data); |
466 } else { | 496 } else { |
467 // Make a copy of the message data for the Task we will run. | 497 // Make a copy of the message data for the Task we will run. |
468 PP_Var var_copy(CopyPPVar(message_data)); | 498 PP_Var var_copy(CopyPPVar(message_data)); |
469 | 499 |
470 base::MessageLoop::current()->PostTask( | 500 base::MessageLoop::current()->PostTask( |
(...skipping 25 matching lines...) Expand all Loading... | |
496 // invokes: | 526 // invokes: |
497 // SetPassthroughObject(passthrough_object()); | 527 // SetPassthroughObject(passthrough_object()); |
498 if (passthrough_object_) | 528 if (passthrough_object_) |
499 WebBindings::releaseObject(passthrough_object_); | 529 WebBindings::releaseObject(passthrough_object_); |
500 | 530 |
501 passthrough_object_ = passthrough; | 531 passthrough_object_ = passthrough; |
502 } | 532 } |
503 | 533 |
504 } // namespace ppapi | 534 } // namespace ppapi |
505 } // namespace webkit | 535 } // namespace webkit |
OLD | NEW |