michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim: set ts=8 sts=4 et sw=4 tw=99: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "xpcprivate.h" michael@0: #include "XPCJSWeakReference.h" michael@0: michael@0: #include "nsContentUtils.h" michael@0: michael@0: using namespace JS; michael@0: michael@0: xpcJSWeakReference::xpcJSWeakReference() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(xpcJSWeakReference, xpcIJSWeakReference) michael@0: michael@0: nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object) michael@0: { michael@0: if (!object.isObject()) michael@0: return NS_OK; michael@0: michael@0: JS::RootedObject obj(cx, &object.toObject()); michael@0: michael@0: XPCCallContext ccx(NATIVE_CALLER, cx); michael@0: michael@0: // See if the object is a wrapped native that supports weak references. michael@0: nsISupports* supports = michael@0: nsXPConnect::XPConnect()->GetNativeOfWrapper(cx, obj); michael@0: nsCOMPtr supportsWeakRef = michael@0: do_QueryInterface(supports); michael@0: if (supportsWeakRef) { michael@0: supportsWeakRef->GetWeakReference(getter_AddRefs(mReferent)); michael@0: if (mReferent) { michael@0: return NS_OK; michael@0: } michael@0: } michael@0: // If it's not a wrapped native, or it is a wrapped native that does not michael@0: // support weak references, fall back to getting a weak ref to the object. michael@0: michael@0: // See if object is a wrapped JSObject. michael@0: nsRefPtr wrapped; michael@0: nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, michael@0: NS_GET_IID(nsISupports), michael@0: getter_AddRefs(wrapped)); michael@0: if (!wrapped) { michael@0: NS_ERROR("can't get nsISupportsWeakReference wrapper for obj"); michael@0: return rv; michael@0: } michael@0: michael@0: return wrapped->GetWeakReference(getter_AddRefs(mReferent)); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: xpcJSWeakReference::Get(JSContext* aCx, MutableHandleValue aRetval) michael@0: { michael@0: aRetval.setNull(); michael@0: michael@0: if (!mReferent) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr supports = do_QueryReferent(mReferent); michael@0: if (!supports) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr wrappedObj = do_QueryInterface(supports); michael@0: if (!wrappedObj) { michael@0: // We have a generic XPCOM object that supports weak references here. michael@0: // Wrap it and pass it out. michael@0: return nsContentUtils::WrapNative(aCx, supports, michael@0: &NS_GET_IID(nsISupports), michael@0: aRetval); michael@0: } michael@0: michael@0: JS::RootedObject obj(aCx, wrappedObj->GetJSObject()); michael@0: if (!obj) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Most users of XPCWrappedJS don't need to worry about michael@0: // re-wrapping because things are implicitly rewrapped by michael@0: // xpcconvert. However, because we're doing this directly michael@0: // through the native call context, we need to call michael@0: // JS_WrapObject(). michael@0: if (!JS_WrapObject(aCx, &obj)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: aRetval.setObject(*obj); michael@0: return NS_OK; michael@0: }