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

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

Issue 601923003: Revert of PPAPI: Never re-enter JavaScript for PostMessage. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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
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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 return message_channel; 103 return message_channel;
104 } 104 }
105 105
106 MessageChannel::~MessageChannel() { 106 MessageChannel::~MessageChannel() {
107 passthrough_object_.Reset(); 107 passthrough_object_.Reset();
108 if (instance_) 108 if (instance_)
109 instance_->MessageChannelDestroyed(); 109 instance_->MessageChannelDestroyed();
110 } 110 }
111 111
112 void MessageChannel::InstanceDeleted() { 112 void MessageChannel::InstanceDeleted() {
113 ppapi::proxy::HostDispatcher* dispatcher =
114 ppapi::proxy::HostDispatcher::GetForInstance(instance_->pp_instance());
115 // The dispatcher is NULL for in-process.
116 if (dispatcher)
117 dispatcher->RemoveSyncMessageStatusObserver(this);
118
119 instance_ = NULL; 113 instance_ = NULL;
120 } 114 }
121 115
122 void MessageChannel::PostMessageToJavaScript(PP_Var message_data) { 116 void MessageChannel::PostMessageToJavaScript(PP_Var message_data) {
123 v8::HandleScope scope(v8::Isolate::GetCurrent()); 117 v8::HandleScope scope(v8::Isolate::GetCurrent());
124 118
125 // Because V8 is probably not on the stack for Native->JS calls, we need to 119 // Because V8 is probably not on the stack for Native->JS calls, we need to
126 // enter the appropriate context for the plugin. 120 // enter the appropriate context for the plugin.
127 v8::Local<v8::Context> context = instance_->GetContext(); 121 v8::Local<v8::Context> context = instance_->GetContext();
128 if (context.IsEmpty()) 122 if (context.IsEmpty())
129 return; 123 return;
130 124
131 v8::Context::Scope context_scope(context); 125 v8::Context::Scope context_scope(context);
132 126
133 v8::Handle<v8::Value> v8_val; 127 v8::Handle<v8::Value> v8_val;
134 if (!V8VarConverter(instance_->pp_instance()) 128 if (!V8VarConverter(instance_->pp_instance())
135 .ToV8Value(message_data, context, &v8_val)) { 129 .ToV8Value(message_data, context, &v8_val)) {
136 PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(), 130 PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(),
137 PP_LOGLEVEL_ERROR, 131 PP_LOGLEVEL_ERROR,
138 std::string(), 132 std::string(),
139 kVarToV8ConversionError); 133 kVarToV8ConversionError);
140 return; 134 return;
141 } 135 }
142 136
143 WebSerializedScriptValue serialized_val = 137 WebSerializedScriptValue serialized_val =
144 WebSerializedScriptValue::serialize(v8_val); 138 WebSerializedScriptValue::serialize(v8_val);
145 139
146 if (js_message_queue_state_ != SEND_DIRECTLY) { 140 if (early_message_queue_state_ != SEND_DIRECTLY) {
147 // We can't just PostTask here; the messages would arrive out of 141 // We can't just PostTask here; the messages would arrive out of
148 // order. Instead, we queue them up until we're ready to post 142 // order. Instead, we queue them up until we're ready to post
149 // them. 143 // them.
150 js_message_queue_.push_back(serialized_val); 144 early_message_queue_.push_back(serialized_val);
151 } else { 145 } else {
152 // The proxy sent an asynchronous message, so the plugin is already 146 // The proxy sent an asynchronous message, so the plugin is already
153 // unblocked. Therefore, there's no need to PostTask. 147 // unblocked. Therefore, there's no need to PostTask.
154 DCHECK(js_message_queue_.empty()); 148 DCHECK(early_message_queue_.empty());
155 PostMessageToJavaScriptImpl(serialized_val); 149 PostMessageToJavaScriptImpl(serialized_val);
156 } 150 }
157 } 151 }
158 152
159 void MessageChannel::Start() { 153 void MessageChannel::Start() {
160 DCHECK_EQ(WAITING_TO_START, js_message_queue_state_); 154 // We PostTask here instead of draining the message queue directly
161 DCHECK_EQ(WAITING_TO_START, plugin_message_queue_state_);
162
163 ppapi::proxy::HostDispatcher* dispatcher =
164 ppapi::proxy::HostDispatcher::GetForInstance(instance_->pp_instance());
165 // The dispatcher is NULL for in-process.
166 if (dispatcher)
167 dispatcher->AddSyncMessageStatusObserver(this);
168
169 // We can't drain the JS message queue directly
170 // since we haven't finished initializing the PepperWebPluginImpl yet, so 155 // since we haven't finished initializing the PepperWebPluginImpl yet, so
171 // the plugin isn't available in the DOM. 156 // the plugin isn't available in the DOM.
172 DrainJSMessageQueueSoon(); 157 base::MessageLoop::current()->PostTask(
173 158 FROM_HERE,
174 plugin_message_queue_state_ = SEND_DIRECTLY; 159 base::Bind(&MessageChannel::DrainEarlyMessageQueue,
175 DrainCompletedPluginMessages(); 160 weak_ptr_factory_.GetWeakPtr()));
176 } 161 }
177 162
178 void MessageChannel::SetPassthroughObject(v8::Handle<v8::Object> passthrough) { 163 void MessageChannel::SetPassthroughObject(v8::Handle<v8::Object> passthrough) {
179 passthrough_object_.Reset(instance_->GetIsolate(), passthrough); 164 passthrough_object_.Reset(instance_->GetIsolate(), passthrough);
180 } 165 }
181 166
182 void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) { 167 void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) {
183 StringVar* key_string = StringVar::FromPPVar(key); 168 StringVar* key_string = StringVar::FromPPVar(key);
184 if (key_string) { 169 if (key_string) {
185 internal_named_properties_[key_string->value()] = ScopedPPVar(value); 170 internal_named_properties_[key_string->value()] = ScopedPPVar(value);
186 } else { 171 } else {
187 NOTREACHED(); 172 NOTREACHED();
188 } 173 }
189 } 174 }
190 175
191 MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance) 176 MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance)
192 : gin::NamedPropertyInterceptor(instance->GetIsolate(), this), 177 : gin::NamedPropertyInterceptor(instance->GetIsolate(), this),
193 instance_(instance), 178 instance_(instance),
194 js_message_queue_state_(WAITING_TO_START), 179 early_message_queue_state_(QUEUE_MESSAGES),
195 blocking_message_depth_(0),
196 plugin_message_queue_state_(WAITING_TO_START),
197 weak_ptr_factory_(this) { 180 weak_ptr_factory_(this) {
198 } 181 }
199 182
200 gin::ObjectTemplateBuilder MessageChannel::GetObjectTemplateBuilder( 183 gin::ObjectTemplateBuilder MessageChannel::GetObjectTemplateBuilder(
201 v8::Isolate* isolate) { 184 v8::Isolate* isolate) {
202 return Wrappable<MessageChannel>::GetObjectTemplateBuilder(isolate) 185 return Wrappable<MessageChannel>::GetObjectTemplateBuilder(isolate)
203 .AddNamedPropertyInterceptor(); 186 .AddNamedPropertyInterceptor();
204 } 187 }
205 188
206 void MessageChannel::BeginBlockOnSyncMessage() {
207 js_message_queue_state_ = QUEUE_MESSAGES;
208 ++blocking_message_depth_;
209 }
210
211 void MessageChannel::EndBlockOnSyncMessage() {
212 --blocking_message_depth_;
213 if (!blocking_message_depth_)
214 DrainJSMessageQueueSoon();
215 }
216
217 v8::Local<v8::Value> MessageChannel::GetNamedProperty( 189 v8::Local<v8::Value> MessageChannel::GetNamedProperty(
218 v8::Isolate* isolate, 190 v8::Isolate* isolate,
219 const std::string& identifier) { 191 const std::string& identifier) {
220 if (!instance_) 192 if (!instance_)
221 return v8::Local<v8::Value>(); 193 return v8::Local<v8::Value>();
222 194
223 PepperTryCatchV8 try_catch(instance_, V8VarConverter::kDisallowObjectVars, 195 PepperTryCatchV8 try_catch(instance_, V8VarConverter::kDisallowObjectVars,
224 isolate); 196 isolate);
225 if (identifier == kPostMessage) { 197 if (identifier == kPostMessage) {
226 return gin::CreateFunctionTemplate(isolate, 198 return gin::CreateFunctionTemplate(isolate,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 try_catch.ThrowException( 279 try_catch.ThrowException(
308 "postMessageAndAwaitResponse requires one argument"); 280 "postMessageAndAwaitResponse requires one argument");
309 return; 281 return;
310 } 282 }
311 283
312 v8::Handle<v8::Value> message_data; 284 v8::Handle<v8::Value> message_data;
313 if (!args->GetNext(&message_data)) { 285 if (!args->GetNext(&message_data)) {
314 NOTREACHED(); 286 NOTREACHED();
315 } 287 }
316 288
317 if (plugin_message_queue_state_ == WAITING_TO_START) { 289 if (early_message_queue_state_ == QUEUE_MESSAGES) {
318 try_catch.ThrowException( 290 try_catch.ThrowException(
319 "Attempted to call a synchronous method on a plugin that was not " 291 "Attempted to call a synchronous method on a plugin that was not "
320 "yet loaded."); 292 "yet loaded.");
321 return; 293 return;
322 } 294 }
323 295
324 // If the queue of messages to the plugin is non-empty, we're still waiting on 296 // If the queue of messages to the plugin is non-empty, we're still waiting on
325 // pending Var conversions. This means at some point in the past, JavaScript 297 // pending Var conversions. This means at some point in the past, JavaScript
326 // called postMessage (the async one) and passed us something with a browser- 298 // called postMessage (the async one) and passed us something with a browser-
327 // side host (e.g., FileSystem) and we haven't gotten a response from the 299 // side host (e.g., FileSystem) and we haven't gotten a response from the
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 const ScopedPPVar& result, 392 const ScopedPPVar& result,
421 bool success) { 393 bool success) {
422 if (!instance_) 394 if (!instance_)
423 return; 395 return;
424 result_holder->ConversionCompleted(result, success); 396 result_holder->ConversionCompleted(result, success);
425 DrainCompletedPluginMessages(); 397 DrainCompletedPluginMessages();
426 } 398 }
427 399
428 void MessageChannel::DrainCompletedPluginMessages() { 400 void MessageChannel::DrainCompletedPluginMessages() {
429 DCHECK(instance_); 401 DCHECK(instance_);
430 if (plugin_message_queue_state_ == WAITING_TO_START) 402 if (early_message_queue_state_ == QUEUE_MESSAGES)
431 return; 403 return;
432 404
433 while (!plugin_message_queue_.empty() && 405 while (!plugin_message_queue_.empty() &&
434 plugin_message_queue_.front().conversion_completed()) { 406 plugin_message_queue_.front().conversion_completed()) {
435 const VarConversionResult& front = plugin_message_queue_.front(); 407 const VarConversionResult& front = plugin_message_queue_.front();
436 if (front.success()) { 408 if (front.success()) {
437 instance_->HandleMessage(front.var()); 409 instance_->HandleMessage(front.var());
438 } else { 410 } else {
439 PpapiGlobals::Get()->LogWithSource(instance()->pp_instance(), 411 PpapiGlobals::Get()->LogWithSource(instance()->pp_instance(),
440 PP_LOGLEVEL_ERROR, 412 PP_LOGLEVEL_ERROR,
441 std::string(), 413 std::string(),
442 kV8ToVarConversionError); 414 kV8ToVarConversionError);
443 } 415 }
444 plugin_message_queue_.pop_front(); 416 plugin_message_queue_.pop_front();
445 } 417 }
446 } 418 }
447 419
448 void MessageChannel::DrainJSMessageQueue() { 420 void MessageChannel::DrainEarlyMessageQueue() {
449 if (!instance_) 421 if (!instance_)
450 return; 422 return;
451 if (js_message_queue_state_ == SEND_DIRECTLY) 423 DCHECK(early_message_queue_state_ == QUEUE_MESSAGES);
452 return;
453 424
454 // Take a reference on the PluginInstance. This is because JavaScript code 425 // Take a reference on the PluginInstance. This is because JavaScript code
455 // may delete the plugin, which would destroy the PluginInstance and its 426 // may delete the plugin, which would destroy the PluginInstance and its
456 // corresponding MessageChannel. 427 // corresponding MessageChannel.
457 scoped_refptr<PepperPluginInstanceImpl> instance_ref(instance_); 428 scoped_refptr<PepperPluginInstanceImpl> instance_ref(instance_);
458 while (!js_message_queue_.empty()) { 429 while (!early_message_queue_.empty()) {
459 PostMessageToJavaScriptImpl(js_message_queue_.front()); 430 PostMessageToJavaScriptImpl(early_message_queue_.front());
460 js_message_queue_.pop_front(); 431 early_message_queue_.pop_front();
461 } 432 }
462 js_message_queue_state_ = SEND_DIRECTLY; 433 early_message_queue_state_ = SEND_DIRECTLY;
463 }
464 434
465 void MessageChannel::DrainJSMessageQueueSoon() { 435 DrainCompletedPluginMessages();
466 base::MessageLoop::current()->PostTask(
467 FROM_HERE,
468 base::Bind(&MessageChannel::DrainJSMessageQueue,
469 weak_ptr_factory_.GetWeakPtr()));
470 } 436 }
471 437
472 } // namespace content 438 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/pepper/message_channel.h ('k') | content/renderer/pepper/pepper_hung_plugin_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698