15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/message_channel.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstdlib>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
13bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/host_array_buffer_var.h"
14bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/npapi_glue.h"
1558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
16bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/plugin_module.h"
17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/v8_var_converter.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ppapi/shared_impl/scoped_pp_var.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var_tracker.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebBindings.h"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDocument.h"
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebElement.h"
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebNode.h"
287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebPluginContainer.h"
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::ArrayBufferVar;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::PpapiGlobals;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::StringVar;
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebBindings;
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebElement;
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebDOMEvent;
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebDOMMessageEvent;
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebPluginContainer;
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebSerializedScriptValue;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochnamespace content {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPostMessage[] = "postMessage";
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char kV8ToVarConversionError[] = "Failed to convert a PostMessage "
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "argument from a JavaScript value to a PP_Var. It may have cycles or be of "
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "an unsupported type.";
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char kVarToV8ConversionError[] = "Failed to convert a PostMessage "
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "argument from a PP_Var to a Javascript value. It may have cycles or be of "
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "an unsupported type.";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to get the MessageChannel that is associated with an
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NPObject*.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageChannel* ToMessageChannel(NPObject* object) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<MessageChannel::MessageChannelNPObject*>(object)->
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      message_channel.get();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPObject* ToPassThroughObject(NPObject* object) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageChannel* channel = ToMessageChannel(object);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel ? channel->passthrough_object() : NULL;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to determine if a given identifier is equal to kPostMessage.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentifierIsPostMessage(NPIdentifier identifier) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WebBindings::getStringIdentifier(kPostMessage) == identifier;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copy a PP_Var in to a PP_Var that is appropriate for sending via postMessage.
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This currently just copies the value.  For a string Var, the result is a
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// PP_Var with the a copy of |var|'s string contents and a reference count of 1.
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PP_Var CopyPPVar(const PP_Var& var) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (var.type) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_UNDEFINED:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_NULL:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_BOOL:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_INT32:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_DOUBLE:
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return var;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_STRING: {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StringVar* string = StringVar::FromPPVar(var);
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!string)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return PP_MakeUndefined();
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return StringVar::StringToPPVar(string->value());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_ARRAY_BUFFER: {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var);
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!buffer)
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return PP_MakeUndefined();
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      PP_Var new_buffer_var = PpapiGlobals::Get()->GetVarTracker()->
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          MakeArrayBufferPPVar(buffer->ByteLength());
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DCHECK(new_buffer_var.type == PP_VARTYPE_ARRAY_BUFFER);
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (new_buffer_var.type != PP_VARTYPE_ARRAY_BUFFER)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return PP_MakeUndefined();
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ArrayBufferVar* new_buffer = ArrayBufferVar::FromPPVar(new_buffer_var);
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DCHECK(new_buffer);
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!new_buffer)
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return PP_MakeUndefined();
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      memcpy(new_buffer->Map(), buffer->Map(), buffer->ByteLength());
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return new_buffer_var;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_OBJECT:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_ARRAY:
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_DICTIONARY:
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    case PP_VARTYPE_RESOURCE:
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // These types are not supported by PostMessage in-process. In some rare
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // cases with the NaCl plugin, they may be sent but they will be dropped
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // anyway (see crbug.com/318837 for details).
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return PP_MakeUndefined();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NOTREACHED();
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PP_MakeUndefined();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementations of NPClass functions.  These are here to:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Implement postMessage behavior.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Forward calls to the 'passthrough' object to allow backwards-compatibility
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   with GetInstanceObject() objects.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new MessageChannel::MessageChannelNPObject;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageChannelDeallocate(NPObject* object) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageChannel::MessageChannelNPObject* instance =
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<MessageChannel::MessageChannelNPObject*>(object);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete instance;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageChannelHasMethod(NPObject* np_obj, NPIdentifier name) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!np_obj)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only handle a function called postMessage.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IdentifierIsPostMessage(name))
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Other method names we will pass to the passthrough object, if we have one.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* passthrough = ToPassThroughObject(np_obj);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebBindings::hasMethod(NULL, passthrough, name);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const NPVariant* args, uint32 arg_count,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          NPVariant* result) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!np_obj)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only handle a function called postMessage.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IdentifierIsPostMessage(name) && (arg_count == 1)) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageChannel* message_channel = ToMessageChannel(np_obj);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (message_channel) {
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      message_channel->NPVariantToPPVar(&args[0]);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Other method calls we will pass to the passthrough object, if we have one.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* passthrough = ToPassThroughObject(np_obj);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebBindings::invoke(NULL, passthrough, name, args, arg_count,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               result);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageChannelInvokeDefault(NPObject* np_obj,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const NPVariant* args,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 uint32 arg_count,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 NPVariant* result) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!np_obj)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke on the passthrough object, if we have one.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* passthrough = ToPassThroughObject(np_obj);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebBindings::invokeDefault(NULL, passthrough, args, arg_count,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      result);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageChannelHasProperty(NPObject* np_obj, NPIdentifier name) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!np_obj)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MessageChannel* message_channel = ToMessageChannel(np_obj);
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (message_channel) {
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (message_channel->GetReadOnlyProperty(name, NULL))
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return true;
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke on the passthrough object, if we have one.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* passthrough = ToPassThroughObject(np_obj);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebBindings::hasProperty(NULL, passthrough, name);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageChannelGetProperty(NPObject* np_obj, NPIdentifier name,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               NPVariant* result) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!np_obj)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't allow getting the postMessage function.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IdentifierIsPostMessage(name))
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MessageChannel* message_channel = ToMessageChannel(np_obj);
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (message_channel) {
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (message_channel->GetReadOnlyProperty(name, result))
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return true;
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke on the passthrough object, if we have one.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* passthrough = ToPassThroughObject(np_obj);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebBindings::getProperty(NULL, passthrough, name, result);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageChannelSetProperty(NPObject* np_obj, NPIdentifier name,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const NPVariant* variant) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!np_obj)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't allow setting the postMessage function.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IdentifierIsPostMessage(name))
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke on the passthrough object, if we have one.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* passthrough = ToPassThroughObject(np_obj);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebBindings::setProperty(NULL, passthrough, name, variant);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageChannelEnumerate(NPObject *np_obj, NPIdentifier **value,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             uint32_t *count) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!np_obj)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke on the passthrough object, if we have one, to enumerate its
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // properties.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* passthrough = ToPassThroughObject(np_obj);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = WebBindings::enumerate(NULL, passthrough, value, count);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (success) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add postMessage to the list and return it.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (std::numeric_limits<size_t>::max() / sizeof(NPIdentifier) <=
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          static_cast<size_t>(*count) + 1)  // Else, "always false" x64 warning.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NPIdentifier* new_array = static_cast<NPIdentifier*>(
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::malloc(sizeof(NPIdentifier) * (*count + 1)));
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::memcpy(new_array, *value, sizeof(NPIdentifier)*(*count));
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_array[*count] = WebBindings::getStringIdentifier(kPostMessage);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::free(*value);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *value = new_array;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++(*count);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, build an array that includes only postMessage.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier)));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*value)[0] = WebBindings::getStringIdentifier(kPostMessage);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *count = 1;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPClass message_channel_class = {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NP_CLASS_STRUCT_VERSION,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelAllocate,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelDeallocate,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelHasMethod,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelInvoke,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelInvokeDefault,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelHasProperty,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelGetProperty,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelSetProperty,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &MessageChannelEnumerate,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageChannel --------------------------------------------------------------
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct MessageChannel::VarConversionResult {
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  VarConversionResult(const ppapi::ScopedPPVar& r, bool s)
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : result(r),
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        success(s),
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        conversion_completed(true) {}
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  VarConversionResult()
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : success(false),
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        conversion_completed(false) {}
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ppapi::ScopedPPVar result;
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool success;
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool conversion_completed;
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageChannel::MessageChannelNPObject::MessageChannelNPObject() {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageChannel::MessageChannelNPObject::~MessageChannelNPObject() {}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben MurdochMessageChannel::MessageChannel(PepperPluginInstanceImpl* instance)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : instance_(instance),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      passthrough_object_(NULL),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      np_object_(NULL),
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      early_message_queue_state_(QUEUE_MESSAGES),
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now create an NPObject for receiving calls to postMessage. This sets the
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference count to 1.  We release it in the destructor.
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NPObject* obj = WebBindings::createObject(instance_->instanceNPP(),
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            &message_channel_class);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(obj);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  np_object_ = static_cast<MessageChannel::MessageChannelNPObject*>(obj);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void MessageChannel::NPVariantToPPVar(const NPVariant* variant) {
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  converted_var_queue_.push_back(VarConversionResult());
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::list<VarConversionResult>::iterator result_iterator =
3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      --converted_var_queue_.end();
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (variant->type) {
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case NPVariantType_Void:
3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NPVariantToPPVarComplete(result_iterator,
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          ppapi::ScopedPPVar(PP_MakeUndefined()), true);
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case NPVariantType_Null:
3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NPVariantToPPVarComplete(result_iterator,
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          ppapi::ScopedPPVar(PP_MakeNull()), true);
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case NPVariantType_Bool:
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NPVariantToPPVarComplete(result_iterator,
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          ppapi::ScopedPPVar(
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant)))),
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          true);
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case NPVariantType_Int32:
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NPVariantToPPVarComplete(result_iterator,
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          ppapi::ScopedPPVar(
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              PP_MakeInt32(NPVARIANT_TO_INT32(*variant))),
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          true);
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case NPVariantType_Double:
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NPVariantToPPVarComplete(result_iterator,
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          ppapi::ScopedPPVar(
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant))),
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          true);
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case NPVariantType_String:
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NPVariantToPPVarComplete(result_iterator,
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          ppapi::ScopedPPVar(ppapi::ScopedPPVar::PassRef(),
3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                             StringVar::StringToPPVar(
3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 NPVARIANT_TO_STRING(*variant).UTF8Characters,
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 NPVARIANT_TO_STRING(*variant).UTF8Length)),
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          true);
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case NPVariantType_Object: {
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      // shouldn't result in a deep copy.
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant);
371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      V8VarConverter(instance_->pp_instance()).FromV8Value(
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          v8_value, v8::Isolate::GetCurrent()->GetCurrentContext(),
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::Bind(&MessageChannel::NPVariantToPPVarComplete,
374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(), result_iterator));
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NPVariantToPPVarComplete(result_iterator,
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi::ScopedPPVar(PP_MakeUndefined()), false);
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageChannel::PostMessageToJavaScript(PP_Var message_data) {
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  v8::HandleScope scope(v8::Isolate::GetCurrent());
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Because V8 is probably not on the stack for Native->JS calls, we need to
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // enter the appropriate context for the plugin.
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  WebPluginContainer* container = instance_->container();
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It's possible that container() is NULL if the plugin has been removed from
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the DOM (but the PluginInstance is not destroyed yet).
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!container)
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Local<v8::Context> context =
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      container->element().document().frame()->mainWorldScriptContext();
395ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // If the page is being destroyed, the context may be empty.
396ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (context.IsEmpty())
397ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Context::Scope context_scope(context);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  v8::Handle<v8::Value> v8_val;
401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!V8VarConverter(instance_->pp_instance()).ToV8Value(
402424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          message_data, context, &v8_val)) {
4037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(),
4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        PP_LOGLEVEL_ERROR, std::string(), kVarToV8ConversionError);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This is for backward compatibility. It usually makes sense for us to return
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // a string object rather than a string primitive because it allows multiple
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // references to the same string (as with PP_Var strings). However, prior to
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // implementing dictionary and array, vars we would return a string primitive
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // here. Changing it to an object now will break existing code that uses
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // strict comparisons for strings returned from PostMessage. e.g. x === "123"
41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // will no longer return true. So if the only value to return is a string
41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // object, just return the string primitive.
41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (v8_val->IsStringObject())
41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8_val = v8_val->ToString();
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSerializedScriptValue serialized_val =
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebSerializedScriptValue::serialize(v8_val);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (instance_->module()->IsProxied()) {
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (early_message_queue_state_ != SEND_DIRECTLY) {
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // We can't just PostTask here; the messages would arrive out of
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // order. Instead, we queue them up until we're ready to post
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // them.
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      early_message_queue_.push_back(serialized_val);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The proxy sent an asynchronous message, so the plugin is already
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // unblocked. Therefore, there's no need to PostTask.
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(early_message_queue_.size() == 0);
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PostMessageToJavaScriptImpl(serialized_val);
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&MessageChannel::PostMessageToJavaScriptImpl,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   serialized_val));
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageChannel::StopQueueingJavaScriptMessages() {
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We PostTask here instead of draining the message queue directly
44558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  // since we haven't finished initializing the PepperWebPluginImpl yet, so
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the plugin isn't available in the DOM.
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  early_message_queue_state_ = DRAIN_PENDING;
448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&MessageChannel::DrainEarlyMessageQueue,
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageChannel::QueueJavaScriptMessages() {
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (early_message_queue_state_ == DRAIN_PENDING)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    early_message_queue_state_ = DRAIN_CANCELLED;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    early_message_queue_state_ = QUEUE_MESSAGES;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void MessageChannel::NPVariantToPPVarComplete(
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::list<VarConversionResult>::iterator& result_iterator,
4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const ppapi::ScopedPPVar& result,
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    bool success) {
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *result_iterator = VarConversionResult(result, success);
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::list<VarConversionResult>::iterator it = converted_var_queue_.begin();
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  while (it != converted_var_queue_.end() && it->conversion_completed) {
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (it->success) {
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      PostMessageToNative(it->result.get());
4703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else {
4713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      PpapiGlobals::Get()->LogWithSource(instance()->pp_instance(),
4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          PP_LOGLEVEL_ERROR, std::string(), kV8ToVarConversionError);
4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
4743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    converted_var_queue_.erase(it++);
4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageChannel::DrainEarlyMessageQueue() {
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Take a reference on the PluginInstance. This is because JavaScript code
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // may delete the plugin, which would destroy the PluginInstance and its
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // corresponding MessageChannel.
48358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  scoped_refptr<PepperPluginInstanceImpl> instance_ref(instance_);
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (early_message_queue_state_ == DRAIN_CANCELLED) {
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    early_message_queue_state_ = QUEUE_MESSAGES;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(early_message_queue_state_ == DRAIN_PENDING);
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!early_message_queue_.empty()) {
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostMessageToJavaScriptImpl(early_message_queue_.front());
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    early_message_queue_.pop_front();
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  early_message_queue_state_ = SEND_DIRECTLY;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageChannel::PostMessageToJavaScriptImpl(
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSerializedScriptValue& message_data) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(instance_);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPluginContainer* container = instance_->container();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible that container() is NULL if the plugin has been removed from
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the DOM (but the PluginInstance is not destroyed yet).
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!container)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebDOMEvent event =
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      container->element().document().createEvent("MessageEvent");
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg_event.initMessageEvent("message",  // type
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             false,  // canBubble
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             false,  // cancelable
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             message_data,  // data
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "",  // origin [*]
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             NULL,  // source [*]
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "");  // lastEventId
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [*] Note that the |origin| is only specified for cross-document and server-
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     sent messages, while |source| is only specified for cross-document
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     messages:
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     This currently behaves like Web Workers. On Firefox, Chrome, and Safari
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     at least, postMessage on Workers does not provide the origin or source.
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     TODO(dmichael):  Add origin if we change to a more iframe-like origin
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                      policy (see crbug.com/81537)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  container->element().dispatchEvent(msg_event);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageChannel::PostMessageToNative(PP_Var message_data) {
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (instance_->module()->IsProxied()) {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // In the proxied case, the copy will happen via serializiation, and the
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // message is asynchronous. Therefore there's no need to copy the Var, nor
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to PostTask.
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostMessageToNativeImpl(message_data);
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make a copy of the message data for the Task we will run.
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PP_Var var_copy(CopyPPVar(message_data));
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
540b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
541b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        FROM_HERE,
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&MessageChannel::PostMessageToNativeImpl,
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   var_copy));
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageChannel::PostMessageToNativeImpl(PP_Var message_data) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->HandleMessage(message_data);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageChannel::~MessageChannel() {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebBindings::releaseObject(np_object_);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough_object_)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebBindings::releaseObject(passthrough_object_);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageChannel::SetPassthroughObject(NPObject* passthrough) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retain the passthrough object; We need to ensure it lives as long as this
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MessageChannel.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebBindings::retainObject(passthrough);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we had a passthrough set already, release it. Note that we retain the
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // incoming passthrough object first, so that we behave correctly if anyone
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invokes:
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   SetPassthroughObject(passthrough_object());
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (passthrough_object_)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebBindings::releaseObject(passthrough_object_);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  passthrough_object_ = passthrough;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool MessageChannel::GetReadOnlyProperty(NPIdentifier key,
575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         NPVariant *value) const {
576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::map<NPIdentifier, ppapi::ScopedPPVar>::const_iterator it =
577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      internal_properties_.find(key);
578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (it != internal_properties_.end()) {
579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (value)
580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return PPVarToNPVariant(it->second.get(), value);
581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
586f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) {
587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  internal_properties_[PPVarToNPIdentifier(key)] = ppapi::ScopedPPVar(value);
588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
59058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}  // namespace content
591