Index: webkit/plugins/ppapi/message_channel.cc |
diff --git a/webkit/plugins/ppapi/message_channel.cc b/webkit/plugins/ppapi/message_channel.cc |
index bab0cf8c2c53f9e199285d6a62c5ead4e14e327c..e0e0a390ce789c1212d8bcd2e0d85bf5969ac574 100644 |
--- a/webkit/plugins/ppapi/message_channel.cc |
+++ b/webkit/plugins/ppapi/message_channel.cc |
@@ -26,6 +26,7 @@ |
#include "webkit/plugins/ppapi/npapi_glue.h" |
#include "webkit/plugins/ppapi/plugin_module.h" |
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
+#include "webkit/plugins/ppapi/v8_var_converter.h" |
using ppapi::ArrayBufferVar; |
using ppapi::PpapiGlobals; |
@@ -62,96 +63,80 @@ bool IdentifierIsPostMessage(NPIdentifier identifier) { |
return WebBindings::getStringIdentifier(kPostMessage) == identifier; |
} |
-// Converts the given PP_Var to a v8::Value, returning true on success. |
-// False means that the given variant is invalid. In this case, |result| will |
-// be set to an empty handle. |
-bool PPVarToV8Value(PP_Var var, v8::Handle<v8::Value>* result) { |
+bool NPVariantToPPVar(const NPVariant* variant, PP_Var* result) { |
+ switch (variant->type) { |
+ case NPVariantType_Void: |
+ *result = PP_MakeUndefined(); |
+ return true; |
+ case NPVariantType_Null: |
+ *result = PP_MakeNull(); |
+ return true; |
+ case NPVariantType_Bool: |
+ *result = PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant))); |
+ return true; |
+ case NPVariantType_Int32: |
+ *result = PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); |
+ return true; |
+ case NPVariantType_Double: |
+ *result = PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); |
+ return true; |
+ case NPVariantType_String: |
+ *result = StringVar::StringToPPVar( |
+ NPVARIANT_TO_STRING(*variant).UTF8Characters, |
+ NPVARIANT_TO_STRING(*variant).UTF8Length); |
+ return true; |
+ case NPVariantType_Object: |
+ V8VarConverter converter; |
+ // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it |
+ // shouldn't result in a deep copy. |
+ return converter.FromV8Value(WebBindings::toV8Value(variant), |
+ v8::Context::GetCurrent(), result); |
+ } |
+ return false; |
+} |
+ |
+// Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage. |
+// This currently just copies the value. For a string Var, the result is a |
+// PP_Var with the a copy of |var|'s string contents and a reference count of 1. |
+PP_Var CopyPPVar(const PP_Var& var) { |
switch (var.type) { |
case PP_VARTYPE_UNDEFINED: |
- *result = v8::Undefined(); |
- break; |
case PP_VARTYPE_NULL: |
- *result = v8::Null(); |
- break; |
case PP_VARTYPE_BOOL: |
- *result = (var.value.as_bool == PP_TRUE) ? v8::True() : v8::False(); |
- break; |
case PP_VARTYPE_INT32: |
- *result = v8::Integer::New(var.value.as_int); |
- break; |
case PP_VARTYPE_DOUBLE: |
- *result = v8::Number::New(var.value.as_double); |
- break; |
+ return var; |
case PP_VARTYPE_STRING: { |
StringVar* string = StringVar::FromPPVar(var); |
- if (!string) { |
- result->Clear(); |
- return false; |
- } |
- const std::string& value = string->value(); |
- // TODO(dmichael): We should consider caching the V8 string in the host- |
- // side StringVar, so that we only have to convert/copy once if a |
- // string is sent more than once. |
- *result = v8::String::New(value.c_str(), value.size()); |
- break; |
+ if (!string) |
+ return PP_MakeUndefined(); |
+ return StringVar::StringToPPVar(string->value()); |
} |
case PP_VARTYPE_ARRAY_BUFFER: { |
ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); |
- if (!buffer) { |
- result->Clear(); |
- return false; |
- } |
- HostArrayBufferVar* host_buffer = |
- static_cast<HostArrayBufferVar*>(buffer); |
- *result = |
- v8::Local<v8::Value>::New(host_buffer->webkit_buffer().toV8Value()); |
- break; |
+ if (!buffer) |
+ return PP_MakeUndefined(); |
+ PP_Var new_buffer_var = PpapiGlobals::Get()->GetVarTracker()-> |
+ MakeArrayBufferPPVar(buffer->ByteLength()); |
+ DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER); |
+ if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER) |
+ return PP_MakeUndefined(); |
+ ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var); |
+ DCHECK(new_buffer); |
+ if (!new_buffer) |
+ return PP_MakeUndefined(); |
+ memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength()); |
+ return new_buffer_var; |
} |
case PP_VARTYPE_OBJECT: |
case PP_VARTYPE_ARRAY: |
case PP_VARTYPE_DICTIONARY: |
- // These are not currently supported. |
- NOTIMPLEMENTED(); |
- result->Clear(); |
- return false; |
- } |
- return true; |
-} |
- |
-// Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage. |
-// This currently just copies the value. For a string Var, the result is a |
-// PP_Var with the a copy of |var|'s string contents and a reference count of 1. |
-// |
-// TODO(dmichael): Bypass this step for out-of-process plugins, since a copy |
-// happens already when the Var is serialized. |
-PP_Var CopyPPVar(const PP_Var& var) { |
- if (var.type == PP_VARTYPE_OBJECT) { |
- // Objects are not currently supported. |
- NOTIMPLEMENTED(); |
- return PP_MakeUndefined(); |
- } else if (var.type == PP_VARTYPE_STRING) { |
- StringVar* string = StringVar::FromPPVar(var); |
- if (!string) |
- return PP_MakeUndefined(); |
- return StringVar::StringToPPVar(string->value()); |
- } else if (var.type == PP_VARTYPE_ARRAY_BUFFER) { |
- ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); |
- if (!buffer) |
- return PP_MakeUndefined(); |
- PP_Var new_buffer_var = PpapiGlobals::Get()->GetVarTracker()-> |
- MakeArrayBufferPPVar(buffer->ByteLength()); |
- DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER); |
- if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER) |
- return PP_MakeUndefined(); |
- ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var); |
- DCHECK(new_buffer); |
- if (!new_buffer) |
+ // Objects/Arrays/Dictionaries not supported by PostMessage in-process. |
+ NOTREACHED(); |
return PP_MakeUndefined(); |
- memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength()); |
- return new_buffer_var; |
- } else { |
- return var; |
} |
+ NOTREACHED(); |
+ return PP_MakeUndefined(); |
} |
//------------------------------------------------------------------------------ |
@@ -195,7 +180,11 @@ bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name, |
if (IdentifierIsPostMessage(name) && (arg_count == 1)) { |
MessageChannel* message_channel = ToMessageChannel(np_obj); |
if (message_channel) { |
- PP_Var argument(NPVariantToPPVar(message_channel->instance(), &args[0])); |
+ PP_Var argument = PP_MakeUndefined(); |
+ if (!NPVariantToPPVar(&args[0], &argument)) { |
+ NOTREACHED(); |
+ return false; |
+ } |
message_channel->PostMessageToNative(argument); |
PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument); |
return true; |
@@ -357,11 +346,23 @@ void MessageChannel::PostMessageToJavaScript(PP_Var message_data) { |
v8::Context::Scope context_scope(context); |
v8::Local<v8::Value> v8_val; |
- if (!PPVarToV8Value(message_data, &v8_val)) { |
+ V8VarConverter converter; |
+ if (!converter.ToV8Value(message_data, context, &v8_val)) { |
NOTREACHED(); |
return; |
} |
+ // This is for backward compatibility. It usually makes sense for us to return |
+ // a string object rather than a string primitive because it allows multiple |
+ // references to the same string (as with PP_Var strings). However, prior to |
+ // implementing dictionary and array, vars we would return a string primitive |
+ // here. Changing it to an object now will break existing code that uses |
+ // strict comparisons for strings returned from PostMessage. e.g. x === "123" |
+ // will no longer return true. So if the only value to return is a string |
+ // object, just return the string primitive. |
+ if (v8_val->IsStringObject()) |
+ v8_val = v8_val->ToString(); |
+ |
WebSerializedScriptValue serialized_val = |
WebSerializedScriptValue::serialize(v8_val); |