Chromium Code Reviews| 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 |