Replace NPObject usage in ppapi with gin

This replaces usage of NPObject in pepper with gin-backed V8 objects. It is unfortunate that this CL is so large, but there isn't a nice way to have the old implementation and the new one side-by-side.

There are 4 major parts to this CL:
1) Changing the HostVarTracker to track V8ObjectVars rather than NPObjectVars (host_var_tracker.cc).
2) Changing plugin elements (in plugin_object.cc) to be gin-backed objects.
3) Changing postMessage bindings (message_channel.cc) be gin-backed objects.
4) Changing the implementation of PPB_Var_Deprecated (ppb_var_deprecated_impl.cc) to call directly into V8.

BUG=351636

Review URL: https://codereview.chromium.org/459553003

Cr-Commit-Position: refs/heads/master@{#293366}
diff --git a/content/renderer/pepper/ppb_var_deprecated_impl.cc b/content/renderer/pepper/ppb_var_deprecated_impl.cc
index bafbada..a0712778 100644
--- a/content/renderer/pepper/ppb_var_deprecated_impl.cc
+++ b/content/renderer/pepper/ppb_var_deprecated_impl.cc
@@ -7,314 +7,259 @@
 #include <limits>
 
 #include "content/renderer/pepper/host_globals.h"
-#include "content/renderer/pepper/npapi_glue.h"
-#include "content/renderer/pepper/npobject_var.h"
+#include "content/renderer/pepper/message_channel.h"
 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/pepper_try_catch.h"
 #include "content/renderer/pepper/plugin_module.h"
 #include "content/renderer/pepper/plugin_object.h"
+#include "content/renderer/pepper/v8object_var.h"
 #include "ppapi/c/dev/ppb_var_deprecated.h"
 #include "ppapi/c/ppb_var.h"
-#include "ppapi/c/pp_var.h"
 #include "ppapi/shared_impl/ppb_var_shared.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebPluginContainer.h"
 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
 
-using ppapi::NPObjectVar;
+using ppapi::V8ObjectVar;
 using ppapi::PpapiGlobals;
+using ppapi::ScopedPPVar;
+using ppapi::ScopedPPVarArray;
 using ppapi::StringVar;
 using ppapi::Var;
-using blink::WebBindings;
 
 namespace content {
 
 namespace {
 
+const char kInvalidIdentifierException[] = "Error: Invalid identifier.";
 const char kInvalidObjectException[] = "Error: Invalid object";
-const char kInvalidPropertyException[] = "Error: Invalid property";
-const char kInvalidValueException[] = "Error: Invalid value";
-const char kUnableToGetPropertyException[] = "Error: Unable to get property";
-const char kUnableToSetPropertyException[] = "Error: Unable to set property";
-const char kUnableToRemovePropertyException[] =
-    "Error: Unable to remove property";
-const char kUnableToGetAllPropertiesException[] =
-    "Error: Unable to get all properties";
 const char kUnableToCallMethodException[] = "Error: Unable to call method";
-const char kUnableToConstructException[] = "Error: Unable to construct";
 
-// ---------------------------------------------------------------------------
-// Utilities
+class ObjectAccessor {
+ public:
+  ObjectAccessor(PP_Var var)
+      : object_var_(V8ObjectVar::FromPPVar(var)),
+        instance_(object_var_ ? object_var_->instance() : NULL) {
+  }
 
-// Converts the given PP_Var to an NPVariant, returning true on success.
-// False means that the given variant is invalid. In this case, the result
-// NPVariant will be set to a void one.
-//
-// The contents of the PP_Var will NOT be copied, so you need to ensure that
-// the PP_Var remains valid while the resultant NPVariant is in use.
-bool PPVarToNPVariantNoCopy(PP_Var var, NPVariant* result) {
-  switch (var.type) {
-    case PP_VARTYPE_UNDEFINED:
-      VOID_TO_NPVARIANT(*result);
-      break;
-    case PP_VARTYPE_NULL:
-      NULL_TO_NPVARIANT(*result);
-      break;
-    case PP_VARTYPE_BOOL:
-      BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
-      break;
-    case PP_VARTYPE_INT32:
-      INT32_TO_NPVARIANT(var.value.as_int, *result);
-      break;
-    case PP_VARTYPE_DOUBLE:
-      DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
-      break;
-    case PP_VARTYPE_STRING: {
-      StringVar* string = StringVar::FromPPVar(var);
-      if (!string) {
-        VOID_TO_NPVARIANT(*result);
-        return false;
-      }
-      const std::string& value = string->value();
-      STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result);
-      break;
-    }
-    case PP_VARTYPE_OBJECT: {
-      scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
-      if (!object.get()) {
-        VOID_TO_NPVARIANT(*result);
-        return false;
-      }
-      OBJECT_TO_NPVARIANT(object->np_object(), *result);
-      break;
-    }
-    default:
-      VOID_TO_NPVARIANT(*result);
+  // Check if the object is valid. If it isn't, set an exception and return
+  // false.
+  bool IsValid(PP_Var* exception) {
+    // If we already have an exception, then the call is invalid according to
+    // the unittests.
+    if (exception && exception->type != PP_VARTYPE_UNDEFINED)
       return false;
+    if (instance_)
+      return true;
+    if (exception)
+      *exception = ppapi::StringVar::StringToPPVar(kInvalidObjectException);
+    return false;
   }
-  return true;
-}
-
-// ObjectAccessorTryCatch ------------------------------------------------------
-
-// Automatically sets up a TryCatch for accessing the object identified by the
-// given PP_Var. The module from the object will be used for the exception
-// strings generated by the TryCatch.
-//
-// This will automatically retrieve the ObjectVar from the object and throw
-// an exception if it's invalid. At the end of construction, if there is no
-// exception, you know that there is no previously set exception, that the
-// object passed in is valid and ready to use (via the object() getter), and
-// that the TryCatch's pp_module() getter is also set up properly and ready to
-// use.
-class ObjectAccessorTryCatch : public TryCatch {
- public:
-  ObjectAccessorTryCatch(PP_Var object, PP_Var* exception)
-      : TryCatch(exception), object_(NPObjectVar::FromPPVar(object)) {
-    if (!object_.get()) {
-      SetException(kInvalidObjectException);
-    }
-  }
-
-  NPObjectVar* object() { return object_.get(); }
-
-  PepperPluginInstanceImpl* GetPluginInstance() {
-    return HostGlobals::Get()->GetInstance(object()->pp_instance());
-  }
-
- protected:
-  scoped_refptr<NPObjectVar> object_;
-
-  DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch);
-};
-
-// ObjectAccessiorWithIdentifierTryCatch ---------------------------------------
-
-// Automatically sets up a TryCatch for accessing the identifier on the given
-// object. This just extends ObjectAccessorTryCatch to additionally convert
-// the given identifier to an NPIdentifier and validate it, throwing an
-// exception if it's invalid.
-//
-// At the end of construction, if there is no exception, you know that there is
-// no previously set exception, that the object passed in is valid and ready to
-// use (via the object() getter), that the identifier is valid and ready to
-// use (via the identifier() getter), and that the TryCatch's pp_module() getter
-// is also set up properly and ready to use.
-class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch {
- public:
-  ObjectAccessorWithIdentifierTryCatch(PP_Var object,
-                                       PP_Var identifier,
-                                       PP_Var* exception)
-      : ObjectAccessorTryCatch(object, exception), identifier_(0) {
-    if (!has_exception()) {
-      identifier_ = PPVarToNPIdentifier(identifier);
-      if (!identifier_)
-        SetException(kInvalidPropertyException);
-    }
-  }
-
-  NPIdentifier identifier() const { return identifier_; }
+  // Lazily grab the object so that the handle is created in the current handle
+  // scope.
+  v8::Handle<v8::Object> GetObject() { return object_var_->GetHandle(); }
+  PepperPluginInstanceImpl* instance() { return instance_; }
 
  private:
-  NPIdentifier identifier_;
-
-  DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch);
+  V8ObjectVar* object_var_;
+  PepperPluginInstanceImpl* instance_;
 };
 
-PP_Bool HasProperty(PP_Var var, PP_Var name, PP_Var* exception) {
-  ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
-  if (accessor.has_exception())
-    return PP_FALSE;
-  return PP_FromBool(WebBindings::hasProperty(
-      NULL, accessor.object()->np_object(), accessor.identifier()));
+bool IsValidIdentifer(PP_Var identifier, PP_Var* exception) {
+  if (identifier.type == PP_VARTYPE_INT32 ||
+      identifier.type == PP_VARTYPE_STRING) {
+    return true;
+  }
+  if (exception)
+    *exception = ppapi::StringVar::StringToPPVar(kInvalidIdentifierException);
+  return false;
 }
 
 bool HasPropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
-  return PP_ToBool(HasProperty(var, name, exception));
+  ObjectAccessor accessor(var);
+  if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
+    return false;
+
+  PepperTryCatchVar try_catch(accessor.instance(), exception);
+  v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+  if (try_catch.HasException())
+    return false;
+
+  bool result = accessor.GetObject()->Has(v8_name);
+  if (try_catch.HasException())
+    return false;
+  return result;
 }
 
 bool HasMethodDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
-  ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
-  if (accessor.has_exception())
+  ObjectAccessor accessor(var);
+  if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
     return false;
-  return WebBindings::hasMethod(
-      NULL, accessor.object()->np_object(), accessor.identifier());
+
+  PepperTryCatchVar try_catch(accessor.instance(), exception);
+  v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+  if (try_catch.HasException())
+    return false;
+
+  bool result = accessor.GetObject()->Has(v8_name) &&
+      accessor.GetObject()->Get(v8_name)->IsFunction();
+  if (try_catch.HasException())
+    return false;
+  return result;
 }
 
 PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) {
-  ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
-  if (accessor.has_exception())
+  ObjectAccessor accessor(var);
+  if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
     return PP_MakeUndefined();
 
-  NPVariant result;
-  if (!WebBindings::getProperty(NULL,
-                                accessor.object()->np_object(),
-                                accessor.identifier(),
-                                &result)) {
-    // An exception may have been raised.
-    accessor.SetException(kUnableToGetPropertyException);
+  PepperTryCatchVar try_catch(accessor.instance(), exception);
+  v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+  if (try_catch.HasException())
     return PP_MakeUndefined();
-  }
 
-  PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
-  WebBindings::releaseVariantValue(&result);
-  return ret;
+  ScopedPPVar result_var = try_catch.FromV8(accessor.GetObject()->Get(v8_name));
+  if (try_catch.HasException())
+    return PP_MakeUndefined();
+
+  return result_var.Release();
 }
 
 void EnumerateProperties(PP_Var var,
                          uint32_t* property_count,
                          PP_Var** properties,
                          PP_Var* exception) {
+  ObjectAccessor accessor(var);
+  if (!accessor.IsValid(exception))
+    return;
+
+  PepperTryCatchVar try_catch(accessor.instance(), exception);
+
   *properties = NULL;
   *property_count = 0;
 
-  ObjectAccessorTryCatch accessor(var, exception);
-  if (accessor.has_exception())
+  v8::Local<v8::Array> identifiers = accessor.GetObject()->GetPropertyNames();
+  if (try_catch.HasException())
     return;
-
-  NPIdentifier* identifiers = NULL;
-  uint32_t count = 0;
-  if (!WebBindings::enumerate(
-          NULL, accessor.object()->np_object(), &identifiers, &count)) {
-    accessor.SetException(kUnableToGetAllPropertiesException);
-    return;
+  ScopedPPVarArray identifier_vars(identifiers->Length());
+  for (uint32_t i = 0; i < identifiers->Length(); ++i) {
+    ScopedPPVar var = try_catch.FromV8(identifiers->Get(i));
+    if (try_catch.HasException())
+      return;
+    identifier_vars.Set(i, var);
   }
 
-  if (count == 0)
-    return;
-
-  *property_count = count;
-  *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count));
-  for (uint32_t i = 0; i < count; ++i) {
-    (*properties)[i] = NPIdentifierToPPVar(identifiers[i]);
-  }
-  free(identifiers);
+  size_t size = identifier_vars.size();
+  *properties = identifier_vars.Release(
+      ScopedPPVarArray::PassPPBMemoryAllocatedArray());
+  *property_count = size;
 }
 
 void SetPropertyDeprecated(PP_Var var,
                            PP_Var name,
                            PP_Var value,
                            PP_Var* exception) {
-  ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
-  if (accessor.has_exception())
+  ObjectAccessor accessor(var);
+  if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
     return;
 
-  NPVariant variant;
-  if (!PPVarToNPVariantNoCopy(value, &variant)) {
-    accessor.SetException(kInvalidValueException);
+  PepperTryCatchVar try_catch(accessor.instance(), exception);
+  v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+  v8::Handle<v8::Value> v8_value = try_catch.ToV8(value);
+
+  if (try_catch.HasException())
     return;
-  }
-  if (!WebBindings::setProperty(NULL,
-                                accessor.object()->np_object(),
-                                accessor.identifier(),
-                                &variant))
-    accessor.SetException(kUnableToSetPropertyException);
+
+  accessor.GetObject()->Set(v8_name, v8_value);
+  try_catch.HasException();  // Ensure an exception gets set if one occured.
 }
 
 void DeletePropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
