Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */ |
michael@0 | 7 | |
michael@0 | 8 | #include "xptiprivate.h" |
michael@0 | 9 | #include "mozilla/XPTInterfaceInfoManager.h" |
michael@0 | 10 | |
michael@0 | 11 | using namespace mozilla; |
michael@0 | 12 | |
michael@0 | 13 | /***************************************************************************/ |
michael@0 | 14 | // Debug Instrumentation... |
michael@0 | 15 | |
michael@0 | 16 | #ifdef SHOW_INFO_COUNT_STATS |
michael@0 | 17 | static int DEBUG_TotalInfos = 0; |
michael@0 | 18 | static int DEBUG_CurrentInfos = 0; |
michael@0 | 19 | static int DEBUG_MaxInfos = 0; |
michael@0 | 20 | static int DEBUG_ReentrantMonitorEntryCount = 0; |
michael@0 | 21 | |
michael@0 | 22 | #define LOG_INFO_CREATE(t) \ |
michael@0 | 23 | DEBUG_TotalInfos++; \ |
michael@0 | 24 | DEBUG_CurrentInfos++; \ |
michael@0 | 25 | if(DEBUG_MaxInfos < DEBUG_CurrentInfos) \ |
michael@0 | 26 | DEBUG_MaxInfos = DEBUG_CurrentInfos /* no ';' */ |
michael@0 | 27 | |
michael@0 | 28 | #define LOG_INFO_DESTROY(t) \ |
michael@0 | 29 | DEBUG_CurrentInfos-- /* no ';' */ |
michael@0 | 30 | |
michael@0 | 31 | #define LOG_INFO_MONITOR_ENTRY \ |
michael@0 | 32 | DEBUG_ReentrantMonitorEntryCount++ /* no ';' */ |
michael@0 | 33 | |
michael@0 | 34 | #else /* SHOW_INFO_COUNT_STATS */ |
michael@0 | 35 | |
michael@0 | 36 | #define LOG_INFO_CREATE(t) ((void)0) |
michael@0 | 37 | #define LOG_INFO_DESTROY(t) ((void)0) |
michael@0 | 38 | #define LOG_INFO_MONITOR_ENTRY ((void)0) |
michael@0 | 39 | #endif /* SHOW_INFO_COUNT_STATS */ |
michael@0 | 40 | |
michael@0 | 41 | /* static */ xptiInterfaceEntry* |
michael@0 | 42 | xptiInterfaceEntry::Create(const char* name, const nsID& iid, |
michael@0 | 43 | XPTInterfaceDescriptor* aDescriptor, |
michael@0 | 44 | xptiTypelibGuts* aTypelib) |
michael@0 | 45 | { |
michael@0 | 46 | int namelen = strlen(name); |
michael@0 | 47 | return new (XPT_MALLOC(gXPTIStructArena, |
michael@0 | 48 | sizeof(xptiInterfaceEntry) + namelen)) |
michael@0 | 49 | xptiInterfaceEntry(name, namelen, iid, aDescriptor, aTypelib); |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | xptiInterfaceEntry::xptiInterfaceEntry(const char* name, |
michael@0 | 53 | size_t nameLength, |
michael@0 | 54 | const nsID& iid, |
michael@0 | 55 | XPTInterfaceDescriptor* aDescriptor, |
michael@0 | 56 | xptiTypelibGuts* aTypelib) |
michael@0 | 57 | : mIID(iid) |
michael@0 | 58 | , mDescriptor(aDescriptor) |
michael@0 | 59 | , mMethodBaseIndex(0) |
michael@0 | 60 | , mConstantBaseIndex(0) |
michael@0 | 61 | , mTypelib(aTypelib) |
michael@0 | 62 | , mParent(nullptr) |
michael@0 | 63 | , mInfo(nullptr) |
michael@0 | 64 | , mFlags(0) |
michael@0 | 65 | { |
michael@0 | 66 | memcpy(mName, name, nameLength); |
michael@0 | 67 | SetResolvedState(PARTIALLY_RESOLVED); |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | bool |
michael@0 | 71 | xptiInterfaceEntry::Resolve() |
michael@0 | 72 | { |
michael@0 | 73 | MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock()); |
michael@0 | 74 | return ResolveLocked(); |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | bool |
michael@0 | 78 | xptiInterfaceEntry::ResolveLocked() |
michael@0 | 79 | { |
michael@0 | 80 | int resolvedState = GetResolveState(); |
michael@0 | 81 | |
michael@0 | 82 | if(resolvedState == FULLY_RESOLVED) |
michael@0 | 83 | return true; |
michael@0 | 84 | if(resolvedState == RESOLVE_FAILED) |
michael@0 | 85 | return false; |
michael@0 | 86 | |
michael@0 | 87 | NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!"); |
michael@0 | 88 | |
michael@0 | 89 | // Finish out resolution by finding parent and Resolving it so |
michael@0 | 90 | // we can set the info we get from it. |
michael@0 | 91 | |
michael@0 | 92 | uint16_t parent_index = mDescriptor->parent_interface; |
michael@0 | 93 | |
michael@0 | 94 | if(parent_index) |
michael@0 | 95 | { |
michael@0 | 96 | xptiInterfaceEntry* parent = |
michael@0 | 97 | mTypelib->GetEntryAt(parent_index - 1); |
michael@0 | 98 | |
michael@0 | 99 | if(!parent || !parent->EnsureResolvedLocked()) |
michael@0 | 100 | { |
michael@0 | 101 | SetResolvedState(RESOLVE_FAILED); |
michael@0 | 102 | return false; |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | mParent = parent; |
michael@0 | 106 | |
michael@0 | 107 | mMethodBaseIndex = |
michael@0 | 108 | parent->mMethodBaseIndex + |
michael@0 | 109 | parent->mDescriptor->num_methods; |
michael@0 | 110 | |
michael@0 | 111 | mConstantBaseIndex = |
michael@0 | 112 | parent->mConstantBaseIndex + |
michael@0 | 113 | parent->mDescriptor->num_constants; |
michael@0 | 114 | |
michael@0 | 115 | } |
michael@0 | 116 | LOG_RESOLVE(("+ complete resolve of %s\n", mName)); |
michael@0 | 117 | |
michael@0 | 118 | SetResolvedState(FULLY_RESOLVED); |
michael@0 | 119 | return true; |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | /**************************************************/ |
michael@0 | 123 | // These non-virtual methods handle the delegated nsIInterfaceInfo methods. |
michael@0 | 124 | |
michael@0 | 125 | nsresult |
michael@0 | 126 | xptiInterfaceEntry::GetName(char **name) |
michael@0 | 127 | { |
michael@0 | 128 | // It is not necessary to Resolve because this info is read from manifest. |
michael@0 | 129 | *name = (char*) nsMemory::Clone(mName, strlen(mName)+1); |
michael@0 | 130 | return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | nsresult |
michael@0 | 134 | xptiInterfaceEntry::GetIID(nsIID **iid) |
michael@0 | 135 | { |
michael@0 | 136 | // It is not necessary to Resolve because this info is read from manifest. |
michael@0 | 137 | *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID)); |
michael@0 | 138 | return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | nsresult |
michael@0 | 142 | xptiInterfaceEntry::IsScriptable(bool* result) |
michael@0 | 143 | { |
michael@0 | 144 | // It is not necessary to Resolve because this info is read from manifest. |
michael@0 | 145 | *result = GetScriptableFlag(); |
michael@0 | 146 | return NS_OK; |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | nsresult |
michael@0 | 150 | xptiInterfaceEntry::IsFunction(bool* result) |
michael@0 | 151 | { |
michael@0 | 152 | if(!EnsureResolved()) |
michael@0 | 153 | return NS_ERROR_UNEXPECTED; |
michael@0 | 154 | |
michael@0 | 155 | *result = XPT_ID_IS_FUNCTION(mDescriptor->flags); |
michael@0 | 156 | return NS_OK; |
michael@0 | 157 | } |
michael@0 | 158 | |
michael@0 | 159 | nsresult |
michael@0 | 160 | xptiInterfaceEntry::GetMethodCount(uint16_t* count) |
michael@0 | 161 | { |
michael@0 | 162 | if(!EnsureResolved()) |
michael@0 | 163 | return NS_ERROR_UNEXPECTED; |
michael@0 | 164 | |
michael@0 | 165 | *count = mMethodBaseIndex + |
michael@0 | 166 | mDescriptor->num_methods; |
michael@0 | 167 | return NS_OK; |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | nsresult |
michael@0 | 171 | xptiInterfaceEntry::GetConstantCount(uint16_t* count) |
michael@0 | 172 | { |
michael@0 | 173 | if(!EnsureResolved()) |
michael@0 | 174 | return NS_ERROR_UNEXPECTED; |
michael@0 | 175 | |
michael@0 | 176 | *count = mConstantBaseIndex + |
michael@0 | 177 | mDescriptor->num_constants; |
michael@0 | 178 | return NS_OK; |
michael@0 | 179 | } |
michael@0 | 180 | |
michael@0 | 181 | nsresult |
michael@0 | 182 | xptiInterfaceEntry::GetMethodInfo(uint16_t index, const nsXPTMethodInfo** info) |
michael@0 | 183 | { |
michael@0 | 184 | if(!EnsureResolved()) |
michael@0 | 185 | return NS_ERROR_UNEXPECTED; |
michael@0 | 186 | |
michael@0 | 187 | if(index < mMethodBaseIndex) |
michael@0 | 188 | return mParent->GetMethodInfo(index, info); |
michael@0 | 189 | |
michael@0 | 190 | if(index >= mMethodBaseIndex + |
michael@0 | 191 | mDescriptor->num_methods) |
michael@0 | 192 | { |
michael@0 | 193 | NS_ERROR("bad param"); |
michael@0 | 194 | *info = nullptr; |
michael@0 | 195 | return NS_ERROR_INVALID_ARG; |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | // else... |
michael@0 | 199 | *info = reinterpret_cast<nsXPTMethodInfo*> |
michael@0 | 200 | (&mDescriptor->method_descriptors[index - mMethodBaseIndex]); |
michael@0 | 201 | return NS_OK; |
michael@0 | 202 | } |
michael@0 | 203 | |
michael@0 | 204 | nsresult |
michael@0 | 205 | xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16_t *index, |
michael@0 | 206 | const nsXPTMethodInfo** result) |
michael@0 | 207 | { |
michael@0 | 208 | if(!EnsureResolved()) |
michael@0 | 209 | return NS_ERROR_UNEXPECTED; |
michael@0 | 210 | |
michael@0 | 211 | // This is a slow algorithm, but this is not expected to be called much. |
michael@0 | 212 | for(uint16_t i = 0; i < mDescriptor->num_methods; ++i) |
michael@0 | 213 | { |
michael@0 | 214 | const nsXPTMethodInfo* info; |
michael@0 | 215 | info = reinterpret_cast<nsXPTMethodInfo*> |
michael@0 | 216 | (&mDescriptor-> |
michael@0 | 217 | method_descriptors[i]); |
michael@0 | 218 | if (PL_strcmp(methodName, info->GetName()) == 0) { |
michael@0 | 219 | *index = i + mMethodBaseIndex; |
michael@0 | 220 | *result = info; |
michael@0 | 221 | return NS_OK; |
michael@0 | 222 | } |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | if(mParent) |
michael@0 | 226 | return mParent->GetMethodInfoForName(methodName, index, result); |
michael@0 | 227 | else |
michael@0 | 228 | { |
michael@0 | 229 | *index = 0; |
michael@0 | 230 | *result = 0; |
michael@0 | 231 | return NS_ERROR_INVALID_ARG; |
michael@0 | 232 | } |
michael@0 | 233 | } |
michael@0 | 234 | |
michael@0 | 235 | nsresult |
michael@0 | 236 | xptiInterfaceEntry::GetConstant(uint16_t index, const nsXPTConstant** constant) |
michael@0 | 237 | { |
michael@0 | 238 | if(!EnsureResolved()) |
michael@0 | 239 | return NS_ERROR_UNEXPECTED; |
michael@0 | 240 | |
michael@0 | 241 | if(index < mConstantBaseIndex) |
michael@0 | 242 | return mParent->GetConstant(index, constant); |
michael@0 | 243 | |
michael@0 | 244 | if(index >= mConstantBaseIndex + |
michael@0 | 245 | mDescriptor->num_constants) |
michael@0 | 246 | { |
michael@0 | 247 | NS_PRECONDITION(0, "bad param"); |
michael@0 | 248 | *constant = nullptr; |
michael@0 | 249 | return NS_ERROR_INVALID_ARG; |
michael@0 | 250 | } |
michael@0 | 251 | |
michael@0 | 252 | // else... |
michael@0 | 253 | *constant = |
michael@0 | 254 | reinterpret_cast<nsXPTConstant*> |
michael@0 | 255 | (&mDescriptor-> |
michael@0 | 256 | const_descriptors[index - |
michael@0 | 257 | mConstantBaseIndex]); |
michael@0 | 258 | return NS_OK; |
michael@0 | 259 | } |
michael@0 | 260 | |
michael@0 | 261 | // this is a private helper |
michael@0 | 262 | |
michael@0 | 263 | nsresult |
michael@0 | 264 | xptiInterfaceEntry::GetEntryForParam(uint16_t methodIndex, |
michael@0 | 265 | const nsXPTParamInfo * param, |
michael@0 | 266 | xptiInterfaceEntry** entry) |
michael@0 | 267 | { |
michael@0 | 268 | if(!EnsureResolved()) |
michael@0 | 269 | return NS_ERROR_UNEXPECTED; |
michael@0 | 270 | |
michael@0 | 271 | if(methodIndex < mMethodBaseIndex) |
michael@0 | 272 | return mParent->GetEntryForParam(methodIndex, param, entry); |
michael@0 | 273 | |
michael@0 | 274 | if(methodIndex >= mMethodBaseIndex + |
michael@0 | 275 | mDescriptor->num_methods) |
michael@0 | 276 | { |
michael@0 | 277 | NS_ERROR("bad param"); |
michael@0 | 278 | return NS_ERROR_INVALID_ARG; |
michael@0 | 279 | } |
michael@0 | 280 | |
michael@0 | 281 | const XPTTypeDescriptor *td = ¶m->type; |
michael@0 | 282 | |
michael@0 | 283 | while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { |
michael@0 | 284 | td = &mDescriptor->additional_types[td->type.additional_type]; |
michael@0 | 285 | } |
michael@0 | 286 | |
michael@0 | 287 | if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) { |
michael@0 | 288 | NS_ERROR("not an interface"); |
michael@0 | 289 | return NS_ERROR_INVALID_ARG; |
michael@0 | 290 | } |
michael@0 | 291 | |
michael@0 | 292 | xptiInterfaceEntry* theEntry = mTypelib-> |
michael@0 | 293 | GetEntryAt(td->type.iface - 1); |
michael@0 | 294 | |
michael@0 | 295 | // This can happen if a declared interface is not available at runtime. |
michael@0 | 296 | if(!theEntry) |
michael@0 | 297 | { |
michael@0 | 298 | NS_WARNING("Declared InterfaceInfo not found"); |
michael@0 | 299 | *entry = nullptr; |
michael@0 | 300 | return NS_ERROR_FAILURE; |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | *entry = theEntry; |
michael@0 | 304 | return NS_OK; |
michael@0 | 305 | } |
michael@0 | 306 | |
michael@0 | 307 | nsresult |
michael@0 | 308 | xptiInterfaceEntry::GetInfoForParam(uint16_t methodIndex, |
michael@0 | 309 | const nsXPTParamInfo *param, |
michael@0 | 310 | nsIInterfaceInfo** info) |
michael@0 | 311 | { |
michael@0 | 312 | xptiInterfaceEntry* entry; |
michael@0 | 313 | nsresult rv = GetEntryForParam(methodIndex, param, &entry); |
michael@0 | 314 | if(NS_FAILED(rv)) |
michael@0 | 315 | return rv; |
michael@0 | 316 | |
michael@0 | 317 | *info = entry->InterfaceInfo().take(); |
michael@0 | 318 | |
michael@0 | 319 | return NS_OK; |
michael@0 | 320 | } |
michael@0 | 321 | |
michael@0 | 322 | nsresult |
michael@0 | 323 | xptiInterfaceEntry::GetIIDForParam(uint16_t methodIndex, |
michael@0 | 324 | const nsXPTParamInfo* param, nsIID** iid) |
michael@0 | 325 | { |
michael@0 | 326 | xptiInterfaceEntry* entry; |
michael@0 | 327 | nsresult rv = GetEntryForParam(methodIndex, param, &entry); |
michael@0 | 328 | if(NS_FAILED(rv)) |
michael@0 | 329 | return rv; |
michael@0 | 330 | return entry->GetIID(iid); |
michael@0 | 331 | } |
michael@0 | 332 | |
michael@0 | 333 | nsresult |
michael@0 | 334 | xptiInterfaceEntry::GetIIDForParamNoAlloc(uint16_t methodIndex, |
michael@0 | 335 | const nsXPTParamInfo * param, |
michael@0 | 336 | nsIID *iid) |
michael@0 | 337 | { |
michael@0 | 338 | xptiInterfaceEntry* entry; |
michael@0 | 339 | nsresult rv = GetEntryForParam(methodIndex, param, &entry); |
michael@0 | 340 | if(NS_FAILED(rv)) |
michael@0 | 341 | return rv; |
michael@0 | 342 | *iid = entry->mIID; |
michael@0 | 343 | return NS_OK; |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | // this is a private helper |
michael@0 | 347 | nsresult |
michael@0 | 348 | xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param, |
michael@0 | 349 | uint16_t dimension, |
michael@0 | 350 | const XPTTypeDescriptor** type) |
michael@0 | 351 | { |
michael@0 | 352 | NS_ASSERTION(IsFullyResolved(), "bad state"); |
michael@0 | 353 | |
michael@0 | 354 | const XPTTypeDescriptor *td = ¶m->type; |
michael@0 | 355 | const XPTTypeDescriptor *additional_types = |
michael@0 | 356 | mDescriptor->additional_types; |
michael@0 | 357 | |
michael@0 | 358 | for (uint16_t i = 0; i < dimension; i++) { |
michael@0 | 359 | if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) { |
michael@0 | 360 | NS_ERROR("bad dimension"); |
michael@0 | 361 | return NS_ERROR_INVALID_ARG; |
michael@0 | 362 | } |
michael@0 | 363 | td = &additional_types[td->type.additional_type]; |
michael@0 | 364 | } |
michael@0 | 365 | |
michael@0 | 366 | *type = td; |
michael@0 | 367 | return NS_OK; |
michael@0 | 368 | } |
michael@0 | 369 | |
michael@0 | 370 | nsresult |
michael@0 | 371 | xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex, |
michael@0 | 372 | const nsXPTParamInfo* param, |
michael@0 | 373 | uint16_t dimension, |
michael@0 | 374 | nsXPTType* type) |
michael@0 | 375 | { |
michael@0 | 376 | if(!EnsureResolved()) |
michael@0 | 377 | return NS_ERROR_UNEXPECTED; |
michael@0 | 378 | |
michael@0 | 379 | if(methodIndex < mMethodBaseIndex) |
michael@0 | 380 | return mParent-> |
michael@0 | 381 | GetTypeForParam(methodIndex, param, dimension, type); |
michael@0 | 382 | |
michael@0 | 383 | if(methodIndex >= mMethodBaseIndex + |
michael@0 | 384 | mDescriptor->num_methods) |
michael@0 | 385 | { |
michael@0 | 386 | NS_ERROR("bad index"); |
michael@0 | 387 | return NS_ERROR_INVALID_ARG; |
michael@0 | 388 | } |
michael@0 | 389 | |
michael@0 | 390 | const XPTTypeDescriptor *td; |
michael@0 | 391 | |
michael@0 | 392 | if(dimension) { |
michael@0 | 393 | nsresult rv = GetTypeInArray(param, dimension, &td); |
michael@0 | 394 | if(NS_FAILED(rv)) |
michael@0 | 395 | return rv; |
michael@0 | 396 | } |
michael@0 | 397 | else |
michael@0 | 398 | td = ¶m->type; |
michael@0 | 399 | |
michael@0 | 400 | *type = nsXPTType(td->prefix); |
michael@0 | 401 | return NS_OK; |
michael@0 | 402 | } |
michael@0 | 403 | |
michael@0 | 404 | nsresult |
michael@0 | 405 | xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16_t methodIndex, |
michael@0 | 406 | const nsXPTParamInfo* param, |
michael@0 | 407 | uint16_t dimension, |
michael@0 | 408 | uint8_t* argnum) |
michael@0 | 409 | { |
michael@0 | 410 | if(!EnsureResolved()) |
michael@0 | 411 | return NS_ERROR_UNEXPECTED; |
michael@0 | 412 | |
michael@0 | 413 | if(methodIndex < mMethodBaseIndex) |
michael@0 | 414 | return mParent-> |
michael@0 | 415 | GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum); |
michael@0 | 416 | |
michael@0 | 417 | if(methodIndex >= mMethodBaseIndex + |
michael@0 | 418 | mDescriptor->num_methods) |
michael@0 | 419 | { |
michael@0 | 420 | NS_ERROR("bad index"); |
michael@0 | 421 | return NS_ERROR_INVALID_ARG; |
michael@0 | 422 | } |
michael@0 | 423 | |
michael@0 | 424 | const XPTTypeDescriptor *td; |
michael@0 | 425 | |
michael@0 | 426 | if(dimension) { |
michael@0 | 427 | nsresult rv = GetTypeInArray(param, dimension, &td); |
michael@0 | 428 | if(NS_FAILED(rv)) |
michael@0 | 429 | return rv; |
michael@0 | 430 | } |
michael@0 | 431 | else |
michael@0 | 432 | td = ¶m->type; |
michael@0 | 433 | |
michael@0 | 434 | // verify that this is a type that has size_is |
michael@0 | 435 | switch (XPT_TDP_TAG(td->prefix)) { |
michael@0 | 436 | case TD_ARRAY: |
michael@0 | 437 | case TD_PSTRING_SIZE_IS: |
michael@0 | 438 | case TD_PWSTRING_SIZE_IS: |
michael@0 | 439 | break; |
michael@0 | 440 | default: |
michael@0 | 441 | NS_ERROR("not a size_is"); |
michael@0 | 442 | return NS_ERROR_INVALID_ARG; |
michael@0 | 443 | } |
michael@0 | 444 | |
michael@0 | 445 | *argnum = td->argnum; |
michael@0 | 446 | return NS_OK; |
michael@0 | 447 | } |
michael@0 | 448 | |
michael@0 | 449 | nsresult |
michael@0 | 450 | xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex, |
michael@0 | 451 | const nsXPTParamInfo* param, |
michael@0 | 452 | uint8_t* argnum) |
michael@0 | 453 | { |
michael@0 | 454 | if(!EnsureResolved()) |
michael@0 | 455 | return NS_ERROR_UNEXPECTED; |
michael@0 | 456 | |
michael@0 | 457 | if(methodIndex < mMethodBaseIndex) |
michael@0 | 458 | return mParent-> |
michael@0 | 459 | GetInterfaceIsArgNumberForParam(methodIndex, param, argnum); |
michael@0 | 460 | |
michael@0 | 461 | if(methodIndex >= mMethodBaseIndex + |
michael@0 | 462 | mDescriptor->num_methods) |
michael@0 | 463 | { |
michael@0 | 464 | NS_ERROR("bad index"); |
michael@0 | 465 | return NS_ERROR_INVALID_ARG; |
michael@0 | 466 | } |
michael@0 | 467 | |
michael@0 | 468 | const XPTTypeDescriptor *td = ¶m->type; |
michael@0 | 469 | |
michael@0 | 470 | while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { |
michael@0 | 471 | td = &mDescriptor-> |
michael@0 | 472 | additional_types[td->type.additional_type]; |
michael@0 | 473 | } |
michael@0 | 474 | |
michael@0 | 475 | if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) { |
michael@0 | 476 | NS_ERROR("not an iid_is"); |
michael@0 | 477 | return NS_ERROR_INVALID_ARG; |
michael@0 | 478 | } |
michael@0 | 479 | |
michael@0 | 480 | *argnum = td->argnum; |
michael@0 | 481 | return NS_OK; |
michael@0 | 482 | } |
michael@0 | 483 | |
michael@0 | 484 | /* bool isIID (in nsIIDPtr IID); */ |
michael@0 | 485 | nsresult |
michael@0 | 486 | xptiInterfaceEntry::IsIID(const nsIID * IID, bool *_retval) |
michael@0 | 487 | { |
michael@0 | 488 | // It is not necessary to Resolve because this info is read from manifest. |
michael@0 | 489 | *_retval = mIID.Equals(*IID); |
michael@0 | 490 | return NS_OK; |
michael@0 | 491 | } |
michael@0 | 492 | |
michael@0 | 493 | /* void getNameShared ([shared, retval] out string name); */ |
michael@0 | 494 | nsresult |
michael@0 | 495 | xptiInterfaceEntry::GetNameShared(const char **name) |
michael@0 | 496 | { |
michael@0 | 497 | // It is not necessary to Resolve because this info is read from manifest. |
michael@0 | 498 | *name = mName; |
michael@0 | 499 | return NS_OK; |
michael@0 | 500 | } |
michael@0 | 501 | |
michael@0 | 502 | /* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */ |
michael@0 | 503 | nsresult |
michael@0 | 504 | xptiInterfaceEntry::GetIIDShared(const nsIID * *iid) |
michael@0 | 505 | { |
michael@0 | 506 | // It is not necessary to Resolve because this info is read from manifest. |
michael@0 | 507 | *iid = &mIID; |
michael@0 | 508 | return NS_OK; |
michael@0 | 509 | } |
michael@0 | 510 | |
michael@0 | 511 | /* bool hasAncestor (in nsIIDPtr iid); */ |
michael@0 | 512 | nsresult |
michael@0 | 513 | xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval) |
michael@0 | 514 | { |
michael@0 | 515 | *_retval = false; |
michael@0 | 516 | |
michael@0 | 517 | for(xptiInterfaceEntry* current = this; |
michael@0 | 518 | current; |
michael@0 | 519 | current = current->mParent) |
michael@0 | 520 | { |
michael@0 | 521 | if(current->mIID.Equals(*iid)) |
michael@0 | 522 | { |
michael@0 | 523 | *_retval = true; |
michael@0 | 524 | break; |
michael@0 | 525 | } |
michael@0 | 526 | if(!current->EnsureResolved()) |
michael@0 | 527 | return NS_ERROR_UNEXPECTED; |
michael@0 | 528 | } |
michael@0 | 529 | |
michael@0 | 530 | return NS_OK; |
michael@0 | 531 | } |
michael@0 | 532 | |
michael@0 | 533 | /***************************************************/ |
michael@0 | 534 | |
michael@0 | 535 | already_AddRefed<xptiInterfaceInfo> |
michael@0 | 536 | xptiInterfaceEntry::InterfaceInfo() |
michael@0 | 537 | { |
michael@0 | 538 | #ifdef DEBUG |
michael@0 | 539 | XPTInterfaceInfoManager::GetSingleton()->mWorkingSet.mTableReentrantMonitor. |
michael@0 | 540 | AssertCurrentThreadIn(); |
michael@0 | 541 | #endif |
michael@0 | 542 | LOG_INFO_MONITOR_ENTRY; |
michael@0 | 543 | |
michael@0 | 544 | if(!mInfo) |
michael@0 | 545 | { |
michael@0 | 546 | mInfo = new xptiInterfaceInfo(this); |
michael@0 | 547 | } |
michael@0 | 548 | |
michael@0 | 549 | nsRefPtr<xptiInterfaceInfo> info = mInfo; |
michael@0 | 550 | return info.forget(); |
michael@0 | 551 | } |
michael@0 | 552 | |
michael@0 | 553 | void |
michael@0 | 554 | xptiInterfaceEntry::LockedInvalidateInterfaceInfo() |
michael@0 | 555 | { |
michael@0 | 556 | if(mInfo) |
michael@0 | 557 | { |
michael@0 | 558 | mInfo->Invalidate(); |
michael@0 | 559 | mInfo = nullptr; |
michael@0 | 560 | } |
michael@0 | 561 | } |
michael@0 | 562 | |
michael@0 | 563 | bool |
michael@0 | 564 | xptiInterfaceInfo::BuildParent() |
michael@0 | 565 | { |
michael@0 | 566 | mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::GetSingleton()-> |
michael@0 | 567 | mWorkingSet.mTableReentrantMonitor); |
michael@0 | 568 | NS_ASSERTION(mEntry && |
michael@0 | 569 | mEntry->IsFullyResolved() && |
michael@0 | 570 | !mParent && |
michael@0 | 571 | mEntry->Parent(), |
michael@0 | 572 | "bad BuildParent call"); |
michael@0 | 573 | mParent = mEntry->Parent()->InterfaceInfo().take(); |
michael@0 | 574 | return true; |
michael@0 | 575 | } |
michael@0 | 576 | |
michael@0 | 577 | /***************************************************************************/ |
michael@0 | 578 | |
michael@0 | 579 | NS_IMPL_QUERY_INTERFACE(xptiInterfaceInfo, nsIInterfaceInfo) |
michael@0 | 580 | |
michael@0 | 581 | xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry) |
michael@0 | 582 | : mEntry(entry), mParent(nullptr) |
michael@0 | 583 | { |
michael@0 | 584 | LOG_INFO_CREATE(this); |
michael@0 | 585 | } |
michael@0 | 586 | |
michael@0 | 587 | xptiInterfaceInfo::~xptiInterfaceInfo() |
michael@0 | 588 | { |
michael@0 | 589 | LOG_INFO_DESTROY(this); |
michael@0 | 590 | NS_IF_RELEASE(mParent); |
michael@0 | 591 | NS_ASSERTION(!mEntry, "bad state in dtor"); |
michael@0 | 592 | } |
michael@0 | 593 | |
michael@0 | 594 | MozExternalRefCountType |
michael@0 | 595 | xptiInterfaceInfo::AddRef(void) |
michael@0 | 596 | { |
michael@0 | 597 | nsrefcnt cnt = ++mRefCnt; |
michael@0 | 598 | NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this)); |
michael@0 | 599 | return cnt; |
michael@0 | 600 | } |
michael@0 | 601 | |
michael@0 | 602 | MozExternalRefCountType |
michael@0 | 603 | xptiInterfaceInfo::Release(void) |
michael@0 | 604 | { |
michael@0 | 605 | xptiInterfaceEntry* entry = mEntry; |
michael@0 | 606 | nsrefcnt cnt = --mRefCnt; |
michael@0 | 607 | NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo"); |
michael@0 | 608 | if(!cnt) |
michael@0 | 609 | { |
michael@0 | 610 | mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager:: |
michael@0 | 611 | GetSingleton()->mWorkingSet. |
michael@0 | 612 | mTableReentrantMonitor); |
michael@0 | 613 | LOG_INFO_MONITOR_ENTRY; |
michael@0 | 614 | |
michael@0 | 615 | // If InterfaceInfo added and *released* a reference before we |
michael@0 | 616 | // acquired the monitor then 'this' might already be dead. In that |
michael@0 | 617 | // case we would not want to try to access any instance data. We |
michael@0 | 618 | // would want to bail immediately. If 'this' is already dead then the |
michael@0 | 619 | // entry will no longer have a pointer to 'this'. So, we can protect |
michael@0 | 620 | // ourselves from danger without more aggressive locking. |
michael@0 | 621 | if(entry && !entry->InterfaceInfoEquals(this)) |
michael@0 | 622 | return 0; |
michael@0 | 623 | |
michael@0 | 624 | // If InterfaceInfo added a reference before we acquired the monitor |
michael@0 | 625 | // then we want to bail out of here without destorying the object. |
michael@0 | 626 | if(mRefCnt) |
michael@0 | 627 | return 1; |
michael@0 | 628 | |
michael@0 | 629 | if(mEntry) |
michael@0 | 630 | { |
michael@0 | 631 | mEntry->LockedInterfaceInfoDeathNotification(); |
michael@0 | 632 | mEntry = nullptr; |
michael@0 | 633 | } |
michael@0 | 634 | |
michael@0 | 635 | delete this; |
michael@0 | 636 | return 0; |
michael@0 | 637 | } |
michael@0 | 638 | return cnt; |
michael@0 | 639 | } |
michael@0 | 640 | |
michael@0 | 641 | /***************************************************************************/ |