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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "ppapi/shared_impl/ppapi_globals.h" | 13 #include "ppapi/shared_impl/ppapi_globals.h" |
| 14 #include "ppapi/shared_impl/var.h" | 14 #include "ppapi/shared_impl/var.h" |
| 15 #include "ppapi/shared_impl/var_tracker.h" | 15 #include "ppapi/shared_impl/var_tracker.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMMessageEvent.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMMessageEvent.h" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptVa lue.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptVa lue.h" |
| 24 #include "v8/include/v8.h" | 24 #include "v8/include/v8.h" |
| 25 #include "webkit/plugins/ppapi/host_array_buffer_var.h" | 25 #include "webkit/plugins/ppapi/host_array_buffer_var.h" |
| 26 #include "webkit/plugins/ppapi/npapi_glue.h" | 26 #include "webkit/plugins/ppapi/npapi_glue.h" |
| 27 #include "webkit/plugins/ppapi/plugin_module.h" | 27 #include "webkit/plugins/ppapi/plugin_module.h" |
| 28 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 28 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 29 #include "webkit/plugins/ppapi/v8_var_converter.h" | |
| 29 | 30 |
| 30 using ppapi::ArrayBufferVar; | 31 using ppapi::ArrayBufferVar; |
| 31 using ppapi::PpapiGlobals; | 32 using ppapi::PpapiGlobals; |
| 32 using ppapi::StringVar; | 33 using ppapi::StringVar; |
| 33 using WebKit::WebBindings; | 34 using WebKit::WebBindings; |
| 34 using WebKit::WebElement; | 35 using WebKit::WebElement; |
| 35 using WebKit::WebDOMEvent; | 36 using WebKit::WebDOMEvent; |
| 36 using WebKit::WebDOMMessageEvent; | 37 using WebKit::WebDOMMessageEvent; |
| 37 using WebKit::WebPluginContainer; | 38 using WebKit::WebPluginContainer; |
| 38 using WebKit::WebSerializedScriptValue; | 39 using WebKit::WebSerializedScriptValue; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 55 NPObject* ToPassThroughObject(NPObject* object) { | 56 NPObject* ToPassThroughObject(NPObject* object) { |
| 56 MessageChannel* channel = ToMessageChannel(object); | 57 MessageChannel* channel = ToMessageChannel(object); |
| 57 return channel ? channel->passthrough_object() : NULL; | 58 return channel ? channel->passthrough_object() : NULL; |
| 58 } | 59 } |
| 59 | 60 |
| 60 // Helper function to determine if a given identifier is equal to kPostMessage. | 61 // Helper function to determine if a given identifier is equal to kPostMessage. |
| 61 bool IdentifierIsPostMessage(NPIdentifier identifier) { | 62 bool IdentifierIsPostMessage(NPIdentifier identifier) { |
| 62 return WebBindings::getStringIdentifier(kPostMessage) == identifier; | 63 return WebBindings::getStringIdentifier(kPostMessage) == identifier; |
| 63 } | 64 } |
| 64 | 65 |
| 65 // Converts the given PP_Var to a v8::Value, returning true on success. | 66 bool NPVariantToPPVar(const NPVariant* variant, PP_Var* result) { |
| 66 // False means that the given variant is invalid. In this case, |result| will | 67 switch (variant->type) { |
| 67 // be set to an empty handle. | 68 case NPVariantType_Void: |
| 68 bool PPVarToV8Value(PP_Var var, v8::Handle<v8::Value>* result) { | 69 *result = PP_MakeUndefined(); |
| 69 switch (var.type) { | 70 return true; |
| 70 case PP_VARTYPE_UNDEFINED: | 71 case NPVariantType_Null: |
| 71 *result = v8::Undefined(); | 72 *result = PP_MakeNull(); |
| 72 break; | 73 return true; |
| 73 case PP_VARTYPE_NULL: | 74 case NPVariantType_Bool: |
| 74 *result = v8::Null(); | 75 *result = PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant))); |
| 75 break; | 76 return true; |
| 76 case PP_VARTYPE_BOOL: | 77 case NPVariantType_Int32: |
| 77 *result = (var.value.as_bool == PP_TRUE) ? v8::True() : v8::False(); | 78 *result = PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); |
| 78 break; | 79 return true; |
| 79 case PP_VARTYPE_INT32: | 80 case NPVariantType_Double: |
| 80 *result = v8::Integer::New(var.value.as_int); | 81 *result = PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); |
| 81 break; | 82 return true; |
| 82 case PP_VARTYPE_DOUBLE: | 83 case NPVariantType_String: |
| 83 *result = v8::Number::New(var.value.as_double); | 84 *result = StringVar::StringToPPVar( |
| 84 break; | 85 NPVARIANT_TO_STRING(*variant).UTF8Characters, |
| 85 case PP_VARTYPE_STRING: { | 86 NPVARIANT_TO_STRING(*variant).UTF8Length); |
| 86 StringVar* string = StringVar::FromPPVar(var); | 87 return true; |
| 87 if (!string) { | 88 case NPVariantType_Object: |
| 88 result->Clear(); | 89 V8VarConverter converter; |
| 89 return false; | 90 // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it |
| 90 } | 91 // shouldn't result in a deep copy. |
| 91 const std::string& value = string->value(); | 92 return converter.FromV8Value(WebBindings::toV8Value(variant), |
| 92 // TODO(dmichael): We should consider caching the V8 string in the host- | 93 v8::Context::GetCurrent(), result); |
| 93 // side StringVar, so that we only have to convert/copy once if a | |
| 94 // string is sent more than once. | |
| 95 *result = v8::String::New(value.c_str(), value.size()); | |
| 96 break; | |
| 97 } | |
| 98 case PP_VARTYPE_ARRAY_BUFFER: { | |
| 99 ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); | |
| 100 if (!buffer) { | |
| 101 result->Clear(); | |
| 102 return false; | |
| 103 } | |
| 104 HostArrayBufferVar* host_buffer = | |
| 105 static_cast<HostArrayBufferVar*>(buffer); | |
| 106 *result = | |
| 107 v8::Local<v8::Value>::New(host_buffer->webkit_buffer().toV8Value()); | |
| 108 break; | |
| 109 } | |
| 110 case PP_VARTYPE_OBJECT: | |
| 111 case PP_VARTYPE_ARRAY: | |
| 112 case PP_VARTYPE_DICTIONARY: | |
| 113 // These are not currently supported. | |
| 114 NOTIMPLEMENTED(); | |
| 115 result->Clear(); | |
| 116 return false; | |
| 117 } | 94 } |
| 118 return true; | 95 return false; |
| 119 } | 96 } |
| 120 | 97 |
| 121 // Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage. | 98 // Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage. |
| 122 // This currently just copies the value. For a string Var, the result is a | 99 // This currently just copies the value. For a string Var, the result is a |
| 123 // PP_Var with the a copy of |var|'s string contents and a reference count of 1. | 100 // PP_Var with the a copy of |var|'s string contents and a reference count of 1. |
| 124 // | 101 // |
| 125 // TODO(dmichael): Bypass this step for out-of-process plugins, since a copy | 102 // TODO(dmichael): Bypass this step for out-of-process plugins, since a copy |
| 126 // happens already when the Var is serialized. | 103 // happens already when the Var is serialized. |
|
dmichael (off chromium)
2013/05/09 20:21:12
Oops, this TODO has been done, so you can remove i
raymes
2013/05/13 17:09:43
Done.
| |
| 127 PP_Var CopyPPVar(const PP_Var& var) { | 104 PP_Var CopyPPVar(const PP_Var& var) { |
| 128 if (var.type == PP_VARTYPE_OBJECT) { | 105 switch (var.type) { |
| 129 // Objects are not currently supported. | 106 case PP_VARTYPE_UNDEFINED: |
| 130 NOTIMPLEMENTED(); | 107 case PP_VARTYPE_NULL: |
| 131 return PP_MakeUndefined(); | 108 case PP_VARTYPE_BOOL: |
| 132 } else if (var.type == PP_VARTYPE_STRING) { | 109 case PP_VARTYPE_INT32: |
| 133 StringVar* string = StringVar::FromPPVar(var); | 110 case PP_VARTYPE_DOUBLE: |
| 134 if (!string) | 111 return var; |
| 112 case PP_VARTYPE_STRING: { | |
| 113 StringVar* string = StringVar::FromPPVar(var); | |
| 114 if (!string) | |
| 115 return PP_MakeUndefined(); | |
| 116 return StringVar::StringToPPVar(string->value()); | |
| 117 } | |
| 118 case PP_VARTYPE_ARRAY_BUFFER: { | |
| 119 ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); | |
| 120 if (!buffer) | |
| 121 return PP_MakeUndefined(); | |
| 122 PP_Var new_buffer_var = PpapiGlobals::Get()->GetVarTracker()-> | |
| 123 MakeArrayBufferPPVar(buffer->ByteLength()); | |
| 124 DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER); | |
| 125 if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER) | |
| 126 return PP_MakeUndefined(); | |
| 127 ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var); | |
| 128 DCHECK(new_buffer); | |
| 129 if (!new_buffer) | |
| 130 return PP_MakeUndefined(); | |
| 131 memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength()); | |
| 132 return new_buffer_var; | |
| 133 } | |
| 134 case PP_VARTYPE_OBJECT: | |
| 135 case PP_VARTYPE_ARRAY: | |
| 136 case PP_VARTYPE_DICTIONARY: | |
| 137 // Objects/Arrays/Dictionaries not supported by PostMessage in-process. | |
| 138 NOTREACHED(); | |
| 135 return PP_MakeUndefined(); | 139 return PP_MakeUndefined(); |
| 136 return StringVar::StringToPPVar(string->value()); | |
| 137 } else if (var.type == PP_VARTYPE_ARRAY_BUFFER) { | |
| 138 ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); | |
| 139 if (!buffer) | |
| 140 return PP_MakeUndefined(); | |
| 141 PP_Var new_buffer_var = PpapiGlobals::Get()->GetVarTracker()-> | |
| 142 MakeArrayBufferPPVar(buffer->ByteLength()); | |
| 143 DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER); | |
| 144 if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER) | |
| 145 return PP_MakeUndefined(); | |
| 146 ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var); | |
| 147 DCHECK(new_buffer); | |
| 148 if (!new_buffer) | |
| 149 return PP_MakeUndefined(); | |
| 150 memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength()); | |
| 151 return new_buffer_var; | |
| 152 } else { | |
| 153 return var; | |
| 154 } | 140 } |
| 141 NOTREACHED(); | |
| 142 return PP_MakeUndefined(); | |
| 155 } | 143 } |
| 156 | 144 |
| 157 //------------------------------------------------------------------------------ | 145 //------------------------------------------------------------------------------ |
| 158 // Implementations of NPClass functions. These are here to: | 146 // Implementations of NPClass functions. These are here to: |
| 159 // - Implement postMessage behavior. | 147 // - Implement postMessage behavior. |
| 160 // - Forward calls to the 'passthrough' object to allow backwards-compatibility | 148 // - Forward calls to the 'passthrough' object to allow backwards-compatibility |
| 161 // with GetInstanceObject() objects. | 149 // with GetInstanceObject() objects. |
| 162 //------------------------------------------------------------------------------ | 150 //------------------------------------------------------------------------------ |
| 163 NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) { | 151 NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) { |
| 164 return new MessageChannel::MessageChannelNPObject; | 152 return new MessageChannel::MessageChannelNPObject; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 188 bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name, | 176 bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name, |
| 189 const NPVariant* args, uint32 arg_count, | 177 const NPVariant* args, uint32 arg_count, |
| 190 NPVariant* result) { | 178 NPVariant* result) { |
| 191 if (!np_obj) | 179 if (!np_obj) |
| 192 return false; | 180 return false; |
| 193 | 181 |
| 194 // We only handle a function called postMessage. | 182 // We only handle a function called postMessage. |
| 195 if (IdentifierIsPostMessage(name) && (arg_count == 1)) { | 183 if (IdentifierIsPostMessage(name) && (arg_count == 1)) { |
| 196 MessageChannel* message_channel = ToMessageChannel(np_obj); | 184 MessageChannel* message_channel = ToMessageChannel(np_obj); |
| 197 if (message_channel) { | 185 if (message_channel) { |
| 198 PP_Var argument(NPVariantToPPVar(message_channel->instance(), &args[0])); | 186 PP_Var argument; |
|
dmichael (off chromium)
2013/05/09 20:21:12
nit: PP_Var argument = PP_MakeUndefined();
raymes
2013/05/13 17:09:43
Done.
| |
| 187 if (!NPVariantToPPVar(&args[0], &argument)) { | |
| 188 NOTREACHED(); | |
| 189 return false; | |
| 190 } | |
| 199 message_channel->PostMessageToNative(argument); | 191 message_channel->PostMessageToNative(argument); |
| 200 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument); | 192 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument); |
| 201 return true; | 193 return true; |
| 202 } else { | 194 } else { |
| 203 return false; | 195 return false; |
| 204 } | 196 } |
| 205 } | 197 } |
| 206 // Other method calls we will pass to the passthrough object, if we have one. | 198 // Other method calls we will pass to the passthrough object, if we have one. |
| 207 NPObject* passthrough = ToPassThroughObject(np_obj); | 199 NPObject* passthrough = ToPassThroughObject(np_obj); |
| 208 if (passthrough) { | 200 if (passthrough) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 // It's possible that container() is NULL if the plugin has been removed from | 342 // It's possible that container() is NULL if the plugin has been removed from |
| 351 // the DOM (but the PluginInstance is not destroyed yet). | 343 // the DOM (but the PluginInstance is not destroyed yet). |
| 352 if (!container) | 344 if (!container) |
| 353 return; | 345 return; |
| 354 | 346 |
| 355 v8::Local<v8::Context> context = | 347 v8::Local<v8::Context> context = |
| 356 container->element().document().frame()->mainWorldScriptContext(); | 348 container->element().document().frame()->mainWorldScriptContext(); |
| 357 v8::Context::Scope context_scope(context); | 349 v8::Context::Scope context_scope(context); |
| 358 | 350 |
| 359 v8::Local<v8::Value> v8_val; | 351 v8::Local<v8::Value> v8_val; |
| 360 if (!PPVarToV8Value(message_data, &v8_val)) { | 352 V8VarConverter converter; |
| 353 if (!converter.ToV8Value(message_data, context, &v8_val)) { | |
| 361 NOTREACHED(); | 354 NOTREACHED(); |
| 362 return; | 355 return; |
| 363 } | 356 } |
| 364 | 357 |
| 358 // This is for backward compatibility. It usually makes sense for us to return | |
| 359 // a string object rather than a string primitive because it allows multiple | |
| 360 // references to the same string (as with PP_Var strings). However, prior to | |
| 361 // implementing dictionary and array, vars we would return a string primitive | |
| 362 // here. Changing it to an object now will break existing code that uses | |
| 363 // strict comparisons for strings returned from PostMessage. e.g. x === "123" | |
| 364 // will no longer return true. So if the only value to return is a string | |
| 365 // object, just return the string primitive. | |
| 366 if (v8_val->IsStringObject()) | |
| 367 v8_val = v8_val->ToString(); | |
| 368 | |
| 365 WebSerializedScriptValue serialized_val = | 369 WebSerializedScriptValue serialized_val = |
| 366 WebSerializedScriptValue::serialize(v8_val); | 370 WebSerializedScriptValue::serialize(v8_val); |
| 367 | 371 |
| 368 if (instance_->module()->IsProxied()) { | 372 if (instance_->module()->IsProxied()) { |
| 369 if (early_message_queue_state_ != SEND_DIRECTLY) { | 373 if (early_message_queue_state_ != SEND_DIRECTLY) { |
| 370 // We can't just PostTask here; the messages would arrive out of | 374 // We can't just PostTask here; the messages would arrive out of |
| 371 // order. Instead, we queue them up until we're ready to post | 375 // order. Instead, we queue them up until we're ready to post |
| 372 // them. | 376 // them. |
| 373 early_message_queue_.push_back(serialized_val); | 377 early_message_queue_.push_back(serialized_val); |
| 374 } else { | 378 } else { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 // invokes: | 497 // invokes: |
| 494 // SetPassthroughObject(passthrough_object()); | 498 // SetPassthroughObject(passthrough_object()); |
| 495 if (passthrough_object_) | 499 if (passthrough_object_) |
| 496 WebBindings::releaseObject(passthrough_object_); | 500 WebBindings::releaseObject(passthrough_object_); |
| 497 | 501 |
| 498 passthrough_object_ = passthrough; | 502 passthrough_object_ = passthrough; |
| 499 } | 503 } |
| 500 | 504 |
| 501 } // namespace ppapi | 505 } // namespace ppapi |
| 502 } // namespace webkit | 506 } // namespace webkit |
| OLD | NEW |