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

Side by Side Diff: webkit/plugins/ppapi/message_channel.cc

Issue 14636009: Hook up V8<->Var conversion in the pepper message channel (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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 "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
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 //
125 // TODO(dmichael): Bypass this step for out-of-process plugins, since a copy
126 // happens already when the Var is serialized.
127 PP_Var CopyPPVar(const PP_Var& var) { 101 PP_Var CopyPPVar(const PP_Var& var) {
128 if (var.type == PP_VARTYPE_OBJECT) { 102 switch (var.type) {
129 // Objects are not currently supported. 103 case PP_VARTYPE_UNDEFINED:
130 NOTIMPLEMENTED(); 104 case PP_VARTYPE_NULL:
131 return PP_MakeUndefined(); 105 case PP_VARTYPE_BOOL:
132 } else if (var.type == PP_VARTYPE_STRING) { 106 case PP_VARTYPE_INT32:
133 StringVar* string = StringVar::FromPPVar(var); 107 case PP_VARTYPE_DOUBLE:
134 if (!string) 108 return var;
109 case PP_VARTYPE_STRING: {
110 StringVar* string = StringVar::FromPPVar(var);
111 if (!string)
112 return PP_MakeUndefined();
113 return StringVar::StringToPPVar(string->value());
114 }
115 case PP_VARTYPE_ARRAY_BUFFER: {
116 ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var);
117 if (!buffer)
118 return PP_MakeUndefined();
119 PP_Var new_buffer_var = PpapiGlobals::Get()->GetVarTracker()->
120 MakeArrayBufferPPVar(buffer->ByteLength());
121 DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER);
122 if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER)
123 return PP_MakeUndefined();
124 ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var);
125 DCHECK(new_buffer);
126 if (!new_buffer)
127 return PP_MakeUndefined();
128 memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength());
129 return new_buffer_var;
130 }
131 case PP_VARTYPE_OBJECT:
132 case PP_VARTYPE_ARRAY:
133 case PP_VARTYPE_DICTIONARY:
134 // Objects/Arrays/Dictionaries not supported by PostMessage in-process.
135 NOTREACHED();
135 return PP_MakeUndefined(); 136 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 } 137 }
138 NOTREACHED();
139 return PP_MakeUndefined();
155 } 140 }
156 141
157 //------------------------------------------------------------------------------ 142 //------------------------------------------------------------------------------
158 // Implementations of NPClass functions. These are here to: 143 // Implementations of NPClass functions. These are here to:
159 // - Implement postMessage behavior. 144 // - Implement postMessage behavior.
160 // - Forward calls to the 'passthrough' object to allow backwards-compatibility 145 // - Forward calls to the 'passthrough' object to allow backwards-compatibility
161 // with GetInstanceObject() objects. 146 // with GetInstanceObject() objects.
162 //------------------------------------------------------------------------------ 147 //------------------------------------------------------------------------------
163 NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) { 148 NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) {
164 return new MessageChannel::MessageChannelNPObject; 149 return new MessageChannel::MessageChannelNPObject;
(...skipping 23 matching lines...) Expand all
188 bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name, 173 bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name,
189 const NPVariant* args, uint32 arg_count, 174 const NPVariant* args, uint32 arg_count,
190 NPVariant* result) { 175 NPVariant* result) {
191 if (!np_obj) 176 if (!np_obj)
192 return false; 177 return false;
193 178
194 // We only handle a function called postMessage. 179 // We only handle a function called postMessage.
195 if (IdentifierIsPostMessage(name) && (arg_count == 1)) { 180 if (IdentifierIsPostMessage(name) && (arg_count == 1)) {
196 MessageChannel* message_channel = ToMessageChannel(np_obj); 181 MessageChannel* message_channel = ToMessageChannel(np_obj);
197 if (message_channel) { 182 if (message_channel) {
198 PP_Var argument(NPVariantToPPVar(message_channel->instance(), &args[0])); 183 PP_Var argument = PP_MakeUndefined();
184 if (!NPVariantToPPVar(&args[0], &argument)) {
185 NOTREACHED();
186 return false;
187 }
199 message_channel->PostMessageToNative(argument); 188 message_channel->PostMessageToNative(argument);
200 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument); 189 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument);
201 return true; 190 return true;
202 } else { 191 } else {
203 return false; 192 return false;
204 } 193 }
205 } 194 }
206 // Other method calls we will pass to the passthrough object, if we have one. 195 // Other method calls we will pass to the passthrough object, if we have one.
207 NPObject* passthrough = ToPassThroughObject(np_obj); 196 NPObject* passthrough = ToPassThroughObject(np_obj);
208 if (passthrough) { 197 if (passthrough) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 // It's possible that container() is NULL if the plugin has been removed from 339 // It's possible that container() is NULL if the plugin has been removed from
351 // the DOM (but the PluginInstance is not destroyed yet). 340 // the DOM (but the PluginInstance is not destroyed yet).
352 if (!container) 341 if (!container)
353 return; 342 return;
354 343
355 v8::Local<v8::Context> context = 344 v8::Local<v8::Context> context =
356 container->element().document().frame()->mainWorldScriptContext(); 345 container->element().document().frame()->mainWorldScriptContext();
357 v8::Context::Scope context_scope(context); 346 v8::Context::Scope context_scope(context);
358 347
359 v8::Local<v8::Value> v8_val; 348 v8::Local<v8::Value> v8_val;
360 if (!PPVarToV8Value(message_data, &v8_val)) { 349 V8VarConverter converter;
350 if (!converter.ToV8Value(message_data, context, &v8_val)) {
361 NOTREACHED(); 351 NOTREACHED();
362 return; 352 return;
363 } 353 }
364 354
355 // This is for backward compatibility. It usually makes sense for us to return
356 // a string object rather than a string primitive because it allows multiple
357 // references to the same string (as with PP_Var strings). However, prior to
358 // implementing dictionary and array, vars we would return a string primitive
359 // here. Changing it to an object now will break existing code that uses
360 // strict comparisons for strings returned from PostMessage. e.g. x === "123"
361 // will no longer return true. So if the only value to return is a string
362 // object, just return the string primitive.
363 if (v8_val->IsStringObject())
364 v8_val = v8_val->ToString();
365
365 WebSerializedScriptValue serialized_val = 366 WebSerializedScriptValue serialized_val =
366 WebSerializedScriptValue::serialize(v8_val); 367 WebSerializedScriptValue::serialize(v8_val);
367 368
368 if (instance_->module()->IsProxied()) { 369 if (instance_->module()->IsProxied()) {
369 if (early_message_queue_state_ != SEND_DIRECTLY) { 370 if (early_message_queue_state_ != SEND_DIRECTLY) {
370 // We can't just PostTask here; the messages would arrive out of 371 // 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 372 // order. Instead, we queue them up until we're ready to post
372 // them. 373 // them.
373 early_message_queue_.push_back(serialized_val); 374 early_message_queue_.push_back(serialized_val);
374 } else { 375 } else {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 // invokes: 494 // invokes:
494 // SetPassthroughObject(passthrough_object()); 495 // SetPassthroughObject(passthrough_object());
495 if (passthrough_object_) 496 if (passthrough_object_)
496 WebBindings::releaseObject(passthrough_object_); 497 WebBindings::releaseObject(passthrough_object_);
497 498
498 passthrough_object_ = passthrough; 499 passthrough_object_ = passthrough;
499 } 500 }
500 501
501 } // namespace ppapi 502 } // namespace ppapi
502 } // namespace webkit 503 } // namespace webkit
OLDNEW
« ppapi/tests/test_post_message.cc ('K') | « ppapi/tests/test_post_message.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698