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

Unified Diff: webkit/plugins/ppapi/message_channel.cc

Issue 20165002: Move webkit/plugins/ppapi to content/renderer/pepper. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: more more clang fun Created 7 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/plugins/ppapi/message_channel.h ('k') | webkit/plugins/ppapi/mock_platform_image_2d.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/plugins/ppapi/message_channel.cc
===================================================================
--- webkit/plugins/ppapi/message_channel.cc (revision 213561)
+++ webkit/plugins/ppapi/message_channel.cc (working copy)
@@ -1,520 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/plugins/ppapi/message_channel.h"
-
-#include <cstdlib>
-#include <string>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "ppapi/shared_impl/ppapi_globals.h"
-#include "ppapi/shared_impl/var.h"
-#include "ppapi/shared_impl/var_tracker.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebNode.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
-#include "v8/include/v8.h"
-#include "webkit/plugins/ppapi/host_array_buffer_var.h"
-#include "webkit/plugins/ppapi/npapi_glue.h"
-#include "webkit/plugins/ppapi/plugin_module.h"
-#include "webkit/plugins/ppapi/ppapi_plugin_instance_impl.h"
-#include "webkit/plugins/ppapi/v8_var_converter.h"
-
-using ppapi::ArrayBufferVar;
-using ppapi::PpapiGlobals;
-using ppapi::StringVar;
-using WebKit::WebBindings;
-using WebKit::WebElement;
-using WebKit::WebDOMEvent;
-using WebKit::WebDOMMessageEvent;
-using WebKit::WebPluginContainer;
-using WebKit::WebSerializedScriptValue;
-
-namespace webkit {
-
-namespace ppapi {
-
-namespace {
-
-const char kPostMessage[] = "postMessage";
-const char kV8ToVarConversionError[] = "Failed to convert a PostMessage "
- "argument from a JavaScript value to a PP_Var. It may have cycles or be of "
- "an unsupported type.";
-const char kVarToV8ConversionError[] = "Failed to convert a PostMessage "
- "argument from a PP_Var to a Javascript value. It may have cycles or be of "
- "an unsupported type.";
-
-// Helper function to get the MessageChannel that is associated with an
-// NPObject*.
-MessageChannel* ToMessageChannel(NPObject* object) {
- return static_cast<MessageChannel::MessageChannelNPObject*>(object)->
- message_channel.get();
-}
-
-NPObject* ToPassThroughObject(NPObject* object) {
- MessageChannel* channel = ToMessageChannel(object);
- return channel ? channel->passthrough_object() : NULL;
-}
-
-// Helper function to determine if a given identifier is equal to kPostMessage.
-bool IdentifierIsPostMessage(NPIdentifier identifier) {
- return WebBindings::getStringIdentifier(kPostMessage) == identifier;
-}
-
-bool NPVariantToPPVar(const NPVariant* variant, PP_Var* result) {
- switch (variant->type) {
- case NPVariantType_Void:
- *result = PP_MakeUndefined();
- return true;
- case NPVariantType_Null:
- *result = PP_MakeNull();
- return true;
- case NPVariantType_Bool:
- *result = PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant)));
- return true;
- case NPVariantType_Int32:
- *result = PP_MakeInt32(NPVARIANT_TO_INT32(*variant));
- return true;
- case NPVariantType_Double:
- *result = PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant));
- return true;
- case NPVariantType_String:
- *result = StringVar::StringToPPVar(
- NPVARIANT_TO_STRING(*variant).UTF8Characters,
- NPVARIANT_TO_STRING(*variant).UTF8Length);
- return true;
- case NPVariantType_Object: {
- // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it
- // shouldn't result in a deep copy.
- v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant);
- if (!V8VarConverter::FromV8Value(v8_value, v8::Context::GetCurrent(),
- result)) {
- return false;
- }
- return true;
- }
- }
- return false;
-}
-
-// Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage.
-// This currently just copies the value. For a string Var, the result is a
-// PP_Var with the a copy of |var|'s string contents and a reference count of 1.
-PP_Var CopyPPVar(const PP_Var& var) {
- switch (var.type) {
- case PP_VARTYPE_UNDEFINED:
- case PP_VARTYPE_NULL:
- case PP_VARTYPE_BOOL:
- case PP_VARTYPE_INT32:
- case PP_VARTYPE_DOUBLE:
- return var;
- case PP_VARTYPE_STRING: {
- StringVar* string = StringVar::FromPPVar(var);
- if (!string)
- return PP_MakeUndefined();
- return StringVar::StringToPPVar(string->value());
- }
- case PP_VARTYPE_ARRAY_BUFFER: {
- ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var);
- if (!buffer)
- return PP_MakeUndefined();
- PP_Var new_buffer_var = PpapiGlobals::Get()->GetVarTracker()->
- MakeArrayBufferPPVar(buffer->ByteLength());
- DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER);
- if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER)
- return PP_MakeUndefined();
- ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var);
- DCHECK(new_buffer);
- if (!new_buffer)
- return PP_MakeUndefined();
- memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength());
- return new_buffer_var;
- }
- case PP_VARTYPE_OBJECT:
- case PP_VARTYPE_ARRAY:
- case PP_VARTYPE_DICTIONARY:
- // Objects/Arrays/Dictionaries not supported by PostMessage in-process.
- NOTREACHED();
- return PP_MakeUndefined();
- }
- NOTREACHED();
- return PP_MakeUndefined();
-}
-
-//------------------------------------------------------------------------------
-// Implementations of NPClass functions. These are here to:
-// - Implement postMessage behavior.
-// - Forward calls to the 'passthrough' object to allow backwards-compatibility
-// with GetInstanceObject() objects.
-//------------------------------------------------------------------------------
-NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) {
- return new MessageChannel::MessageChannelNPObject;
-}
-
-void MessageChannelDeallocate(NPObject* object) {
- MessageChannel::MessageChannelNPObject* instance =
- static_cast<MessageChannel::MessageChannelNPObject*>(object);
- delete instance;
-}
-
-bool MessageChannelHasMethod(NPObject* np_obj, NPIdentifier name) {
- if (!np_obj)
- return false;
-
- // We only handle a function called postMessage.
- if (IdentifierIsPostMessage(name))
- return true;
-
- // Other method names we will pass to the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::hasMethod(NULL, passthrough, name);
- return false;
-}
-
-bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name,
- const NPVariant* args, uint32 arg_count,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- // We only handle a function called postMessage.
- if (IdentifierIsPostMessage(name) && (arg_count == 1)) {
- MessageChannel* message_channel = ToMessageChannel(np_obj);
- if (message_channel) {
- PP_Var argument = PP_MakeUndefined();
- if (!NPVariantToPPVar(&args[0], &argument)) {
- PpapiGlobals::Get()->LogWithSource(
- message_channel->instance()->pp_instance(),
- PP_LOGLEVEL_ERROR, std::string(), kV8ToVarConversionError);
- return false;
- }
- message_channel->PostMessageToNative(argument);
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(argument);
- return true;
- } else {
- return false;
- }
- }
- // Other method calls we will pass to the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough) {
- return WebBindings::invoke(NULL, passthrough, name, args, arg_count,
- result);
- }
- return false;
-}
-
-bool MessageChannelInvokeDefault(NPObject* np_obj,
- const NPVariant* args,
- uint32 arg_count,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough) {
- return WebBindings::invokeDefault(NULL, passthrough, args, arg_count,
- result);
- }
- return false;
-}
-
-bool MessageChannelHasProperty(NPObject* np_obj, NPIdentifier name) {
- if (!np_obj)
- return false;
-
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::hasProperty(NULL, passthrough, name);
- return false;
-}
-
-bool MessageChannelGetProperty(NPObject* np_obj, NPIdentifier name,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- // Don't allow getting the postMessage function.
- if (IdentifierIsPostMessage(name))
- return false;
-
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::getProperty(NULL, passthrough, name, result);
- return false;
-}
-
-bool MessageChannelSetProperty(NPObject* np_obj, NPIdentifier name,
- const NPVariant* variant) {
- if (!np_obj)
- return false;
-
- // Don't allow setting the postMessage function.
- if (IdentifierIsPostMessage(name))
- return false;
-
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::setProperty(NULL, passthrough, name, variant);
- return false;
-}
-
-bool MessageChannelEnumerate(NPObject *np_obj, NPIdentifier **value,
- uint32_t *count) {
- if (!np_obj)
- return false;
-
- // Invoke on the passthrough object, if we have one, to enumerate its
- // properties.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough) {
- bool success = WebBindings::enumerate(NULL, passthrough, value, count);
- if (success) {
- // Add postMessage to the list and return it.
- if (std::numeric_limits<size_t>::max() / sizeof(NPIdentifier) <=
- static_cast<size_t>(*count) + 1) // Else, "always false" x64 warning.
- return false;
- NPIdentifier* new_array = static_cast<NPIdentifier*>(
- std::malloc(sizeof(NPIdentifier) * (*count + 1)));
- std::memcpy(new_array, *value, sizeof(NPIdentifier)*(*count));
- new_array[*count] = WebBindings::getStringIdentifier(kPostMessage);
- std::free(*value);
- *value = new_array;
- ++(*count);
- return true;
- }
- }
-
- // Otherwise, build an array that includes only postMessage.
- *value = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier)));
- (*value)[0] = WebBindings::getStringIdentifier(kPostMessage);
- *count = 1;
- return true;
-}
-
-NPClass message_channel_class = {
- NP_CLASS_STRUCT_VERSION,
- &MessageChannelAllocate,
- &MessageChannelDeallocate,
- NULL,
- &MessageChannelHasMethod,
- &MessageChannelInvoke,
- &MessageChannelInvokeDefault,
- &MessageChannelHasProperty,
- &MessageChannelGetProperty,
- &MessageChannelSetProperty,
- NULL,
- &MessageChannelEnumerate,
-};
-
-} // namespace
-
-// MessageChannel --------------------------------------------------------------
-MessageChannel::MessageChannelNPObject::MessageChannelNPObject() {
-}
-
-MessageChannel::MessageChannelNPObject::~MessageChannelNPObject() {}
-
-MessageChannel::MessageChannel(PluginInstanceImpl* instance)
- : instance_(instance),
- passthrough_object_(NULL),
- np_object_(NULL),
- weak_ptr_factory_(this),
- early_message_queue_state_(QUEUE_MESSAGES) {
- // Now create an NPObject for receiving calls to postMessage. This sets the
- // reference count to 1. We release it in the destructor.
- NPObject* obj = WebBindings::createObject(instance_->instanceNPP(),
- &message_channel_class);
- DCHECK(obj);
- np_object_ = static_cast<MessageChannel::MessageChannelNPObject*>(obj);
- np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
-}
-
-void MessageChannel::PostMessageToJavaScript(PP_Var message_data) {
- v8::HandleScope scope;
-
- // Because V8 is probably not on the stack for Native->JS calls, we need to
- // enter the appropriate context for the plugin.
- WebPluginContainer* container = instance_->container();
- // It's possible that container() is NULL if the plugin has been removed from
- // the DOM (but the PluginInstance is not destroyed yet).
- if (!container)
- return;
-
- v8::Local<v8::Context> context =
- container->element().document().frame()->mainWorldScriptContext();
- // If the page is being destroyed, the context may be empty.
- if (context.IsEmpty())
- return;
- v8::Context::Scope context_scope(context);
-
- v8::Handle<v8::Value> v8_val;
- if (!V8VarConverter::ToV8Value(message_data, context, &v8_val)) {
- PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(),
- PP_LOGLEVEL_ERROR, std::string(), kVarToV8ConversionError);
- return;
- }
-
- // This is for backward compatibility. It usually makes sense for us to return
- // a string object rather than a string primitive because it allows multiple
- // references to the same string (as with PP_Var strings). However, prior to
- // implementing dictionary and array, vars we would return a string primitive
- // here. Changing it to an object now will break existing code that uses
- // strict comparisons for strings returned from PostMessage. e.g. x === "123"
- // will no longer return true. So if the only value to return is a string
- // object, just return the string primitive.
- if (v8_val->IsStringObject())
- v8_val = v8_val->ToString();
-
- WebSerializedScriptValue serialized_val =
- WebSerializedScriptValue::serialize(v8_val);
-
- if (instance_->module()->IsProxied()) {
- if (early_message_queue_state_ != SEND_DIRECTLY) {
- // We can't just PostTask here; the messages would arrive out of
- // order. Instead, we queue them up until we're ready to post
- // them.
- early_message_queue_.push_back(serialized_val);
- } else {
- // The proxy sent an asynchronous message, so the plugin is already
- // unblocked. Therefore, there's no need to PostTask.
- DCHECK(early_message_queue_.size() == 0);
- PostMessageToJavaScriptImpl(serialized_val);
- }
- } else {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&MessageChannel::PostMessageToJavaScriptImpl,
- weak_ptr_factory_.GetWeakPtr(),
- serialized_val));
- }
-}
-
-void MessageChannel::StopQueueingJavaScriptMessages() {
- // We PostTask here instead of draining the message queue directly
- // since we haven't finished initializing the WebPluginImpl yet, so
- // the plugin isn't available in the DOM.
- early_message_queue_state_ = DRAIN_PENDING;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&MessageChannel::DrainEarlyMessageQueue,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void MessageChannel::QueueJavaScriptMessages() {
- if (early_message_queue_state_ == DRAIN_PENDING)
- early_message_queue_state_ = DRAIN_CANCELLED;
- else
- early_message_queue_state_ = QUEUE_MESSAGES;
-}
-
-void MessageChannel::DrainEarlyMessageQueue() {
- // Take a reference on the PluginInstance. This is because JavaScript code
- // may delete the plugin, which would destroy the PluginInstance and its
- // corresponding MessageChannel.
- scoped_refptr<PluginInstanceImpl> instance_ref(instance_);
-
- if (early_message_queue_state_ == DRAIN_CANCELLED) {
- early_message_queue_state_ = QUEUE_MESSAGES;
- return;
- }
- DCHECK(early_message_queue_state_ == DRAIN_PENDING);
-
- while (!early_message_queue_.empty()) {
- PostMessageToJavaScriptImpl(early_message_queue_.front());
- early_message_queue_.pop_front();
- }
- early_message_queue_state_ = SEND_DIRECTLY;
-}
-
-void MessageChannel::PostMessageToJavaScriptImpl(
- const WebSerializedScriptValue& message_data) {
- DCHECK(instance_);
-
- WebPluginContainer* container = instance_->container();
- // It's possible that container() is NULL if the plugin has been removed from
- // the DOM (but the PluginInstance is not destroyed yet).
- if (!container)
- return;
-
- WebDOMEvent event =
- container->element().document().createEvent("MessageEvent");
- WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
- msg_event.initMessageEvent("message", // type
- false, // canBubble
- false, // cancelable
- message_data, // data
- "", // origin [*]
- NULL, // source [*]
- ""); // lastEventId
- // [*] Note that the |origin| is only specified for cross-document and server-
- // sent messages, while |source| is only specified for cross-document
- // messages:
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html
- // This currently behaves like Web Workers. On Firefox, Chrome, and Safari
- // at least, postMessage on Workers does not provide the origin or source.
- // TODO(dmichael): Add origin if we change to a more iframe-like origin
- // policy (see crbug.com/81537)
-
- container->element().dispatchEvent(msg_event);
-}
-
-void MessageChannel::PostMessageToNative(PP_Var message_data) {
- if (instance_->module()->IsProxied()) {
- // In the proxied case, the copy will happen via serializiation, and the
- // message is asynchronous. Therefore there's no need to copy the Var, nor
- // to PostTask.
- PostMessageToNativeImpl(message_data);
- } else {
- // Make a copy of the message data for the Task we will run.
- PP_Var var_copy(CopyPPVar(message_data));
-
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&MessageChannel::PostMessageToNativeImpl,
- weak_ptr_factory_.GetWeakPtr(),
- var_copy));
- }
-}
-
-void MessageChannel::PostMessageToNativeImpl(PP_Var message_data) {
- instance_->HandleMessage(message_data);
-}
-
-MessageChannel::~MessageChannel() {
- WebBindings::releaseObject(np_object_);
- if (passthrough_object_)
- WebBindings::releaseObject(passthrough_object_);
-}
-
-void MessageChannel::SetPassthroughObject(NPObject* passthrough) {
- // Retain the passthrough object; We need to ensure it lives as long as this
- // MessageChannel.
- if (passthrough)
- WebBindings::retainObject(passthrough);
-
- // If we had a passthrough set already, release it. Note that we retain the
- // incoming passthrough object first, so that we behave correctly if anyone
- // invokes:
- // SetPassthroughObject(passthrough_object());
- if (passthrough_object_)
- WebBindings::releaseObject(passthrough_object_);
-
- passthrough_object_ = passthrough;
-}
-
-} // namespace ppapi
-} // namespace webkit
« no previous file with comments | « webkit/plugins/ppapi/message_channel.h ('k') | webkit/plugins/ppapi/mock_platform_image_2d.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698