| 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 |