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 "content/renderer/pepper/message_channel.h" | 5 #include "content/renderer/pepper/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 13 matching lines...) Expand all Loading... |
24 #include "third_party/WebKit/public/web/WebDOMMessageEvent.h" | 24 #include "third_party/WebKit/public/web/WebDOMMessageEvent.h" |
25 #include "third_party/WebKit/public/web/WebElement.h" | 25 #include "third_party/WebKit/public/web/WebElement.h" |
26 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 26 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
27 #include "third_party/WebKit/public/web/WebNode.h" | 27 #include "third_party/WebKit/public/web/WebNode.h" |
28 #include "third_party/WebKit/public/web/WebPluginContainer.h" | 28 #include "third_party/WebKit/public/web/WebPluginContainer.h" |
29 #include "third_party/WebKit/public/web/WebSerializedScriptValue.h" | 29 #include "third_party/WebKit/public/web/WebSerializedScriptValue.h" |
30 #include "v8/include/v8.h" | 30 #include "v8/include/v8.h" |
31 | 31 |
32 using ppapi::ArrayBufferVar; | 32 using ppapi::ArrayBufferVar; |
33 using ppapi::PpapiGlobals; | 33 using ppapi::PpapiGlobals; |
| 34 using ppapi::ScopedPPVar; |
34 using ppapi::StringVar; | 35 using ppapi::StringVar; |
35 using blink::WebBindings; | 36 using blink::WebBindings; |
36 using blink::WebElement; | 37 using blink::WebElement; |
37 using blink::WebDOMEvent; | 38 using blink::WebDOMEvent; |
38 using blink::WebDOMMessageEvent; | 39 using blink::WebDOMMessageEvent; |
39 using blink::WebPluginContainer; | 40 using blink::WebPluginContainer; |
40 using blink::WebSerializedScriptValue; | 41 using blink::WebSerializedScriptValue; |
41 | 42 |
42 namespace content { | 43 namespace content { |
43 | 44 |
(...skipping 14 matching lines...) Expand all Loading... |
58 MessageChannel* ToMessageChannel(NPObject* object) { | 59 MessageChannel* ToMessageChannel(NPObject* object) { |
59 return static_cast<MessageChannel::MessageChannelNPObject*>(object) | 60 return static_cast<MessageChannel::MessageChannelNPObject*>(object) |
60 ->message_channel.get(); | 61 ->message_channel.get(); |
61 } | 62 } |
62 | 63 |
63 NPObject* ToPassThroughObject(NPObject* object) { | 64 NPObject* ToPassThroughObject(NPObject* object) { |
64 MessageChannel* channel = ToMessageChannel(object); | 65 MessageChannel* channel = ToMessageChannel(object); |
65 return channel ? channel->passthrough_object() : NULL; | 66 return channel ? channel->passthrough_object() : NULL; |
66 } | 67 } |
67 | 68 |
68 // Helper function to determine if a given identifier is equal to kPostMessage. | 69 // Return true iff |identifier| is equal to |string|. |
69 bool IdentifierIsPostMessage(NPIdentifier identifier) { | 70 bool IdentifierIs(NPIdentifier identifier, const char string[]) { |
70 return WebBindings::getStringIdentifier(kPostMessage) == identifier; | 71 return WebBindings::getStringIdentifier(string) == identifier; |
71 } | |
72 | |
73 // Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage. | |
74 // This currently just copies the value. For a string Var, the result is a | |
75 // PP_Var with the a copy of |var|'s string contents and a reference count of 1. | |
76 PP_Var CopyPPVar(const PP_Var& var) { | |
77 switch (var.type) { | |
78 case PP_VARTYPE_UNDEFINED: | |
79 case PP_VARTYPE_NULL: | |
80 case PP_VARTYPE_BOOL: | |
81 case PP_VARTYPE_INT32: | |
82 case PP_VARTYPE_DOUBLE: | |
83 return var; | |
84 case PP_VARTYPE_STRING: { | |
85 StringVar* string = StringVar::FromPPVar(var); | |
86 if (!string) | |
87 return PP_MakeUndefined(); | |
88 return StringVar::StringToPPVar(string->value()); | |
89 } | |
90 case PP_VARTYPE_ARRAY_BUFFER: { | |
91 ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); | |
92 if (!buffer) | |
93 return PP_MakeUndefined(); | |
94 PP_Var new_buffer_var = | |
95 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | |
96 buffer->ByteLength()); | |
97 DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER); | |
98 if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER) | |
99 return PP_MakeUndefined(); | |
100 ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var); | |
101 DCHECK(new_buffer); | |
102 if (!new_buffer) | |
103 return PP_MakeUndefined(); | |
104 memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength()); | |
105 return new_buffer_var; | |
106 } | |
107 case PP_VARTYPE_OBJECT: | |
108 case PP_VARTYPE_ARRAY: | |
109 case PP_VARTYPE_DICTIONARY: | |
110 case PP_VARTYPE_RESOURCE: | |
111 // These types are not supported by PostMessage in-process. In some rare | |
112 // cases with the NaCl plugin, they may be sent but they will be dropped | |
113 // anyway (see crbug.com/318837 for details). | |
114 return PP_MakeUndefined(); | |
115 } | |
116 NOTREACHED(); | |
117 return PP_MakeUndefined(); | |
118 } | 72 } |
119 | 73 |
120 //------------------------------------------------------------------------------ | 74 //------------------------------------------------------------------------------ |
121 // Implementations of NPClass functions. These are here to: | 75 // Implementations of NPClass functions. These are here to: |
122 // - Implement postMessage behavior. | 76 // - Implement postMessage behavior. |
123 // - Forward calls to the 'passthrough' object to allow backwards-compatibility | 77 // - Forward calls to the 'passthrough' object to allow backwards-compatibility |
124 // with GetInstanceObject() objects. | 78 // with GetInstanceObject() objects. |
125 //------------------------------------------------------------------------------ | 79 //------------------------------------------------------------------------------ |
126 NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) { | 80 NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) { |
127 return new MessageChannel::MessageChannelNPObject; | 81 return new MessageChannel::MessageChannelNPObject; |
128 } | 82 } |
129 | 83 |
130 void MessageChannelDeallocate(NPObject* object) { | 84 void MessageChannelDeallocate(NPObject* object) { |
131 MessageChannel::MessageChannelNPObject* instance = | 85 MessageChannel::MessageChannelNPObject* instance = |
132 static_cast<MessageChannel::MessageChannelNPObject*>(object); | 86 static_cast<MessageChannel::MessageChannelNPObject*>(object); |
133 delete instance; | 87 delete instance; |
134 } | 88 } |
135 | 89 |
136 bool MessageChannelHasMethod(NPObject* np_obj, NPIdentifier name) { | 90 bool MessageChannelHasMethod(NPObject* np_obj, NPIdentifier name) { |
137 if (!np_obj) | 91 if (!np_obj) |
138 return false; | 92 return false; |
139 | 93 |
140 // We only handle a function called postMessage. | 94 if (IdentifierIs(name, kPostMessage)) |
141 if (IdentifierIsPostMessage(name)) | |
142 return true; | 95 return true; |
143 | 96 |
144 // Other method names we will pass to the passthrough object, if we have one. | 97 // Other method names we will pass to the passthrough object, if we have one. |
145 NPObject* passthrough = ToPassThroughObject(np_obj); | 98 NPObject* passthrough = ToPassThroughObject(np_obj); |
146 if (passthrough) | 99 if (passthrough) |
147 return WebBindings::hasMethod(NULL, passthrough, name); | 100 return WebBindings::hasMethod(NULL, passthrough, name); |
148 return false; | 101 return false; |
149 } | 102 } |
150 | 103 |
151 bool MessageChannelInvoke(NPObject* np_obj, | 104 bool MessageChannelInvoke(NPObject* np_obj, |
152 NPIdentifier name, | 105 NPIdentifier name, |
153 const NPVariant* args, | 106 const NPVariant* args, |
154 uint32 arg_count, | 107 uint32 arg_count, |
155 NPVariant* result) { | 108 NPVariant* result) { |
156 if (!np_obj) | 109 if (!np_obj) |
157 return false; | 110 return false; |
158 | 111 |
159 // We only handle a function called postMessage. | 112 MessageChannel* message_channel = ToMessageChannel(np_obj); |
160 if (IdentifierIsPostMessage(name) && (arg_count == 1)) { | 113 if (!message_channel) |
161 MessageChannel* message_channel = ToMessageChannel(np_obj); | 114 return false; |
162 if (message_channel) { | 115 |
163 message_channel->NPVariantToPPVar(&args[0]); | 116 // Check to see if we should handle this function ourselves. We only handle |
164 return true; | 117 // kPostMessage. |
165 } else { | 118 if (IdentifierIs(name, kPostMessage) && (arg_count == 1)) { |
166 return false; | 119 message_channel->PostMessageToNative(&args[0]); |
167 } | 120 return true; |
168 } | 121 } |
169 // Other method calls we will pass to the passthrough object, if we have one. | 122 // Other method calls we will pass to the passthrough object, if we have one. |
170 NPObject* passthrough = ToPassThroughObject(np_obj); | 123 NPObject* passthrough = ToPassThroughObject(np_obj); |
171 if (passthrough) { | 124 if (passthrough) { |
172 return WebBindings::invoke( | 125 return WebBindings::invoke( |
173 NULL, passthrough, name, args, arg_count, result); | 126 NULL, passthrough, name, args, arg_count, result); |
174 } | 127 } |
175 return false; | 128 return false; |
176 } | 129 } |
177 | 130 |
(...skipping 30 matching lines...) Expand all Loading... |
208 return false; | 161 return false; |
209 } | 162 } |
210 | 163 |
211 bool MessageChannelGetProperty(NPObject* np_obj, | 164 bool MessageChannelGetProperty(NPObject* np_obj, |
212 NPIdentifier name, | 165 NPIdentifier name, |
213 NPVariant* result) { | 166 NPVariant* result) { |
214 if (!np_obj) | 167 if (!np_obj) |
215 return false; | 168 return false; |
216 | 169 |
217 // Don't allow getting the postMessage function. | 170 // Don't allow getting the postMessage function. |
218 if (IdentifierIsPostMessage(name)) | 171 if (IdentifierIs(name, kPostMessage)) |
219 return false; | 172 return false; |
220 | 173 |
221 MessageChannel* message_channel = ToMessageChannel(np_obj); | 174 MessageChannel* message_channel = ToMessageChannel(np_obj); |
222 if (message_channel) { | 175 if (message_channel) { |
223 if (message_channel->GetReadOnlyProperty(name, result)) | 176 if (message_channel->GetReadOnlyProperty(name, result)) |
224 return true; | 177 return true; |
225 } | 178 } |
226 | 179 |
227 // Invoke on the passthrough object, if we have one. | 180 // Invoke on the passthrough object, if we have one. |
228 NPObject* passthrough = ToPassThroughObject(np_obj); | 181 NPObject* passthrough = ToPassThroughObject(np_obj); |
229 if (passthrough) | 182 if (passthrough) |
230 return WebBindings::getProperty(NULL, passthrough, name, result); | 183 return WebBindings::getProperty(NULL, passthrough, name, result); |
231 return false; | 184 return false; |
232 } | 185 } |
233 | 186 |
234 bool MessageChannelSetProperty(NPObject* np_obj, | 187 bool MessageChannelSetProperty(NPObject* np_obj, |
235 NPIdentifier name, | 188 NPIdentifier name, |
236 const NPVariant* variant) { | 189 const NPVariant* variant) { |
237 if (!np_obj) | 190 if (!np_obj) |
238 return false; | 191 return false; |
239 | 192 |
240 // Don't allow setting the postMessage function. | 193 // Don't allow setting the postMessage function. |
241 if (IdentifierIsPostMessage(name)) | 194 if (IdentifierIs(name, kPostMessage)) |
242 return false; | 195 return false; |
243 | 196 |
244 // Invoke on the passthrough object, if we have one. | 197 // Invoke on the passthrough object, if we have one. |
245 NPObject* passthrough = ToPassThroughObject(np_obj); | 198 NPObject* passthrough = ToPassThroughObject(np_obj); |
246 if (passthrough) | 199 if (passthrough) |
247 return WebBindings::setProperty(NULL, passthrough, name, variant); | 200 return WebBindings::setProperty(NULL, passthrough, name, variant); |
248 return false; | 201 return false; |
249 } | 202 } |
250 | 203 |
251 bool MessageChannelEnumerate(NPObject* np_obj, | 204 bool MessageChannelEnumerate(NPObject* np_obj, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 &MessageChannelDeallocate, NULL, | 240 &MessageChannelDeallocate, NULL, |
288 &MessageChannelHasMethod, &MessageChannelInvoke, | 241 &MessageChannelHasMethod, &MessageChannelInvoke, |
289 &MessageChannelInvokeDefault, &MessageChannelHasProperty, | 242 &MessageChannelInvokeDefault, &MessageChannelHasProperty, |
290 &MessageChannelGetProperty, &MessageChannelSetProperty, | 243 &MessageChannelGetProperty, &MessageChannelSetProperty, |
291 NULL, &MessageChannelEnumerate, }; | 244 NULL, &MessageChannelEnumerate, }; |
292 | 245 |
293 } // namespace | 246 } // namespace |
294 | 247 |
295 // MessageChannel -------------------------------------------------------------- | 248 // MessageChannel -------------------------------------------------------------- |
296 struct MessageChannel::VarConversionResult { | 249 struct MessageChannel::VarConversionResult { |
297 VarConversionResult(const ppapi::ScopedPPVar& r, bool s) | 250 VarConversionResult() : success_(false), conversion_completed_(false) {} |
298 : result(r), success(s), conversion_completed(true) {} | 251 void ConversionCompleted(const ScopedPPVar& var, |
299 VarConversionResult() : success(false), conversion_completed(false) {} | 252 bool success) { |
300 ppapi::ScopedPPVar result; | 253 conversion_completed_ = true; |
301 bool success; | 254 var_ = var; |
302 bool conversion_completed; | 255 success_ = success; |
| 256 } |
| 257 const ScopedPPVar& var() const { return var_; } |
| 258 bool success() const { return success_; } |
| 259 bool conversion_completed() const { return conversion_completed_; } |
| 260 |
| 261 private: |
| 262 ScopedPPVar var_; |
| 263 bool success_; |
| 264 bool conversion_completed_; |
303 }; | 265 }; |
304 | 266 |
305 MessageChannel::MessageChannelNPObject::MessageChannelNPObject() {} | 267 MessageChannel::MessageChannelNPObject::MessageChannelNPObject() {} |
306 | 268 |
307 MessageChannel::MessageChannelNPObject::~MessageChannelNPObject() {} | 269 MessageChannel::MessageChannelNPObject::~MessageChannelNPObject() {} |
308 | 270 |
309 MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance) | 271 MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance) |
310 : instance_(instance), | 272 : instance_(instance), |
311 passthrough_object_(NULL), | 273 passthrough_object_(NULL), |
312 np_object_(NULL), | 274 np_object_(NULL), |
313 early_message_queue_state_(QUEUE_MESSAGES), | 275 early_message_queue_state_(QUEUE_MESSAGES), |
314 weak_ptr_factory_(this) { | 276 weak_ptr_factory_(this) { |
315 // Now create an NPObject for receiving calls to postMessage. This sets the | 277 // Now create an NPObject for receiving calls to postMessage. This sets the |
316 // reference count to 1. We release it in the destructor. | 278 // reference count to 1. We release it in the destructor. |
317 NPObject* obj = WebBindings::createObject(instance_->instanceNPP(), | 279 NPObject* obj = WebBindings::createObject(instance_->instanceNPP(), |
318 &message_channel_class); | 280 &message_channel_class); |
319 DCHECK(obj); | 281 DCHECK(obj); |
320 np_object_ = static_cast<MessageChannel::MessageChannelNPObject*>(obj); | 282 np_object_ = static_cast<MessageChannel::MessageChannelNPObject*>(obj); |
321 np_object_->message_channel = weak_ptr_factory_.GetWeakPtr(); | 283 np_object_->message_channel = weak_ptr_factory_.GetWeakPtr(); |
322 } | 284 } |
323 | 285 |
324 void MessageChannel::NPVariantToPPVar(const NPVariant* variant) { | 286 void MessageChannel::EnqueuePluginMessage(const NPVariant* variant) { |
325 converted_var_queue_.push_back(VarConversionResult()); | 287 plugin_message_queue_.push_back(VarConversionResult()); |
326 std::list<VarConversionResult>::iterator result_iterator = | 288 if (variant->type == NPVariantType_Object) { |
327 --converted_var_queue_.end(); | 289 // Convert NPVariantType_Object in to an appropriate PP_Var like Dictionary, |
328 switch (variant->type) { | 290 // Array, etc. Note NPVariantToVar would convert to an "Object" PP_Var, |
329 case NPVariantType_Void: | 291 // which we don't support for Messaging. |
330 NPVariantToPPVarComplete( | 292 |
331 result_iterator, ppapi::ScopedPPVar(PP_MakeUndefined()), true); | 293 // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it |
332 return; | 294 // won't result in a deep copy. |
333 case NPVariantType_Null: | 295 v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant); |
334 NPVariantToPPVarComplete( | 296 V8VarConverter v8_var_converter(instance_->pp_instance()); |
335 result_iterator, ppapi::ScopedPPVar(PP_MakeNull()), true); | 297 v8_var_converter.FromV8Value( |
336 return; | 298 v8_value, |
337 case NPVariantType_Bool: | 299 v8::Isolate::GetCurrent()->GetCurrentContext(), |
338 NPVariantToPPVarComplete(result_iterator, | 300 base::Bind(&MessageChannel::FromV8ValueComplete, |
339 ppapi::ScopedPPVar(PP_MakeBool(PP_FromBool( | 301 weak_ptr_factory_.GetWeakPtr(), |
340 NPVARIANT_TO_BOOLEAN(*variant)))), | 302 &plugin_message_queue_.back())); |
341 true); | 303 } else { |
342 return; | 304 plugin_message_queue_.back().ConversionCompleted( |
343 case NPVariantType_Int32: | 305 ScopedPPVar(ScopedPPVar::PassRef(), |
344 NPVariantToPPVarComplete( | 306 NPVariantToPPVar(instance(), variant)), |
345 result_iterator, | 307 true); |
346 ppapi::ScopedPPVar(PP_MakeInt32(NPVARIANT_TO_INT32(*variant))), | 308 DCHECK(plugin_message_queue_.back().var().get().type != PP_VARTYPE_OBJECT); |
347 true); | |
348 return; | |
349 case NPVariantType_Double: | |
350 NPVariantToPPVarComplete( | |
351 result_iterator, | |
352 ppapi::ScopedPPVar(PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant))), | |
353 true); | |
354 return; | |
355 case NPVariantType_String: | |
356 NPVariantToPPVarComplete( | |
357 result_iterator, | |
358 ppapi::ScopedPPVar(ppapi::ScopedPPVar::PassRef(), | |
359 StringVar::StringToPPVar( | |
360 NPVARIANT_TO_STRING(*variant).UTF8Characters, | |
361 NPVARIANT_TO_STRING(*variant).UTF8Length)), | |
362 true); | |
363 return; | |
364 case NPVariantType_Object: { | |
365 // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it | |
366 // shouldn't result in a deep copy. | |
367 v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant); | |
368 V8VarConverter(instance_->pp_instance()) | |
369 .FromV8Value(v8_value, | |
370 v8::Isolate::GetCurrent()->GetCurrentContext(), | |
371 base::Bind(&MessageChannel::NPVariantToPPVarComplete, | |
372 weak_ptr_factory_.GetWeakPtr(), | |
373 result_iterator)); | |
374 return; | |
375 } | |
376 } | 309 } |
377 NPVariantToPPVarComplete( | |
378 result_iterator, ppapi::ScopedPPVar(PP_MakeUndefined()), false); | |
379 } | 310 } |
380 | 311 |
381 void MessageChannel::PostMessageToJavaScript(PP_Var message_data) { | 312 void MessageChannel::PostMessageToJavaScript(PP_Var message_data) { |
382 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 313 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
383 | 314 |
384 // Because V8 is probably not on the stack for Native->JS calls, we need to | 315 // Because V8 is probably not on the stack for Native->JS calls, we need to |
385 // enter the appropriate context for the plugin. | 316 // enter the appropriate context for the plugin. |
386 WebPluginContainer* container = instance_->container(); | 317 WebPluginContainer* container = instance_->container(); |
387 // It's possible that container() is NULL if the plugin has been removed from | 318 // It's possible that container() is NULL if the plugin has been removed from |
388 // the DOM (but the PluginInstance is not destroyed yet). | 319 // the DOM (but the PluginInstance is not destroyed yet). |
(...skipping 13 matching lines...) Expand all Loading... |
402 PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(), | 333 PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(), |
403 PP_LOGLEVEL_ERROR, | 334 PP_LOGLEVEL_ERROR, |
404 std::string(), | 335 std::string(), |
405 kVarToV8ConversionError); | 336 kVarToV8ConversionError); |
406 return; | 337 return; |
407 } | 338 } |
408 | 339 |
409 WebSerializedScriptValue serialized_val = | 340 WebSerializedScriptValue serialized_val = |
410 WebSerializedScriptValue::serialize(v8_val); | 341 WebSerializedScriptValue::serialize(v8_val); |
411 | 342 |
412 if (instance_->module()->IsProxied()) { | 343 if (early_message_queue_state_ != SEND_DIRECTLY) { |
413 if (early_message_queue_state_ != SEND_DIRECTLY) { | 344 // We can't just PostTask here; the messages would arrive out of |
414 // We can't just PostTask here; the messages would arrive out of | 345 // order. Instead, we queue them up until we're ready to post |
415 // order. Instead, we queue them up until we're ready to post | 346 // them. |
416 // them. | 347 early_message_queue_.push_back(serialized_val); |
417 early_message_queue_.push_back(serialized_val); | |
418 } else { | |
419 // The proxy sent an asynchronous message, so the plugin is already | |
420 // unblocked. Therefore, there's no need to PostTask. | |
421 DCHECK(early_message_queue_.size() == 0); | |
422 PostMessageToJavaScriptImpl(serialized_val); | |
423 } | |
424 } else { | 348 } else { |
425 base::MessageLoop::current()->PostTask( | 349 // The proxy sent an asynchronous message, so the plugin is already |
426 FROM_HERE, | 350 // unblocked. Therefore, there's no need to PostTask. |
427 base::Bind(&MessageChannel::PostMessageToJavaScriptImpl, | 351 DCHECK(early_message_queue_.empty()); |
428 weak_ptr_factory_.GetWeakPtr(), | 352 PostMessageToJavaScriptImpl(serialized_val); |
429 serialized_val)); | |
430 } | 353 } |
431 } | 354 } |
432 | 355 |
433 void MessageChannel::StopQueueingJavaScriptMessages() { | 356 void MessageChannel::Start() { |
434 // We PostTask here instead of draining the message queue directly | 357 // We PostTask here instead of draining the message queue directly |
435 // since we haven't finished initializing the PepperWebPluginImpl yet, so | 358 // since we haven't finished initializing the PepperWebPluginImpl yet, so |
436 // the plugin isn't available in the DOM. | 359 // the plugin isn't available in the DOM. |
437 early_message_queue_state_ = DRAIN_PENDING; | |
438 base::MessageLoop::current()->PostTask( | 360 base::MessageLoop::current()->PostTask( |
439 FROM_HERE, | 361 FROM_HERE, |
440 base::Bind(&MessageChannel::DrainEarlyMessageQueue, | 362 base::Bind(&MessageChannel::DrainEarlyMessageQueue, |
441 weak_ptr_factory_.GetWeakPtr())); | 363 weak_ptr_factory_.GetWeakPtr())); |
442 } | 364 } |
443 | 365 |
444 void MessageChannel::QueueJavaScriptMessages() { | 366 void MessageChannel::FromV8ValueComplete(VarConversionResult* result_holder, |
445 if (early_message_queue_state_ == DRAIN_PENDING) | 367 const ScopedPPVar& result, |
446 early_message_queue_state_ = DRAIN_CANCELLED; | 368 bool success) { |
447 else | 369 result_holder->ConversionCompleted(result, success); |
448 early_message_queue_state_ = QUEUE_MESSAGES; | 370 DrainCompletedPluginMessages(); |
449 } | 371 } |
450 | 372 |
451 void MessageChannel::NPVariantToPPVarComplete( | 373 void MessageChannel::DrainCompletedPluginMessages() { |
452 const std::list<VarConversionResult>::iterator& result_iterator, | 374 if (early_message_queue_state_ == QUEUE_MESSAGES) |
453 const ppapi::ScopedPPVar& result, | 375 return; |
454 bool success) { | 376 |
455 *result_iterator = VarConversionResult(result, success); | 377 while (!plugin_message_queue_.empty() && |
456 std::list<VarConversionResult>::iterator it = converted_var_queue_.begin(); | 378 plugin_message_queue_.front().conversion_completed()) { |
457 while (it != converted_var_queue_.end() && it->conversion_completed) { | 379 const VarConversionResult& front = plugin_message_queue_.front(); |
458 if (it->success) { | 380 if (front.success()) { |
459 PostMessageToNative(it->result.get()); | 381 instance_->HandleMessage(front.var()); |
460 } else { | 382 } else { |
461 PpapiGlobals::Get()->LogWithSource(instance()->pp_instance(), | 383 PpapiGlobals::Get()->LogWithSource(instance()->pp_instance(), |
462 PP_LOGLEVEL_ERROR, | 384 PP_LOGLEVEL_ERROR, |
463 std::string(), | 385 std::string(), |
464 kV8ToVarConversionError); | 386 kV8ToVarConversionError); |
465 } | 387 } |
466 | 388 plugin_message_queue_.pop_front(); |
467 converted_var_queue_.erase(it++); | |
468 } | 389 } |
469 } | 390 } |
470 | 391 |
471 void MessageChannel::DrainEarlyMessageQueue() { | 392 void MessageChannel::DrainEarlyMessageQueue() { |
| 393 DCHECK(early_message_queue_state_ == QUEUE_MESSAGES); |
| 394 |
472 // Take a reference on the PluginInstance. This is because JavaScript code | 395 // Take a reference on the PluginInstance. This is because JavaScript code |
473 // may delete the plugin, which would destroy the PluginInstance and its | 396 // may delete the plugin, which would destroy the PluginInstance and its |
474 // corresponding MessageChannel. | 397 // corresponding MessageChannel. |
475 scoped_refptr<PepperPluginInstanceImpl> instance_ref(instance_); | 398 scoped_refptr<PepperPluginInstanceImpl> instance_ref(instance_); |
476 | |
477 if (early_message_queue_state_ == DRAIN_CANCELLED) { | |
478 early_message_queue_state_ = QUEUE_MESSAGES; | |
479 return; | |
480 } | |
481 DCHECK(early_message_queue_state_ == DRAIN_PENDING); | |
482 | |
483 while (!early_message_queue_.empty()) { | 399 while (!early_message_queue_.empty()) { |
484 PostMessageToJavaScriptImpl(early_message_queue_.front()); | 400 PostMessageToJavaScriptImpl(early_message_queue_.front()); |
485 early_message_queue_.pop_front(); | 401 early_message_queue_.pop_front(); |
486 } | 402 } |
487 early_message_queue_state_ = SEND_DIRECTLY; | 403 early_message_queue_state_ = SEND_DIRECTLY; |
| 404 |
| 405 DrainCompletedPluginMessages(); |
488 } | 406 } |
489 | 407 |
490 void MessageChannel::PostMessageToJavaScriptImpl( | 408 void MessageChannel::PostMessageToJavaScriptImpl( |
491 const WebSerializedScriptValue& message_data) { | 409 const WebSerializedScriptValue& message_data) { |
492 DCHECK(instance_); | 410 DCHECK(instance_); |
493 | 411 |
494 WebPluginContainer* container = instance_->container(); | 412 WebPluginContainer* container = instance_->container(); |
495 // It's possible that container() is NULL if the plugin has been removed from | 413 // It's possible that container() is NULL if the plugin has been removed from |
496 // the DOM (but the PluginInstance is not destroyed yet). | 414 // the DOM (but the PluginInstance is not destroyed yet). |
497 if (!container) | 415 if (!container) |
(...skipping 10 matching lines...) Expand all Loading... |
508 NULL, // source [*] | 426 NULL, // source [*] |
509 ""); // lastEventId | 427 ""); // lastEventId |
510 // [*] Note that the |origin| is only specified for cross-document and server- | 428 // [*] Note that the |origin| is only specified for cross-document and server- |
511 // sent messages, while |source| is only specified for cross-document | 429 // sent messages, while |source| is only specified for cross-document |
512 // messages: | 430 // messages: |
513 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html | 431 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html |
514 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari | 432 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari |
515 // at least, postMessage on Workers does not provide the origin or source. | 433 // at least, postMessage on Workers does not provide the origin or source. |
516 // TODO(dmichael): Add origin if we change to a more iframe-like origin | 434 // TODO(dmichael): Add origin if we change to a more iframe-like origin |
517 // policy (see crbug.com/81537) | 435 // policy (see crbug.com/81537) |
518 | |
519 container->element().dispatchEvent(msg_event); | 436 container->element().dispatchEvent(msg_event); |
520 } | 437 } |
521 | 438 |
522 void MessageChannel::PostMessageToNative(PP_Var message_data) { | 439 void MessageChannel::PostMessageToNative(const NPVariant* message_data) { |
523 if (instance_->module()->IsProxied()) { | 440 EnqueuePluginMessage(message_data); |
524 // In the proxied case, the copy will happen via serializiation, and the | 441 DrainCompletedPluginMessages(); |
525 // message is asynchronous. Therefore there's no need to copy the Var, nor | |
526 // to PostTask. | |
527 PostMessageToNativeImpl(message_data); | |
528 } else { | |
529 // Make a copy of the message data for the Task we will run. | |
530 PP_Var var_copy(CopyPPVar(message_data)); | |
531 | |
532 base::MessageLoop::current()->PostTask( | |
533 FROM_HERE, | |
534 base::Bind(&MessageChannel::PostMessageToNativeImpl, | |
535 weak_ptr_factory_.GetWeakPtr(), | |
536 var_copy)); | |
537 } | |
538 } | |
539 | |
540 void MessageChannel::PostMessageToNativeImpl(PP_Var message_data) { | |
541 instance_->HandleMessage(message_data); | |
542 } | 442 } |
543 | 443 |
544 MessageChannel::~MessageChannel() { | 444 MessageChannel::~MessageChannel() { |
545 WebBindings::releaseObject(np_object_); | 445 WebBindings::releaseObject(np_object_); |
546 if (passthrough_object_) | 446 if (passthrough_object_) |
547 WebBindings::releaseObject(passthrough_object_); | 447 WebBindings::releaseObject(passthrough_object_); |
548 } | 448 } |
549 | 449 |
550 void MessageChannel::SetPassthroughObject(NPObject* passthrough) { | 450 void MessageChannel::SetPassthroughObject(NPObject* passthrough) { |
551 // Retain the passthrough object; We need to ensure it lives as long as this | 451 // Retain the passthrough object; We need to ensure it lives as long as this |
552 // MessageChannel. | 452 // MessageChannel. |
553 if (passthrough) | 453 if (passthrough) |
554 WebBindings::retainObject(passthrough); | 454 WebBindings::retainObject(passthrough); |
555 | 455 |
556 // If we had a passthrough set already, release it. Note that we retain the | 456 // If we had a passthrough set already, release it. Note that we retain the |
557 // incoming passthrough object first, so that we behave correctly if anyone | 457 // incoming passthrough object first, so that we behave correctly if anyone |
558 // invokes: | 458 // invokes: |
559 // SetPassthroughObject(passthrough_object()); | 459 // SetPassthroughObject(passthrough_object()); |
560 if (passthrough_object_) | 460 if (passthrough_object_) |
561 WebBindings::releaseObject(passthrough_object_); | 461 WebBindings::releaseObject(passthrough_object_); |
562 | 462 |
563 passthrough_object_ = passthrough; | 463 passthrough_object_ = passthrough; |
564 } | 464 } |
565 | 465 |
566 bool MessageChannel::GetReadOnlyProperty(NPIdentifier key, | 466 bool MessageChannel::GetReadOnlyProperty(NPIdentifier key, |
567 NPVariant* value) const { | 467 NPVariant* value) const { |
568 std::map<NPIdentifier, ppapi::ScopedPPVar>::const_iterator it = | 468 std::map<NPIdentifier, ScopedPPVar>::const_iterator it = |
569 internal_properties_.find(key); | 469 internal_properties_.find(key); |
570 if (it != internal_properties_.end()) { | 470 if (it != internal_properties_.end()) { |
571 if (value) | 471 if (value) |
572 return PPVarToNPVariant(it->second.get(), value); | 472 return PPVarToNPVariant(it->second.get(), value); |
573 return true; | 473 return true; |
574 } | 474 } |
575 return false; | 475 return false; |
576 } | 476 } |
577 | 477 |
578 void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) { | 478 void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) { |
579 internal_properties_[PPVarToNPIdentifier(key)] = ppapi::ScopedPPVar(value); | 479 internal_properties_[PPVarToNPIdentifier(key)] = ScopedPPVar(value); |
580 } | 480 } |
581 | 481 |
582 } // namespace content | 482 } // namespace content |
OLD | NEW |