diff options
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 2 | ||||
-rw-r--r-- | webkit/plugins/ppapi/message_channel.cc | 3 | ||||
-rw-r--r-- | webkit/plugins/ppapi/npapi_glue.cc | 69 | ||||
-rw-r--r-- | webkit/plugins/ppapi/npapi_glue.h | 37 | ||||
-rw-r--r-- | webkit/plugins/ppapi/plugin_module.cc | 5 | ||||
-rw-r--r-- | webkit/plugins/ppapi/plugin_object.cc | 7 | ||||
-rw-r--r-- | webkit/plugins/ppapi/plugin_object.h | 4 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppapi_plugin_instance.cc | 36 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppapi_plugin_instance.h | 18 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppb_url_util_impl.cc | 28 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppb_var_impl.cc | 456 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppb_var_impl.h | 23 | ||||
-rw-r--r-- | webkit/plugins/ppapi/resource_tracker.cc | 95 | ||||
-rw-r--r-- | webkit/plugins/ppapi/resource_tracker.h | 18 | ||||
-rw-r--r-- | webkit/plugins/ppapi/resource_tracker_unittest.cc | 11 | ||||
-rw-r--r-- | webkit/plugins/ppapi/var.cc | 526 | ||||
-rw-r--r-- | webkit/plugins/ppapi/var.h | 79 |
17 files changed, 741 insertions, 676 deletions
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index 1573e1d..8db2606 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -296,6 +296,8 @@ '../plugins/ppapi/ppb_url_response_info_impl.h', '../plugins/ppapi/ppb_url_util_impl.cc', '../plugins/ppapi/ppb_url_util_impl.h', + '../plugins/ppapi/ppb_var_impl.cc', + '../plugins/ppapi/ppb_var_impl.h', '../plugins/ppapi/ppb_video_decoder_impl.cc', '../plugins/ppapi/ppb_video_decoder_impl.h', '../plugins/ppapi/ppb_video_layer_impl.cc', diff --git a/webkit/plugins/ppapi/message_channel.cc b/webkit/plugins/ppapi/message_channel.cc index 759f8175..2edfe13 100644 --- a/webkit/plugins/ppapi/message_channel.cc +++ b/webkit/plugins/ppapi/message_channel.cc @@ -150,8 +150,7 @@ bool MessageChannelInvoke(NPObject* np_obj, NPIdentifier name, // We only handle a function called postMessage. if (IdentifierIsPostMessage(name) && (arg_count == 1)) { MessageChannel& message_channel(ToMessageChannel(np_obj)); - PP_Var argument(Var::NPVariantToPPVar(message_channel.instance(), - &args[0])); + PP_Var argument(NPVariantToPPVar(message_channel.instance(), &args[0])); message_channel.PostMessageToNative(argument); return true; } diff --git a/webkit/plugins/ppapi/npapi_glue.cc b/webkit/plugins/ppapi/npapi_glue.cc index ad9f248..2d2c342 100644 --- a/webkit/plugins/ppapi/npapi_glue.cc +++ b/webkit/plugins/ppapi/npapi_glue.cc @@ -10,6 +10,7 @@ #include "webkit/plugins/ppapi/plugin_module.h" #include "webkit/plugins/ppapi/plugin_object.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/resource_tracker.h" #include "webkit/plugins/ppapi/var.h" #include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/npruntime.h" @@ -75,6 +76,68 @@ bool PPVarToNPVariant(PP_Var var, NPVariant* result) { return true; } +PP_Var NPVariantToPPVar(PluginInstance* instance, const NPVariant* variant) { + switch (variant->type) { + case NPVariantType_Void: + return PP_MakeUndefined(); + case NPVariantType_Null: + return PP_MakeNull(); + case NPVariantType_Bool: + return PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant))); + case NPVariantType_Int32: + return PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); + case NPVariantType_Double: + return PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); + case NPVariantType_String: + return StringVar::StringToPPVar( + instance->module()->pp_module(), + NPVARIANT_TO_STRING(*variant).UTF8Characters, + NPVARIANT_TO_STRING(*variant).UTF8Length); + case NPVariantType_Object: + return NPObjectToPPVar(instance, NPVARIANT_TO_OBJECT(*variant)); + } + NOTREACHED(); + return PP_MakeUndefined(); +} + +NPIdentifier PPVarToNPIdentifier(PP_Var var) { + switch (var.type) { + case PP_VARTYPE_STRING: { + scoped_refptr<StringVar> string(StringVar::FromPPVar(var)); + if (!string) + return NULL; + return WebBindings::getStringIdentifier(string->value().c_str()); + } + case PP_VARTYPE_INT32: + return WebBindings::getIntIdentifier(var.value.as_int); + default: + return NULL; + } +} + +PP_Var NPIdentifierToPPVar(PP_Module module, 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 StringVar::StringToPPVar(module, string_value); + + return PP_MakeInt32(int_value); +} + +PP_Var NPObjectToPPVar(PluginInstance* instance, NPObject* object) { + DCHECK(object); + scoped_refptr<ObjectVar> object_var( + ResourceTracker::Get()->ObjectVarForNPObject(instance->pp_instance(), + object)); + if (!object_var) { // No object for this module yet, make a new one. + object_var = new ObjectVar(instance->module()->pp_module(), + instance->pp_instance(), object); + } + return object_var->GetPPVar(); +} + // PPResultAndExceptionToNPResult ---------------------------------------------- PPResultAndExceptionToNPResult::PPResultAndExceptionToNPResult( @@ -166,7 +229,7 @@ PPVarArrayFromNPVariantArray::PPVarArrayFromNPVariantArray( if (size_ > 0) { array_.reset(new PP_Var[size_]); for (size_t i = 0; i < size_; i++) - array_[i] = Var::NPVariantToPPVar(instance, &variants[i]); + array_[i] = NPVariantToPPVar(instance, &variants[i]); } } @@ -178,7 +241,7 @@ PPVarArrayFromNPVariantArray::~PPVarArrayFromNPVariantArray() { // PPVarFromNPObject ----------------------------------------------------------- PPVarFromNPObject::PPVarFromNPObject(PluginInstance* instance, NPObject* object) - : var_(ObjectVar::NPObjectToPPVar(instance, object)) { + : var_(NPObjectToPPVar(instance, object)) { } PPVarFromNPObject::~PPVarFromNPObject() { @@ -194,7 +257,7 @@ NPObjectAccessorWithIdentifier::NPObjectAccessorWithIdentifier( : object_(PluginObject::FromNPObject(object)), identifier_(PP_MakeUndefined()) { if (object_) { - identifier_ = Var::NPIdentifierToPPVar( + identifier_ = NPIdentifierToPPVar( object_->instance()->module()->pp_module(), identifier); if (identifier_.type == PP_VARTYPE_INT32 && !allow_integer_identifier) identifier_.type = PP_VARTYPE_UNDEFINED; // Mark it invalid. diff --git a/webkit/plugins/ppapi/npapi_glue.h b/webkit/plugins/ppapi/npapi_glue.h index f0dfd43..ced0fe6 100644 --- a/webkit/plugins/ppapi/npapi_glue.h +++ b/webkit/plugins/ppapi/npapi_glue.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "ppapi/c/pp_module.h" #include "ppapi/c/pp_var.h" struct NPObject; @@ -30,6 +31,42 @@ class PluginObject; // an object. bool PPVarToNPVariant(PP_Var var, NPVariant* result); +// 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. This will handle all Variant types including POD, strings, and +// objects. +// +// The returned PP_Var will have a refcount of 1, this passing ownership of +// the reference to the caller. This is suitable for returning to a plugin. +PP_Var NPVariantToPPVar(PluginInstance* instance, const NPVariant* variant); + +// Returns a NPIdentifier that corresponds to the given PP_Var. The contents +// of the PP_Var will be copied. Returns 0 if the given PP_Var is not a a +// string or integer type. +NPIdentifier PPVarToNPIdentifier(PP_Var var); + +// Returns a PP_Var corresponding to the given identifier. In the case of +// a string identifier, the string will be allocated associated with the +// given module. A returned string will have a reference count of 1. +PP_Var NPIdentifierToPPVar(PP_Module module, NPIdentifier id); + +// Helper function to create a PP_Var of type object that contains the given +// NPObject for use byt he given module. Calling this function multiple times +// given the same module + NPObject results in the same PP_Var, assuming that +// there is still a PP_Var with a reference open to it from the previous +// call. +// +// The module is necessary because we can have different modules pointing to +// the same NPObject, and we want to keep their refs separate. +// +// If no ObjectVar currently exists corresponding to the NPObject, one is +// created associated with the given module. +// +// Note: this could easily be changed to take a PP_Instance instead if that +// makes certain calls in the future easier. Currently all callers have a +// PluginInstance so that's what we use here. +PP_Var NPObjectToPPVar(PluginInstance* instance, NPObject* object); + // PPResultAndExceptionToNPResult ---------------------------------------------- // Convenience object for converting a PPAPI call that can throw an exception diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc index 6337ad2..bff83f1 100644 --- a/webkit/plugins/ppapi/plugin_module.cc +++ b/webkit/plugins/ppapi/plugin_module.cc @@ -100,6 +100,7 @@ #include "webkit/plugins/ppapi/ppb_scrollbar_impl.h" #include "webkit/plugins/ppapi/ppb_uma_private_impl.h" #include "webkit/plugins/ppapi/ppb_url_util_impl.h" +#include "webkit/plugins/ppapi/ppb_var_impl.h" #include "webkit/plugins/ppapi/ppb_video_decoder_impl.h" #include "webkit/plugins/ppapi/ppb_video_layer_impl.h" #include "webkit/plugins/ppapi/resource_tracker.h" @@ -322,9 +323,9 @@ const void* GetInterface(const char* name) { if (strcmp(name, PPB_URLUTIL_DEV_INTERFACE) == 0) return PPB_URLUtil_Impl::GetInterface(); if (strcmp(name, PPB_VAR_DEPRECATED_INTERFACE) == 0) - return Var::GetDeprecatedInterface(); + return PPB_Var_Impl::GetVarDeprecatedInterface(); if (strcmp(name, PPB_VAR_INTERFACE_1_0) == 0) - return Var::GetInterface(); + return PPB_Var_Impl::GetVarInterface(); if (strcmp(name, PPB_VIDEODECODER_DEV_INTERFACE) == 0) return ::ppapi::thunk::GetPPB_VideoDecoder_Thunk(); if (strcmp(name, PPB_VIDEOLAYER_DEV_INTERFACE) == 0) diff --git a/webkit/plugins/ppapi/plugin_object.cc b/webkit/plugins/ppapi/plugin_object.cc index e24e1b2..b20b9ff 100644 --- a/webkit/plugins/ppapi/plugin_object.cc +++ b/webkit/plugins/ppapi/plugin_object.cc @@ -130,8 +130,7 @@ bool WrapperClass_SetProperty(NPObject* object, NPIdentifier property_name, PPResultAndExceptionToNPResult result_converter( accessor.object()->GetNPObject(), NULL); - PP_Var value_var = Var::NPVariantToPPVar(accessor.object()->instance(), - value); + PP_Var value_var = NPVariantToPPVar(accessor.object()->instance(), value); accessor.object()->ppp_class()->SetProperty( accessor.object()->ppp_class_data(), accessor.identifier(), value_var, result_converter.exception()); @@ -175,7 +174,7 @@ bool WrapperClass_Enumerate(NPObject* object, NPIdentifier** values, malloc(sizeof(NPIdentifier) * property_count)); *count = 0; // Will be the number of items successfully converted. for (uint32_t i = 0; i < property_count; ++i) { - if (!((*values)[i] = Var::PPVarToNPIdentifier(properties[i]))) { + if (!((*values)[i] = PPVarToNPIdentifier(properties[i]))) { // Throw an exception for the failed convertion. *result_converter.exception() = StringVar::StringToPPVar( obj->instance()->module()->pp_module(), kInvalidValueException); @@ -290,7 +289,7 @@ PP_Var PluginObject::Create(PluginInstance* instance, // We can just use a normal ObjectVar to refer to this object from the // plugin. It will hold a ref to the underlying NPObject which will in turn // hold our pluginObject. - PP_Var obj_var(ObjectVar::NPObjectToPPVar(instance, wrapper)); + PP_Var obj_var(NPObjectToPPVar(instance, wrapper)); // Note that the ObjectVar constructor incremented the reference count, and so // did WebBindings::createObject above. Now that the PP_Var has taken diff --git a/webkit/plugins/ppapi/plugin_object.h b/webkit/plugins/ppapi/plugin_object.h index 9f4b607..55d054f 100644 --- a/webkit/plugins/ppapi/plugin_object.h +++ b/webkit/plugins/ppapi/plugin_object.h @@ -19,6 +19,10 @@ namespace ppapi { class PluginInstance; +// A PluginObject is a JS-accessible object implemented by the plugin. +// +// In contrast, a var of type PP_VARTYPE_OBJECT is a reference to a JS object, +// which might be implemented by the plugin (here) or by the JS engine. class PluginObject { public: virtual ~PluginObject(); diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc index 17756c2..44c908f 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc @@ -50,6 +50,7 @@ #include "webkit/plugins/ppapi/event_conversion.h" #include "webkit/plugins/ppapi/fullscreen_container.h" #include "webkit/plugins/ppapi/message_channel.h" +#include "webkit/plugins/ppapi/npapi_glue.h" #include "webkit/plugins/ppapi/plugin_delegate.h" #include "webkit/plugins/ppapi/plugin_module.h" #include "webkit/plugins/ppapi/plugin_object.h" @@ -1304,34 +1305,6 @@ void PluginInstance::RemovePluginObject(PluginObject* plugin_object) { live_plugin_objects_.erase(plugin_object); } -void PluginInstance::AddNPObjectVar(ObjectVar* object_var) { - DCHECK(np_object_to_object_var_.find(object_var->np_object()) == - np_object_to_object_var_.end()) << "ObjectVar already in map"; - np_object_to_object_var_[object_var->np_object()] = object_var; -} - -void PluginInstance::RemoveNPObjectVar(ObjectVar* object_var) { - NPObjectToObjectVarMap::iterator found = - np_object_to_object_var_.find(object_var->np_object()); - if (found == np_object_to_object_var_.end()) { - NOTREACHED() << "ObjectVar not registered."; - return; - } - if (found->second != object_var) { - NOTREACHED() << "ObjectVar doesn't match."; - return; - } - np_object_to_object_var_.erase(found); -} - -ObjectVar* PluginInstance::ObjectVarForNPObject(NPObject* np_object) const { - NPObjectToObjectVarMap::const_iterator found = - np_object_to_object_var_.find(np_object); - if (found == np_object_to_object_var_.end()) - return NULL; - return found->second; -} - bool PluginInstance::IsFullPagePlugin() const { WebFrame* frame = container()->element().document().frame(); return frame->view()->mainFrame()->document().isPluginDocument(); @@ -1424,14 +1397,13 @@ PP_Var PluginInstance::GetWindowObject(PP_Instance instance) { if (!frame) return PP_MakeUndefined(); - return ObjectVar::NPObjectToPPVar(this, frame->windowObject()); + return NPObjectToPPVar(this, frame->windowObject()); } PP_Var PluginInstance::GetOwnerElementObject(PP_Instance instance) { if (!container_) return PP_MakeUndefined(); - return ObjectVar::NPObjectToPPVar(this, - container_->scriptableObjectForElement()); + return NPObjectToPPVar(this, container_->scriptableObjectForElement()); } PP_Var PluginInstance::ExecuteScript(PP_Instance instance, @@ -1471,7 +1443,7 @@ PP_Var PluginInstance::ExecuteScript(PP_Instance instance, return PP_MakeUndefined(); } - PP_Var ret = Var::NPVariantToPPVar(this, &result); + PP_Var ret = NPVariantToPPVar(this, &result); WebBindings::releaseVariantValue(&result); return ret; } diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h index f3e71a2..1380039 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.h +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h @@ -33,7 +33,6 @@ #include "ui/gfx/rect.h" #include "webkit/plugins/ppapi/plugin_delegate.h" -typedef struct NPObject NPObject; struct PP_Var; struct PPP_Find_Dev; struct PPP_InputEvent; @@ -237,18 +236,6 @@ class PluginInstance : public base::RefCounted<PluginInstance>, PluginDelegate::PlatformContext3D* CreateContext3D(); - // Tracks all live ObjectVar. This is so we can map between PluginModule + - // NPObject and get the ObjectVar corresponding to it. This Add/Remove - // function should be called by the ObjectVar when it is created and - // destroyed. - void AddNPObjectVar(ObjectVar* object_var); - void RemoveNPObjectVar(ObjectVar* object_var); - - // Looks up a previously registered ObjectVar for the given NPObject and - // module. Returns NULL if there is no ObjectVar corresponding to the given - // NPObject for the given module. See AddNPObjectVar above. - ObjectVar* ObjectVarForNPObject(NPObject* np_object) const; - // Returns true iff the plugin is a full-page plugin (i.e. not in an iframe or // embedded in a page). bool IsFullPagePlugin() const; @@ -491,11 +478,6 @@ class PluginInstance : public base::RefCounted<PluginInstance>, typedef std::set<PluginObject*> PluginObjectSet; PluginObjectSet live_plugin_objects_; - // Tracks all live ObjectVars used by this module so we can map NPObjects to - // the corresponding object. These are non-owning references. - typedef std::map<NPObject*, ObjectVar*> NPObjectToObjectVarMap; - NPObjectToObjectVarMap np_object_to_object_var_; - // Classes of events that the plugin has registered for, both for filtering // and not. The bits are PP_INPUTEVENT_CLASS_*. uint32_t input_event_mask_; diff --git a/webkit/plugins/ppapi/ppb_url_util_impl.cc b/webkit/plugins/ppapi/ppb_url_util_impl.cc index 64625f4..6791de1 100644 --- a/webkit/plugins/ppapi/ppb_url_util_impl.cc +++ b/webkit/plugins/ppapi/ppb_url_util_impl.cc @@ -18,6 +18,7 @@ #include "webkit/plugins/ppapi/common.h" #include "webkit/plugins/ppapi/plugin_module.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/ppb_var_impl.h" #include "webkit/plugins/ppapi/resource_tracker.h" #include "webkit/plugins/ppapi/string.h" #include "webkit/plugins/ppapi/var.h" @@ -61,7 +62,7 @@ bool SecurityOriginForInstance(PP_Instance instance_id, PP_Var Canonicalize(PP_Var url, PP_URLComponents_Dev* components) { return URLUtilImpl::Canonicalize(&StringFromVar, - Var::GetInterface()->VarFromUtf8, + PPB_Var_Impl::GetVarInterface()->VarFromUtf8, GetModuleFromVar(url), url, components); } @@ -69,10 +70,11 @@ PP_Var Canonicalize(PP_Var url, PP_URLComponents_Dev* components) { PP_Var ResolveRelativeToURL(PP_Var base_url, PP_Var relative, PP_URLComponents_Dev* components) { - return URLUtilImpl::ResolveRelativeToURL(&StringFromVar, - Var::GetInterface()->VarFromUtf8, - GetModuleFromVar(base_url), - base_url, relative, components); + return URLUtilImpl::ResolveRelativeToURL( + &StringFromVar, + PPB_Var_Impl::GetVarInterface()->VarFromUtf8, + GetModuleFromVar(base_url), + base_url, relative, components); } PP_Var ResolveRelativeToDocument(PP_Instance instance_id, @@ -89,7 +91,7 @@ PP_Var ResolveRelativeToDocument(PP_Instance instance_id, WebKit::WebElement plugin_element = instance->container()->element(); GURL document_url = plugin_element.document().baseURL(); return URLUtilImpl::GenerateURLReturn( - Var::GetInterface()->VarFromUtf8, + PPB_Var_Impl::GetVarInterface()->VarFromUtf8, instance->module()->pp_module(), document_url.Resolve(relative_string->value()), components); @@ -134,9 +136,10 @@ PP_Var GetDocumentURL(PP_Instance instance_id, return PP_MakeNull(); WebKit::WebDocument document = instance->container()->element().document(); - return URLUtilImpl::GenerateURLReturn(Var::GetInterface()->VarFromUtf8, - instance->module()->pp_module(), - document.url(), components); + return URLUtilImpl::GenerateURLReturn( + PPB_Var_Impl::GetVarInterface()->VarFromUtf8, + instance->module()->pp_module(), + document.url(), components); } PP_Var GetPluginInstanceURL(PP_Instance instance_id, @@ -146,9 +149,10 @@ PP_Var GetPluginInstanceURL(PP_Instance instance_id, return PP_MakeNull(); const GURL& url = instance->plugin_url(); - return URLUtilImpl::GenerateURLReturn(Var::GetInterface()->VarFromUtf8, - instance->module()->pp_module(), - url, components); + return URLUtilImpl::GenerateURLReturn( + PPB_Var_Impl::GetVarInterface()->VarFromUtf8, + instance->module()->pp_module(), + url, components); } const PPB_URLUtil_Dev ppb_url_util = { diff --git a/webkit/plugins/ppapi/ppb_var_impl.cc b/webkit/plugins/ppapi/ppb_var_impl.cc new file mode 100644 index 0000000..a3cf3d5d --- /dev/null +++ b/webkit/plugins/ppapi/ppb_var_impl.cc @@ -0,0 +1,456 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/plugins/ppapi/ppb_var_impl.h" + +#include <limits> + +#include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/c/ppb_var.h" +#include "ppapi/c/pp_var.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" +#include "webkit/plugins/ppapi/common.h" +#include "webkit/plugins/ppapi/npapi_glue.h" +#include "webkit/plugins/ppapi/plugin_module.h" +#include "webkit/plugins/ppapi/plugin_object.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/resource_tracker.h" +#include "webkit/plugins/ppapi/var.h" +#include "v8/include/v8.h" + +using WebKit::WebBindings; + +namespace webkit { +namespace ppapi { + +namespace { + +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 + +// 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: { + scoped_refptr<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<ObjectVar> object(ObjectVar::FromPPVar(var)); + if (!object) { + VOID_TO_NPVARIANT(*result); + return false; + } + OBJECT_TO_NPVARIANT(object->np_object(), *result); + break; + } + default: + VOID_TO_NPVARIANT(*result); + 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(0, exception), + object_(ObjectVar::FromPPVar(object)) { + if (!object_) { + // No object or an invalid object was given. This means we have no module + // to associated with the exception text, so use the magic invalid object + // exception. + SetInvalidObjectException(); + } else { + // When the object is valid, we have a valid module to associate + set_pp_module(object_->pp_module()); + } + } + + ObjectVar* object() { return object_.get(); } + + PluginInstance* GetPluginInstance() { + return ResourceTracker::Get()->GetInstance(object()->pp_instance()); + } + + protected: + scoped_refptr<ObjectVar> 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_; } + + private: + NPIdentifier identifier_; + + DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); +}; + +// PPB_Var methods ------------------------------------------------------------- + +PP_Var VarFromUtf8(PP_Module module, const char* data, uint32_t len) { + return StringVar::StringToPPVar(module, data, len); +} + +const char* VarToUtf8(PP_Var var, uint32_t* len) { + scoped_refptr<StringVar> str(StringVar::FromPPVar(var)); + if (!str) { + *len = 0; + return NULL; + } + *len = static_cast<uint32_t>(str->value().size()); + if (str->value().empty()) + return ""; // Don't return NULL on success. + return str->value().data(); +} + +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 BoolToPPBool(WebBindings::hasProperty(NULL, + accessor.object()->np_object(), + accessor.identifier())); +} + +bool HasPropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + return PPBoolToBool(HasProperty(var, name, exception)); +} + +bool HasMethodDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) + return false; + return WebBindings::hasMethod(NULL, accessor.object()->np_object(), + accessor.identifier()); +} + +PP_Var GetProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_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); + return PP_MakeUndefined(); + } + + PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); + WebBindings::releaseVariantValue(&result); + return ret; +} + +void EnumerateProperties(PP_Var var, + uint32_t* property_count, + PP_Var** properties, + PP_Var* exception) { + *properties = NULL; + *property_count = 0; + + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) + return; + + NPIdentifier* identifiers = NULL; + uint32_t count = 0; + if (!WebBindings::enumerate(NULL, accessor.object()->np_object(), + &identifiers, &count)) { + accessor.SetException(kUnableToGetAllPropertiesException); + return; + } + + 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( + accessor.GetPluginInstance()->module()->pp_module(), + identifiers[i]); + } + free(identifiers); +} + +void SetPropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var value, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) + return; + + NPVariant variant; + if (!PPVarToNPVariantNoCopy(value, &variant)) { + accessor.SetException(kInvalidValueException); + return; + } + if (!WebBindings::setProperty(NULL, accessor.object()->np_object(), + accessor.identifier(), &variant)) + accessor.SetException(kUnableToSetPropertyException); +} + +void DeletePropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) + return; + + if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(), + accessor.identifier())) + accessor.SetException(kUnableToRemovePropertyException); +} + +PP_Var CallDeprecated(PP_Var var, + PP_Var method_name, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) + return PP_MakeUndefined(); + + NPIdentifier identifier; + 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); + return PP_MakeUndefined(); + } + } else { + accessor.SetException(kInvalidPropertyException); + return PP_MakeUndefined(); + } + + scoped_array<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(); + } + } + } + + 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); + return PP_MakeUndefined(); + } + + PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); + WebBindings::releaseVariantValue(&result); + return ret; +} + +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_array<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; +} + +bool IsInstanceOfDeprecated(PP_Var var, + const PPP_Class_Deprecated* ppp_class, + void** ppp_class_data) { + scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var)); + if (!object) + return false; // Not an object at all. + + return PluginObject::IsInstanceOf(object->np_object(), + ppp_class, ppp_class_data); +} + +PP_Var CreateObjectDeprecated(PP_Instance instance_id, + const PPP_Class_Deprecated* ppp_class, + void* ppp_class_data) { + PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); + if (!instance) { + DLOG(ERROR) << "Create object passed an invalid instance."; + return PP_MakeNull(); + } + return PluginObject::Create(instance, ppp_class, ppp_class_data); +} + +PP_Var CreateObjectWithModuleDeprecated(PP_Module module_id, + const PPP_Class_Deprecated* ppp_class, + void* ppp_class_data) { + PluginModule* module = ResourceTracker::Get()->GetModule(module_id); + if (!module) + return PP_MakeNull(); + return PluginObject::Create(module->GetSomeInstance(), + ppp_class, ppp_class_data); +} + +const PPB_Var_Deprecated var_deprecated_interface = { + &Var::PluginAddRefPPVar, + &Var::PluginReleasePPVar, + &VarFromUtf8, + &VarToUtf8, + &HasPropertyDeprecated, + &HasMethodDeprecated, + &GetProperty, + &EnumerateProperties, + &SetPropertyDeprecated, + &DeletePropertyDeprecated, + &CallDeprecated, + &Construct, + &IsInstanceOfDeprecated, + &CreateObjectDeprecated, + &CreateObjectWithModuleDeprecated, +}; + +const PPB_Var var_interface = { + &Var::PluginAddRefPPVar, + &Var::PluginReleasePPVar, + &VarFromUtf8, + &VarToUtf8 +}; + +} // namespace + +// static +const PPB_Var* PPB_Var_Impl::GetVarInterface() { + return &var_interface; +} + +// static +const PPB_Var_Deprecated* PPB_Var_Impl::GetVarDeprecatedInterface() { + return &var_deprecated_interface; +} + +} // namespace ppapi +} // namespace webkit + diff --git a/webkit/plugins/ppapi/ppb_var_impl.h b/webkit/plugins/ppapi/ppb_var_impl.h new file mode 100644 index 0000000..d2c63a1 --- /dev/null +++ b/webkit/plugins/ppapi/ppb_var_impl.h @@ -0,0 +1,23 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_PLUGINS_PPAPI_PPB_VAR_IMPL_H_ +#define WEBKIT_PLUGINS_PPAPI_PPB_VAR_IMPL_H_ + +struct PPB_Var; +struct PPB_Var_Deprecated; + +namespace webkit { +namespace ppapi { + +class PPB_Var_Impl { + public: + static const PPB_Var* GetVarInterface(); + static const PPB_Var_Deprecated* GetVarDeprecatedInterface(); +}; + +} // namespace ppapi +} // namespace webkit + +#endif // WEBKIT_PLUGINS_PPAPI_PPB_VAR_IMPL_H_ diff --git a/webkit/plugins/ppapi/resource_tracker.cc b/webkit/plugins/ppapi/resource_tracker.cc index edd103b..7e75fe9 100644 --- a/webkit/plugins/ppapi/resource_tracker.cc +++ b/webkit/plugins/ppapi/resource_tracker.cc @@ -58,6 +58,8 @@ namespace { } // namespace +typedef std::map<NPObject*, ObjectVar*> NPObjectToObjectVarMap; + struct ResourceTracker::InstanceData { InstanceData() : instance(0) {} @@ -65,10 +67,14 @@ struct ResourceTracker::InstanceData { // destroyed, it will notify us and we'll delete all associated data. PluginInstance* instance; - // Resources and object vars associated with the instance. + // Resources associated with the instance. ResourceSet ref_resources; std::set<Resource*> assoc_resources; - VarSet object_vars; + + // Tracks all live ObjectVars used by this module so we can map NPObjects to + // the corresponding object, and also release these properly if the instance + // goes away when there are still refs. These are non-owning references. + NPObjectToObjectVarMap np_object_to_object_var; // Lazily allocated function proxies for the different interfaces. scoped_ptr< ::ppapi::FunctionGroupBase > @@ -159,14 +165,6 @@ int32 ResourceTracker::AddVar(Var* var) { int32 new_id = MakeTypedId(++last_var_id_, PP_ID_TYPE_VAR); live_vars_.insert(std::make_pair(new_id, std::make_pair(var, 1))); - // Object vars must be associated with the instance. - ObjectVar* object_var = var->AsObjectVar(); - if (object_var) { - PP_Instance instance = object_var->instance()->pp_instance(); - DCHECK(instance_map_.find(instance) != instance_map_.end()); - instance_map_[instance]->object_vars.insert(new_id); - } - return new_id; } @@ -241,24 +239,23 @@ void ResourceTracker::CleanupInstanceData(PP_Instance instance, } DCHECK(data.ref_resources.empty()); - // Force delete all var references. - VarSet::iterator cur_var = data.object_vars.begin(); - while (cur_var != data.object_vars.end()) { - VarSet::iterator current = cur_var++; - - // Tell the corresponding ObjectVar that the instance is gone. - PP_Var object_pp_var; - object_pp_var.type = PP_VARTYPE_OBJECT; - object_pp_var.value.as_id = *current; - scoped_refptr<ObjectVar> object_var(ObjectVar::FromPPVar(object_pp_var)); - if (object_var.get()) - object_var->InstanceDeleted(); + // Force delete all var references. Need to make a copy so we can iterate over + // the map while deleting stuff from it. + NPObjectToObjectVarMap np_object_map_copy = data.np_object_to_object_var; + NPObjectToObjectVarMap::iterator cur_var = + np_object_map_copy.begin(); + while (cur_var != np_object_map_copy.end()) { + NPObjectToObjectVarMap::iterator current = cur_var++; // Clear the object from the var mapping and the live instance object list. - live_vars_.erase(*current); - data.object_vars.erase(*current); + int32 var_id = current->second->GetExistingVarID(); + if (var_id) + live_vars_.erase(var_id); + + current->second->InstanceDeleted(); + data.np_object_to_object_var.erase(current->first); } - DCHECK(data.object_vars.empty()); + DCHECK(data.np_object_to_object_var.empty()); // Clear any resources that still reference this instance. for (std::set<Resource*>::iterator res = data.assoc_resources.begin(); @@ -277,7 +274,7 @@ uint32 ResourceTracker::GetLiveObjectsForInstance( if (found == instance_map_.end()) return 0; return static_cast<uint32>(found->second->ref_resources.size() + - found->second->object_vars.size()); + found->second->np_object_to_object_var.size()); } ::ppapi::ResourceObjectBase* ResourceTracker::GetResourceAPI( @@ -367,19 +364,51 @@ bool ResourceTracker::UnrefVar(int32 var_id) { << var_id << " is not a PP_Var ID."; VarMap::iterator i = live_vars_.find(var_id); if (i != live_vars_.end()) { - if (!--i->second.second) { - ObjectVar* object_var = i->second.first->AsObjectVar(); - if (object_var) { - instance_map_[object_var->instance()->pp_instance()]->object_vars.erase( - var_id); - } + if (!--i->second.second) live_vars_.erase(i); - } return true; } return false; } +void ResourceTracker::AddNPObjectVar(ObjectVar* object_var) { + DCHECK(instance_map_.find(object_var->pp_instance()) != instance_map_.end()); + InstanceData& data = *instance_map_[object_var->pp_instance()].get(); + + DCHECK(data.np_object_to_object_var.find(object_var->np_object()) == + data.np_object_to_object_var.end()) << "ObjectVar already in map"; + data.np_object_to_object_var[object_var->np_object()] = object_var; +} + +void ResourceTracker::RemoveNPObjectVar(ObjectVar* object_var) { + DCHECK(instance_map_.find(object_var->pp_instance()) != instance_map_.end()); + InstanceData& data = *instance_map_[object_var->pp_instance()].get(); + + NPObjectToObjectVarMap::iterator found = + data.np_object_to_object_var.find(object_var->np_object()); + if (found == data.np_object_to_object_var.end()) { + NOTREACHED() << "ObjectVar not registered."; + return; + } + if (found->second != object_var) { + NOTREACHED() << "ObjectVar doesn't match."; + return; + } + data.np_object_to_object_var.erase(found); +} + +ObjectVar* ResourceTracker::ObjectVarForNPObject(PP_Instance instance, + NPObject* np_object) { + DCHECK(instance_map_.find(instance) != instance_map_.end()); + InstanceData& data = *instance_map_[instance].get(); + + NPObjectToObjectVarMap::iterator found = + data.np_object_to_object_var.find(np_object); + if (found == data.np_object_to_object_var.end()) + return NULL; + return found->second; +} + PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) { DCHECK(instance_map_.find(instance->pp_instance()) == instance_map_.end()); diff --git a/webkit/plugins/ppapi/resource_tracker.h b/webkit/plugins/ppapi/resource_tracker.h index 84669e1..a079c02 100644 --- a/webkit/plugins/ppapi/resource_tracker.h +++ b/webkit/plugins/ppapi/resource_tracker.h @@ -22,9 +22,12 @@ #include "ppapi/shared_impl/function_group_base.h" #include "ppapi/shared_impl/tracker_base.h" +typedef struct NPObject NPObject; + namespace webkit { namespace ppapi { +class ObjectVar; class PluginInstance; class PluginModule; class Resource; @@ -72,6 +75,18 @@ class ResourceTracker : public ::ppapi::TrackerBase { bool AddRefVar(int32 var_id); bool UnrefVar(int32 var_id); + // Tracks all live ObjectVar. This is so we can map between instance + + // NPObject and get the ObjectVar corresponding to it. This Add/Remove + // function is called by the ObjectVar when it is created and + // destroyed. + void AddNPObjectVar(ObjectVar* object_var); + void RemoveNPObjectVar(ObjectVar* object_var); + + // Looks up a previously registered ObjectVar for the given NPObject and + // instance. Returns NULL if there is no ObjectVar corresponding to the given + // NPObject for the given instance. See AddNPObjectVar above. + ObjectVar* ObjectVarForNPObject(PP_Instance instance, NPObject* np_object); + // PP_Modules ---------------------------------------------------------------- // Adds a new plugin module to the list of tracked module, and returns a new @@ -110,9 +125,6 @@ class ResourceTracker : public ::ppapi::TrackerBase { typedef std::set<PP_Resource> ResourceSet; - // Indexed by the var ID. - typedef std::set<int32> VarSet; - // Per-instance data we track. struct InstanceData; diff --git a/webkit/plugins/ppapi/resource_tracker_unittest.cc b/webkit/plugins/ppapi/resource_tracker_unittest.cc index 75ea9983..c1199dd 100644 --- a/webkit/plugins/ppapi/resource_tracker_unittest.cc +++ b/webkit/plugins/ppapi/resource_tracker_unittest.cc @@ -10,6 +10,7 @@ #include "third_party/npapi/bindings/npruntime.h" #include "webkit/plugins/ppapi/mock_plugin_delegate.h" #include "webkit/plugins/ppapi/mock_resource.h" +#include "webkit/plugins/ppapi/npapi_glue.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" #include "webkit/plugins/ppapi/resource_tracker.h" #include "webkit/plugins/ppapi/var.h" @@ -181,7 +182,7 @@ TEST_F(ResourceTrackerTest, DeleteObjectVarWithInstance) { // Make an object var. scoped_ptr<NPObject> npobject(NewTrackedNPObject()); - ObjectVar::NPObjectToPPVar(instance2.get(), npobject.get()); + NPObjectToPPVar(instance2.get(), npobject.get()); EXPECT_EQ(1, g_npobjects_alive); EXPECT_EQ(1u, tracker().GetLiveObjectsForInstance(pp_instance2)); @@ -196,8 +197,8 @@ TEST_F(ResourceTrackerTest, DeleteObjectVarWithInstance) { TEST_F(ResourceTrackerTest, ReuseVar) { scoped_ptr<NPObject> npobject(NewTrackedNPObject()); - PP_Var pp_object1 = ObjectVar::NPObjectToPPVar(instance(), npobject.get()); - PP_Var pp_object2 = ObjectVar::NPObjectToPPVar(instance(), npobject.get()); + PP_Var pp_object1 = NPObjectToPPVar(instance(), npobject.get()); + PP_Var pp_object2 = NPObjectToPPVar(instance(), npobject.get()); // The two results should be the same. EXPECT_EQ(pp_object1.value.as_id, pp_object2.value.as_id); @@ -208,7 +209,7 @@ TEST_F(ResourceTrackerTest, ReuseVar) { { scoped_refptr<ObjectVar> check_object(ObjectVar::FromPPVar(pp_object1)); ASSERT_TRUE(check_object.get()); - EXPECT_EQ(instance(), check_object->instance()); + EXPECT_EQ(instance()->pp_instance(), check_object->pp_instance()); EXPECT_EQ(npobject.get(), check_object->np_object()); } @@ -218,7 +219,7 @@ TEST_F(ResourceTrackerTest, ReuseVar) { // Releasing the resource should free the internal ref, and so making a new // one now should generate a new ID. - PP_Var pp_object3 = ObjectVar::NPObjectToPPVar(instance(), npobject.get()); + PP_Var pp_object3 = NPObjectToPPVar(instance(), npobject.get()); EXPECT_NE(pp_object1.value.as_id, pp_object3.value.as_id); tracker().UnrefVar(static_cast<int32_t>(pp_object3.value.as_id)); } diff --git a/webkit/plugins/ppapi/var.cc b/webkit/plugins/ppapi/var.cc index 98ccc23..b061a55 100644 --- a/webkit/plugins/ppapi/var.cc +++ b/webkit/plugins/ppapi/var.cc @@ -19,431 +19,12 @@ #include "webkit/plugins/ppapi/plugin_object.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" #include "webkit/plugins/ppapi/resource_tracker.h" -#include "v8/include/v8.h" using WebKit::WebBindings; namespace webkit { namespace ppapi { -namespace { - -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 - -// 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: { - scoped_refptr<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<ObjectVar> object(ObjectVar::FromPPVar(var)); - if (!object) { - VOID_TO_NPVARIANT(*result); - return false; - } - OBJECT_TO_NPVARIANT(object->np_object(), *result); - break; - } - default: - VOID_TO_NPVARIANT(*result); - 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(0, exception), - object_(ObjectVar::FromPPVar(object)) { - if (!object_) { - // No object or an invalid object was given. This means we have no module - // to associated with the exception text, so use the magic invalid object - // exception. - SetInvalidObjectException(); - } else { - // When the object is valid, we have a valid module to associate - set_pp_module(object_->pp_module()); - } - } - - ObjectVar* object() { return object_.get(); } - - protected: - scoped_refptr<ObjectVar> 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_ = Var::PPVarToNPIdentifier(identifier); - if (!identifier_) - SetException(kInvalidPropertyException); - } - } - - NPIdentifier identifier() const { return identifier_; } - - private: - NPIdentifier identifier_; - - DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); -}; - -// PPB_Var methods ------------------------------------------------------------- - -PP_Var VarFromUtf8(PP_Module module, const char* data, uint32_t len) { - return StringVar::StringToPPVar(module, data, len); -} - -const char* VarToUtf8(PP_Var var, uint32_t* len) { - scoped_refptr<StringVar> str(StringVar::FromPPVar(var)); - if (!str) { - *len = 0; - return NULL; - } - *len = static_cast<uint32_t>(str->value().size()); - if (str->value().empty()) - return ""; // Don't return NULL on success. - return str->value().data(); -} - -PP_Var BoolToPPVar(bool value) { - return PP_MakeBool(BoolToPPBool(value)); -} - -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 BoolToPPBool(WebBindings::hasProperty(NULL, - accessor.object()->np_object(), - accessor.identifier())); -} - -bool HasPropertyDeprecated(PP_Var var, - PP_Var name, - PP_Var* exception) { - return PPBoolToBool(HasProperty(var, name, exception)); -} - -bool HasMethodDeprecated(PP_Var var, - PP_Var name, - PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_exception()) - return false; - return WebBindings::hasMethod(NULL, accessor.object()->np_object(), - accessor.identifier()); -} - -PP_Var GetProperty(PP_Var var, - PP_Var name, - PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_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); - return PP_MakeUndefined(); - } - - PP_Var ret = Var::NPVariantToPPVar(accessor.object()->instance(), &result); - WebBindings::releaseVariantValue(&result); - return ret; -} - -void EnumerateProperties(PP_Var var, - uint32_t* property_count, - PP_Var** properties, - PP_Var* exception) { - *properties = NULL; - *property_count = 0; - - ObjectAccessorTryCatch accessor(var, exception); - if (accessor.has_exception()) - return; - - NPIdentifier* identifiers = NULL; - uint32_t count = 0; - if (!WebBindings::enumerate(NULL, accessor.object()->np_object(), - &identifiers, &count)) { - accessor.SetException(kUnableToGetAllPropertiesException); - return; - } - - 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] = Var::NPIdentifierToPPVar( - accessor.object()->instance()->module()->pp_module(), - identifiers[i]); - } - free(identifiers); -} - -void SetPropertyDeprecated(PP_Var var, - PP_Var name, - PP_Var value, - PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_exception()) - return; - - NPVariant variant; - if (!PPVarToNPVariantNoCopy(value, &variant)) { - accessor.SetException(kInvalidValueException); - return; - } - if (!WebBindings::setProperty(NULL, accessor.object()->np_object(), - accessor.identifier(), &variant)) - accessor.SetException(kUnableToSetPropertyException); -} - -void DeletePropertyDeprecated(PP_Var var, - PP_Var name, - PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_exception()) - return; - - if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(), - accessor.identifier())) - accessor.SetException(kUnableToRemovePropertyException); -} - -PP_Var CallDeprecated(PP_Var var, - PP_Var method_name, - uint32_t argc, - PP_Var* argv, - PP_Var* exception) { - ObjectAccessorTryCatch accessor(var, exception); - if (accessor.has_exception()) - return PP_MakeUndefined(); - - NPIdentifier identifier; - 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 = Var::PPVarToNPIdentifier(method_name); - if (!identifier) { - accessor.SetException(kInvalidPropertyException); - return PP_MakeUndefined(); - } - } else { - accessor.SetException(kInvalidPropertyException); - return PP_MakeUndefined(); - } - - scoped_array<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(); - } - } - } - - 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); - return PP_MakeUndefined(); - } - - PP_Var ret = Var::NPVariantToPPVar(accessor.object()->instance(), &result); - WebBindings::releaseVariantValue(&result); - return ret; -} - -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_array<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 = Var::NPVariantToPPVar(accessor.object()->instance(), &result); - WebBindings::releaseVariantValue(&result); - return ret; -} - -bool IsInstanceOfDeprecated(PP_Var var, - const PPP_Class_Deprecated* ppp_class, - void** ppp_class_data) { - scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var)); - if (!object) - return false; // Not an object at all. - - return PluginObject::IsInstanceOf(object->np_object(), - ppp_class, ppp_class_data); -} - -PP_Var CreateObjectDeprecated(PP_Instance instance_id, - const PPP_Class_Deprecated* ppp_class, - void* ppp_class_data) { - PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); - if (!instance) { - DLOG(ERROR) << "Create object passed an invalid instance."; - return PP_MakeNull(); - } - return PluginObject::Create(instance, ppp_class, ppp_class_data); -} - -PP_Var CreateObjectWithModuleDeprecated(PP_Module module_id, - const PPP_Class_Deprecated* ppp_class, - void* ppp_class_data) { - PluginModule* module = ResourceTracker::Get()->GetModule(module_id); - if (!module) - return PP_MakeNull(); - return PluginObject::Create(module->GetSomeInstance(), - ppp_class, ppp_class_data); -} - -const PPB_Var_Deprecated var_deprecated_interface = { - &Var::PluginAddRefPPVar, - &Var::PluginReleasePPVar, - &VarFromUtf8, - &VarToUtf8, - &HasPropertyDeprecated, - &HasMethodDeprecated, - &GetProperty, - &EnumerateProperties, - &SetPropertyDeprecated, - &DeletePropertyDeprecated, - &CallDeprecated, - &Construct, - &IsInstanceOfDeprecated, - &CreateObjectDeprecated, - &CreateObjectWithModuleDeprecated, -}; - -const PPB_Var var_interface = { - &Var::PluginAddRefPPVar, - &Var::PluginReleasePPVar, - &VarFromUtf8, - &VarToUtf8 -}; - - -} // namespace - // Var ------------------------------------------------------------------------- Var::Var(PP_Module module) : pp_module_(module), var_id_(0) { @@ -453,61 +34,6 @@ Var::~Var() { } // static -PP_Var Var::NPVariantToPPVar(PluginInstance* instance, - const NPVariant* variant) { - switch (variant->type) { - case NPVariantType_Void: - return PP_MakeUndefined(); - case NPVariantType_Null: - return PP_MakeNull(); - case NPVariantType_Bool: - return BoolToPPVar(NPVARIANT_TO_BOOLEAN(*variant)); - case NPVariantType_Int32: - return PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); - case NPVariantType_Double: - return PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); - case NPVariantType_String: - return StringVar::StringToPPVar( - instance->module()->pp_module(), - NPVARIANT_TO_STRING(*variant).UTF8Characters, - NPVARIANT_TO_STRING(*variant).UTF8Length); - case NPVariantType_Object: - return ObjectVar::NPObjectToPPVar(instance, - NPVARIANT_TO_OBJECT(*variant)); - } - NOTREACHED(); - return PP_MakeUndefined(); -} - -// static -NPIdentifier Var::PPVarToNPIdentifier(PP_Var var) { - switch (var.type) { - case PP_VARTYPE_STRING: { - scoped_refptr<StringVar> string(StringVar::FromPPVar(var)); - if (!string) - return NULL; - return WebBindings::getStringIdentifier(string->value().c_str()); - } - case PP_VARTYPE_INT32: - return WebBindings::getIntIdentifier(var.value.as_int); - default: - return NULL; - } -} - -// static -PP_Var Var::NPIdentifierToPPVar(PP_Module module, 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 StringVar::StringToPPVar(module, string_value); - - return PP_MakeInt32(int_value); -} - -// static std::string Var::PPVarToLogString(PP_Var var) { switch (var.type) { case PP_VARTYPE_UNDEFINED: @@ -555,15 +81,6 @@ void Var::PluginReleasePPVar(PP_Var var) { } } -// static -const PPB_Var_Deprecated* Var::GetDeprecatedInterface() { - return &var_deprecated_interface; -} - -const PPB_Var* Var::GetInterface() { - return &var_interface; -} - StringVar* Var::AsStringVar() { return NULL; } @@ -572,7 +89,11 @@ ObjectVar* Var::AsObjectVar() { return NULL; } -int32 Var::GetID() { +int32 Var::GetExistingVarID() const { + return var_id_; +} + +int32 Var::GetOrCreateVarID() { ResourceTracker *tracker = ResourceTracker::Get(); if (var_id_) { if (!tracker->AddRefVar(var_id_)) @@ -600,7 +121,7 @@ StringVar* StringVar::AsStringVar() { } PP_Var StringVar::GetPPVar() { - int32 id = GetID(); + int32 id = GetOrCreateVarID(); if (!id) return PP_MakeNull(); @@ -635,19 +156,22 @@ scoped_refptr<StringVar> StringVar::FromPPVar(PP_Var var) { return scoped_refptr<StringVar>(var_object->AsStringVar()); } -// ObjectVar ------------------------------------------------------------- +// ObjectVar ------------------------------------------------------------------- -ObjectVar::ObjectVar(PluginInstance* instance, NPObject* np_object) - : Var(instance->module()->pp_module()), - instance_(instance), +ObjectVar::ObjectVar(PP_Module module, + PP_Instance instance, + NPObject* np_object) + : Var(module), + pp_instance_(instance), np_object_(np_object) { WebBindings::retainObject(np_object_); - instance->AddNPObjectVar(this); + ResourceTracker::Get()->AddNPObjectVar(this); } ObjectVar::~ObjectVar() { - if (instance_) - instance_->RemoveNPObjectVar(this); + if (pp_instance_) + ResourceTracker::Get()->RemoveNPObjectVar(this); + WebBindings::releaseObject(np_object_); } @@ -656,7 +180,7 @@ ObjectVar* ObjectVar::AsObjectVar() { } PP_Var ObjectVar::GetPPVar() { - int32 id = GetID(); + int32 id = GetOrCreateVarID(); if (!id) return PP_MakeNull(); @@ -667,20 +191,8 @@ PP_Var ObjectVar::GetPPVar() { } void ObjectVar::InstanceDeleted() { - DCHECK(instance_); - instance_ = NULL; -} - -// static -PP_Var ObjectVar::NPObjectToPPVar(PluginInstance* instance, NPObject* object) { - DCHECK(object); - scoped_refptr<ObjectVar> object_var(instance->ObjectVarForNPObject(object)); - if (!object_var) // No object for this module yet, make a new one. - object_var = new ObjectVar(instance, object); - - if (!object_var) - return PP_MakeUndefined(); - return object_var->GetPPVar(); + DCHECK(pp_instance_); + pp_instance_ = NULL; } // static diff --git a/webkit/plugins/ppapi/var.h b/webkit/plugins/ppapi/var.h index 730d87e..edbcec7 100644 --- a/webkit/plugins/ppapi/var.h +++ b/webkit/plugins/ppapi/var.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_module.h" struct PP_Var; @@ -22,7 +23,6 @@ namespace webkit { namespace ppapi { class ObjectVar; -class PluginInstance; class StringVar; // Var ------------------------------------------------------------------------- @@ -34,26 +34,6 @@ class Var : public base::RefCounted<Var> { public: virtual ~Var(); - // 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. This will handle all Variant types including POD, strings, and - // objects. - // - // The returned PP_Var will have a refcount of 1, this passing ownership of - // the reference to the caller. This is suitable for returning to a plugin. - static PP_Var NPVariantToPPVar(PluginInstance* instance, - const NPVariant* variant); - - // Returns a NPIdentifier that corresponds to the given PP_Var. The contents - // of the PP_Var will be copied. Returns 0 if the given PP_Var is not a a - // string or integer type. - static NPIdentifier PPVarToNPIdentifier(PP_Var var); - - // Returns a PP_Var corresponding to the given identifier. In the case of - // a string identifier, the string will be allocated associated with the - // given module. A returned string will have a reference count of 1. - static PP_Var NPIdentifierToPPVar(PP_Module module, NPIdentifier id); - // Returns a string representing the given var for logging purposes. static std::string PPVarToLogString(PP_Var var); @@ -87,12 +67,6 @@ class Var : public base::RefCounted<Var> { static void PluginAddRefPPVar(PP_Var var); static void PluginReleasePPVar(PP_Var var); - // Returns the PPB_Var_Deprecated interface for the plugin to use. - static const PPB_Var_Deprecated* GetDeprecatedInterface(); - - // Returns the PPB_Var interface for the plugin to use. - static const PPB_Var* GetInterface(); - virtual StringVar* AsStringVar(); virtual ObjectVar* AsObjectVar(); @@ -100,18 +74,27 @@ class Var : public base::RefCounted<Var> { // one reference addrefed on behalf of the caller. virtual PP_Var GetPPVar() = 0; + // Returns the ID corresponing to the string or object if it exists already, + // or 0 if an ID hasn't been generated for this object (the plugin is holding + // no refs). + // + // Contrast to GetOrCreateVarID which creates the ID and a ref on behalf of + // the plugin. + int32 GetExistingVarID() const; + PP_Module pp_module() const { return pp_module_; } protected: // This can only be constructed as a StringVar or an ObjectVar. explicit Var(PP_Module module); - // Returns the unique ID associated with this string or object. The return - // value will be 0 if the string or object is invalid. + // Returns the unique ID associated with this string or object, creating it + // if necessary. The return value will be 0 if the string or object is + // invalid. // // This function will take a reference to the var that will be passed to the // caller. - int32 GetID(); + int32 GetOrCreateVarID(); private: PP_Module pp_module_; @@ -179,6 +162,11 @@ class StringVar : public Var { // strings. class ObjectVar : public Var { public: + // You should always use FromNPObject to create an ObjectVar. This function + // guarantees that we maintain the 1:1 mapping between NPObject and + // ObjectVar. + ObjectVar(PP_Module module, PP_Instance instance, NPObject* np_object); + virtual ~ObjectVar(); // Var overrides. @@ -189,39 +177,20 @@ class ObjectVar : public Var { // Guaranteed non-NULL. NPObject* np_object() const { return np_object_; } - // Notification that the instance was deleted, the internal pointer will be - // NULLed out. + // Notification that the instance was deleted, the internal reference will be + // zeroed out. void InstanceDeleted(); - // Possibly NULL if the object has outlived its instance. - PluginInstance* instance() const { return instance_; } - - // Helper function to create a PP_Var of type object that contains the given - // NPObject for use byt he given module. Calling this function multiple times - // given the same module + NPObject results in the same PP_Var, assuming that - // there is still a PP_Var with a reference open to it from the previous - // call. - // - // The module is necessary because we can have different modules pointing to - // the same NPObject, and we want to keep their refs separate. - // - // If no ObjectVar currently exists corresponding to the NPObject, one is - // created associated with the given module. - static PP_Var NPObjectToPPVar(PluginInstance* instance, NPObject* object); + // Possibly 0 if the object has outlived its instance. + PP_Instance pp_instance() const { return pp_instance_; } // Helper function that converts a PP_Var to an object. This will return NULL // if the PP_Var is not of object type or the object is invalid. static scoped_refptr<ObjectVar> FromPPVar(PP_Var var); - protected: - // You should always use FromNPObject to create an ObjectVar. This function - // guarantees that we maintain the 1:1 mapping between NPObject and - // ObjectVar. - ObjectVar(PluginInstance* instance, NPObject* np_object); - private: - // Possibly NULL if the object has outlived its instance. - PluginInstance* instance_; + // Possibly 0 if the object has outlived its instance. + PP_Instance pp_instance_; // Guaranteed non-NULL, this is the underlying object used by WebKit. We // hold a reference to this object. |