1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/npobject_util.h"
7 #include "base/string_util.h"
8 #include "content/common/np_channel_base.h"
9 #include "content/common/npobject_proxy.h"
10 #include "content/common/plugin_messages.h"
11 #include "third_party/npapi/bindings/nphostapi.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
13 #include "webkit/plugins/npapi/plugin_host.h"
14 #include "webkit/glue/webkit_glue.h"
16 using WebKit::WebBindings
;
20 // true if the current process is a plugin process, false otherwise.
21 static bool g_plugin_process
;
24 // The next 7 functions are called by the plugin code when it's using the
25 // NPObject. Plugins always ignore the functions in NPClass (except allocate
26 // and deallocate), and instead just use the function pointers that were
27 // passed in NPInitialize.
28 // When the renderer interacts with an NPObject from the plugin, it of course
29 // uses the function pointers in its NPClass structure.
30 static bool NPN_HasMethodPatch(NPP npp
,
32 NPIdentifier methodName
) {
33 return NPObjectProxy::NPHasMethod(npobj
, methodName
);
36 static bool NPN_InvokePatch(NPP npp
, NPObject
*npobj
,
37 NPIdentifier methodName
,
38 const NPVariant
*args
,
41 return NPObjectProxy::NPInvokePrivate(npp
, npobj
, false, methodName
, args
,
45 static bool NPN_InvokeDefaultPatch(NPP npp
,
47 const NPVariant
*args
,
50 return NPObjectProxy::NPInvokePrivate(npp
, npobj
, true, 0, args
, argCount
,
54 static bool NPN_HasPropertyPatch(NPP npp
,
56 NPIdentifier propertyName
) {
57 return NPObjectProxy::NPHasProperty(npobj
, propertyName
);
60 static bool NPN_GetPropertyPatch(NPP npp
,
62 NPIdentifier propertyName
,
64 return NPObjectProxy::NPGetProperty(npobj
, propertyName
, result
);
67 static bool NPN_SetPropertyPatch(NPP npp
,
69 NPIdentifier propertyName
,
70 const NPVariant
*value
) {
71 return NPObjectProxy::NPSetProperty(npobj
, propertyName
, value
);
74 static bool NPN_RemovePropertyPatch(NPP npp
,
76 NPIdentifier propertyName
) {
77 return NPObjectProxy::NPRemoveProperty(npobj
, propertyName
);
80 static bool NPN_EvaluatePatch(NPP npp
,
84 return NPObjectProxy::NPNEvaluate(npp
, npobj
, script
, result
);
88 static void NPN_SetExceptionPatch(NPObject
*obj
, const NPUTF8
*message
) {
89 std::string
message_str(message
);
90 if (IsPluginProcess()) {
91 NPChannelBase
* renderer_channel
= NPChannelBase::GetCurrentChannel();
93 renderer_channel
->Send(new PluginHostMsg_SetException(message_str
));
95 WebBindings::setException(obj
, message_str
.c_str());
99 static bool NPN_EnumeratePatch(NPP npp
, NPObject
*obj
,
100 NPIdentifier
**identifier
, uint32_t *count
) {
101 return NPObjectProxy::NPNEnumerate(obj
, identifier
, count
);
104 // The overrided table of functions provided to the plugin.
105 NPNetscapeFuncs
*GetHostFunctions() {
106 static bool init
= false;
107 static NPNetscapeFuncs host_funcs
;
111 memset(&host_funcs
, 0, sizeof(host_funcs
));
112 host_funcs
.invoke
= NPN_InvokePatch
;
113 host_funcs
.invokeDefault
= NPN_InvokeDefaultPatch
;
114 host_funcs
.evaluate
= NPN_EvaluatePatch
;
115 host_funcs
.getproperty
= NPN_GetPropertyPatch
;
116 host_funcs
.setproperty
= NPN_SetPropertyPatch
;
117 host_funcs
.removeproperty
= NPN_RemovePropertyPatch
;
118 host_funcs
.hasproperty
= NPN_HasPropertyPatch
;
119 host_funcs
.hasmethod
= NPN_HasMethodPatch
;
120 host_funcs
.setexception
= NPN_SetExceptionPatch
;
121 host_funcs
.enumerate
= NPN_EnumeratePatch
;
129 void PatchNPNFunctions() {
130 g_plugin_process
= true;
131 NPNetscapeFuncs
* funcs
= GetHostFunctions();
132 webkit::npapi::PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs
);
135 bool IsPluginProcess() {
136 return g_plugin_process
;
139 void CreateNPIdentifierParam(NPIdentifier id
, NPIdentifier_Param
* param
) {
140 param
->identifier
= id
;
143 NPIdentifier
CreateNPIdentifier(const NPIdentifier_Param
& param
) {
144 return param
.identifier
;
147 void CreateNPVariantParam(const NPVariant
& variant
,
148 NPChannelBase
* channel
,
149 NPVariant_Param
* param
,
152 const GURL
& page_url
) {
153 switch (variant
.type
) {
154 case NPVariantType_Void
:
155 param
->type
= NPVARIANT_PARAM_VOID
;
157 case NPVariantType_Null
:
158 param
->type
= NPVARIANT_PARAM_NULL
;
160 case NPVariantType_Bool
:
161 param
->type
= NPVARIANT_PARAM_BOOL
;
162 param
->bool_value
= variant
.value
.boolValue
;
164 case NPVariantType_Int32
:
165 param
->type
= NPVARIANT_PARAM_INT
;
166 param
->int_value
= variant
.value
.intValue
;
168 case NPVariantType_Double
:
169 param
->type
= NPVARIANT_PARAM_DOUBLE
;
170 param
->double_value
= variant
.value
.doubleValue
;
172 case NPVariantType_String
:
173 param
->type
= NPVARIANT_PARAM_STRING
;
174 if (variant
.value
.stringValue
.UTF8Length
) {
175 param
->string_value
.assign(variant
.value
.stringValue
.UTF8Characters
,
176 variant
.value
.stringValue
.UTF8Length
);
179 case NPVariantType_Object
: {
180 if (variant
.value
.objectValue
->_class
== NPObjectProxy::npclass()) {
181 param
->type
= NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID
;
182 NPObjectProxy
* proxy
=
183 NPObjectProxy::GetProxy(variant
.value
.objectValue
);
185 param
->npobject_routing_id
= proxy
->route_id();
186 // Don't release, because our original variant is the same as our proxy.
189 // The channel could be NULL if there was a channel error. The caller's
190 // Send call will fail anyways.
192 // NPObjectStub adds its own reference to the NPObject it owns, so if
193 // we were supposed to release the corresponding variant
194 // (release==true), we should still do that.
195 param
->type
= NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID
;
196 int route_id
= channel
->GetExistingRouteForNPObjectStub(
197 variant
.value
.objectValue
);
198 if (route_id
!= MSG_ROUTING_NONE
) {
199 param
->npobject_routing_id
= route_id
;
201 route_id
= channel
->GenerateRouteID();
203 variant
.value
.objectValue
, channel
, route_id
, render_view_id
,
205 param
->npobject_routing_id
= route_id
;
208 param
->type
= NPVARIANT_PARAM_VOID
;
218 WebBindings::releaseVariantValue(const_cast<NPVariant
*>(&variant
));
221 bool CreateNPVariant(const NPVariant_Param
& param
,
222 NPChannelBase
* channel
,
225 const GURL
& page_url
) {
226 switch (param
.type
) {
227 case NPVARIANT_PARAM_VOID
:
228 result
->type
= NPVariantType_Void
;
230 case NPVARIANT_PARAM_NULL
:
231 result
->type
= NPVariantType_Null
;
233 case NPVARIANT_PARAM_BOOL
:
234 result
->type
= NPVariantType_Bool
;
235 result
->value
.boolValue
= param
.bool_value
;
237 case NPVARIANT_PARAM_INT
:
238 result
->type
= NPVariantType_Int32
;
239 result
->value
.intValue
= param
.int_value
;
241 case NPVARIANT_PARAM_DOUBLE
:
242 result
->type
= NPVariantType_Double
;
243 result
->value
.doubleValue
= param
.double_value
;
245 case NPVARIANT_PARAM_STRING
: {
246 result
->type
= NPVariantType_String
;
247 void* buffer
= malloc(param
.string_value
.size());
248 size_t size
= param
.string_value
.size();
249 result
->value
.stringValue
.UTF8Characters
= static_cast<NPUTF8
*>(buffer
);
250 memcpy(buffer
, param
.string_value
.c_str(), size
);
251 result
->value
.stringValue
.UTF8Length
= static_cast<int>(size
);
254 case NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID
: {
255 result
->type
= NPVariantType_Object
;
257 channel
->GetExistingNPObjectProxy(param
.npobject_routing_id
);
259 WebBindings::retainObject(object
);
260 result
->value
.objectValue
= object
;
262 result
->value
.objectValue
=
263 NPObjectProxy::Create(channel
,
264 param
.npobject_routing_id
,
270 case NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID
: {
271 NPObjectBase
* npobject_base
=
272 channel
->GetNPObjectListenerForRoute(param
.npobject_routing_id
);
273 if (!npobject_base
) {
274 DLOG(WARNING
) << "Invalid routing id passed in"
275 << param
.npobject_routing_id
;
279 DCHECK(npobject_base
->GetUnderlyingNPObject() != NULL
);
281 result
->type
= NPVariantType_Object
;
282 result
->value
.objectValue
= npobject_base
->GetUnderlyingNPObject();
283 WebBindings::retainObject(result
->value
.objectValue
);
292 } // namespace content