1 // Copyright 2013 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/child/npapi/npobject_util.h"
7 #include "base/strings/string_util.h"
8 #include "content/child/npapi/np_channel_base.h"
9 #include "content/child/npapi/npobject_proxy.h"
10 #include "content/child/npapi/plugin_host.h"
11 #include "content/child/plugin_messages.h"
12 #include "third_party/WebKit/public/web/WebBindings.h"
13 #include "third_party/npapi/bindings/nphostapi.h"
15 using blink::WebBindings
;
19 // true if the current process is a plugin process, false otherwise.
20 static bool g_plugin_process
;
23 #if defined(ENABLE_PLUGINS)
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
;
127 #endif // defined(ENABLE_PLUGINS)
130 #if defined(ENABLE_PLUGINS)
131 void PatchNPNFunctions() {
132 g_plugin_process
= true;
133 NPNetscapeFuncs
* funcs
= GetHostFunctions();
134 PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs
);
138 bool IsPluginProcess() {
139 return g_plugin_process
;
142 void CreateNPIdentifierParam(NPIdentifier id
, NPIdentifier_Param
* param
) {
143 param
->identifier
= id
;
146 NPIdentifier
CreateNPIdentifier(const NPIdentifier_Param
& param
) {
147 return param
.identifier
;
150 void CreateNPVariantParam(const NPVariant
& variant
,
151 NPChannelBase
* channel
,
152 NPVariant_Param
* param
,
155 const GURL
& page_url
) {
156 switch (variant
.type
) {
157 case NPVariantType_Void
:
158 param
->type
= NPVARIANT_PARAM_VOID
;
160 case NPVariantType_Null
:
161 param
->type
= NPVARIANT_PARAM_NULL
;
163 case NPVariantType_Bool
:
164 param
->type
= NPVARIANT_PARAM_BOOL
;
165 param
->bool_value
= variant
.value
.boolValue
;
167 case NPVariantType_Int32
:
168 param
->type
= NPVARIANT_PARAM_INT
;
169 param
->int_value
= variant
.value
.intValue
;
171 case NPVariantType_Double
:
172 param
->type
= NPVARIANT_PARAM_DOUBLE
;
173 param
->double_value
= variant
.value
.doubleValue
;
175 case NPVariantType_String
:
176 param
->type
= NPVARIANT_PARAM_STRING
;
177 if (variant
.value
.stringValue
.UTF8Length
) {
178 param
->string_value
.assign(variant
.value
.stringValue
.UTF8Characters
,
179 variant
.value
.stringValue
.UTF8Length
);
182 case NPVariantType_Object
: {
183 if (variant
.value
.objectValue
->_class
== NPObjectProxy::npclass()) {
184 param
->type
= NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID
;
185 NPObjectProxy
* proxy
=
186 NPObjectProxy::GetProxy(variant
.value
.objectValue
);
188 param
->npobject_routing_id
= proxy
->route_id();
189 // Don't release, because our original variant is the same as our proxy.
192 // The channel could be NULL if there was a channel error. The caller's
193 // Send call will fail anyways.
195 // NPObjectStub adds its own reference to the NPObject it owns, so if
196 // we were supposed to release the corresponding variant
197 // (release==true), we should still do that.
198 param
->type
= NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID
;
199 int route_id
= channel
->GetExistingRouteForNPObjectStub(
200 variant
.value
.objectValue
);
201 if (route_id
!= MSG_ROUTING_NONE
) {
202 param
->npobject_routing_id
= route_id
;
204 route_id
= channel
->GenerateRouteID();
206 variant
.value
.objectValue
, channel
, route_id
, render_view_id
,
208 param
->npobject_routing_id
= route_id
;
211 // Include the object's owner.
212 NPP owner
= WebBindings::getObjectOwner(variant
.value
.objectValue
);
213 param
->npobject_owner_id
=
214 channel
->GetExistingRouteForNPObjectOwner(owner
);
216 param
->type
= NPVARIANT_PARAM_VOID
;
226 WebBindings::releaseVariantValue(const_cast<NPVariant
*>(&variant
));
229 bool CreateNPVariant(const NPVariant_Param
& param
,
230 NPChannelBase
* channel
,
233 const GURL
& page_url
) {
234 switch (param
.type
) {
235 case NPVARIANT_PARAM_VOID
:
236 result
->type
= NPVariantType_Void
;
238 case NPVARIANT_PARAM_NULL
:
239 result
->type
= NPVariantType_Null
;
241 case NPVARIANT_PARAM_BOOL
:
242 result
->type
= NPVariantType_Bool
;
243 result
->value
.boolValue
= param
.bool_value
;
245 case NPVARIANT_PARAM_INT
:
246 result
->type
= NPVariantType_Int32
;
247 result
->value
.intValue
= param
.int_value
;
249 case NPVARIANT_PARAM_DOUBLE
:
250 result
->type
= NPVariantType_Double
;
251 result
->value
.doubleValue
= param
.double_value
;
253 case NPVARIANT_PARAM_STRING
: {
254 result
->type
= NPVariantType_String
;
255 void* buffer
= malloc(param
.string_value
.size());
256 size_t size
= param
.string_value
.size();
257 result
->value
.stringValue
.UTF8Characters
= static_cast<NPUTF8
*>(buffer
);
258 memcpy(buffer
, param
.string_value
.c_str(), size
);
259 result
->value
.stringValue
.UTF8Length
= static_cast<int>(size
);
262 case NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID
: {
263 result
->type
= NPVariantType_Object
;
265 channel
->GetExistingNPObjectProxy(param
.npobject_routing_id
);
267 WebBindings::retainObject(object
);
268 result
->value
.objectValue
= object
;
271 channel
->GetExistingNPObjectOwner(param
.npobject_owner_id
);
272 // TODO(wez): Once NPObject tracking lands in Blink, check |owner| and
273 // return NPVariantType_Void if it is NULL.
274 result
->value
.objectValue
=
275 NPObjectProxy::Create(channel
,
276 param
.npobject_routing_id
,
283 case NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID
: {
284 NPObjectBase
* npobject_base
=
285 channel
->GetNPObjectListenerForRoute(param
.npobject_routing_id
);
286 if (!npobject_base
) {
287 DLOG(WARNING
) << "Invalid routing id passed in"
288 << param
.npobject_routing_id
;
292 DCHECK(npobject_base
->GetUnderlyingNPObject() != NULL
);
294 result
->type
= NPVariantType_Object
;
295 result
->value
.objectValue
= npobject_base
->GetUnderlyingNPObject();
296 WebBindings::retainObject(result
->value
.objectValue
);
305 } // namespace content