|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "xpcprivate.h" |
|
8 #include "XPCJSWeakReference.h" |
|
9 |
|
10 #include "nsContentUtils.h" |
|
11 |
|
12 using namespace JS; |
|
13 |
|
14 xpcJSWeakReference::xpcJSWeakReference() |
|
15 { |
|
16 } |
|
17 |
|
18 NS_IMPL_ISUPPORTS(xpcJSWeakReference, xpcIJSWeakReference) |
|
19 |
|
20 nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object) |
|
21 { |
|
22 if (!object.isObject()) |
|
23 return NS_OK; |
|
24 |
|
25 JS::RootedObject obj(cx, &object.toObject()); |
|
26 |
|
27 XPCCallContext ccx(NATIVE_CALLER, cx); |
|
28 |
|
29 // See if the object is a wrapped native that supports weak references. |
|
30 nsISupports* supports = |
|
31 nsXPConnect::XPConnect()->GetNativeOfWrapper(cx, obj); |
|
32 nsCOMPtr<nsISupportsWeakReference> supportsWeakRef = |
|
33 do_QueryInterface(supports); |
|
34 if (supportsWeakRef) { |
|
35 supportsWeakRef->GetWeakReference(getter_AddRefs(mReferent)); |
|
36 if (mReferent) { |
|
37 return NS_OK; |
|
38 } |
|
39 } |
|
40 // If it's not a wrapped native, or it is a wrapped native that does not |
|
41 // support weak references, fall back to getting a weak ref to the object. |
|
42 |
|
43 // See if object is a wrapped JSObject. |
|
44 nsRefPtr<nsXPCWrappedJS> wrapped; |
|
45 nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, |
|
46 NS_GET_IID(nsISupports), |
|
47 getter_AddRefs(wrapped)); |
|
48 if (!wrapped) { |
|
49 NS_ERROR("can't get nsISupportsWeakReference wrapper for obj"); |
|
50 return rv; |
|
51 } |
|
52 |
|
53 return wrapped->GetWeakReference(getter_AddRefs(mReferent)); |
|
54 } |
|
55 |
|
56 NS_IMETHODIMP |
|
57 xpcJSWeakReference::Get(JSContext* aCx, MutableHandleValue aRetval) |
|
58 { |
|
59 aRetval.setNull(); |
|
60 |
|
61 if (!mReferent) { |
|
62 return NS_OK; |
|
63 } |
|
64 |
|
65 nsCOMPtr<nsISupports> supports = do_QueryReferent(mReferent); |
|
66 if (!supports) { |
|
67 return NS_OK; |
|
68 } |
|
69 |
|
70 nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(supports); |
|
71 if (!wrappedObj) { |
|
72 // We have a generic XPCOM object that supports weak references here. |
|
73 // Wrap it and pass it out. |
|
74 return nsContentUtils::WrapNative(aCx, supports, |
|
75 &NS_GET_IID(nsISupports), |
|
76 aRetval); |
|
77 } |
|
78 |
|
79 JS::RootedObject obj(aCx, wrappedObj->GetJSObject()); |
|
80 if (!obj) { |
|
81 return NS_OK; |
|
82 } |
|
83 |
|
84 // Most users of XPCWrappedJS don't need to worry about |
|
85 // re-wrapping because things are implicitly rewrapped by |
|
86 // xpcconvert. However, because we're doing this directly |
|
87 // through the native call context, we need to call |
|
88 // JS_WrapObject(). |
|
89 if (!JS_WrapObject(aCx, &obj)) { |
|
90 return NS_ERROR_FAILURE; |
|
91 } |
|
92 |
|
93 aRetval.setObject(*obj); |
|
94 return NS_OK; |
|
95 } |