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

Side by Side Diff: content/renderer/pepper/message_channel.cc

Issue 290553004: PPAPI: Refactor MessageChannel to prep for sync postMessae (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move NaClHelper in to nacl namespace Created 6 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 "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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/renderer/pepper/message_channel.h ('k') | content/renderer/pepper/mock_renderer_ppapi_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698