1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla XPConnect code, released
18 : * June 30, 2009.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * The Mozilla Foundation
22 : *
23 : * Contributor(s):
24 : * Andreas Gal <gal@mozilla.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef xpcpublic_h
41 : #define xpcpublic_h
42 :
43 : #include "jsapi.h"
44 : #include "js/MemoryMetrics.h"
45 : #include "jsclass.h"
46 : #include "jsfriendapi.h"
47 : #include "jsgc.h"
48 : #include "jspubtd.h"
49 : #include "jsproxy.h"
50 :
51 : #include "nsISupports.h"
52 : #include "nsIPrincipal.h"
53 : #include "nsWrapperCache.h"
54 : #include "nsStringGlue.h"
55 : #include "nsTArray.h"
56 :
57 : class nsIPrincipal;
58 : class nsIXPConnectWrappedJS;
59 : struct nsDOMClassInfoData;
60 :
61 : #ifndef BAD_TLS_INDEX
62 : #define BAD_TLS_INDEX ((PRUint32) -1)
63 : #endif
64 :
65 : nsresult
66 : xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
67 : nsIPrincipal *principal, nsISupports *ptr,
68 : bool wantXrays, JSObject **global,
69 : JSCompartment **compartment);
70 :
71 : nsresult
72 : xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp,
73 : nsISupports *ptr, JSObject **global,
74 : JSCompartment **compartment);
75 :
76 : #define XPCONNECT_GLOBAL_FLAGS \
77 : JSCLASS_XPCONNECT_GLOBAL | JSCLASS_HAS_PRIVATE | \
78 : JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_IMPLEMENTS_BARRIERS | \
79 : JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(1)
80 :
81 : void
82 : TraceXPCGlobal(JSTracer *trc, JSObject *obj);
83 :
84 : // XXX where should this live?
85 : NS_EXPORT_(void)
86 : xpc_LocalizeContext(JSContext *cx);
87 :
88 : nsresult
89 : xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph);
90 :
91 70532042 : static inline bool IS_WRAPPER_CLASS(js::Class* clazz)
92 : {
93 70532042 : return clazz->ext.isWrappedNative;
94 : }
95 :
96 : inline JSBool
97 33321185 : DebugCheckWrapperClass(JSObject* obj)
98 : {
99 33321185 : NS_ASSERTION(IS_WRAPPER_CLASS(js::GetObjectClass(obj)),
100 : "Forgot to check if this is a wrapper?");
101 33321185 : return true;
102 : }
103 :
104 : // If IS_WRAPPER_CLASS for the JSClass of an object is true, the object can be
105 : // a slim wrapper, holding a native in its private slot, or a wrappednative
106 : // wrapper, holding the XPCWrappedNative in its private slot. A slim wrapper
107 : // also holds a pointer to its XPCWrappedNativeProto in a reserved slot, we can
108 : // check that slot for a non-void value to distinguish between the two.
109 :
110 : // Only use these macros if IS_WRAPPER_CLASS(GetObjectClass(obj)) is true.
111 : #define IS_WN_WRAPPER_OBJECT(obj) \
112 : (DebugCheckWrapperClass(obj) && js::GetReservedSlot(obj, 0).isUndefined())
113 : #define IS_SLIM_WRAPPER_OBJECT(obj) \
114 : (DebugCheckWrapperClass(obj) && !js::GetReservedSlot(obj, 0).isUndefined())
115 :
116 : // Use these macros if IS_WRAPPER_CLASS(GetObjectClass(obj)) might be false.
117 : // Avoid calling them if IS_WRAPPER_CLASS(GetObjectClass(obj)) can only be
118 : // true, as we'd do a redundant call to IS_WRAPPER_CLASS.
119 : #define IS_WN_WRAPPER(obj) \
120 : (IS_WRAPPER_CLASS(js::GetObjectClass(obj)) && IS_WN_WRAPPER_OBJECT(obj))
121 : #define IS_SLIM_WRAPPER(obj) \
122 : (IS_WRAPPER_CLASS(js::GetObjectClass(obj)) && IS_SLIM_WRAPPER_OBJECT(obj))
123 :
124 : inline JSObject *
125 : xpc_GetGlobalForObject(JSObject *obj)
126 : {
127 : while (JSObject *parent = js::GetObjectParent(obj))
128 : obj = parent;
129 : return obj;
130 : }
131 :
132 : extern bool
133 : xpc_OkToHandOutWrapper(nsWrapperCache *cache);
134 :
135 : inline JSObject*
136 52557 : xpc_FastGetCachedWrapper(nsWrapperCache *cache, JSObject *scope, jsval *vp)
137 : {
138 52557 : if (cache) {
139 33925 : JSObject* wrapper = cache->GetWrapper();
140 33925 : NS_ASSERTION(!wrapper ||
141 : !cache->IsProxy() ||
142 : !IS_SLIM_WRAPPER(wrapper),
143 : "Should never have a slim wrapper when IsProxy()");
144 126013 : if (wrapper &&
145 19950 : js::GetObjectCompartment(wrapper) == js::GetObjectCompartment(scope) &&
146 53664 : (IS_SLIM_WRAPPER(wrapper) ||
147 18474 : xpc_OkToHandOutWrapper(cache))) {
148 19950 : *vp = OBJECT_TO_JSVAL(wrapper);
149 19950 : return wrapper;
150 : }
151 : }
152 :
153 32607 : return nsnull;
154 : }
155 :
156 : inline JSObject*
157 : xpc_FastGetCachedWrapper(nsWrapperCache *cache, JSObject *scope)
158 : {
159 : jsval dummy;
160 : return xpc_FastGetCachedWrapper(cache, scope, &dummy);
161 : }
162 :
163 : // The JS GC marks objects gray that are held alive directly or
164 : // indirectly by an XPConnect root. The cycle collector explores only
165 : // this subset of the JS heap.
166 : inline JSBool
167 0 : xpc_IsGrayGCThing(void *thing)
168 : {
169 0 : return js::GCThingIsMarkedGray(thing);
170 : }
171 :
172 : // The cycle collector only cares about some kinds of GCthings that are
173 : // reachable from an XPConnect root. Implemented in nsXPConnect.cpp.
174 : extern JSBool
175 : xpc_GCThingIsGrayCCThing(void *thing);
176 :
177 : // Implemented in nsXPConnect.cpp.
178 : extern void
179 : xpc_UnmarkGrayObjectRecursive(JSObject* obj);
180 :
181 : // Remove the gray color from the given JSObject and any other objects that can
182 : // be reached through it.
183 : inline void
184 20405225 : xpc_UnmarkGrayObject(JSObject *obj)
185 : {
186 20405225 : if (obj) {
187 20319929 : if (xpc_IsGrayGCThing(obj))
188 5600 : xpc_UnmarkGrayObjectRecursive(obj);
189 20314329 : else if (js::IsIncrementalBarrierNeededOnObject(obj))
190 0 : js::IncrementalReferenceBarrier(obj);
191 : }
192 20405225 : }
193 :
194 : // If aVariant is an XPCVariant, this marks the object to be in aGeneration.
195 : // This also unmarks the gray JSObject.
196 : extern void
197 : xpc_MarkInCCGeneration(nsISupports* aVariant, PRUint32 aGeneration);
198 :
199 : // Unmarks aWrappedJS's JSObject.
200 : extern void
201 : xpc_UnmarkGrayObject(nsIXPConnectWrappedJS* aWrappedJS);
202 :
203 : extern void
204 : xpc_UnmarkSkippableJSHolders();
205 :
206 : // No JS can be on the stack when this is called. Probably only useful from
207 : // xpcshell.
208 : NS_EXPORT_(void)
209 : xpc_ActivateDebugMode();
210 :
211 : namespace xpc {
212 :
213 : // If these functions return false, then an exception will be set on cx.
214 : bool Base64Encode(JSContext *cx, JS::Value val, JS::Value *out);
215 : bool Base64Decode(JSContext *cx, JS::Value val, JS::Value *out);
216 :
217 : /**
218 : * Convert an nsString to jsval, returning true on success.
219 : * Note, the ownership of the string buffer may be moved from str to rval.
220 : * If that happens, str will point to an empty string after this call.
221 : */
222 : bool StringToJsval(JSContext *cx, nsAString &str, JS::Value *rval);
223 : bool NonVoidStringToJsval(JSContext *cx, nsAString &str, JS::Value *rval);
224 :
225 : #ifdef DEBUG
226 : void DumpJSHeap(FILE* file);
227 : #endif
228 : } // namespace xpc
229 :
230 : class nsIMemoryMultiReporterCallback;
231 :
232 : namespace mozilla {
233 : namespace xpconnect {
234 : namespace memory {
235 :
236 : // This reports all the stats in |rtStats| that belong in the "explicit" tree,
237 : // (which isn't all of them).
238 : nsresult
239 : ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
240 : const nsACString &pathPrefix,
241 : nsIMemoryMultiReporterCallback *cb,
242 : nsISupports *closure);
243 :
244 : } // namespace memory
245 : } // namespace xpconnect
246 :
247 : namespace dom {
248 : namespace binding {
249 :
250 : extern int HandlerFamily;
251 43668 : inline void* ProxyFamily() { return &HandlerFamily; }
252 464195 : inline bool instanceIsProxy(JSObject *obj)
253 : {
254 464195 : return js::IsProxy(obj) &&
255 464195 : js::GetProxyHandler(obj)->family() == ProxyFamily();
256 : }
257 : extern JSClass ExpandoClass;
258 0 : inline bool isExpandoObject(JSObject *obj)
259 : {
260 0 : return js::GetObjectJSClass(obj) == &ExpandoClass;
261 : }
262 :
263 : enum {
264 : JSPROXYSLOT_PROTOSHAPE = 0,
265 : JSPROXYSLOT_EXPANDO = 1
266 : };
267 :
268 : typedef JSObject*
269 : (*DefineInterface)(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled);
270 :
271 : extern bool
272 : DefineStaticJSVals(JSContext *cx);
273 : void
274 : Register(nsDOMClassInfoData *aData);
275 : extern bool
276 : DefineConstructor(JSContext *cx, JSObject *obj, DefineInterface aDefine,
277 : nsresult *aResult);
278 :
279 : } // namespace binding
280 : } // namespace dom
281 : } // namespace mozilla
282 :
283 : #endif
|