OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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. | |
4 | |
5 #include "chrome/plugin/npobject_util.h" | |
6 | |
7 #include "base/string_util.h" | |
8 #include "chrome/plugin/npobject_proxy.h" | |
9 #include "chrome/plugin/plugin_channel_base.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" | |
15 | |
16 using WebKit::WebBindings; | |
17 | |
18 // true if the current process is a plugin process, false if it's a renderer | |
19 // process. | |
20 static bool g_plugin_process; | |
21 | |
22 namespace { | |
23 // The next 7 functions are called by the plugin code when it's using the | |
24 // NPObject. Plugins always ignore the functions in NPClass (except allocate | |
25 // and deallocate), and instead just use the function pointers that were | |
26 // passed in NPInitialize. | |
27 // When the renderer interacts with an NPObject from the plugin, it of course | |
28 // uses the function pointers in its NPClass structure. | |
29 static bool NPN_HasMethodPatch(NPP npp, | |
30 NPObject *npobj, | |
31 NPIdentifier methodName) { | |
32 return NPObjectProxy::NPHasMethod(npobj, methodName); | |
33 } | |
34 | |
35 static bool NPN_InvokePatch(NPP npp, NPObject *npobj, | |
36 NPIdentifier methodName, | |
37 const NPVariant *args, | |
38 uint32_t argCount, | |
39 NPVariant *result) { | |
40 return NPObjectProxy::NPInvokePrivate(npp, npobj, false, methodName, args, | |
41 argCount, result); | |
42 } | |
43 | |
44 static bool NPN_InvokeDefaultPatch(NPP npp, | |
45 NPObject *npobj, | |
46 const NPVariant *args, | |
47 uint32_t argCount, | |
48 NPVariant *result) { | |
49 return NPObjectProxy::NPInvokePrivate(npp, npobj, true, 0, args, argCount, | |
50 result); | |
51 } | |
52 | |
53 static bool NPN_HasPropertyPatch(NPP npp, | |
54 NPObject *npobj, | |
55 NPIdentifier propertyName) { | |
56 return NPObjectProxy::NPHasProperty(npobj, propertyName); | |
57 } | |
58 | |
59 static bool NPN_GetPropertyPatch(NPP npp, | |
60 NPObject *npobj, | |
61 NPIdentifier propertyName, | |
62 NPVariant *result) { | |
63 return NPObjectProxy::NPGetProperty(npobj, propertyName, result); | |
64 } | |
65 | |
66 static bool NPN_SetPropertyPatch(NPP npp, | |
67 NPObject *npobj, | |
68 NPIdentifier propertyName, | |
69 const NPVariant *value) { | |
70 return NPObjectProxy::NPSetProperty(npobj, propertyName, value); | |
71 } | |
72 | |
73 static bool NPN_RemovePropertyPatch(NPP npp, | |
74 NPObject *npobj, | |
75 NPIdentifier propertyName) { | |
76 return NPObjectProxy::NPRemoveProperty(npobj, propertyName); | |
77 } | |
78 | |
79 static bool NPN_EvaluatePatch(NPP npp, | |
80 NPObject *npobj, | |
81 NPString *script, | |
82 NPVariant *result) { | |
83 return NPObjectProxy::NPNEvaluate(npp, npobj, script, result); | |
84 } | |
85 | |
86 | |
87 static void NPN_SetExceptionPatch(NPObject *obj, const NPUTF8 *message) { | |
88 std::string message_str(message); | |
89 if (IsPluginProcess()) { | |
90 PluginChannelBase* renderer_channel = | |
91 PluginChannelBase::GetCurrentChannel(); | |
92 if (renderer_channel) | |
93 renderer_channel->Send(new PluginHostMsg_SetException(message_str)); | |
94 } else { | |
95 WebBindings::setException(obj, message_str.c_str()); | |
96 } | |
97 } | |
98 | |
99 static bool NPN_EnumeratePatch(NPP npp, NPObject *obj, | |
100 NPIdentifier **identifier, uint32_t *count) { | |
101 return NPObjectProxy::NPNEnumerate(obj, identifier, count); | |
102 } | |
103 | |
104 // The overrided table of functions provided to the plugin. | |
105 NPNetscapeFuncs *GetHostFunctions() { | |
106 static bool init = false; | |
107 static NPNetscapeFuncs host_funcs; | |
108 if (init) | |
109 return &host_funcs; | |
110 | |
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; | |
122 | |
123 init = true; | |
124 return &host_funcs; | |
125 } | |
126 | |
127 } | |
128 | |
129 void PatchNPNFunctions() { | |
130 g_plugin_process = true; | |
131 NPNetscapeFuncs* funcs = GetHostFunctions(); | |
132 webkit::npapi::PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs); | |
133 } | |
134 | |
135 bool IsPluginProcess() { | |
136 return g_plugin_process; | |
137 } | |
138 | |
139 void CreateNPIdentifierParam(NPIdentifier id, NPIdentifier_Param* param) { | |
140 param->identifier = id; | |
141 } | |
142 | |
143 NPIdentifier CreateNPIdentifier(const NPIdentifier_Param& param) { | |
144 return param.identifier; | |
145 } | |
146 | |
147 void CreateNPVariantParam(const NPVariant& variant, | |
148 PluginChannelBase* channel, | |
149 NPVariant_Param* param, | |
150 bool release, | |
151 gfx::NativeViewId containing_window, | |
152 const GURL& page_url) { | |
153 switch (variant.type) { | |
154 case NPVariantType_Void: | |
155 param->type = NPVARIANT_PARAM_VOID; | |
156 break; | |
157 case NPVariantType_Null: | |
158 param->type = NPVARIANT_PARAM_NULL; | |
159 break; | |
160 case NPVariantType_Bool: | |
161 param->type = NPVARIANT_PARAM_BOOL; | |
162 param->bool_value = variant.value.boolValue; | |
163 break; | |
164 case NPVariantType_Int32: | |
165 param->type = NPVARIANT_PARAM_INT; | |
166 param->int_value = variant.value.intValue; | |
167 break; | |
168 case NPVariantType_Double: | |
169 param->type = NPVARIANT_PARAM_DOUBLE; | |
170 param->double_value = variant.value.doubleValue; | |
171 break; | |
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); | |
177 } | |
178 break; | |
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); | |
184 param->npobject_routing_id = proxy->route_id(); | |
185 // Don't release, because our original variant is the same as our proxy. | |
186 release = false; | |
187 } else { | |
188 // The channel could be NULL if there was a channel error. The caller's | |
189 // Send call will fail anyways. | |
190 if (channel) { | |
191 // NPObjectStub adds its own reference to the NPObject it owns, so if | |
192 // we were supposed to release the corresponding variant | |
193 // (release==true), we should still do that. | |
194 param->type = NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID; | |
195 int route_id = channel->GenerateRouteID(); | |
196 new NPObjectStub( | |
197 variant.value.objectValue, channel, route_id, containing_window, | |
198 page_url); | |
199 param->npobject_routing_id = route_id; | |
200 } else { | |
201 param->type = NPVARIANT_PARAM_VOID; | |
202 } | |
203 } | |
204 break; | |
205 } | |
206 default: | |
207 NOTREACHED(); | |
208 } | |
209 | |
210 if (release) | |
211 WebBindings::releaseVariantValue(const_cast<NPVariant*>(&variant)); | |
212 } | |
213 | |
214 bool CreateNPVariant(const NPVariant_Param& param, | |
215 PluginChannelBase* channel, | |
216 NPVariant* result, | |
217 gfx::NativeViewId containing_window, | |
218 const GURL& page_url) { | |
219 switch (param.type) { | |
220 case NPVARIANT_PARAM_VOID: | |
221 result->type = NPVariantType_Void; | |
222 break; | |
223 case NPVARIANT_PARAM_NULL: | |
224 result->type = NPVariantType_Null; | |
225 break; | |
226 case NPVARIANT_PARAM_BOOL: | |
227 result->type = NPVariantType_Bool; | |
228 result->value.boolValue = param.bool_value; | |
229 break; | |
230 case NPVARIANT_PARAM_INT: | |
231 result->type = NPVariantType_Int32; | |
232 result->value.intValue = param.int_value; | |
233 break; | |
234 case NPVARIANT_PARAM_DOUBLE: | |
235 result->type = NPVariantType_Double; | |
236 result->value.doubleValue = param.double_value; | |
237 break; | |
238 case NPVARIANT_PARAM_STRING: | |
239 result->type = NPVariantType_String; | |
240 result->value.stringValue.UTF8Characters = | |
241 static_cast<NPUTF8 *>(base::strdup(param.string_value.c_str())); | |
242 result->value.stringValue.UTF8Length = | |
243 static_cast<int>(param.string_value.size()); | |
244 break; | |
245 case NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID: | |
246 result->type = NPVariantType_Object; | |
247 result->value.objectValue = | |
248 NPObjectProxy::Create(channel, | |
249 param.npobject_routing_id, | |
250 containing_window, | |
251 page_url); | |
252 break; | |
253 case NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID: { | |
254 NPObjectBase* npobject_base = | |
255 channel->GetNPObjectListenerForRoute(param.npobject_routing_id); | |
256 if (!npobject_base) { | |
257 DLOG(WARNING) << "Invalid routing id passed in" | |
258 << param.npobject_routing_id; | |
259 return false; | |
260 } | |
261 | |
262 DCHECK(npobject_base->GetUnderlyingNPObject() != NULL); | |
263 | |
264 result->type = NPVariantType_Object; | |
265 result->value.objectValue = npobject_base->GetUnderlyingNPObject(); | |
266 WebBindings::retainObject(result->value.objectValue); | |
267 break; | |
268 } | |
269 default: | |
270 NOTREACHED(); | |
271 } | |
272 return true; | |
273 } | |
OLD | NEW |