| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 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 "webkit/activex_shim/dispatch_object.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <string> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/logging.h" | |
| 12 #include "webkit/activex_shim/activex_util.h" | |
| 13 #include "webkit/activex_shim/npp_impl.h" | |
| 14 | |
| 15 using std::string; | |
| 16 using std::wstring; | |
| 17 | |
| 18 namespace activex_shim { | |
| 19 | |
| 20 // Used when the browser asks for scriptable object. | |
| 21 static NPClass npclass = { | |
| 22 1, // NP_CLASS_STRUCT_VERSION, | |
| 23 NPAllocate, | |
| 24 NPDeallocate, | |
| 25 NPInvalidate, | |
| 26 NPHasMethod, | |
| 27 NPInvoke, | |
| 28 NPInvokeDefault, | |
| 29 NPHasProperty, | |
| 30 NPGetProperty, | |
| 31 NPSetProperty, | |
| 32 NPRemoveProperty | |
| 33 }; | |
| 34 | |
| 35 DispatchObject::DispatchObject(DispatchObject* root) | |
| 36 : npobject_(NULL), | |
| 37 root_(root), | |
| 38 deleting_spawned_children_(false) { | |
| 39 } | |
| 40 | |
| 41 DispatchObject::~DispatchObject() { | |
| 42 if (npobject_) { | |
| 43 // We are gone, but the NPObject may still be there. So remove | |
| 44 // the reference to myself to avoid future trouble. | |
| 45 npobject_->dispatch_object = NULL; | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 NPObject* DispatchObject::GetScriptableNPObject() { | |
| 50 if (npobject_ == NULL) { | |
| 51 npobject_ = static_cast<DispatchNPObject*>(NPAllocate(&npclass)); | |
| 52 } else { | |
| 53 // If it is requesting the object again, we should just return the | |
| 54 // object with increased reference count. | |
| 55 g_browser->retainobject(npobject_); | |
| 56 } | |
| 57 return npobject_; | |
| 58 } | |
| 59 | |
| 60 NPObject* DispatchObject::NPAllocate(NPClass* cls) { | |
| 61 DispatchNPObject* obj = new DispatchNPObject(); | |
| 62 obj->_class = cls; | |
| 63 obj->referenceCount = 1; | |
| 64 obj->dispatch_object = this; | |
| 65 return obj; | |
| 66 } | |
| 67 | |
| 68 void DispatchObject::NPInvalidate() { | |
| 69 } | |
| 70 | |
| 71 void DispatchObject::OnDeallocateObject(DispatchNPObject* obj) { | |
| 72 DCHECK_EQ(obj, npobject_); | |
| 73 if (obj == npobject_) { | |
| 74 // Just null our reference so that we won't accidentally access it | |
| 75 // during destruction. | |
| 76 npobject_ = NULL; | |
| 77 if (NPObjectOwnsMe()) { | |
| 78 delete this; | |
| 79 } | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 bool DispatchObject::NPHasMethod(NPIdentifier name) { | |
| 84 wstring wname; | |
| 85 if (!NPIdentifierToWString(name, &wname)) | |
| 86 return false; | |
| 87 return DispIsMethodOrProperty(GetDispatch(), wname.c_str(), true); | |
| 88 } | |
| 89 | |
| 90 bool DispatchObject::NPHasProperty(NPIdentifier name) { | |
| 91 wstring wname; | |
| 92 if (!NPIdentifierToWString(name, &wname)) | |
| 93 return false; | |
| 94 return DispIsMethodOrProperty(GetDispatch(), wname.c_str(), false); | |
| 95 // Here is another way. But the problem is it can not distiguish between | |
| 96 // method and property. | |
| 97 // DISPID dispid; | |
| 98 // if (GetDispID(npobj->dispatch_object->GetDispatch(), wname.c_str(), &dispid
)) | |
| 99 // return true; | |
| 100 } | |
| 101 | |
| 102 bool DispatchObject::NPInvoke(NPIdentifier name, const NPVariant* args, | |
| 103 uint32_t argCount, NPVariant* result) { | |
| 104 wstring wname; | |
| 105 if (!NPIdentifierToWString(name, &wname)) | |
| 106 return false; | |
| 107 std::vector<ScopedVariant> vars; | |
| 108 ScopedVariant vtres; | |
| 109 bool res = false; | |
| 110 do { | |
| 111 if (argCount > 0) { | |
| 112 vars.resize(argCount); | |
| 113 unsigned int i; | |
| 114 for (i = 0; i < argCount; i++) { | |
| 115 // Note that we need to reverse the order of arguments for | |
| 116 // IDispatch::Invoke. | |
| 117 if (!NPVariantToVariant(&args[argCount - i - 1], &vars[i])) | |
| 118 break; | |
| 119 } | |
| 120 if (i < argCount) | |
| 121 break; | |
| 122 } | |
| 123 if (!DispInvoke(GetDispatch(), wname.c_str(), | |
| 124 argCount > 0 ? &vars[0] : NULL, | |
| 125 argCount, &vtres)) | |
| 126 break; | |
| 127 if (!VariantToNPVariant(this, &vtres, result)) | |
| 128 break; | |
| 129 res = true; | |
| 130 } while (false); | |
| 131 return res; | |
| 132 } | |
| 133 | |
| 134 bool DispatchObject::NPInvokeDefault(const NPVariant* args, uint32_t argCount, | |
| 135 NPVariant* result) { | |
| 136 return false; | |
| 137 } | |
| 138 | |
| 139 bool DispatchObject::NPGetProperty(NPIdentifier name, NPVariant* variant) { | |
| 140 wstring wname; | |
| 141 if (!NPIdentifierToWString(name, &wname)) | |
| 142 return false; | |
| 143 ScopedVariant result; | |
| 144 if (!DispInvoke(GetDispatch(), wname.c_str(), NULL, 0, &result)) | |
| 145 return false; | |
| 146 if (!VariantToNPVariant(this, &result, variant)) | |
| 147 return false; | |
| 148 return true; | |
| 149 } | |
| 150 | |
| 151 bool DispatchObject::NPSetProperty(NPIdentifier name, const NPVariant* variant)
{ | |
| 152 wstring wname; | |
| 153 if (!NPIdentifierToWString(name, &wname)) | |
| 154 return false; | |
| 155 ScopedVariant rvalue; | |
| 156 if (!NPVariantToVariant(variant, &rvalue)) | |
| 157 return false; | |
| 158 if (!DispSetProperty(GetDispatch(), wname.c_str(), rvalue)) | |
| 159 return false; | |
| 160 return true; | |
| 161 } | |
| 162 | |
| 163 bool DispatchObject::NPRemoveProperty(NPIdentifier propertyName) { | |
| 164 return false; | |
| 165 } | |
| 166 | |
| 167 void DispatchObject::AddSpawned(DispatchObject* obj) { | |
| 168 // I myself must be the root. | |
| 169 DCHECK(root_ == NULL); | |
| 170 spawned_children_.push_back(obj); | |
| 171 } | |
| 172 | |
| 173 void DispatchObject::RemoveSpawned(DispatchObject* obj) { | |
| 174 // This is to avoid problem when the root object is calling ReleaseSpawned to | |
| 175 // delete all spawned children. | |
| 176 if (deleting_spawned_children_) | |
| 177 return; | |
| 178 DCHECK(root_ == NULL); | |
| 179 SpawnedChildrenList::iterator it = std::find(spawned_children_.begin(), | |
| 180 spawned_children_.end(), obj); | |
| 181 if (it == spawned_children_.end()) { | |
| 182 DCHECK(false); | |
| 183 return; | |
| 184 } | |
| 185 spawned_children_.erase(it); | |
| 186 } | |
| 187 | |
| 188 void DispatchObject::ReleaseSpawned() { | |
| 189 DCHECK(root_ == NULL); | |
| 190 deleting_spawned_children_ = true; | |
| 191 for (SpawnedChildrenList::iterator it = spawned_children_.begin(); | |
| 192 it != spawned_children_.end(); ++it) | |
| 193 delete *it; | |
| 194 deleting_spawned_children_ = false; | |
| 195 spawned_children_.clear(); | |
| 196 } | |
| 197 | |
| 198 SpawnedDispatchObject::SpawnedDispatchObject(IDispatch* dispatch, | |
| 199 DispatchObject* root) | |
| 200 : DispatchObject(root), | |
| 201 dispatch_(dispatch) { | |
| 202 if (dispatch) | |
| 203 dispatch->AddRef(); | |
| 204 DCHECK(root != NULL); | |
| 205 root->AddSpawned(this); | |
| 206 } | |
| 207 | |
| 208 SpawnedDispatchObject::~SpawnedDispatchObject() { | |
| 209 if (dispatch_) | |
| 210 dispatch_->Release(); | |
| 211 DCHECK(root_ != NULL); | |
| 212 root_->RemoveSpawned(this); | |
| 213 } | |
| 214 | |
| 215 /////////////////////////////////////////////////////////////////////////////// | |
| 216 // Scripting object functions implementation. | |
| 217 | |
| 218 NPObject* NPAllocate(NPP npp, NPClass* theClass) { | |
| 219 DispatchObject* dispatch_object = static_cast<DispatchObject*>(npp->pdata); | |
| 220 return dispatch_object->NPAllocate(theClass); | |
| 221 } | |
| 222 | |
| 223 void NPDeallocate(NPObject* obj) { | |
| 224 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 225 // The dispatch_object could be well gone before the NPObject is released. | |
| 226 if (npobj->dispatch_object != NULL) { | |
| 227 npobj->dispatch_object->OnDeallocateObject(npobj); | |
| 228 } | |
| 229 delete npobj; | |
| 230 } | |
| 231 | |
| 232 void NPInvalidate(NPObject* obj) { | |
| 233 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 234 if (npobj->dispatch_object == NULL) | |
| 235 return; | |
| 236 npobj->dispatch_object->NPInvalidate(); | |
| 237 } | |
| 238 | |
| 239 bool NPHasMethod(NPObject* obj, NPIdentifier name) { | |
| 240 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 241 if (npobj->dispatch_object == NULL) | |
| 242 return false; | |
| 243 return npobj->dispatch_object->NPHasMethod(name); | |
| 244 } | |
| 245 | |
| 246 bool NPInvoke(NPObject* obj, NPIdentifier name, const NPVariant* args, | |
| 247 uint32_t argCount, NPVariant* result) { | |
| 248 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 249 if (npobj->dispatch_object == NULL) | |
| 250 return false; | |
| 251 return npobj->dispatch_object->NPInvoke(name, args, argCount, result); | |
| 252 } | |
| 253 | |
| 254 bool NPInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t argCount, | |
| 255 NPVariant* result) { | |
| 256 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 257 if (npobj->dispatch_object == NULL) | |
| 258 return false; | |
| 259 return npobj->dispatch_object->NPInvokeDefault(args, argCount, result); | |
| 260 } | |
| 261 | |
| 262 bool NPHasProperty(NPObject* obj, NPIdentifier name) { | |
| 263 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 264 if (npobj->dispatch_object == NULL) | |
| 265 return false; | |
| 266 return npobj->dispatch_object->NPHasProperty(name); | |
| 267 } | |
| 268 | |
| 269 bool NPGetProperty(NPObject* obj, NPIdentifier name, NPVariant* variant) { | |
| 270 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 271 if (npobj->dispatch_object == NULL) | |
| 272 return false; | |
| 273 return npobj->dispatch_object->NPGetProperty(name, variant); | |
| 274 } | |
| 275 | |
| 276 bool NPSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant) { | |
| 277 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 278 if (npobj->dispatch_object == NULL) | |
| 279 return false; | |
| 280 return npobj->dispatch_object->NPSetProperty(name, variant); | |
| 281 } | |
| 282 | |
| 283 bool NPRemoveProperty(NPObject* obj, NPIdentifier name) { | |
| 284 DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); | |
| 285 if (npobj->dispatch_object == NULL) | |
| 286 return false; | |
| 287 return npobj->dispatch_object->NPRemoveProperty(name); | |
| 288 } | |
| 289 | |
| 290 } // namespace activex_shim | |
| OLD | NEW |