| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "content/child/npobject_util.h" | |
| 6 | |
| 7 #include "base/strings/string_util.h" | |
| 8 #include "content/child/np_channel_base.h" | |
| 9 #include "content/child/npapi/plugin_host.h" | |
| 10 #include "content/child/npobject_proxy.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" | |
| 14 #include "webkit/glue/webkit_glue.h" | |
| 15 | |
| 16 using WebKit::WebBindings; | |
| 17 | |
| 18 namespace content { | |
| 19 | |
| 20 // true if the current process is a plugin process, false otherwise. | |
| 21 static bool g_plugin_process; | |
| 22 | |
| 23 namespace { | |
| 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, | |
| 31 NPObject *npobj, | |
| 32 NPIdentifier methodName) { | |
| 33 return NPObjectProxy::NPHasMethod(npobj, methodName); | |
| 34 } | |
| 35 | |
| 36 static bool NPN_InvokePatch(NPP npp, NPObject *npobj, | |
| 37 NPIdentifier methodName, | |
| 38 const NPVariant *args, | |
| 39 uint32_t argCount, | |
| 40 NPVariant *result) { | |
| 41 return NPObjectProxy::NPInvokePrivate(npp, npobj, false, methodName, args, | |
| 42 argCount, result); | |
| 43 } | |
| 44 | |
| 45 static bool NPN_InvokeDefaultPatch(NPP npp, | |
| 46 NPObject *npobj, | |
| 47 const NPVariant *args, | |
| 48 uint32_t argCount, | |
| 49 NPVariant *result) { | |
| 50 return NPObjectProxy::NPInvokePrivate(npp, npobj, true, 0, args, argCount, | |
| 51 result); | |
| 52 } | |
| 53 | |
| 54 static bool NPN_HasPropertyPatch(NPP npp, | |
| 55 NPObject *npobj, | |
| 56 NPIdentifier propertyName) { | |
| 57 return NPObjectProxy::NPHasProperty(npobj, propertyName); | |
| 58 } | |
| 59 | |
| 60 static bool NPN_GetPropertyPatch(NPP npp, | |
| 61 NPObject *npobj, | |
| 62 NPIdentifier propertyName, | |
| 63 NPVariant *result) { | |
| 64 return NPObjectProxy::NPGetProperty(npobj, propertyName, result); | |
| 65 } | |
| 66 | |
| 67 static bool NPN_SetPropertyPatch(NPP npp, | |
| 68 NPObject *npobj, | |
| 69 NPIdentifier propertyName, | |
| 70 const NPVariant *value) { | |
| 71 return NPObjectProxy::NPSetProperty(npobj, propertyName, value); | |
| 72 } | |
| 73 | |
| 74 static bool NPN_RemovePropertyPatch(NPP npp, | |
| 75 NPObject *npobj, | |
| 76 NPIdentifier propertyName) { | |
| 77 return NPObjectProxy::NPRemoveProperty(npobj, propertyName); | |
| 78 } | |
| 79 | |
| 80 static bool NPN_EvaluatePatch(NPP npp, | |
| 81 NPObject *npobj, | |
| 82 NPString *script, | |
| 83 NPVariant *result) { | |
| 84 return NPObjectProxy::NPNEvaluate(npp, npobj, script, result); | |
| 85 } | |
| 86 | |
| 87 | |
| 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(); | |
| 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 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 NPChannelBase* channel, | |
| 149 NPVariant_Param* param, | |
| 150 bool release, | |
| 151 int render_view_id, | |
| 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 DCHECK(proxy); | |
| 185 param->npobject_routing_id = proxy->route_id(); | |
| 186 // Don't release, because our original variant is the same as our proxy. | |
| 187 release = false; | |
| 188 } else { | |
| 189 // The channel could be NULL if there was a channel error. The caller's | |
| 190 // Send call will fail anyways. | |
| 191 if (channel) { | |
| 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; | |
| 200 } else { | |
| 201 route_id = channel->GenerateRouteID(); | |
| 202 new NPObjectStub( | |
| 203 variant.value.objectValue, channel, route_id, render_view_id, | |
| 204 page_url); | |
| 205 param->npobject_routing_id = route_id; | |
| 206 } | |
| 207 | |
| 208 // Include the object's owner. | |
| 209 NPP owner = WebBindings::getObjectOwner(variant.value.objectValue); | |
| 210 param->npobject_owner_id = | |
| 211 channel->GetExistingRouteForNPObjectOwner(owner); | |
| 212 } else { | |
| 213 param->type = NPVARIANT_PARAM_VOID; | |
| 214 } | |
| 215 } | |
| 216 break; | |
| 217 } | |
| 218 default: | |
| 219 NOTREACHED(); | |
| 220 } | |
| 221 | |
| 222 if (release) | |
| 223 WebBindings::releaseVariantValue(const_cast<NPVariant*>(&variant)); | |
| 224 } | |
| 225 | |
| 226 bool CreateNPVariant(const NPVariant_Param& param, | |
| 227 NPChannelBase* channel, | |
| 228 NPVariant* result, | |
| 229 int render_view_id, | |
| 230 const GURL& page_url) { | |
| 231 switch (param.type) { | |
| 232 case NPVARIANT_PARAM_VOID: | |
| 233 result->type = NPVariantType_Void; | |
| 234 break; | |
| 235 case NPVARIANT_PARAM_NULL: | |
| 236 result->type = NPVariantType_Null; | |
| 237 break; | |
| 238 case NPVARIANT_PARAM_BOOL: | |
| 239 result->type = NPVariantType_Bool; | |
| 240 result->value.boolValue = param.bool_value; | |
| 241 break; | |
| 242 case NPVARIANT_PARAM_INT: | |
| 243 result->type = NPVariantType_Int32; | |
| 244 result->value.intValue = param.int_value; | |
| 245 break; | |
| 246 case NPVARIANT_PARAM_DOUBLE: | |
| 247 result->type = NPVariantType_Double; | |
| 248 result->value.doubleValue = param.double_value; | |
| 249 break; | |
| 250 case NPVARIANT_PARAM_STRING: { | |
| 251 result->type = NPVariantType_String; | |
| 252 void* buffer = malloc(param.string_value.size()); | |
| 253 size_t size = param.string_value.size(); | |
| 254 result->value.stringValue.UTF8Characters = static_cast<NPUTF8*>(buffer); | |
| 255 memcpy(buffer, param.string_value.c_str(), size); | |
| 256 result->value.stringValue.UTF8Length = static_cast<int>(size); | |
| 257 break; | |
| 258 } | |
| 259 case NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID: { | |
| 260 result->type = NPVariantType_Object; | |
| 261 NPObject* object = | |
| 262 channel->GetExistingNPObjectProxy(param.npobject_routing_id); | |
| 263 if (object) { | |
| 264 WebBindings::retainObject(object); | |
| 265 result->value.objectValue = object; | |
| 266 } else { | |
| 267 NPP owner = | |
| 268 channel->GetExistingNPObjectOwner(param.npobject_owner_id); | |
| 269 // TODO(wez): Once NPObject tracking lands in Blink, check |owner| and | |
| 270 // return NPVariantType_Void if it is NULL. | |
| 271 result->value.objectValue = | |
| 272 NPObjectProxy::Create(channel, | |
| 273 param.npobject_routing_id, | |
| 274 render_view_id, | |
| 275 page_url, | |
| 276 owner); | |
| 277 } | |
| 278 break; | |
| 279 } | |
| 280 case NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID: { | |
| 281 NPObjectBase* npobject_base = | |
| 282 channel->GetNPObjectListenerForRoute(param.npobject_routing_id); | |
| 283 if (!npobject_base) { | |
| 284 DLOG(WARNING) << "Invalid routing id passed in" | |
| 285 << param.npobject_routing_id; | |
| 286 return false; | |
| 287 } | |
| 288 | |
| 289 DCHECK(npobject_base->GetUnderlyingNPObject() != NULL); | |
| 290 | |
| 291 result->type = NPVariantType_Object; | |
| 292 result->value.objectValue = npobject_base->GetUnderlyingNPObject(); | |
| 293 WebBindings::retainObject(result->value.objectValue); | |
| 294 break; | |
| 295 } | |
| 296 default: | |
| 297 NOTREACHED(); | |
| 298 } | |
| 299 return true; | |
| 300 } | |
| 301 | |
| 302 } // namespace content | |
| OLD | NEW |