diff options
Diffstat (limited to 'content/plugin/npobject_util.cc')
-rw-r--r-- | content/plugin/npobject_util.cc | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/content/plugin/npobject_util.cc b/content/plugin/npobject_util.cc new file mode 100644 index 0000000..c9a2a68 --- /dev/null +++ b/content/plugin/npobject_util.cc @@ -0,0 +1,273 @@ +// Copyright (c) 2010 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 "content/plugin/npobject_util.h" + +#include "base/string_util.h" +#include "content/common/plugin_messages.h" +#include "content/plugin/npobject_proxy.h" +#include "content/plugin/plugin_channel_base.h" +#include "third_party/npapi/bindings/nphostapi.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" +#include "webkit/plugins/npapi/plugin_host.h" +#include "webkit/glue/webkit_glue.h" + +using WebKit::WebBindings; + +// true if the current process is a plugin process, false if it's a renderer +// process. +static bool g_plugin_process; + +namespace { +// The next 7 functions are called by the plugin code when it's using the +// NPObject. Plugins always ignore the functions in NPClass (except allocate +// and deallocate), and instead just use the function pointers that were +// passed in NPInitialize. +// When the renderer interacts with an NPObject from the plugin, it of course +// uses the function pointers in its NPClass structure. +static bool NPN_HasMethodPatch(NPP npp, + NPObject *npobj, + NPIdentifier methodName) { + return NPObjectProxy::NPHasMethod(npobj, methodName); +} + +static bool NPN_InvokePatch(NPP npp, NPObject *npobj, + NPIdentifier methodName, + const NPVariant *args, + uint32_t argCount, + NPVariant *result) { + return NPObjectProxy::NPInvokePrivate(npp, npobj, false, methodName, args, + argCount, result); +} + +static bool NPN_InvokeDefaultPatch(NPP npp, + NPObject *npobj, + const NPVariant *args, + uint32_t argCount, + NPVariant *result) { + return NPObjectProxy::NPInvokePrivate(npp, npobj, true, 0, args, argCount, + result); +} + +static bool NPN_HasPropertyPatch(NPP npp, + NPObject *npobj, + NPIdentifier propertyName) { + return NPObjectProxy::NPHasProperty(npobj, propertyName); +} + +static bool NPN_GetPropertyPatch(NPP npp, + NPObject *npobj, + NPIdentifier propertyName, + NPVariant *result) { + return NPObjectProxy::NPGetProperty(npobj, propertyName, result); +} + +static bool NPN_SetPropertyPatch(NPP npp, + NPObject *npobj, + NPIdentifier propertyName, + const NPVariant *value) { + return NPObjectProxy::NPSetProperty(npobj, propertyName, value); +} + +static bool NPN_RemovePropertyPatch(NPP npp, + NPObject *npobj, + NPIdentifier propertyName) { + return NPObjectProxy::NPRemoveProperty(npobj, propertyName); +} + +static bool NPN_EvaluatePatch(NPP npp, + NPObject *npobj, + NPString *script, + NPVariant *result) { + return NPObjectProxy::NPNEvaluate(npp, npobj, script, result); +} + + +static void NPN_SetExceptionPatch(NPObject *obj, const NPUTF8 *message) { + std::string message_str(message); + if (IsPluginProcess()) { + PluginChannelBase* renderer_channel = + PluginChannelBase::GetCurrentChannel(); + if (renderer_channel) + renderer_channel->Send(new PluginHostMsg_SetException(message_str)); + } else { + WebBindings::setException(obj, message_str.c_str()); + } +} + +static bool NPN_EnumeratePatch(NPP npp, NPObject *obj, + NPIdentifier **identifier, uint32_t *count) { + return NPObjectProxy::NPNEnumerate(obj, identifier, count); +} + +// The overrided table of functions provided to the plugin. +NPNetscapeFuncs *GetHostFunctions() { + static bool init = false; + static NPNetscapeFuncs host_funcs; + if (init) + return &host_funcs; + + memset(&host_funcs, 0, sizeof(host_funcs)); + host_funcs.invoke = NPN_InvokePatch; + host_funcs.invokeDefault = NPN_InvokeDefaultPatch; + host_funcs.evaluate = NPN_EvaluatePatch; + host_funcs.getproperty = NPN_GetPropertyPatch; + host_funcs.setproperty = NPN_SetPropertyPatch; + host_funcs.removeproperty = NPN_RemovePropertyPatch; + host_funcs.hasproperty = NPN_HasPropertyPatch; + host_funcs.hasmethod = NPN_HasMethodPatch; + host_funcs.setexception = NPN_SetExceptionPatch; + host_funcs.enumerate = NPN_EnumeratePatch; + + init = true; + return &host_funcs; +} + +} + +void PatchNPNFunctions() { + g_plugin_process = true; + NPNetscapeFuncs* funcs = GetHostFunctions(); + webkit::npapi::PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs); +} + +bool IsPluginProcess() { + return g_plugin_process; +} + +void CreateNPIdentifierParam(NPIdentifier id, NPIdentifier_Param* param) { + param->identifier = id; +} + +NPIdentifier CreateNPIdentifier(const NPIdentifier_Param& param) { + return param.identifier; +} + +void CreateNPVariantParam(const NPVariant& variant, + PluginChannelBase* channel, + NPVariant_Param* param, + bool release, + gfx::NativeViewId containing_window, + const GURL& page_url) { + switch (variant.type) { + case NPVariantType_Void: + param->type = NPVARIANT_PARAM_VOID; + break; + case NPVariantType_Null: + param->type = NPVARIANT_PARAM_NULL; + break; + case NPVariantType_Bool: + param->type = NPVARIANT_PARAM_BOOL; + param->bool_value = variant.value.boolValue; + break; + case NPVariantType_Int32: + param->type = NPVARIANT_PARAM_INT; + param->int_value = variant.value.intValue; + break; + case NPVariantType_Double: + param->type = NPVARIANT_PARAM_DOUBLE; + param->double_value = variant.value.doubleValue; + break; + case NPVariantType_String: + param->type = NPVARIANT_PARAM_STRING; + if (variant.value.stringValue.UTF8Length) { + param->string_value.assign(variant.value.stringValue.UTF8Characters, + variant.value.stringValue.UTF8Length); + } + break; + case NPVariantType_Object: { + if (variant.value.objectValue->_class == NPObjectProxy::npclass()) { + param->type = NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID; + NPObjectProxy* proxy = + NPObjectProxy::GetProxy(variant.value.objectValue); + param->npobject_routing_id = proxy->route_id(); + // Don't release, because our original variant is the same as our proxy. + release = false; + } else { + // The channel could be NULL if there was a channel error. The caller's + // Send call will fail anyways. + if (channel) { + // NPObjectStub adds its own reference to the NPObject it owns, so if + // we were supposed to release the corresponding variant + // (release==true), we should still do that. + param->type = NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID; + int route_id = channel->GenerateRouteID(); + new NPObjectStub( + variant.value.objectValue, channel, route_id, containing_window, + page_url); + param->npobject_routing_id = route_id; + } else { + param->type = NPVARIANT_PARAM_VOID; + } + } + break; + } + default: + NOTREACHED(); + } + + if (release) + WebBindings::releaseVariantValue(const_cast<NPVariant*>(&variant)); +} + +bool CreateNPVariant(const NPVariant_Param& param, + PluginChannelBase* channel, + NPVariant* result, + gfx::NativeViewId containing_window, + const GURL& page_url) { + switch (param.type) { + case NPVARIANT_PARAM_VOID: + result->type = NPVariantType_Void; + break; + case NPVARIANT_PARAM_NULL: + result->type = NPVariantType_Null; + break; + case NPVARIANT_PARAM_BOOL: + result->type = NPVariantType_Bool; + result->value.boolValue = param.bool_value; + break; + case NPVARIANT_PARAM_INT: + result->type = NPVariantType_Int32; + result->value.intValue = param.int_value; + break; + case NPVARIANT_PARAM_DOUBLE: + result->type = NPVariantType_Double; + result->value.doubleValue = param.double_value; + break; + case NPVARIANT_PARAM_STRING: + result->type = NPVariantType_String; + result->value.stringValue.UTF8Characters = + static_cast<NPUTF8 *>(base::strdup(param.string_value.c_str())); + result->value.stringValue.UTF8Length = + static_cast<int>(param.string_value.size()); + break; + case NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID: + result->type = NPVariantType_Object; + result->value.objectValue = + NPObjectProxy::Create(channel, + param.npobject_routing_id, + containing_window, + page_url); + break; + case NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID: { + NPObjectBase* npobject_base = + channel->GetNPObjectListenerForRoute(param.npobject_routing_id); + if (!npobject_base) { + DLOG(WARNING) << "Invalid routing id passed in" + << param.npobject_routing_id; + return false; + } + + DCHECK(npobject_base->GetUnderlyingNPObject() != NULL); + + result->type = NPVariantType_Object; + result->value.objectValue = npobject_base->GetUnderlyingNPObject(); + WebBindings::retainObject(result->value.objectValue); + break; + } + default: + NOTREACHED(); + } + return true; +} |