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 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } | 180 } |
181 | 181 |
182 MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance) | 182 MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance) |
183 : gin::NamedPropertyInterceptor(instance->GetIsolate(), this), | 183 : gin::NamedPropertyInterceptor(instance->GetIsolate(), this), |
184 instance_(instance), | 184 instance_(instance), |
185 js_message_queue_state_(WAITING_TO_START), | 185 js_message_queue_state_(WAITING_TO_START), |
186 blocking_message_depth_(0), | 186 blocking_message_depth_(0), |
187 plugin_message_queue_state_(WAITING_TO_START), | 187 plugin_message_queue_state_(WAITING_TO_START), |
188 var_converter_(instance->pp_instance(), | 188 var_converter_(instance->pp_instance(), |
189 V8VarConverter::kDisallowObjectVars), | 189 V8VarConverter::kDisallowObjectVars), |
| 190 var_conversion_weak_ptr_factory_(this), |
190 weak_ptr_factory_(this) { | 191 weak_ptr_factory_(this) { |
191 } | 192 } |
192 | 193 |
193 gin::ObjectTemplateBuilder MessageChannel::GetObjectTemplateBuilder( | 194 gin::ObjectTemplateBuilder MessageChannel::GetObjectTemplateBuilder( |
194 v8::Isolate* isolate) { | 195 v8::Isolate* isolate) { |
195 return Wrappable<MessageChannel>::GetObjectTemplateBuilder(isolate) | 196 return Wrappable<MessageChannel>::GetObjectTemplateBuilder(isolate) |
196 .AddNamedPropertyInterceptor(); | 197 .AddNamedPropertyInterceptor(); |
197 } | 198 } |
198 | 199 |
199 void MessageChannel::BeginBlockOnSyncMessage() { | 200 void MessageChannel::BeginBlockOnSyncMessage() { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 NOTREACHED(); | 307 NOTREACHED(); |
307 } | 308 } |
308 | 309 |
309 if (plugin_message_queue_state_ == WAITING_TO_START) { | 310 if (plugin_message_queue_state_ == WAITING_TO_START) { |
310 try_catch.ThrowException( | 311 try_catch.ThrowException( |
311 "Attempted to call a synchronous method on a plugin that was not " | 312 "Attempted to call a synchronous method on a plugin that was not " |
312 "yet loaded."); | 313 "yet loaded."); |
313 return; | 314 return; |
314 } | 315 } |
315 | 316 |
316 // If the queue of messages to the plugin is non-empty, we're still waiting on | |
317 // pending Var conversions. This means at some point in the past, JavaScript | |
318 // called postMessage (the async one) and passed us something with a browser- | |
319 // side host (e.g., FileSystem) and we haven't gotten a response from the | |
320 // browser yet. We can't currently support sending a sync message if the | |
321 // plugin does this, because it will break the ordering of the messages | |
322 // arriving at the plugin. | |
323 // TODO(dmichael): Fix this. | |
324 // See https://code.google.com/p/chromium/issues/detail?id=367896#c4 | |
325 if (!plugin_message_queue_.empty()) { | |
326 try_catch.ThrowException( | |
327 "Failed to convert parameter synchronously, because a prior " | |
328 "call to postMessage contained a type which required asynchronous " | |
329 "transfer which has not completed. Not all types are supported yet by " | |
330 "postMessageAndAwaitResponse. See crbug.com/367896."); | |
331 return; | |
332 } | |
333 ScopedPPVar param = try_catch.FromV8(message_data); | 317 ScopedPPVar param = try_catch.FromV8(message_data); |
334 if (try_catch.ThrowException()) | 318 if (try_catch.ThrowException()) |
335 return; | 319 return; |
| 320 if (!plugin_message_queue_.empty()) { |
| 321 // If the queue of messages to the plugin is non-empty, we're still waiting |
| 322 // on pending Var conversions. This means at some point in the past, |
| 323 // JavaScript called postMessage (the async one) and passed us something |
| 324 // with a browser-side host (e.g., FileSystem) and we haven't gotten a |
| 325 // response from the browser yet. We have to force all the conversions to |
| 326 // happen synchronously so that we can preserve message order. |
| 327 |
| 328 // CURRENT STRATEGY: |
| 329 // 1) Always push async conversions to the browser. They'll be guaranteed |
| 330 // to arrive in order. |
| 331 // 2) For blocking messages, after you've queued up the conversion, if |
| 332 // there's anything waiting in the queue, it's irrelevant whether it |
| 333 // is from that sync message or an earlier one. We want to block until |
| 334 // it's complete. |
| 335 |
| 336 // TODO/FIXME Force the browser to convert all pending vars here |
| 337 // Mark all messages in the queue completed. |
| 338 // Now all our pending vars have completed synchronously, but the browser |
| 339 // might already have sent us a response for one or more of them, so we |
| 340 // make sure the conversion callbacks don't get invoked. |
| 341 var_conversion_weak_ptr_factory_.InvalidateWeakPtrs(); |
| 342 } |
336 | 343 |
337 ScopedPPVar pp_result; | 344 ScopedPPVar pp_result; |
338 bool was_handled = instance_->HandleBlockingMessage(param, &pp_result); | 345 bool was_handled = instance_->HandleBlockingMessage(param, &pp_result); |
339 if (!was_handled) { | 346 if (!was_handled) { |
340 try_catch.ThrowException( | 347 try_catch.ThrowException( |
341 "The plugin has not registered a handler for synchronous messages. " | 348 "The plugin has not registered a handler for synchronous messages. " |
342 "See the documentation for PPB_Messaging::RegisterMessageHandler " | 349 "See the documentation for PPB_Messaging::RegisterMessageHandler " |
343 "and PPP_MessageHandler."); | 350 "and PPP_MessageHandler."); |
344 return; | 351 return; |
345 } | 352 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 // Convert the v8 value in to an appropriate PP_Var like Dictionary, | 398 // Convert the v8 value in to an appropriate PP_Var like Dictionary, |
392 // Array, etc. (We explicitly don't want an "Object" PP_Var, which we don't | 399 // Array, etc. (We explicitly don't want an "Object" PP_Var, which we don't |
393 // support for Messaging.) | 400 // support for Messaging.) |
394 // TODO(raymes): Possibly change this to use TryCatch to do the conversion and | 401 // TODO(raymes): Possibly change this to use TryCatch to do the conversion and |
395 // throw an exception if necessary. | 402 // throw an exception if necessary. |
396 V8VarConverter::VarResult conversion_result = | 403 V8VarConverter::VarResult conversion_result = |
397 var_converter_.FromV8Value( | 404 var_converter_.FromV8Value( |
398 v8_value, | 405 v8_value, |
399 v8::Isolate::GetCurrent()->GetCurrentContext(), | 406 v8::Isolate::GetCurrent()->GetCurrentContext(), |
400 base::Bind(&MessageChannel::FromV8ValueComplete, | 407 base::Bind(&MessageChannel::FromV8ValueComplete, |
401 weak_ptr_factory_.GetWeakPtr(), | 408 var_conversion_weak_ptr_factory_.GetWeakPtr(), |
402 &plugin_message_queue_.back())); | 409 &plugin_message_queue_.back())); |
403 if (conversion_result.completed_synchronously) { | 410 if (conversion_result.completed_synchronously) { |
404 plugin_message_queue_.back().ConversionCompleted( | 411 plugin_message_queue_.back().ConversionCompleted( |
405 conversion_result.var, | 412 conversion_result.var, |
406 conversion_result.success); | 413 conversion_result.success); |
407 } | 414 } |
408 } | 415 } |
409 | 416 |
410 void MessageChannel::FromV8ValueComplete(VarConversionResult* result_holder, | 417 void MessageChannel::FromV8ValueComplete(VarConversionResult* result_holder, |
411 const ScopedPPVar& result, | 418 const ScopedPPVar& result, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 } | 468 } |
462 | 469 |
463 void MessageChannel::UnregisterSyncMessageStatusObserver() { | 470 void MessageChannel::UnregisterSyncMessageStatusObserver() { |
464 if (!unregister_observer_callback_.is_null()) { | 471 if (!unregister_observer_callback_.is_null()) { |
465 unregister_observer_callback_.Run(); | 472 unregister_observer_callback_.Run(); |
466 unregister_observer_callback_.Reset(); | 473 unregister_observer_callback_.Reset(); |
467 } | 474 } |
468 } | 475 } |
469 | 476 |
470 } // namespace content | 477 } // namespace content |
OLD | NEW |