-  ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
-  if (accessor.has_exception())
+  ObjectAccessor accessor(var);
+  if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
     return;
 
-  if (!WebBindings::removeProperty(
-          NULL, accessor.object()->np_object(), accessor.identifier()))
-    accessor.SetException(kUnableToRemovePropertyException);
+  PepperTryCatchVar try_catch(accessor.instance(), exception);
+  v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+
+  if (try_catch.HasException())
+    return;
+
+  accessor.GetObject()->Delete(v8_name);
+  try_catch.HasException();  // Ensure an exception gets set if one occured.
 }
 
-PP_Var InternalCallDeprecated(ObjectAccessorTryCatch* accessor,
+PP_Var CallDeprecatedInternal(PP_Var var,
                               PP_Var method_name,
                               uint32_t argc,
                               PP_Var* argv,
                               PP_Var* exception) {
-  NPIdentifier identifier;
+  ObjectAccessor accessor(var);
+  if (!accessor.IsValid(exception))
+    return PP_MakeUndefined();
+
+  // If the method name is undefined, set it to the empty string to trigger
+  // calling |var| as a function.
+  ScopedPPVar scoped_name(method_name);
   if (method_name.type == PP_VARTYPE_UNDEFINED) {
-    identifier = NULL;
-  } else if (method_name.type == PP_VARTYPE_STRING) {
-    // Specifically allow only string functions to be called.
-    identifier = PPVarToNPIdentifier(method_name);
-    if (!identifier) {
-      accessor->SetException(kInvalidPropertyException);
+    scoped_name = ScopedPPVar(ScopedPPVar::PassRef(),
+                                StringVar::StringToPPVar(""));
+  }
+
+  PepperTryCatchVar try_catch(accessor.instance(), exception);
+  v8::Handle<v8::Value> v8_method_name = try_catch.ToV8(scoped_name.get());
+  if (try_catch.HasException())
+    return PP_MakeUndefined();
+
+  if (!v8_method_name->IsString()) {
+    try_catch.SetException(kUnableToCallMethodException);
+    return PP_MakeUndefined();
+  }
+
+  v8::Handle<v8::Object> function = accessor.GetObject();
+  v8::Handle<v8::Object> recv =
+      accessor.instance()->GetContext()->Global();
+  if (v8_method_name.As<v8::String>()->Length() != 0) {
+    function = function->Get(v8_method_name)->ToObject();
+    recv = accessor.GetObject();
+  }
+
+  if (try_catch.HasException())
+    return PP_MakeUndefined();
+
+  if (!function->IsFunction()) {
+    try_catch.SetException(kUnableToCallMethodException);
+    return PP_MakeUndefined();
+  }
+
+  scoped_ptr<v8::Handle<v8::Value>[] > converted_args(
+      new v8::Handle<v8::Value>[argc]);
+  for (uint32_t i = 0; i < argc; ++i) {
+    converted_args[i] = try_catch.ToV8(argv[i]);
+    if (try_catch.HasException())
       return PP_MakeUndefined();
-    }
-  } else {
-    accessor->SetException(kInvalidPropertyException);
+  }
+
+  blink::WebPluginContainer* container = accessor.instance()->container();
+  blink::WebLocalFrame* frame = NULL;
+  if (container)
+    frame = container->element().document().frame();
+
+  if (!frame) {
+    try_catch.SetException("No frame to execute script in.");
     return PP_MakeUndefined();
   }
 
-  scoped_ptr<NPVariant[]> args;
-  if (argc) {
-    args.reset(new NPVariant[argc]);
-    for (uint32_t i = 0; i < argc; ++i) {
-      if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
-        // This argument was invalid, throw an exception & give up.
-        accessor->SetException(kInvalidValueException);
-        return PP_MakeUndefined();
-      }
-    }
-  }
+  v8::Handle<v8::Value> result = frame->callFunctionEvenIfScriptDisabled(
+      function.As<v8::Function>(), recv, argc, converted_args.get());
+  ScopedPPVar result_var = try_catch.FromV8(result);
 
-  bool ok;
-
-  NPVariant result;
-  if (identifier) {
-    ok = WebBindings::invoke(NULL,
-                             accessor->object()->np_object(),
-                             identifier,
-                             args.get(),
-                             argc,
-                             &result);
-  } else {
-    ok = WebBindings::invokeDefault(
-        NULL, accessor->object()->np_object(), args.get(), argc, &result);
-  }
-
-  if (!ok) {
-    // An exception may have been raised.
-    accessor->SetException(kUnableToCallMethodException);
+  if (try_catch.HasException())
     return PP_MakeUndefined();
-  }
 
-  PP_Var ret = NPVariantToPPVar(accessor->GetPluginInstance(), &result);
-  WebBindings::releaseVariantValue(&result);
-  return ret;
+  return result_var.Release();
 }
 
 PP_Var CallDeprecated(PP_Var var,
@@ -322,57 +267,39 @@
                       uint32_t argc,
                       PP_Var* argv,
                       PP_Var* exception) {
-  ObjectAccessorTryCatch accessor(var, exception);
-  if (accessor.has_exception())
-    return PP_MakeUndefined();
-  PepperPluginInstanceImpl* plugin = accessor.GetPluginInstance();
-  if (plugin && plugin->IsProcessingUserGesture()) {
-    blink::WebScopedUserGesture user_gesture(plugin->CurrentUserGestureToken());
-    return InternalCallDeprecated(
-        &accessor, method_name, argc, argv, exception);
+  ObjectAccessor accessor(var);
+  if (accessor.instance() && accessor.instance()->IsProcessingUserGesture()) {
+    blink::WebScopedUserGesture user_gesture(
+        accessor.instance()->CurrentUserGestureToken());
+    return CallDeprecatedInternal(var, method_name, argc, argv, exception);
   }
-  return InternalCallDeprecated(&accessor, method_name, argc, argv, exception);
+  return CallDeprecatedInternal(var, method_name, argc, argv, exception);
 }
 
 PP_Var Construct(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) {
-  ObjectAccessorTryCatch accessor(var, exception);
-  if (accessor.has_exception())
-    return PP_MakeUndefined();
-
-  scoped_ptr<NPVariant[]> args;
-  if (argc) {
-    args.reset(new NPVariant[argc]);
-    for (uint32_t i = 0; i < argc; ++i) {
-      if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
-        // This argument was invalid, throw an exception & give up.
-        accessor.SetException(kInvalidValueException);
-        return PP_MakeUndefined();
-      }
-    }
-  }
-
-  NPVariant result;
-  if (!WebBindings::construct(
-          NULL, accessor.object()->np_object(), args.get(), argc, &result)) {
-    // An exception may have been raised.
-    accessor.SetException(kUnableToConstructException);
-    return PP_MakeUndefined();
-  }
-
-  PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
-  WebBindings::releaseVariantValue(&result);
-  return ret;
+  // Deprecated.
+  NOTREACHED();
+  return PP_MakeUndefined();
 }
 
 bool IsInstanceOfDeprecated(PP_Var var,
                             const PPP_Class_Deprecated* ppp_class,
                             void** ppp_class_data) {
-  scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
+  scoped_refptr<V8ObjectVar> object(V8ObjectVar::FromPPVar(var));
   if (!object.get())
     return false;  // Not an object at all.
 
-  return PluginObject::IsInstanceOf(
-      object->np_object(), ppp_class, ppp_class_data);
+  v8::HandleScope handle_scope(object->instance()->GetIsolate());
+  v8::Context::Scope context_scope(object->instance()->GetContext());
+  PluginObject* plugin_object = PluginObject::FromV8Object(
+      object->instance()->GetIsolate(), object->GetHandle());
+  if (plugin_object && plugin_object->ppp_class() == ppp_class) {
+    if (ppp_class_data)
+      *ppp_class_data = plugin_object->ppp_class_data();
+    return true;
+  }
+
+  return false;
 }
 
 PP_Var CreateObjectDeprecated(PP_Instance pp_instance,