| Index: webkit/glue/plugins/pepper_var.cc | 
| =================================================================== | 
| --- webkit/glue/plugins/pepper_var.cc	(revision 47777) | 
| +++ webkit/glue/plugins/pepper_var.cc	(working copy) | 
| @@ -9,6 +9,7 @@ | 
| #include "base/string_util.h" | 
| #include "third_party/ppapi/c/pp_var.h" | 
| #include "third_party/ppapi/c/ppb_var.h" | 
| +#include "third_party/ppapi/c/ppp_class.h" | 
| #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" | 
| #include "webkit/glue/plugins/pepper_string.h" | 
| #include "v8/include/v8.h" | 
| @@ -22,6 +23,7 @@ | 
|  | 
| namespace { | 
|  | 
| +void Release(PP_Var var); | 
| PP_Var VarFromUtf8(const char* data, uint32_t len); | 
|  | 
| // --------------------------------------------------------------------------- | 
| @@ -78,6 +80,12 @@ | 
| return reinterpret_cast<String*>(var.value.as_id); | 
| } | 
|  | 
| +String* GetString(PP_Var var) { | 
| +  if (var.type != PP_VarType_String) | 
| +    return NULL; | 
| +  return GetStringUnchecked(var); | 
| +} | 
| + | 
| NPObject* GetNPObjectUnchecked(PP_Var var) { | 
| return reinterpret_cast<NPObject*>(var.value.as_id); | 
| } | 
| @@ -90,7 +98,7 @@ | 
|  | 
| // Returns a PP_Var that corresponds to the given NPVariant.  The contents of | 
| // the NPVariant will be copied unless the NPVariant corresponds to an object. | 
| -PP_Var NPVariantToPPVar(NPVariant* variant) { | 
| +PP_Var NPVariantToPPVar(const NPVariant* variant) { | 
| switch (variant->type) { | 
| case NPVariantType_Void: | 
| return PP_MakeVoid(); | 
| @@ -195,7 +203,273 @@ | 
| } | 
| } | 
|  | 
| +PP_Var NPIdentifierToPPVar(NPIdentifier id) { | 
| +  const NPUTF8* string_value = NULL; | 
| +  int32_t int_value = 0; | 
| +  bool is_string = false; | 
| +  WebBindings::extractIdentifierData(id, string_value, int_value, is_string); | 
| +  if (is_string) | 
| +    return VarFromUtf8(string_value, strlen(string_value)); | 
| + | 
| +  return PP_MakeInt32(int_value); | 
| +} | 
| + | 
| +PP_Var NPIdentifierToPPVarString(NPIdentifier id) { | 
| +  PP_Var var = NPIdentifierToPPVar(id); | 
| +  if (var.type == PP_VarType_String) | 
| +    return var; | 
| +  DCHECK(var.type == PP_VarType_Int32); | 
| +  const std::string& str = IntToString(var.value.as_int); | 
| +  return VarFromUtf8(str.data(), str.size()); | 
| +} | 
| + | 
| +void ThrowException(NPObject* object, PP_Var exception) { | 
| +  String* str = GetString(exception); | 
| +  if (str) | 
| +    WebBindings::setException(object, str->value().c_str()); | 
| +} | 
| + | 
| // --------------------------------------------------------------------------- | 
| +// NPObject implementation in terms of PPP_Class | 
| + | 
| +struct WrapperObject : NPObject { | 
| +  const PPP_Class* ppp_class; | 
| +  void* ppp_class_data; | 
| +}; | 
| + | 
| +static WrapperObject* ToWrapper(NPObject* object) { | 
| +  return static_cast<WrapperObject*>(object); | 
| +} | 
| + | 
| +NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) { | 
| +  return new WrapperObject; | 
| +} | 
| + | 
| +void WrapperClass_Deallocate(NPObject* object) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| +  wrapper->ppp_class->Deallocate(wrapper->ppp_class_data); | 
| +  delete object; | 
| +} | 
| + | 
| +void WrapperClass_Invalidate(NPObject* object) { | 
| +  // TODO(darin): Do I need to do something here? | 
| +} | 
| + | 
| +bool WrapperClass_HasMethod(NPObject* object, NPIdentifier method_name) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  PP_Var method_name_var = NPIdentifierToPPVarString(method_name); | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  bool rv = wrapper->ppp_class->HasMethod(wrapper->ppp_class_data, | 
| +                                          method_name_var, | 
| +                                          &exception); | 
| +  Release(method_name_var); | 
| + | 
| +  if (exception.type != PP_VarType_Void) { | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +    return false; | 
| +  } | 
| +  return rv; | 
| +} | 
| + | 
| +bool WrapperClass_Invoke(NPObject* object, NPIdentifier method_name, | 
| +                         const NPVariant* argv, uint32_t argc, | 
| +                         NPVariant* result) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  scoped_array<PP_Var> args; | 
| +  if (argc) { | 
| +    args.reset(new PP_Var[argc]); | 
| +    for (uint32_t i = 0; i < argc; ++i) | 
| +      args[i] = NPVariantToPPVar(&argv[i]); | 
| +  } | 
| +  PP_Var method_name_var = NPIdentifierToPPVarString(method_name); | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  PP_Var result_var = wrapper->ppp_class->Call(wrapper->ppp_class_data, | 
| +                                               method_name_var, argc, | 
| +                                               args.get(), &exception); | 
| +  Release(method_name_var); | 
| +  for (uint32_t i = 0; i < argc; ++i) | 
| +    Release(args[i]); | 
| + | 
| +  bool rv; | 
| +  if (exception.type == PP_VarType_Void) { | 
| +    rv = true; | 
| +    *result = PPVarToNPVariant(result_var); | 
| +  } else { | 
| +    rv = false; | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +  } | 
| +  Release(result_var); | 
| +  return rv; | 
| +} | 
| + | 
| +bool WrapperClass_InvokeDefault(NPObject* object, const NPVariant* argv, | 
| +                                uint32_t argc, NPVariant* result) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  scoped_array<PP_Var> args; | 
| +  if (argc) { | 
| +    args.reset(new PP_Var[argc]); | 
| +    for (uint32_t i = 0; i < argc; ++i) | 
| +      args[i] = NPVariantToPPVar(&argv[i]); | 
| +  } | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  PP_Var result_var = wrapper->ppp_class->Call(wrapper->ppp_class_data, | 
| +                                               PP_MakeVoid(), argc, args.get(), | 
| +                                               &exception); | 
| +  for (uint32_t i = 0; i < argc; ++i) | 
| +    Release(args[i]); | 
| + | 
| +  bool rv; | 
| +  if (exception.type == PP_VarType_Void) { | 
| +    rv = true; | 
| +    *result = PPVarToNPVariant(result_var); | 
| +  } else { | 
| +    rv = false; | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +  } | 
| +  Release(result_var); | 
| +  return rv; | 
| +} | 
| + | 
| +bool WrapperClass_HasProperty(NPObject* object, NPIdentifier property_name) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  PP_Var property_name_var = NPIdentifierToPPVar(property_name); | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  bool rv = wrapper->ppp_class->HasProperty(wrapper->ppp_class_data, | 
| +                                            property_name_var, | 
| +                                            &exception); | 
| +  Release(property_name_var); | 
| + | 
| +  if (exception.type != PP_VarType_Void) { | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +    return false; | 
| +  } | 
| +  return rv; | 
| +} | 
| + | 
| +bool WrapperClass_GetProperty(NPObject* object, NPIdentifier property_name, | 
| +                              NPVariant* result) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  PP_Var property_name_var = NPIdentifierToPPVar(property_name); | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  PP_Var result_var = wrapper->ppp_class->GetProperty(wrapper->ppp_class_data, | 
| +                                                      property_name_var, | 
| +                                                      &exception); | 
| +  Release(property_name_var); | 
| + | 
| +  bool rv; | 
| +  if (exception.type == PP_VarType_Void) { | 
| +    rv = true; | 
| +    *result = PPVarToNPVariant(result_var); | 
| +  } else { | 
| +    rv = false; | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +  } | 
| +  Release(result_var); | 
| +  return rv; | 
| +} | 
| + | 
| +bool WrapperClass_SetProperty(NPObject* object, NPIdentifier property_name, | 
| +                              const NPVariant* value) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  PP_Var property_name_var = NPIdentifierToPPVar(property_name); | 
| +  PP_Var value_var = NPVariantToPPVar(value); | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  wrapper->ppp_class->SetProperty(wrapper->ppp_class_data, property_name_var, | 
| +                                  value_var, &exception); | 
| +  Release(value_var); | 
| +  Release(property_name_var); | 
| + | 
| +  if (exception.type != PP_VarType_Void) { | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +    return false; | 
| +  } | 
| +  return true; | 
| +} | 
| + | 
| +bool WrapperClass_RemoveProperty(NPObject* object, NPIdentifier property_name) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  PP_Var property_name_var = NPIdentifierToPPVar(property_name); | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  wrapper->ppp_class->RemoveProperty(wrapper->ppp_class_data, property_name_var, | 
| +                                     &exception); | 
| +  Release(property_name_var); | 
| + | 
| +  if (exception.type != PP_VarType_Void) { | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +    return false; | 
| +  } | 
| +  return true; | 
| +} | 
| + | 
| +bool WrapperClass_Enumerate(NPObject* object, NPIdentifier** values, | 
| +                            uint32_t* count) { | 
| +  // TODO(darin): Implement this method! | 
| +  WebBindings::setException(object, kUnableToGetAllPropertiesException); | 
| +  return false; | 
| +} | 
| + | 
| +bool WrapperClass_Construct(NPObject* object, const NPVariant* argv, | 
| +                            uint32_t argc, NPVariant* result) { | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| + | 
| +  scoped_array<PP_Var> args; | 
| +  if (argc) { | 
| +    args.reset(new PP_Var[argc]); | 
| +    for (uint32_t i = 0; i < argc; ++i) | 
| +      args[i] = NPVariantToPPVar(&argv[i]); | 
| +  } | 
| + | 
| +  PP_Var exception = PP_MakeVoid(); | 
| +  PP_Var result_var = wrapper->ppp_class->Construct(wrapper->ppp_class_data, | 
| +                                                    argc, args.get(), | 
| +                                                    &exception); | 
| +  for (uint32_t i = 0; i < argc; ++i) | 
| +    Release(args[i]); | 
| + | 
| +  bool rv; | 
| +  if (exception.type == PP_VarType_Void) { | 
| +    rv = true; | 
| +    *result = PPVarToNPVariant(result_var); | 
| +  } else { | 
| +    rv = false; | 
| +    ThrowException(object, exception); | 
| +    Release(exception); | 
| +  } | 
| +  Release(result_var); | 
| +  return rv; | 
| +} | 
| + | 
| +const NPClass wrapper_class = { | 
| +  NP_CLASS_STRUCT_VERSION, | 
| +  WrapperClass_Allocate, | 
| +  WrapperClass_Deallocate, | 
| +  WrapperClass_Invalidate, | 
| +  WrapperClass_HasMethod, | 
| +  WrapperClass_Invoke, | 
| +  WrapperClass_InvokeDefault, | 
| +  WrapperClass_HasProperty, | 
| +  WrapperClass_GetProperty, | 
| +  WrapperClass_SetProperty, | 
| +  WrapperClass_RemoveProperty, | 
| +  WrapperClass_Enumerate, | 
| +  WrapperClass_Construct | 
| +}; | 
| + | 
| +// --------------------------------------------------------------------------- | 
| // PPB_Var methods | 
|  | 
| void AddRef(PP_Var var) { | 
| @@ -259,6 +533,28 @@ | 
| return WebBindings::hasProperty(NULL, object, identifier); | 
| } | 
|  | 
| +bool HasMethod(PP_Var var, | 
| +               PP_Var name, | 
| +               PP_Var* exception) { | 
| +  TryCatch try_catch(exception); | 
| +  if (try_catch.HasException()) | 
| +    return false; | 
| + | 
| +  NPObject* object = GetNPObject(var); | 
| +  if (!object) { | 
| +    try_catch.SetException(kInvalidObjectException); | 
| +    return false; | 
| +  } | 
| + | 
| +  NPIdentifier identifier = PPVarToNPIdentifier(name); | 
| +  if (!identifier) { | 
| +    try_catch.SetException(kInvalidPropertyException); | 
| +    return false; | 
| +  } | 
| + | 
| +  return WebBindings::hasMethod(NULL, object, identifier); | 
| +} | 
| + | 
| PP_Var GetProperty(PP_Var var, | 
| PP_Var name, | 
| PP_Var* exception) { | 
| @@ -444,23 +740,48 @@ | 
| return ret; | 
| } | 
|  | 
| -PP_Var CreateObject(const PPP_Class* object_class, | 
| -                    void* object_data) { | 
| -  return PP_MakeVoid();  // TODO(darin): Implement this method! | 
| +bool IsInstanceOf(PP_Var var, const PPP_Class* ppp_class, | 
| +                  void** ppp_class_data) { | 
| +  NPObject* object = GetNPObject(var); | 
| +  if (!object) | 
| +    return false; | 
| + | 
| +  if (object->_class != &wrapper_class) | 
| +    return false; | 
| + | 
| +  WrapperObject* wrapper = ToWrapper(object); | 
| +  if (wrapper->ppp_class != ppp_class) | 
| +    return false; | 
| + | 
| +  if (ppp_class_data) | 
| +    *ppp_class_data = wrapper->ppp_class_data; | 
| +  return true; | 
| } | 
|  | 
| +PP_Var CreateObject(const PPP_Class* ppp_class, void* ppp_class_data) { | 
| +  NPObject* object = | 
| +      WebBindings::createObject(NULL, const_cast<NPClass*>(&wrapper_class)); | 
| +  static_cast<WrapperObject*>(object)->ppp_class = ppp_class; | 
| +  static_cast<WrapperObject*>(object)->ppp_class_data = ppp_class_data; | 
| +  PP_Var ret = NPObjectToPPVar(object); | 
| +  WebBindings::releaseObject(object);  // Release reference from createObject | 
| +  return ret; | 
| +} | 
| + | 
| const PPB_Var var_interface = { | 
| &AddRef, | 
| &Release, | 
| &VarFromUtf8, | 
| &VarToUtf8, | 
| &HasProperty, | 
| +  &HasMethod, | 
| &GetProperty, | 
| &GetAllPropertyNames, | 
| &SetProperty, | 
| &RemoveProperty, | 
| &Call, | 
| &Construct, | 
| +  &IsInstanceOf, | 
| &CreateObject | 
| }; | 
|  | 
|  |