| 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 early_message_queue_state_(QUEUE_MESSAGES) { |
| 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 if (early_message_queue_state_ != SEND_DIRECTLY) { |
| 365 // We can't just PostTask here; the messages would arrive out of |
| 366 // order. Instead, we queue them up until we're ready to post |
| 367 // them. |
| 368 early_message_queue_.push_back(serialized_val); |
| 369 } else { |
| 370 // The proxy sent an asynchronous message, so the plugin is already |
| 371 // unblocked. Therefore, there's no need to PostTask. |
| 372 DCHECK(early_message_queue_.size() == 0); |
| 373 PostMessageToJavaScriptImpl(serialized_val); |
| 374 } |
| 375 } else { |
| 376 MessageLoop::current()->PostTask( |
| 377 FROM_HERE, |
| 378 base::Bind(&MessageChannel::PostMessageToJavaScriptImpl, |
| 379 weak_ptr_factory_.GetWeakPtr(), |
| 380 serialized_val)); |
| 381 } |
| 382 } |
| 383 |
| 384 void MessageChannel::StopQueueingJavaScriptMessages() { |
| 385 // We PostTask here instead of draining the message queue directly |
| 386 // since we haven't finished initializing the WebPluginImpl yet, so |
| 387 // the plugin isn't available in the DOM. |
| 388 early_message_queue_state_ = DRAIN_PENDING; |
| 361 MessageLoop::current()->PostTask( | 389 MessageLoop::current()->PostTask( |
| 362 FROM_HERE, | 390 FROM_HERE, |
| 363 base::Bind(&MessageChannel::PostMessageToJavaScriptImpl, | 391 base::Bind(&MessageChannel::DrainEarlyMessageQueue, |
| 364 weak_ptr_factory_.GetWeakPtr(), | 392 weak_ptr_factory_.GetWeakPtr())); |
| 365 serialized_val)); | 393 } |
| 394 |
| 395 void MessageChannel::QueueJavaScriptMessages() { |
| 396 if (early_message_queue_state_ == DRAIN_PENDING) |
| 397 early_message_queue_state_ = DRAIN_CANCELLED; |
| 398 else |
| 399 early_message_queue_state_ = QUEUE_MESSAGES; |
| 400 } |
| 401 |
| 402 void MessageChannel::DrainEarlyMessageQueue() { |
| 403 if (early_message_queue_state_ == DRAIN_CANCELLED) { |
| 404 early_message_queue_state_ = QUEUE_MESSAGES; |
| 405 return; |
| 406 } |
| 407 DCHECK(early_message_queue_state_ == DRAIN_PENDING); |
| 408 |
| 409 while (!early_message_queue_.empty()) { |
| 410 PostMessageToJavaScriptImpl(early_message_queue_.front()); |
| 411 early_message_queue_.pop_front(); |
| 412 } |
| 413 early_message_queue_state_ = SEND_DIRECTLY; |
| 366 } | 414 } |
| 367 | 415 |
| 368 void MessageChannel::PostMessageToJavaScriptImpl( | 416 void MessageChannel::PostMessageToJavaScriptImpl( |
| 369 const WebSerializedScriptValue& message_data) { | 417 const WebSerializedScriptValue& message_data) { |
| 370 DCHECK(instance_); | 418 DCHECK(instance_); |
| 371 | 419 |
| 372 WebPluginContainer* container = instance_->container(); | 420 WebPluginContainer* container = instance_->container(); |
| 373 // It's possible that container() is NULL if the plugin has been removed from | 421 // It's possible that container() is NULL if the plugin has been removed from |
| 374 // the DOM (but the PluginInstance is not destroyed yet). | 422 // the DOM (but the PluginInstance is not destroyed yet). |
| 375 if (!container) | 423 if (!container) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 391 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html | 439 // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html |
| 392 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari | 440 // This currently behaves like Web Workers. On Firefox, Chrome, and Safari |
| 393 // at least, postMessage on Workers does not provide the origin or source. | 441 // 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 | 442 // TODO(dmichael): Add origin if we change to a more iframe-like origin |
| 395 // policy (see crbug.com/81537) | 443 // policy (see crbug.com/81537) |
| 396 | 444 |
| 397 container->element().dispatchEvent(msg_event); | 445 container->element().dispatchEvent(msg_event); |
| 398 } | 446 } |
| 399 | 447 |
| 400 void MessageChannel::PostMessageToNative(PP_Var message_data) { | 448 void MessageChannel::PostMessageToNative(PP_Var message_data) { |
| 401 // Make a copy of the message data for the Task we will run. | 449 if (instance_->module()->IsProxied()) { |
| 402 PP_Var var_copy(CopyPPVar(message_data)); | 450 // In the proxied case, the copy will happen via serializiation, and the |
| 451 // message is asynchronous. Therefore there's no need to copy the Var, nor |
| 452 // to PostTask. |
| 453 PostMessageToNativeImpl(message_data); |
| 454 } else { |
| 455 // Make a copy of the message data for the Task we will run. |
| 456 PP_Var var_copy(CopyPPVar(message_data)); |
| 403 | 457 |
| 404 MessageLoop::current()->PostTask(FROM_HERE, | 458 MessageLoop::current()->PostTask(FROM_HERE, |
| 405 base::Bind(&MessageChannel::PostMessageToNativeImpl, | 459 base::Bind(&MessageChannel::PostMessageToNativeImpl, |
| 406 weak_ptr_factory_.GetWeakPtr(), | 460 weak_ptr_factory_.GetWeakPtr(), |
| 407 var_copy)); | 461 var_copy)); |
| 462 } |
| 408 } | 463 } |
| 409 | 464 |
| 410 void MessageChannel::PostMessageToNativeImpl(PP_Var message_data) { | 465 void MessageChannel::PostMessageToNativeImpl(PP_Var message_data) { |
| 411 instance_->HandleMessage(message_data); | 466 instance_->HandleMessage(message_data); |
| 412 } | 467 } |
| 413 | 468 |
| 414 MessageChannel::~MessageChannel() { | 469 MessageChannel::~MessageChannel() { |
| 415 WebBindings::releaseObject(np_object_); | 470 WebBindings::releaseObject(np_object_); |
| 416 if (passthrough_object_) | 471 if (passthrough_object_) |
| 417 WebBindings::releaseObject(passthrough_object_); | 472 WebBindings::releaseObject(passthrough_object_); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 428 // invokes: | 483 // invokes: |
| 429 // SetPassthroughObject(passthrough_object()); | 484 // SetPassthroughObject(passthrough_object()); |
| 430 if (passthrough_object_) | 485 if (passthrough_object_) |
| 431 WebBindings::releaseObject(passthrough_object_); | 486 WebBindings::releaseObject(passthrough_object_); |
| 432 | 487 |
| 433 passthrough_object_ = passthrough; | 488 passthrough_object_ = passthrough; |
| 434 } | 489 } |
| 435 | 490 |
| 436 } // namespace ppapi | 491 } // namespace ppapi |
| 437 } // namespace webkit | 492 } // namespace webkit |
| OLD | NEW |