static bool XPC_WN_NoMods_Proto_Resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp) { MOZ_ASSERT(js::GetObjectClass(obj) == &XPC_WN_NoMods_Proto_JSClass, "bad proto"); XPCWrappedNativeProto* self = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); if (!self) return false; XPCCallContext ccx(cx); if (!ccx.IsValid()) return false; XPCNativeScriptableInfo* si = self->GetScriptableInfo(); return DefinePropertyIfFound(ccx, obj, id, self->GetSet(), nullptr, nullptr, self->GetScope(), true, nullptr, nullptr, si, JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_ENUMERATE, resolvedp); }
/** * 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(); } } } }
static bool XPC_WN_Shared_Proto_Enumerate(JSContext* cx, HandleObject obj) { MOZ_ASSERT(js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_Proto_JSClass || js::GetObjectClass(obj) == &XPC_WN_NoMods_Proto_JSClass, "bad proto"); XPCWrappedNativeProto* self = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); if (!self) return false; XPCNativeSet* set = self->GetSet(); if (!set) return false; XPCCallContext ccx(cx); if (!ccx.IsValid()) return false; uint16_t interface_count = set->GetInterfaceCount(); XPCNativeInterface** interfaceArray = set->GetInterfaceArray(); for (uint16_t i = 0; i < interface_count; i++) { XPCNativeInterface* iface = interfaceArray[i]; uint16_t member_count = iface->GetMemberCount(); for (uint16_t k = 0; k < member_count; k++) { if (!xpc_ForcePropertyResolve(cx, obj, iface->GetMemberAt(k)->GetName())) return false; } } return true; }
WNProtoSecPolicyClearer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { XPCWrappedNativeProto* proto = ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value; *(proto->GetSecurityInfoAddr()) = nsnull; return JS_DHASH_NEXT; }
static void XPC_WN_Shared_Proto_ObjectMoved(JSObject* obj, const JSObject* old) { // This can be null if xpc shutdown has already happened XPCWrappedNativeProto* p = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); if (p) p->JSProtoObjectMoved(obj, old); }
static void XPC_WN_Shared_Proto_Finalize(js::FreeOp* fop, JSObject* obj) { // This can be null if xpc shutdown has already happened XPCWrappedNativeProto* p = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); if (p) p->JSProtoObjectFinalized(fop, obj); }
DetachedWrappedNativeProtoShutdownMarker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { XPCWrappedNativeProto* proto = (XPCWrappedNativeProto*)((JSDHashEntryStub*)hdr)->key; proto->SystemIsBeingShutDown((JSContext*)arg); return JS_DHASH_NEXT; }
DetachedWrappedNativeProtoMarker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { XPCWrappedNativeProto* proto = (XPCWrappedNativeProto*)((JSDHashEntryStub*)hdr)->key; proto->Mark(); return JS_DHASH_NEXT; }
static PLDHashOperator WNProtoSecPolicyClearer(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number, void *arg) { XPCWrappedNativeProto* proto = ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value; *(proto->GetSecurityInfoAddr()) = nullptr; return PL_DHASH_NEXT; }
static void XPC_WN_Shared_Proto_Trace(JSTracer* trc, JSObject* obj) { // This can be null if xpc shutdown has already happened XPCWrappedNativeProto* p = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); if (p) p->TraceInside(trc); }
/** * 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"); }
/** * 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_WN_REFLECTOR(obj)) { XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj); XPCWrappedNativeProto *proto = wrapper->GetProto(); if (proto) { XPCNativeSet *set = proto->GetSet(); if (set) { XPCNativeMember *member; XPCNativeInterface *iface; if (set->FindMember(memberId, &member, &iface)) *ifaceName = iface->GetNameString(); } } } }
WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { SuspectClosure* closure = static_cast<SuspectClosure*>(arg); XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; XPCWrappedNativeProto* proto = wrapper->GetProto(); if(proto && proto->ClassIsMainThreadOnly() && wrapper->IsValid()) { NS_ASSERTION(NS_IsMainThread(), "Suspecting wrapped natives from non-main thread"); #ifndef DEBUG_CC // Only record objects that might be part of a cycle as roots. if(!JS_IsAboutToBeFinalized(closure->cx, wrapper->GetFlatJSObject())) return JS_DHASH_NEXT; #endif closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, wrapper->GetFlatJSObject(), nsXPConnect::GetXPConnect()); } return JS_DHASH_NEXT; }
/* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out PRBool bp); */ NS_IMETHODIMP nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, const jsval &val, PRBool *bp, PRBool *_retval) { *bp = JS_FALSE; nsresult rv = NS_OK; if(!JSVAL_IS_PRIMITIVE(val)) { // we have a JSObject JSObject* obj = JSVAL_TO_OBJECT(val); NS_ASSERTION(obj, "when is an object not an object?"); // is this really a native xpcom object with a wrapper? const nsIID* iid; mInfo->GetIIDShared(&iid); if(IS_SLIM_WRAPPER(obj)) { XPCWrappedNativeProto* proto = GetSlimWrapperProto(obj); if(proto->GetSet()->HasInterfaceWithAncestor(iid)) { *bp = JS_TRUE; return NS_OK; } #ifdef DEBUG_slimwrappers char foo[NSID_LENGTH]; iid->ToProvidedString(foo); SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, foo); #endif if(!MorphSlimWrapper(cx, obj)) return NS_ERROR_FAILURE; } XPCWrappedNative* other_wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); if(!other_wrapper) return NS_OK; // We'll trust the interface set of the wrapper if this is known // to be an interface that the objects *expects* to be able to // handle. if(other_wrapper->HasInterfaceNoQI(*iid)) { *bp = JS_TRUE; return NS_OK; } // Otherwise, we'll end up Querying the native object to be sure. XPCCallContext ccx(JS_CALLER, cx); AutoMarkingNativeInterfacePtr iface(ccx); iface = XPCNativeInterface::GetNewOrUsed(ccx, iid); if(iface && other_wrapper->FindTearOff(ccx, iface)) *bp = JS_TRUE; } return rv; }
/* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */ NS_IMETHODIMP nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, const jsval &val, bool *bp, bool *_retval) { *bp = false; nsresult rv = NS_OK; if (!JSVAL_IS_PRIMITIVE(val)) { // we have a JSObject JSObject* obj = JSVAL_TO_OBJECT(val); NS_ASSERTION(obj, "when is an object not an object?"); // is this really a native xpcom object with a wrapper? const nsIID* iid; mInfo->GetIIDShared(&iid); if (IS_SLIM_WRAPPER(obj)) { XPCWrappedNativeProto* proto = GetSlimWrapperProto(obj); if (proto->GetSet()->HasInterfaceWithAncestor(iid)) { *bp = true; return NS_OK; } #ifdef DEBUG_slimwrappers char foo[NSID_LENGTH]; iid->ToProvidedString(foo); SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, foo); #endif if (!MorphSlimWrapper(cx, obj)) return NS_ERROR_FAILURE; } nsISupports *identity; if (mozilla::dom::binding::instanceIsProxy(obj)) { identity = static_cast<nsISupports*>(js::GetProxyPrivate(obj).toPrivate()); } else if (mozilla::dom::bindings::IsDOMClass(js::GetObjectJSClass(obj))) { NS_ASSERTION(mozilla::dom::bindings::DOMJSClass::FromJSClass( js::GetObjectJSClass(obj))->mDOMObjectIsISupports, "This only works on nsISupports classes!"); identity = mozilla::dom::bindings::UnwrapDOMObject<nsISupports>(obj, js::GetObjectJSClass(obj)); } else { identity = nsnull; } if (identity) { nsCOMPtr<nsIClassInfo> ci = do_QueryInterface(identity); XPCCallContext ccx(JS_CALLER, cx); AutoMarkingNativeSetPtr set(ccx); set = XPCNativeSet::GetNewOrUsed(ccx, ci); if (!set) return NS_ERROR_FAILURE; *bp = set->HasInterfaceWithAncestor(iid); return NS_OK; } XPCWrappedNative* other_wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); if (!other_wrapper) return NS_OK; // We'll trust the interface set of the wrapper if this is known // to be an interface that the objects *expects* to be able to // handle. if (other_wrapper->HasInterfaceNoQI(*iid)) { *bp = true; return NS_OK; } // Otherwise, we'll end up Querying the native object to be sure. XPCCallContext ccx(JS_CALLER, cx); AutoMarkingNativeInterfacePtr iface(ccx); iface = XPCNativeInterface::GetNewOrUsed(ccx, iid); nsresult findResult = NS_OK; if (iface && other_wrapper->FindTearOff(ccx, iface, false, &findResult)) *bp = true; if (NS_FAILED(findResult) && findResult != NS_ERROR_NO_INTERFACE) rv = findResult; } return rv; }