nsIPrincipal* nsXPConnect::GetPrincipal(JSObject* obj, bool allowShortCircuit) const { MOZ_ASSERT(IS_WN_REFLECTOR(obj), "What kind of wrapper is this?"); XPCWrappedNative* xpcWrapper = XPCWrappedNative::Get(obj); if (xpcWrapper) { if (allowShortCircuit) { nsIPrincipal* result = xpcWrapper->GetObjectPrincipal(); if (result) { return result; } } // If not, check if it points to an nsIScriptObjectPrincipal nsCOMPtr<nsIScriptObjectPrincipal> objPrin = do_QueryInterface(xpcWrapper->Native()); if (objPrin) { nsIPrincipal* result = objPrin->GetPrincipal(); if (result) { return result; } } } return nullptr; }
nsISupports* castNativeFromWrapper(JSContext *cx, JSObject *obj, uint32_t interfaceBit, uint32_t protoID, int32_t protoDepth, nsISupports **pRef, jsval *pVal, nsresult *rv) { XPCWrappedNative *wrapper; XPCWrappedNativeTearOff *tearoff; JSObject *cur; if (IS_WRAPPER_CLASS(js::GetObjectClass(obj))) { cur = obj; wrapper = IS_WN_WRAPPER_OBJECT(cur) ? (XPCWrappedNative*)xpc_GetJSPrivate(obj) : nullptr; tearoff = nullptr; } else { *rv = getWrapper(cx, obj, &wrapper, &cur, &tearoff); if (NS_FAILED(*rv)) return nullptr; } nsISupports *native; if (wrapper) { native = wrapper->GetIdentityObject(); cur = wrapper->GetFlatJSObject(); if (!native || !HasBitInInterfacesBitmap(cur, interfaceBit)) { native = nullptr; } } else if (cur && IS_SLIM_WRAPPER(cur)) { native = static_cast<nsISupports*>(xpc_GetJSPrivate(cur)); if (!native || !HasBitInInterfacesBitmap(cur, interfaceBit)) { native = nullptr; } } else if (cur && protoDepth >= 0) { const mozilla::dom::DOMClass* domClass = mozilla::dom::GetDOMClass(cur); native = mozilla::dom::UnwrapDOMObject<nsISupports>(cur); if (native && (uint32_t)domClass->mInterfaceChain[protoDepth] != protoID) { native = nullptr; } } else { native = nullptr; } if (native) { *pRef = nullptr; *pVal = OBJECT_TO_JSVAL(cur); *rv = NS_OK; } else { *rv = NS_ERROR_XPC_BAD_CONVERT_JS; } return native; }
JSBool XPC_COW_RewrapForChrome(JSContext *cx, JSObject *wrapperObj, jsval *vp) { jsval v = *vp; if (JSVAL_IS_PRIMITIVE(v)) { return JS_TRUE; } // We're rewrapping for chrome, so this is safe. JSObject *obj = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v)); if (!obj) { *vp = JSVAL_NULL; return JS_TRUE; } XPCWrappedNative *wn; if (IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) && (wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj)) && !nsXPCWrappedJSClass::IsWrappedJS(wn->Native())) { // Return an explicit XPCNativeWrapper in case "chrome" code happens to be // XBL code cloned into an untrusted context. return XPCNativeWrapperCtor(cx, obj, 1, vp, vp); } return XPC_SJOW_Construct(cx, obj, 1, vp, vp); }
static JSBool XPC_COW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) { // Convert both sides to XPCWrappedNative and see if they match. if (JSVAL_IS_PRIMITIVE(v)) { *bp = JS_FALSE; return JS_TRUE; } JSObject *test = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v)); obj = GetWrappedObject(cx, obj); if (!obj) { return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } XPCWrappedNative *other = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, test); if (!other) { *bp = JS_FALSE; return JS_TRUE; } XPCWrappedNative *me = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); obj = me->GetFlatJSObject(); test = other->GetFlatJSObject(); return ((JSExtendedClass *)STOBJ_GET_CLASS(obj))-> equality(cx, obj, OBJECT_TO_JSVAL(test), bp); }
JSObject * WrapperFactory::WrapForSameCompartment(JSContext *cx, HandleObject objArg) { RootedObject obj(cx, objArg); MOZ_ASSERT(js::IsObjectInContextCompartment(obj, cx)); // NB: The contract of WrapForSameCompartment says that |obj| may or may not // be a security wrapper. These checks implicitly handle the security // wrapper case. // Outerize if necessary. This, in combination with the check in // PrepareForUnwrapping, means that calling JS_Wrap* always outerizes. obj = JS_ObjectToOuterObject(cx, obj); NS_ENSURE_TRUE(obj, nullptr); if (dom::GetSameCompartmentWrapperForDOMBinding(*obj.address())) { return obj; } MOZ_ASSERT(!dom::IsDOMObject(obj)); if (!IS_WN_WRAPPER(obj)) return obj; // Extract the WN. It should exist. XPCWrappedNative *wn = static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj)); MOZ_ASSERT(wn, "Trying to wrap a dead WN!"); // The WN knows what to do. RootedObject wrapper(cx, wn->GetSameCompartmentSecurityWrapper(cx)); MOZ_ASSERT_IF(wrapper != obj && IsComponentsObject(js::UncheckedUnwrap(obj)), !Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap()); return wrapper; }
static JSObject * EnsureExpandoObject(JSContext *cx, JSObject *holder) { NS_ASSERTION(holder->getJSClass() == &HolderClass, "expected a native property holder object"); JSObject *expando = GetExpandoObject(holder); if (expando) return expando; CompartmentPrivate *priv = (CompartmentPrivate *)JS_GetCompartmentPrivate(cx, holder->compartment()); XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); expando = priv->LookupExpandoObject(wn); if (!expando) { expando = JS_NewObjectWithGivenProto(cx, nsnull, nsnull, holder->getParent()); if (!expando) return NULL; // Add the expando object to the expando map to keep it alive. if (!priv->RegisterExpandoObject(wn, expando)) { JS_ReportOutOfMemory(cx); return NULL; } // Make sure the wn stays alive so it keeps the expando object alive. nsRefPtr<nsXPCClassInfo> ci; CallQueryInterface(wn->Native(), getter_AddRefs(ci)); if (ci) ci->PreserveWrapper(wn->Native()); } holder->setSlot(JSSLOT_EXPANDO, ObjectValue(*expando)); return expando; }
static JSBool holder_set(JSContext *cx, JSObject *wrapper, jsid id, JSBool strict, jsval *vp) { wrapper = FindWrapper(wrapper); JSObject *holder = GetHolder(wrapper); if (IsResolving(holder, id)) { return true; } XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); if (NATIVE_HAS_FLAG(wn, WantSetProperty)) { JSAutoEnterCompartment ac; if (!ac.enter(cx, holder)) return false; PRBool retval = true; nsresult rv = wn->GetScriptableCallback()->SetProperty(wn, cx, wrapper, id, vp, &retval); if (NS_FAILED(rv) || !retval) { if (retval) XPCThrower::Throw(rv, cx); return false; } } return true; }
static JSBool XrayToString(JSContext *cx, uintN argc, jsval *vp) { JSObject *wrapper = JS_THIS_OBJECT(cx, vp); if (!wrapper->isWrapper() || !WrapperFactory::IsXrayWrapper(wrapper)) { JS_ReportError(cx, "XrayToString called on an incompatible object"); return false; } JSObject *holder = GetHolder(wrapper); XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); JSObject *wrappednative = wn->GetFlatJSObject(); XPCCallContext ccx(JS_CALLER, cx, wrappednative); char *wrapperStr = wn->ToString(ccx); if (!wrapperStr) { JS_ReportOutOfMemory(cx); return false; } nsAutoString result(NS_LITERAL_STRING("[object XrayWrapper ")); result.AppendASCII(wrapperStr); JS_smprintf_free(wrapperStr); result.Append(']'); JSString *str = JS_NewUCStringCopyN(cx, reinterpret_cast<const jschar *>(result.get()), result.Length()); if (!str) return false; *vp = STRING_TO_JSVAL(str); return true; }
/** * Get the interface name and member name (for error messages). * * We could instead have each quick stub pass its name to the error-handling * functions, as that name is statically known. But that would be redundant; * the information is handy at runtime anyway. Also, this code often produces * a more specific error message, e.g. "[nsIDOMHTMLDocument.appendChild]" * rather than "[nsIDOMNode.appendChild]". */ static void GetMemberInfo(JSObject *obj, jsid memberId, const char **ifaceName) { *ifaceName = "Unknown"; // Don't try to generate a useful name if there are security wrappers, // because it isn't worth the risk of something going wrong just to generate // an error message. Instead, only handle the simple case where we have the // reflector in hand. if (IS_WRAPPER_CLASS(js::GetObjectClass(obj))) { XPCWrappedNativeProto *proto; if (IS_SLIM_WRAPPER_OBJECT(obj)) { proto = GetSlimWrapperProto(obj); } else { MOZ_ASSERT(IS_WN_WRAPPER_OBJECT(obj)); XPCWrappedNative *wrapper = static_cast<XPCWrappedNative *>(js::GetObjectPrivate(obj)); proto = wrapper->GetProto(); } if (proto) { XPCNativeSet *set = proto->GetSet(); if (set) { XPCNativeMember *member; XPCNativeInterface *iface; if (set->FindMember(memberId, &member, &iface)) *ifaceName = iface->GetNameString(); } } } }
XPCWrappedNative* XPCCallContext::UnwrapThisIfAllowed(HandleObject obj, HandleObject fun, unsigned argc) { // We should only get here for objects that aren't safe to unwrap. MOZ_ASSERT(!js::CheckedUnwrap(obj)); MOZ_ASSERT(js::IsObjectInContextCompartment(obj, mJSContext)); // We can't do anything here without a function. if (!fun) return nullptr; // Determine if we're allowed to unwrap the security wrapper to invoke the // method. // // We have the Interface and Member that this corresponds to, but // unfortunately our access checks are based on the object class name and // property name. So we cheat a little bit here - we verify that the object // does indeed implement the method's Interface, and then just check that we // can successfully access property with method's name from the object. // First, get the XPCWN out of the underlying object. We should have a wrapper // here, potentially an outer window proxy, and then an XPCWN. MOZ_ASSERT(js::IsWrapper(obj)); RootedObject unwrapped(mJSContext, js::UncheckedUnwrap(obj, /* stopAtOuter = */ false)); #ifdef DEBUG JS::Rooted<JSObject*> wrappedObj(mJSContext, js::Wrapper::wrappedObject(obj)); MOZ_ASSERT(unwrapped == JS_ObjectToInnerObject(mJSContext, wrappedObj)); #endif // Make sure we have an XPCWN, and grab it. if (!IS_WN_REFLECTOR(unwrapped)) return nullptr; XPCWrappedNative *wn = XPCWrappedNative::Get(unwrapped); // Next, get the call info off the function object. XPCNativeInterface *interface; XPCNativeMember *member; XPCNativeMember::GetCallInfo(fun, &interface, &member); // To be extra safe, make sure that the underlying native implements the // interface before unwrapping. Even if we didn't check this, we'd still // theoretically fail during tearoff lookup for mismatched methods. if (!wn->HasInterfaceNoQI(*interface->GetIID())) return nullptr; // See if the access is permitted. // // NB: This calculation of SET vs GET is a bit wonky, but that's what // XPC_WN_GetterSetter does. bool set = argc && argc != NO_ARGS && member->IsWritableAttribute(); js::Wrapper::Action act = set ? js::Wrapper::SET : js::Wrapper::GET; const js::Wrapper *handler = js::Wrapper::wrapperHandler(obj); bool ignored; JS::Rooted<jsid> id(mJSContext, member->GetName()); if (!handler->enter(mJSContext, obj, id, act, &ignored)) return nullptr; // Ok, this call is safe. return wn; }
WNSecPolicyClearer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if(wrapper->HasProto() && !wrapper->HasSharedProto()) *(wrapper->GetProto()->GetSecurityInfoAddr()) = nsnull; return JS_DHASH_NEXT; }
DEBUG_WrapperChecker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { XPCWrappedNative* wrapper = (XPCWrappedNative*)((JSDHashEntryStub*)hdr)->key; NS_ASSERTION(!wrapper->IsValid(), "found a 'valid' wrapper!"); ++ *((int*)arg); return JS_DHASH_NEXT; }
static void WrappedNativeObjectMoved(JSObject* obj, const JSObject* old) { nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj)); if (!p) return; XPCWrappedNative* wrapper = static_cast<XPCWrappedNative*>(p); wrapper->FlatJSObjectMoved(obj, old); }
static JSDHashOperator WrappedNativeJSGCThingTracer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32_t number, void *arg) { XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if (wrapper->HasExternalReference() && !wrapper->IsWrapperExpired()) wrapper->TraceSelf((JSTracer *)arg); return JS_DHASH_NEXT; }
JSBool xpc_JSObjectIsID(JSContext *cx, JSObject* obj) { NS_ASSERTION(cx && obj, "bad param"); // NOTE: this call does NOT addref XPCWrappedNative* wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); return wrapper && (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) || wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) || wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID))); }
nsISupports* castNativeFromWrapper(JSContext *cx, JSObject *obj, uint32_t interfaceBit, uint32_t protoID, int32_t protoDepth, nsISupports **pRef, MutableHandleValue pVal, nsresult *rv) { XPCWrappedNative *wrapper; XPCWrappedNativeTearOff *tearoff; JSObject *cur; if (IS_WN_REFLECTOR(obj)) { cur = obj; wrapper = XPCWrappedNative::Get(obj); tearoff = nullptr; } else { *rv = getWrapper(cx, obj, &wrapper, &cur, &tearoff); if (NS_FAILED(*rv)) return nullptr; } nsISupports *native; if (wrapper) { native = wrapper->GetIdentityObject(); cur = wrapper->GetFlatJSObject(); if (!native || !HasBitInInterfacesBitmap(cur, interfaceBit)) { native = nullptr; } } else if (cur && protoDepth >= 0) { const mozilla::dom::DOMClass* domClass = mozilla::dom::GetDOMClass(cur); native = mozilla::dom::UnwrapDOMObject<nsISupports>(cur); if (native && (uint32_t)domClass->mInterfaceChain[protoDepth] != protoID) { native = nullptr; } } else { native = nullptr; } if (native) { *pRef = nullptr; pVal.setObjectOrNull(cur); *rv = NS_OK; } else { *rv = NS_ERROR_XPC_BAD_CONVERT_JS; } return native; }
/* static */ void XPCWrappedNative::Trace(JSTracer* trc, JSObject* obj) { const js::Class* clazz = js::GetObjectClass(obj); if (clazz->flags & JSCLASS_DOM_GLOBAL) { mozilla::dom::TraceProtoAndIfaceCache(trc, obj); } MOZ_ASSERT(IS_WN_CLASS(clazz)); XPCWrappedNative* wrapper = XPCWrappedNative::Get(obj); if (wrapper && wrapper->IsValid()) wrapper->TraceInside(trc); }
bool AccessCheck::needsSystemOnlyWrapper(JSObject *obj) { JSObject* wrapper = obj; if (dom::GetSameCompartmentWrapperForDOMBinding(wrapper)) return wrapper != obj; if (!IS_WN_REFLECTOR(obj)) return false; XPCWrappedNative *wn = XPCWrappedNative::Get(obj); return wn->NeedsSOW(); }
static JSDHashOperator WrappedNativeJSGCThingTracer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32_t number, void *arg) { XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if (wrapper->HasExternalReference() && !wrapper->IsWrapperExpired()) { JSTracer* trc = (JSTracer *)arg; JS_CALL_OBJECT_TRACER(trc, wrapper->GetFlatJSObjectPreserveColor(), "XPCWrappedNative::mFlatJSObject"); } return JS_DHASH_NEXT; }
static JSDHashOperator WrappedNativeShutdownEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32_t number, void *arg) { ShutdownData* data = (ShutdownData*) arg; XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if (wrapper->IsValid()) { wrapper->SystemIsBeingShutDown(); data->wrapperCount++; } return JS_DHASH_REMOVE; }
static JSDHashOperator WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32_t number, void *arg) { XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if (wrapper->HasExternalReference()) { SuspectClosure* closure = static_cast<SuspectClosure*>(arg); XPCJSRuntime::SuspectWrappedNative(closure->cx, wrapper, closure->cb); } return JS_DHASH_NEXT; }
static PLDHashOperator MoveableWrapperFinder(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number, void *arg) { nsTArray<nsRefPtr<XPCWrappedNative> > *array = static_cast<nsTArray<nsRefPtr<XPCWrappedNative> > *>(arg); XPCWrappedNative *wn = ((Native2WrappedNativeMap::Entry*)hdr)->value; // If a wrapper is expired, then there are no references to it from JS, so // we don't have to move it. if (!wn->IsWrapperExpired()) array->AppendElement(wn); return PL_DHASH_NEXT; }
bool xpc_JSObjectIsID(JSContext* cx, JSObject* obj) { MOZ_ASSERT(cx && obj, "bad param"); // NOTE: this call does NOT addref XPCWrappedNative* wrapper = nullptr; obj = js::CheckedUnwrap(obj); if (obj && IS_WN_REFLECTOR(obj)) wrapper = XPCWrappedNative::Get(obj); return wrapper && (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) || wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) || wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID))); }
static JSDHashOperator WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32_t number, void *arg) { XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if (wrapper->HasExternalReference()) { nsCycleCollectionTraversalCallback *cb = static_cast<nsCycleCollectionTraversalCallback *>(arg); XPCJSRuntime::SuspectWrappedNative(wrapper, *cb); } return JS_DHASH_NEXT; }
WrappedNativeShutdownEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { ShutdownData* data = (ShutdownData*) arg; XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if(wrapper->IsValid()) { if(wrapper->HasProto() && !wrapper->HasSharedProto()) data->nonSharedProtoCount++; wrapper->SystemIsBeingShutDown(data->cx); data->wrapperCount++; } return JS_DHASH_REMOVE; }
//static void XPCWrappedNativeScope::SystemIsBeingShutDown() { int liveScopeCount = 0; XPCWrappedNativeScope* cur; // First move all the scopes to the dying list. cur = gScopes; while (cur) { XPCWrappedNativeScope* next = cur->mNext; cur->mNext = gDyingScopes; gDyingScopes = cur; cur = next; liveScopeCount++; } gScopes = nullptr; // We're forcibly killing scopes, rather than allowing them to go away // when they're ready. As such, we need to do some cleanup before they // can safely be destroyed. for (cur = gDyingScopes; cur; cur = cur->mNext) { // Give the Components object a chance to try to clean up. if (cur->mComponents) cur->mComponents->SystemIsBeingShutDown(); // Walk the protos first. Wrapper shutdown can leave dangling // proto pointers in the proto map. for (auto i = cur->mWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast<ClassInfo2WrappedNativeProtoMap::Entry*>(i.Get()); entry->value->SystemIsBeingShutDown(); i.Remove(); } for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast<Native2WrappedNativeMap::Entry*>(i.Get()); XPCWrappedNative* wrapper = entry->value; if (wrapper->IsValid()) { wrapper->SystemIsBeingShutDown(); } i.Remove(); } } // Now it is safe to kill all the scopes. KillDyingScopes(); }
static void WrappedNativeFinalize(js::FreeOp* fop, JSObject* obj, WNHelperType helperType) { const js::Class* clazz = js::GetObjectClass(obj); if (clazz->flags & JSCLASS_DOM_GLOBAL) { mozilla::dom::DestroyProtoAndIfaceCache(obj); } nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj)); if (!p) return; XPCWrappedNative* wrapper = static_cast<XPCWrappedNative*>(p); if (helperType == WN_HELPER) wrapper->GetScriptableCallback()->Finalize(wrapper, js::CastToJSFreeOp(fop), obj); wrapper->FlatJSObjectFinalized(); }
// note: returned pointer is only valid while |obj| remains alive! const nsID* xpc_JSObjectToID(JSContext *cx, JSObject* obj) { if (!cx || !obj) return nsnull; // NOTE: this call does NOT addref XPCWrappedNative* wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); if (wrapper && (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) || wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) || wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID)))) { return ((nsIJSID*)wrapper->GetIdentityObject())->GetID(); } return nsnull; }
/** * Get the interface name and member name (for error messages). * * We could instead have each quick stub pass its name to the error-handling * functions, as that name is statically known. But that would be redundant; * the information is handy at runtime anyway. Also, this code often produces * a more specific error message, e.g. "[nsIDOMHTMLDocument.appendChild]" * rather than "[nsIDOMNode.appendChild]". */ static void GetMemberInfo(JSObject *obj, jsval memberId, const char **ifaceName, const char **memberName) { // Get the interface name. From DefinePropertyIfFound (in // xpcwrappednativejsops.cpp) and XPCThrower::Verbosify. // // We could instead make the quick stub could pass in its interface name, // but this code often produces a more specific error message, e.g. *ifaceName = "Unknown"; NS_ASSERTION(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) || STOBJ_GET_CLASS(obj) == &XPC_WN_Tearoff_JSClass || IS_SLIM_WRAPPER(obj), "obj must be a wrapper"); XPCWrappedNativeProto *proto; if(IS_SLIM_WRAPPER(obj)) { proto = GetSlimWrapperProto(obj); } else { XPCWrappedNative *wrapper = (XPCWrappedNative *) obj->getPrivate(); proto = wrapper->GetProto(); } if(proto) { XPCNativeSet *set = proto->GetSet(); if(set) { XPCNativeMember *member; XPCNativeInterface *iface; if(set->FindMember(memberId, &member, &iface)) *ifaceName = iface->GetNameString(); } } *memberName = (JSVAL_IS_STRING(memberId) ? JS_GetStringBytes(JSVAL_TO_STRING(memberId)) : "unknown"); }
// static void XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt) { // Do JS_CallTracer for all wrapped natives with external references, as // well as any DOM expando objects. for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) { for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast<Native2WrappedNativeMap::Entry*>(i.Get()); XPCWrappedNative* wrapper = entry->value; if (wrapper->HasExternalReference() && !wrapper->IsWrapperExpired()) wrapper->TraceSelf(trc); } if (cur->mDOMExpandoSet) { for (DOMExpandoSet::Enum e(*cur->mDOMExpandoSet); !e.empty(); e.popFront()) JS_CallHashSetObjectTracer(trc, e, e.front(), "DOM expando object"); } } }