Chromium Code Reviews| 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 "webkit/plugins/ppapi/message_channel.h" | 5 #include "webkit/plugins/ppapi/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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "ppapi/shared_impl/ppapi_globals.h" | 13 #include "ppapi/shared_impl/ppapi_globals.h" |
| 14 #include "ppapi/shared_impl/var.h" | 14 #include "ppapi/shared_impl/var.h" |
| 15 #include "ppapi/shared_impl/var_tracker.h" | 15 #include "ppapi/shared_impl/var_tracker.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMMessageEvent.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMMessageEvent.h" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerialize dScriptValue.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerialize dScriptValue.h" |
| 24 #include "v8/include/v8.h" | 24 #include "v8/include/v8.h" |
| 25 #include "webkit/plugins/ppapi/host_array_buffer_var.h" | 25 #include "webkit/plugins/ppapi/host_array_buffer_var.h" |
| 26 #include "webkit/plugins/ppapi/npapi_glue.h" | 26 #include "webkit/plugins/ppapi/npapi_glue.h" |
| 27 #include "webkit/plugins/ppapi/plugin_module.h" | |
| 27 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 28 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 28 | 29 |
| 29 using ppapi::ArrayBufferVar; | 30 using ppapi::ArrayBufferVar; |
| 30 using ppapi::PpapiGlobals; | 31 using ppapi::PpapiGlobals; |
| 31 using ppapi::StringVar; | 32 using ppapi::StringVar; |
| 32 using WebKit::WebBindings; | 33 using WebKit::WebBindings; |
| 33 using WebKit::WebElement; | 34 using WebKit::WebElement; |
| 34 using WebKit::WebDOMEvent; | 35 using WebKit::WebDOMEvent; |
| 35 using WebKit::WebDOMMessageEvent; | 36 using WebKit::WebDOMMessageEvent; |
| 36 using WebKit::WebPluginContainer; | 37 using WebKit::WebPluginContainer; |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 // MessageChannel -------------------------------------------------------------- | 324 // MessageChannel -------------------------------------------------------------- |
| 324 MessageChannel::MessageChannelNPObject::MessageChannelNPObject() { | 325 MessageChannel::MessageChannelNPObject::MessageChannelNPObject() { |
| 325 } | 326 } |
| 326 | 327 |
| 327 MessageChannel::MessageChannelNPObject::~MessageChannelNPObject() {} | 328 MessageChannel::MessageChannelNPObject::~MessageChannelNPObject() {} |
| 328 | 329 |
| 329 MessageChannel::MessageChannel(PluginInstance* instance) | 330 MessageChannel::MessageChannel(PluginInstance* instance) |
| 330 : instance_(instance), | 331 : instance_(instance), |
| 331 passthrough_object_(NULL), | 332 passthrough_object_(NULL), |
| 332 np_object_(NULL), | 333 np_object_(NULL), |
| 333 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 334 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| 335 did_create_finished_(false) { | |
| 334 // Now create an NPObject for receiving calls to postMessage. This sets the | 336 // Now create an NPObject for receiving calls to postMessage. This sets the |
| 335 // reference count to 1. We release it in the destructor. | 337 // reference count to 1. We release it in the destructor. |
| 336 NPObject* obj = WebBindings::createObject(NULL, &message_channel_class); | 338 NPObject* obj = WebBindings::createObject(NULL, &message_channel_class); |
| 337 DCHECK(obj); | 339 DCHECK(obj); |
| 338 np_object_ = static_cast<MessageChannel::MessageChannelNPObject*>(obj); | 340 np_object_ = static_cast<MessageChannel::MessageChannelNPObject*>(obj); |
| 339 np_object_->message_channel = weak_ptr_factory_.GetWeakPtr(); | 341 np_object_->message_channel = weak_ptr_factory_.GetWeakPtr(); |
| 340 } | 342 } |
| 341 | 343 |
| 342 void MessageChannel::PostMessageToJavaScript(PP_Var message_data) { | 344 void MessageChannel::PostMessageToJavaScript(PP_Var message_data) { |
| 343 // Serialize the message data. | 345 // Serialize the message data. |
| 344 v8::HandleScope scope; | 346 v8::HandleScope scope; |
| 345 // Because V8 is probably not on the stack for Native->JS calls, we need to | 347 // Because V8 is probably not on the stack for Native->JS calls, we need to |
| 346 // enter the appropriate context for the plugin. | 348 // enter the appropriate context for the plugin. |
| 347 v8::Local<v8::Context> context = | 349 v8::Local<v8::Context> context = |
| 348 instance_->container()->element().document().frame()-> | 350 instance_->container()->element().document().frame()-> |
| 349 mainWorldScriptContext(); | 351 mainWorldScriptContext(); |
| 350 v8::Context::Scope context_scope(context); | 352 v8::Context::Scope context_scope(context); |
| 351 | 353 |
| 352 v8::Local<v8::Value> v8_val; | 354 v8::Local<v8::Value> v8_val; |
| 353 if (!PPVarToV8Value(message_data, &v8_val)) { | 355 if (!PPVarToV8Value(message_data, &v8_val)) { |
| 354 NOTREACHED(); | 356 NOTREACHED(); |
| 355 return; | 357 return; |
| 356 } | 358 } |
| 357 | 359 |
| 358 WebSerializedScriptValue serialized_val = | 360 WebSerializedScriptValue serialized_val = |
| 359 WebSerializedScriptValue::serialize(v8_val); | 361 WebSerializedScriptValue::serialize(v8_val); |
| 360 | 362 |
| 363 if (instance_->module()->IsProxied()) { | |
| 364 // The proxy sent an asynchronous message, so the plugin is already | |
| 365 // unblocked. Therefore, there's no need to PostTask. | |
|
dmichael (off chromium)
2012/12/10 22:02:52
This comment probably belongs in the first branch
teravest
2012/12/10 22:30:59
Done.
| |
| 366 if (did_create_finished_) { | |
| 367 DCHECK(early_message_queue_.size() == 0); | |
| 368 PostMessageToJavaScriptImpl(serialized_val); | |
| 369 } else { | |
| 370 early_message_queue_.push_back(serialized_val); | |
|
dmichael (off chromium)
2012/12/10 22:02:52
Probably worth a brief comment why we have to defe
teravest
2012/12/10 22:30:59
Done.
| |
| 371 } | |
| 372 } else { | |
| 373 MessageLoop::current()->PostTask( | |
| 374 FROM_HERE, | |
| 375 base::Bind(&MessageChannel::PostMessageToJavaScriptImpl, | |
| 376 weak_ptr_factory_.GetWeakPtr(), | |
| 377 serialized_val)); | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 void MessageChannel::DidCreateFinished() { | |
| 382 // We PostTask here instead of draining the message queue directly | |
| 383 // since we haven't finished initializing the WebPluginImpl yet, so | |
| 384 // the plugin isn't available in the DOM. | |
| 361 MessageLoop::current()->PostTask( | 385 MessageLoop::current()->PostTask( |
| 362 FROM_HERE, | 386 FROM_HERE, |
| 363 base::Bind(&MessageChannel::PostMessageToJavaScriptImpl, | 387 base::Bind(&MessageChannel::DrainEarlyMessageQueue, |
| 364 weak_ptr_factory_.GetWeakPtr(), | 388 weak_ptr_factory_.GetWeakPtr())); |
| 365 serialized_val)); | 389 } |
| 390 | |
| 391 void MessageChannel::DrainEarlyMessageQueue() { | |
|
dmichael (off chromium)
2012/12/10 22:02:52
Might be worth doing:
DCHECK(!did_create_finished_
teravest
2012/12/10 22:30:59
Done.
| |
| 392 while (!early_message_queue_.empty()) { | |
| 393 PostMessageToJavaScriptImpl(early_message_queue_.front()); | |
| 394 early_message_queue_.pop_front(); | |
|
dmichael (off chromium)
2012/12/10 22:02:52
If there's any chance of re-entry, you'd probably
teravest
2012/12/10 22:30:59
I think it's safe as is...
On 2012/12/10 22:02:52
dmichael (off chromium)
2012/12/10 22:49:47
Yes, I wasn't thinking straight; the problem I was
| |
| 395 } | |
| 396 did_create_finished_ = true; | |
| 366 } | 397 } |
| 367 | 398 |
| 368 void MessageChannel::PostMessageToJavaScriptImpl( | 399 void MessageChannel::PostMessageToJavaScriptImpl( |
| 369 const WebSerializedScriptValue& message_data) { | 400 const WebSerializedScriptValue& message_data) { |
| 370 DCHECK(instance_); | 401 DCHECK(instance_); |
| 371 | 402 |
| 372 WebPluginContainer* container = instance_->container(); | 403 WebPluginContainer* container = instance_->container(); |
| 373 // It's possible that container() is NULL if the plugin has been removed from | 404 // It's possible that container() is NULL if the plugin has been removed from |
| 374 // the DOM (but the PluginInstance is not destroyed yet). | 405 // the DOM (but the PluginInstance is not destroyed yet). |
| 375 if (!container) | 406 if (!container) |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 391 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html | 422 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html |
| 392 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari | 423 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari |
| 393 // at least, postMessage on Workers does not provide the origin or source. | 424 // at least, postMessage on Workers does not provide the origin or source. |
| 394 // TODO(dmichael): Add origin if we change to a more iframe-like origin | 425 // TODO(dmichael): Add origin if we change to a more iframe-like origin |
| 395 // policy (see crbug.com/81537) | 426 // policy (see crbug.com/81537) |
| 396 | 427 |
| 397 container->element().dispatchEvent(msg_event); | 428 container->element().dispatchEvent(msg_event); |
| 398 } | 429 } |
| 399 | 430 |
| 400 void MessageChannel::PostMessageToNative(PP_Var message_data) { | 431 void MessageChannel::PostMessageToNative(PP_Var message_data) { |
| 401 // Make a copy of the message data for the Task we will run. | 432 if (instance_->module()->IsProxied()) { |
| 402 PP_Var var_copy(CopyPPVar(message_data)); | 433 // In the proxied case, the copy will happen via serializiation, and the |
| 434 // message is asynchronous. Therefore there's no need to copy the Var, nor | |
| 435 // to PostTask. | |
| 436 PostMessageToNativeImpl(message_data); | |
| 437 } else { | |
| 438 // Make a copy of the message data for the Task we will run. | |
| 439 PP_Var var_copy(CopyPPVar(message_data)); | |
| 403 | 440 |
| 404 MessageLoop::current()->PostTask(FROM_HERE, | 441 MessageLoop::current()->PostTask(FROM_HERE, |
| 405 base::Bind(&MessageChannel::PostMessageToNativeImpl, | 442 base::Bind(&MessageChannel::PostMessageToNativeImpl, |
| 406 weak_ptr_factory_.GetWeakPtr(), | 443 weak_ptr_factory_.GetWeakPtr(), |
| 407 var_copy)); | 444 var_copy)); |
| 445 } | |
| 408 } | 446 } |
| 409 | 447 |
| 410 void MessageChannel::PostMessageToNativeImpl(PP_Var message_data) { | 448 void MessageChannel::PostMessageToNativeImpl(PP_Var message_data) { |
| 411 instance_->HandleMessage(message_data); | 449 instance_->HandleMessage(message_data); |
| 412 } | 450 } |
| 413 | 451 |
| 414 MessageChannel::~MessageChannel() { | 452 MessageChannel::~MessageChannel() { |
| 415 WebBindings::releaseObject(np_object_); | 453 WebBindings::releaseObject(np_object_); |
| 416 if (passthrough_object_) | 454 if (passthrough_object_) |
| 417 WebBindings::releaseObject(passthrough_object_); | 455 WebBindings::releaseObject(passthrough_object_); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 428 // invokes: | 466 // invokes: |
| 429 // SetPassthroughObject(passthrough_object()); | 467 // SetPassthroughObject(passthrough_object()); |
| 430 if (passthrough_object_) | 468 if (passthrough_object_) |
| 431 WebBindings::releaseObject(passthrough_object_); | 469 WebBindings::releaseObject(passthrough_object_); |
| 432 | 470 |
| 433 passthrough_object_ = passthrough; | 471 passthrough_object_ = passthrough; |
| 434 } | 472 } |
| 435 | 473 |
| 436 } // namespace ppapi | 474 } // namespace ppapi |
| 437 } // namespace webkit | 475 } // namespace webkit |
| OLD | NEW |