Index: content/renderer/pepper/message_channel.cc |
diff --git a/content/renderer/pepper/message_channel.cc b/content/renderer/pepper/message_channel.cc |
index 1a4e6383b524f9bd4a3b805b14aec4adf8b0d328..959609ff88013435d2574d32c0233afa40ff17a9 100644 |
--- a/content/renderer/pepper/message_channel.cc |
+++ b/content/renderer/pepper/message_channel.cc |
@@ -187,6 +187,7 @@ MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance) |
plugin_message_queue_state_(WAITING_TO_START), |
var_converter_(instance->pp_instance(), |
V8VarConverter::kDisallowObjectVars), |
+ var_conversion_weak_ptr_factory_(this), |
weak_ptr_factory_(this) { |
} |
@@ -313,26 +314,32 @@ void MessageChannel::PostBlockingMessageToNative(gin::Arguments* args) { |
return; |
} |
- // If the queue of messages to the plugin is non-empty, we're still waiting on |
- // pending Var conversions. This means at some point in the past, JavaScript |
- // called postMessage (the async one) and passed us something with a browser- |
- // side host (e.g., FileSystem) and we haven't gotten a response from the |
- // browser yet. We can't currently support sending a sync message if the |
- // plugin does this, because it will break the ordering of the messages |
- // arriving at the plugin. |
- // TODO(dmichael): Fix this. |
- // See https://code.google.com/p/chromium/issues/detail?id=367896#c4 |
- if (!plugin_message_queue_.empty()) { |
- try_catch.ThrowException( |
- "Failed to convert parameter synchronously, because a prior " |
- "call to postMessage contained a type which required asynchronous " |
- "transfer which has not completed. Not all types are supported yet by " |
- "postMessageAndAwaitResponse. See crbug.com/367896."); |
- return; |
- } |
ScopedPPVar param = try_catch.FromV8(message_data); |
if (try_catch.ThrowException()) |
return; |
+ if (!plugin_message_queue_.empty()) { |
+ // If the queue of messages to the plugin is non-empty, we're still waiting |
+ // on pending Var conversions. This means at some point in the past, |
+ // JavaScript called postMessage (the async one) and passed us something |
+ // with a browser-side host (e.g., FileSystem) and we haven't gotten a |
+ // response from the browser yet. We have to force all the conversions to |
+ // happen synchronously so that we can preserve message order. |
+ |
+ // CURRENT STRATEGY: |
+ // 1) Always push async conversions to the browser. They'll be guaranteed |
+ // to arrive in order. |
+ // 2) For blocking messages, after you've queued up the conversion, if |
+ // there's anything waiting in the queue, it's irrelevant whether it |
+ // is from that sync message or an earlier one. We want to block until |
+ // it's complete. |
+ |
+ // TODO/FIXME Force the browser to convert all pending vars here |
+ // Mark all messages in the queue completed. |
+ // Now all our pending vars have completed synchronously, but the browser |
+ // might already have sent us a response for one or more of them, so we |
+ // make sure the conversion callbacks don't get invoked. |
+ var_conversion_weak_ptr_factory_.InvalidateWeakPtrs(); |
+ } |
ScopedPPVar pp_result; |
bool was_handled = instance_->HandleBlockingMessage(param, &pp_result); |
@@ -398,7 +405,7 @@ void MessageChannel::EnqueuePluginMessage(v8::Handle<v8::Value> v8_value) { |
v8_value, |
v8::Isolate::GetCurrent()->GetCurrentContext(), |
base::Bind(&MessageChannel::FromV8ValueComplete, |
- weak_ptr_factory_.GetWeakPtr(), |
+ var_conversion_weak_ptr_factory_.GetWeakPtr(), |
&plugin_message_queue_.back())); |
if (conversion_result.completed_synchronously) { |
plugin_message_queue_.back().ConversionCompleted( |