|
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 /* |
|
8 * XPConnect allows JS code to manipulate C++ object and C++ code to manipulate |
|
9 * JS objects. JS manipulation of C++ objects tends to be significantly more |
|
10 * complex. This comment explains how it is orchestrated by XPConnect. |
|
11 * |
|
12 * For each C++ object to be manipulated in JS, there is a corresponding JS |
|
13 * object. This is called the "flattened JS object". By default, there is an |
|
14 * additional C++ object involved of type XPCWrappedNative. The XPCWrappedNative |
|
15 * holds pointers to the C++ object and the flat JS object. |
|
16 * |
|
17 * All XPCWrappedNative objects belong to an XPCWrappedNativeScope. These scopes |
|
18 * are essentially in 1:1 correspondence with JS global objects. The |
|
19 * XPCWrappedNativeScope has a pointer to the JS global object. The parent of a |
|
20 * flattened JS object is, by default, the global JS object corresponding to the |
|
21 * wrapper's XPCWrappedNativeScope (the exception to this rule is when a |
|
22 * PreCreate hook asks for a different parent; see nsIXPCScriptable below). |
|
23 * |
|
24 * Some C++ objects (notably DOM objects) have information associated with them |
|
25 * that lists the interfaces implemented by these objects. A C++ object exposes |
|
26 * this information by implementing nsIClassInfo. If a C++ object implements |
|
27 * nsIClassInfo, then JS code can call its methods without needing to use |
|
28 * QueryInterface first. Typically, all instances of a C++ class share the same |
|
29 * nsIClassInfo instance. (That is, obj->QueryInterface(nsIClassInfo) returns |
|
30 * the same result for every obj of a given class.) |
|
31 * |
|
32 * XPConnect tracks nsIClassInfo information in an XPCWrappedNativeProto object. |
|
33 * A given XPCWrappedNativeScope will have one XPCWrappedNativeProto for each |
|
34 * nsIClassInfo instance being used. The XPCWrappedNativeProto has an associated |
|
35 * JS object, which is used as the prototype of all flattened JS objects created |
|
36 * for C++ objects with the given nsIClassInfo. |
|
37 * |
|
38 * Each XPCWrappedNativeProto has a pointer to its XPCWrappedNativeScope. If an |
|
39 * XPCWrappedNative wraps a C++ object with class info, then it points to its |
|
40 * XPCWrappedNativeProto. Otherwise it points to its XPCWrappedNativeScope. (The |
|
41 * pointers are smooshed together in a tagged union.) Either way it can reach |
|
42 * its scope. |
|
43 * |
|
44 * An XPCWrappedNativeProto keeps track of the set of interfaces implemented by |
|
45 * the C++ object in an XPCNativeSet. (The list of interfaces is obtained by |
|
46 * calling a method on the nsIClassInfo.) An XPCNativeSet is a collection of |
|
47 * XPCNativeInterfaces. Each interface stores the list of members, which can be |
|
48 * methods, constants, getters, or setters. |
|
49 * |
|
50 * An XPCWrappedNative also points to an XPCNativeSet. Initially this starts out |
|
51 * the same as the XPCWrappedNativeProto's set. If there is no proto, it starts |
|
52 * out as a singleton set containing nsISupports. If JS code QI's new interfaces |
|
53 * outside of the existing set, the set will grow. All QueryInterface results |
|
54 * are cached in XPCWrappedNativeTearOff objects, which are linked off of the |
|
55 * XPCWrappedNative. |
|
56 * |
|
57 * Besides having class info, a C++ object may be "scriptable" (i.e., implement |
|
58 * nsIXPCScriptable). This allows it to implement a more DOM-like interface, |
|
59 * besides just exposing XPCOM methods and constants. An nsIXPCScriptable |
|
60 * instance has hooks that correspond to all the normal JSClass hooks. Each |
|
61 * nsIXPCScriptable instance is mirrored by an XPCNativeScriptableInfo in |
|
62 * XPConnect. These can have pointers from XPCWrappedNativeProto and |
|
63 * XPCWrappedNative (since C++ objects can have scriptable info without having |
|
64 * class info). |
|
65 * |
|
66 * Most data in an XPCNativeScriptableInfo is shared between instances. The |
|
67 * shared data is stored in an XPCNativeScriptableShared object. This type is |
|
68 * important because it holds the JSClass of the flattened JS objects with the |
|
69 * given scriptable info. |
|
70 */ |
|
71 |
|
72 /* All the XPConnect private declarations - only include locally. */ |
|
73 |
|
74 #ifndef xpcprivate_h___ |
|
75 #define xpcprivate_h___ |
|
76 |
|
77 #include "mozilla/Alignment.h" |
|
78 #include "mozilla/Assertions.h" |
|
79 #include "mozilla/Attributes.h" |
|
80 #include "mozilla/CycleCollectedJSRuntime.h" |
|
81 #include "mozilla/GuardObjects.h" |
|
82 #include "mozilla/Maybe.h" |
|
83 #include "mozilla/MemoryReporting.h" |
|
84 #include "mozilla/TimeStamp.h" |
|
85 |
|
86 #include <math.h> |
|
87 #include <stdint.h> |
|
88 #include <stdlib.h> |
|
89 #include <string.h> |
|
90 |
|
91 #include "xpcpublic.h" |
|
92 #include "js/TracingAPI.h" |
|
93 #include "js/WeakMapPtr.h" |
|
94 #include "pldhash.h" |
|
95 #include "nscore.h" |
|
96 #include "nsXPCOM.h" |
|
97 #include "nsAutoPtr.h" |
|
98 #include "nsCycleCollectionParticipant.h" |
|
99 #include "nsDebug.h" |
|
100 #include "nsISupports.h" |
|
101 #include "nsIServiceManager.h" |
|
102 #include "nsIClassInfoImpl.h" |
|
103 #include "nsIComponentManager.h" |
|
104 #include "nsIComponentRegistrar.h" |
|
105 #include "nsISupportsPrimitives.h" |
|
106 #include "nsMemory.h" |
|
107 #include "nsIXPConnect.h" |
|
108 #include "nsIInterfaceInfo.h" |
|
109 #include "nsIXPCScriptable.h" |
|
110 #include "nsIXPCSecurityManager.h" |
|
111 #include "nsIJSRuntimeService.h" |
|
112 #include "nsWeakReference.h" |
|
113 #include "nsCOMPtr.h" |
|
114 #include "nsXPTCUtils.h" |
|
115 #include "xptinfo.h" |
|
116 #include "XPCForwards.h" |
|
117 #include "XPCLog.h" |
|
118 #include "xpccomponents.h" |
|
119 #include "xpcexception.h" |
|
120 #include "xpcjsid.h" |
|
121 #include "prenv.h" |
|
122 #include "prclist.h" |
|
123 #include "prcvar.h" |
|
124 #include "nsString.h" |
|
125 #include "nsReadableUtils.h" |
|
126 #include "nsXPIDLString.h" |
|
127 #include "nsAutoJSValHolder.h" |
|
128 |
|
129 #include "MainThreadUtils.h" |
|
130 |
|
131 #include "nsIConsoleService.h" |
|
132 #include "nsIScriptError.h" |
|
133 #include "nsIException.h" |
|
134 |
|
135 #include "nsVariant.h" |
|
136 #include "nsIPropertyBag.h" |
|
137 #include "nsIProperty.h" |
|
138 #include "nsCOMArray.h" |
|
139 #include "nsTArray.h" |
|
140 #include "nsBaseHashtable.h" |
|
141 #include "nsHashKeys.h" |
|
142 #include "nsWrapperCache.h" |
|
143 #include "nsStringBuffer.h" |
|
144 #include "nsDataHashtable.h" |
|
145 #include "nsDeque.h" |
|
146 |
|
147 #include "nsIScriptSecurityManager.h" |
|
148 #include "nsNetUtil.h" |
|
149 |
|
150 #include "nsIPrincipal.h" |
|
151 #include "nsJSPrincipals.h" |
|
152 #include "nsIScriptObjectPrincipal.h" |
|
153 #include "xpcObjectHelper.h" |
|
154 #include "nsIThreadInternal.h" |
|
155 |
|
156 #include "SandboxPrivate.h" |
|
157 #include "BackstagePass.h" |
|
158 #include "nsCxPusher.h" |
|
159 #include "nsAXPCNativeCallContext.h" |
|
160 |
|
161 #ifdef XP_WIN |
|
162 // Nasty MS defines |
|
163 #ifdef GetClassInfo |
|
164 #undef GetClassInfo |
|
165 #endif |
|
166 #ifdef GetClassName |
|
167 #undef GetClassName |
|
168 #endif |
|
169 #endif /* XP_WIN */ |
|
170 |
|
171 #include "nsINode.h" |
|
172 |
|
173 /***************************************************************************/ |
|
174 // default initial sizes for maps (hashtables) |
|
175 |
|
176 #define XPC_CONTEXT_MAP_SIZE 16 |
|
177 #define XPC_JS_MAP_SIZE 64 |
|
178 #define XPC_JS_CLASS_MAP_SIZE 64 |
|
179 |
|
180 #define XPC_NATIVE_MAP_SIZE 64 |
|
181 #define XPC_NATIVE_PROTO_MAP_SIZE 16 |
|
182 #define XPC_DYING_NATIVE_PROTO_MAP_SIZE 16 |
|
183 #define XPC_DETACHED_NATIVE_PROTO_MAP_SIZE 32 |
|
184 #define XPC_NATIVE_INTERFACE_MAP_SIZE 64 |
|
185 #define XPC_NATIVE_SET_MAP_SIZE 64 |
|
186 #define XPC_NATIVE_JSCLASS_MAP_SIZE 32 |
|
187 #define XPC_THIS_TRANSLATOR_MAP_SIZE 8 |
|
188 #define XPC_NATIVE_WRAPPER_MAP_SIZE 16 |
|
189 #define XPC_WRAPPER_MAP_SIZE 16 |
|
190 |
|
191 /***************************************************************************/ |
|
192 // data declarations... |
|
193 extern const char XPC_CONTEXT_STACK_CONTRACTID[]; |
|
194 extern const char XPC_RUNTIME_CONTRACTID[]; |
|
195 extern const char XPC_EXCEPTION_CONTRACTID[]; |
|
196 extern const char XPC_CONSOLE_CONTRACTID[]; |
|
197 extern const char XPC_SCRIPT_ERROR_CONTRACTID[]; |
|
198 extern const char XPC_ID_CONTRACTID[]; |
|
199 extern const char XPC_XPCONNECT_CONTRACTID[]; |
|
200 |
|
201 /***************************************************************************/ |
|
202 // Useful macros... |
|
203 |
|
204 #define XPC_STRING_GETTER_BODY(dest, src) \ |
|
205 NS_ENSURE_ARG_POINTER(dest); \ |
|
206 char* result; \ |
|
207 if (src) \ |
|
208 result = (char*) nsMemory::Clone(src, \ |
|
209 sizeof(char)*(strlen(src)+1)); \ |
|
210 else \ |
|
211 result = nullptr; \ |
|
212 *dest = result; \ |
|
213 return (result || !src) ? NS_OK : NS_ERROR_OUT_OF_MEMORY |
|
214 |
|
215 |
|
216 #define WRAPPER_SLOTS (JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS ) |
|
217 |
|
218 #define INVALID_OBJECT ((JSObject *)1) |
|
219 |
|
220 // If IS_WN_CLASS for the JSClass of an object is true, the object is a |
|
221 // wrappednative wrapper, holding the XPCWrappedNative in its private slot. |
|
222 static inline bool IS_WN_CLASS(const js::Class* clazz) |
|
223 { |
|
224 return clazz->ext.isWrappedNative; |
|
225 } |
|
226 |
|
227 static inline bool IS_WN_REFLECTOR(JSObject *obj) |
|
228 { |
|
229 return IS_WN_CLASS(js::GetObjectClass(obj)); |
|
230 } |
|
231 |
|
232 /*************************************************************************** |
|
233 **************************************************************************** |
|
234 * |
|
235 * Core runtime and context classes... |
|
236 * |
|
237 **************************************************************************** |
|
238 ***************************************************************************/ |
|
239 |
|
240 // We have a general rule internally that getters that return addref'd interface |
|
241 // pointer generally do so using an 'out' parm. When interface pointers are |
|
242 // returned as function call result values they are not addref'd. Exceptions |
|
243 // to this rule are noted explicitly. |
|
244 |
|
245 inline bool |
|
246 AddToCCKind(JSGCTraceKind kind) |
|
247 { |
|
248 return kind == JSTRACE_OBJECT || kind == JSTRACE_SCRIPT; |
|
249 } |
|
250 |
|
251 class nsXPConnect : public nsIXPConnect, |
|
252 public nsIThreadObserver, |
|
253 public nsSupportsWeakReference, |
|
254 public nsIJSRuntimeService |
|
255 { |
|
256 public: |
|
257 // all the interface method declarations... |
|
258 NS_DECL_ISUPPORTS |
|
259 NS_DECL_NSIXPCONNECT |
|
260 NS_DECL_NSITHREADOBSERVER |
|
261 NS_DECL_NSIJSRUNTIMESERVICE |
|
262 |
|
263 // non-interface implementation |
|
264 public: |
|
265 // These get non-addref'd pointers |
|
266 static nsXPConnect* XPConnect() |
|
267 { |
|
268 // Do a release-mode assert that we're not doing anything significant in |
|
269 // XPConnect off the main thread. If you're an extension developer hitting |
|
270 // this, you need to change your code. See bug 716167. |
|
271 if (!MOZ_LIKELY(NS_IsMainThread())) |
|
272 MOZ_CRASH(); |
|
273 |
|
274 return gSelf; |
|
275 } |
|
276 |
|
277 static XPCJSRuntime* GetRuntimeInstance(); |
|
278 XPCJSRuntime* GetRuntime() {return mRuntime;} |
|
279 |
|
280 static bool IsISupportsDescendant(nsIInterfaceInfo* info); |
|
281 |
|
282 nsIXPCSecurityManager* GetDefaultSecurityManager() const |
|
283 { |
|
284 // mDefaultSecurityManager is main-thread only. |
|
285 if (!NS_IsMainThread()) { |
|
286 return nullptr; |
|
287 } |
|
288 return mDefaultSecurityManager; |
|
289 } |
|
290 |
|
291 // This returns an AddRef'd pointer. It does not do this with an 'out' param |
|
292 // only because this form is required by the generic module macro: |
|
293 // NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR |
|
294 static nsXPConnect* GetSingleton(); |
|
295 |
|
296 // Called by module code in dll startup |
|
297 static void InitStatics(); |
|
298 // Called by module code on dll shutdown. |
|
299 static void ReleaseXPConnectSingleton(); |
|
300 |
|
301 virtual ~nsXPConnect(); |
|
302 |
|
303 bool IsShuttingDown() const {return mShuttingDown;} |
|
304 |
|
305 nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info); |
|
306 nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info); |
|
307 |
|
308 virtual nsIPrincipal* GetPrincipal(JSObject* obj, |
|
309 bool allowShortCircuit) const; |
|
310 |
|
311 void RecordTraversal(void *p, nsISupports *s); |
|
312 virtual char* DebugPrintJSStack(bool showArgs, |
|
313 bool showLocals, |
|
314 bool showThisProps); |
|
315 |
|
316 |
|
317 static bool ReportAllJSExceptions() |
|
318 { |
|
319 return gReportAllJSExceptions > 0; |
|
320 } |
|
321 |
|
322 static void CheckForDebugMode(JSRuntime *rt); |
|
323 |
|
324 protected: |
|
325 nsXPConnect(); |
|
326 |
|
327 private: |
|
328 // Singleton instance |
|
329 static nsXPConnect* gSelf; |
|
330 static bool gOnceAliveNowDead; |
|
331 |
|
332 XPCJSRuntime* mRuntime; |
|
333 nsRefPtr<nsIXPCSecurityManager> mDefaultSecurityManager; |
|
334 bool mShuttingDown; |
|
335 |
|
336 // nsIThreadInternal doesn't remember which observers it called |
|
337 // OnProcessNextEvent on when it gets around to calling AfterProcessNextEvent. |
|
338 // So if XPConnect gets initialized mid-event (which can happen), we'll get |
|
339 // an 'after' notification without getting an 'on' notification. If we don't |
|
340 // watch out for this, we'll do an unmatched |pop| on the context stack. |
|
341 uint16_t mEventDepth; |
|
342 |
|
343 static uint32_t gReportAllJSExceptions; |
|
344 |
|
345 public: |
|
346 static nsIScriptSecurityManager *gScriptSecurityManager; |
|
347 }; |
|
348 |
|
349 /***************************************************************************/ |
|
350 |
|
351 class XPCRootSetElem |
|
352 { |
|
353 public: |
|
354 XPCRootSetElem() |
|
355 { |
|
356 #ifdef DEBUG |
|
357 mNext = nullptr; |
|
358 mSelfp = nullptr; |
|
359 #endif |
|
360 } |
|
361 |
|
362 ~XPCRootSetElem() |
|
363 { |
|
364 MOZ_ASSERT(!mNext, "Must be unlinked"); |
|
365 MOZ_ASSERT(!mSelfp, "Must be unlinked"); |
|
366 } |
|
367 |
|
368 inline XPCRootSetElem* GetNextRoot() { return mNext; } |
|
369 void AddToRootSet(XPCRootSetElem **listHead); |
|
370 void RemoveFromRootSet(); |
|
371 |
|
372 private: |
|
373 XPCRootSetElem *mNext; |
|
374 XPCRootSetElem **mSelfp; |
|
375 }; |
|
376 |
|
377 /***************************************************************************/ |
|
378 |
|
379 // In the current xpconnect system there can only be one XPCJSRuntime. |
|
380 // So, xpconnect can only be used on one JSRuntime within the process. |
|
381 |
|
382 class XPCJSContextStack; |
|
383 class WatchdogManager; |
|
384 |
|
385 enum WatchdogTimestampCategory |
|
386 { |
|
387 TimestampRuntimeStateChange = 0, |
|
388 TimestampWatchdogWakeup, |
|
389 TimestampWatchdogHibernateStart, |
|
390 TimestampWatchdogHibernateStop, |
|
391 TimestampCount |
|
392 }; |
|
393 |
|
394 class AsyncFreeSnowWhite; |
|
395 |
|
396 class XPCJSRuntime : public mozilla::CycleCollectedJSRuntime |
|
397 { |
|
398 public: |
|
399 static XPCJSRuntime* newXPCJSRuntime(nsXPConnect* aXPConnect); |
|
400 static XPCJSRuntime* Get() { return nsXPConnect::XPConnect()->GetRuntime(); } |
|
401 |
|
402 XPCJSContextStack* GetJSContextStack() {return mJSContextStack;} |
|
403 void DestroyJSContextStack(); |
|
404 |
|
405 XPCCallContext* GetCallContext() const {return mCallContext;} |
|
406 XPCCallContext* SetCallContext(XPCCallContext* ccx) |
|
407 {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;} |
|
408 |
|
409 jsid GetResolveName() const {return mResolveName;} |
|
410 jsid SetResolveName(jsid name) |
|
411 {jsid old = mResolveName; mResolveName = name; return old;} |
|
412 |
|
413 XPCWrappedNative* GetResolvingWrapper() const {return mResolvingWrapper;} |
|
414 XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w) |
|
415 {XPCWrappedNative* old = mResolvingWrapper; |
|
416 mResolvingWrapper = w; return old;} |
|
417 |
|
418 JSObject2WrappedJSMap* GetWrappedJSMap() const |
|
419 {return mWrappedJSMap;} |
|
420 |
|
421 IID2WrappedJSClassMap* GetWrappedJSClassMap() const |
|
422 {return mWrappedJSClassMap;} |
|
423 |
|
424 IID2NativeInterfaceMap* GetIID2NativeInterfaceMap() const |
|
425 {return mIID2NativeInterfaceMap;} |
|
426 |
|
427 ClassInfo2NativeSetMap* GetClassInfo2NativeSetMap() const |
|
428 {return mClassInfo2NativeSetMap;} |
|
429 |
|
430 NativeSetMap* GetNativeSetMap() const |
|
431 {return mNativeSetMap;} |
|
432 |
|
433 IID2ThisTranslatorMap* GetThisTranslatorMap() const |
|
434 {return mThisTranslatorMap;} |
|
435 |
|
436 XPCNativeScriptableSharedMap* GetNativeScriptableSharedMap() const |
|
437 {return mNativeScriptableSharedMap;} |
|
438 |
|
439 XPCWrappedNativeProtoMap* GetDyingWrappedNativeProtoMap() const |
|
440 {return mDyingWrappedNativeProtoMap;} |
|
441 |
|
442 XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const |
|
443 {return mDetachedWrappedNativeProtoMap;} |
|
444 |
|
445 bool OnJSContextNew(JSContext* cx); |
|
446 |
|
447 virtual bool |
|
448 DescribeCustomObjects(JSObject* aObject, const js::Class* aClasp, |
|
449 char (&aName)[72]) const MOZ_OVERRIDE; |
|
450 virtual bool |
|
451 NoteCustomGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj, |
|
452 nsCycleCollectionTraversalCallback& aCb) const MOZ_OVERRIDE; |
|
453 |
|
454 /** |
|
455 * Infrastructure for classes that need to defer part of the finalization |
|
456 * until after the GC has run, for example for objects that we don't want to |
|
457 * destroy during the GC. |
|
458 */ |
|
459 |
|
460 public: |
|
461 bool GetDoingFinalization() const {return mDoingFinalization;} |
|
462 |
|
463 // Mapping of often used strings to jsid atoms that live 'forever'. |
|
464 // |
|
465 // To add a new string: add to this list and to XPCJSRuntime::mStrings |
|
466 // at the top of xpcjsruntime.cpp |
|
467 enum { |
|
468 IDX_CONSTRUCTOR = 0 , |
|
469 IDX_TO_STRING , |
|
470 IDX_TO_SOURCE , |
|
471 IDX_LAST_RESULT , |
|
472 IDX_RETURN_CODE , |
|
473 IDX_VALUE , |
|
474 IDX_QUERY_INTERFACE , |
|
475 IDX_COMPONENTS , |
|
476 IDX_WRAPPED_JSOBJECT , |
|
477 IDX_OBJECT , |
|
478 IDX_FUNCTION , |
|
479 IDX_PROTOTYPE , |
|
480 IDX_CREATE_INSTANCE , |
|
481 IDX_ITEM , |
|
482 IDX_PROTO , |
|
483 IDX_ITERATOR , |
|
484 IDX_EXPOSEDPROPS , |
|
485 IDX_EVAL , |
|
486 IDX_CONTROLLERS , |
|
487 IDX_TOTAL_COUNT // just a count of the above |
|
488 }; |
|
489 |
|
490 JS::HandleId GetStringID(unsigned index) const |
|
491 { |
|
492 MOZ_ASSERT(index < IDX_TOTAL_COUNT, "index out of range"); |
|
493 // fromMarkedLocation() is safe because the string is interned. |
|
494 return JS::HandleId::fromMarkedLocation(&mStrIDs[index]); |
|
495 } |
|
496 JS::HandleValue GetStringJSVal(unsigned index) const |
|
497 { |
|
498 MOZ_ASSERT(index < IDX_TOTAL_COUNT, "index out of range"); |
|
499 // fromMarkedLocation() is safe because the string is interned. |
|
500 return JS::HandleValue::fromMarkedLocation(&mStrJSVals[index]); |
|
501 } |
|
502 const char* GetStringName(unsigned index) const |
|
503 { |
|
504 MOZ_ASSERT(index < IDX_TOTAL_COUNT, "index out of range"); |
|
505 return mStrings[index]; |
|
506 } |
|
507 |
|
508 void TraceNativeBlackRoots(JSTracer* trc) MOZ_OVERRIDE; |
|
509 void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) MOZ_OVERRIDE; |
|
510 void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& cb) MOZ_OVERRIDE; |
|
511 void UnmarkSkippableJSHolders(); |
|
512 void PrepareForForgetSkippable() MOZ_OVERRIDE; |
|
513 void BeginCycleCollectionCallback() MOZ_OVERRIDE; |
|
514 void EndCycleCollectionCallback(mozilla::CycleCollectorResults &aResults) MOZ_OVERRIDE; |
|
515 void DispatchDeferredDeletion(bool continuation) MOZ_OVERRIDE; |
|
516 |
|
517 void CustomGCCallback(JSGCStatus status) MOZ_OVERRIDE; |
|
518 bool CustomContextCallback(JSContext *cx, unsigned operation) MOZ_OVERRIDE; |
|
519 static void GCSliceCallback(JSRuntime *rt, |
|
520 JS::GCProgress progress, |
|
521 const JS::GCDescription &desc); |
|
522 static void FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCompartmentGC); |
|
523 |
|
524 inline void AddVariantRoot(XPCTraceableVariant* variant); |
|
525 inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS); |
|
526 inline void AddObjectHolderRoot(XPCJSObjectHolder* holder); |
|
527 |
|
528 static void SuspectWrappedNative(XPCWrappedNative *wrapper, |
|
529 nsCycleCollectionNoteRootCallback &cb); |
|
530 |
|
531 void DebugDump(int16_t depth); |
|
532 |
|
533 void SystemIsBeingShutDown(); |
|
534 |
|
535 bool GCIsRunning() const {return mGCIsRunning;} |
|
536 |
|
537 ~XPCJSRuntime(); |
|
538 |
|
539 nsString* NewShortLivedString(); |
|
540 void DeleteShortLivedString(nsString *string); |
|
541 |
|
542 void AddGCCallback(xpcGCCallback cb); |
|
543 void RemoveGCCallback(xpcGCCallback cb); |
|
544 void AddContextCallback(xpcContextCallback cb); |
|
545 void RemoveContextCallback(xpcContextCallback cb); |
|
546 |
|
547 static JSContext* DefaultJSContextCallback(JSRuntime *rt); |
|
548 static void ActivityCallback(void *arg, bool active); |
|
549 static void CTypesActivityCallback(JSContext *cx, |
|
550 js::CTypesActivityType type); |
|
551 static bool InterruptCallback(JSContext *cx); |
|
552 static void OutOfMemoryCallback(JSContext *cx); |
|
553 |
|
554 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
555 |
|
556 AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;} |
|
557 |
|
558 JSObject* GetJunkScope(); |
|
559 JSObject* GetCompilationScope(); |
|
560 void DeleteSingletonScopes(); |
|
561 |
|
562 PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory); |
|
563 void OnAfterProcessNextEvent() { mSlowScriptCheckpoint = mozilla::TimeStamp(); } |
|
564 |
|
565 private: |
|
566 XPCJSRuntime(); // no implementation |
|
567 XPCJSRuntime(nsXPConnect* aXPConnect); |
|
568 |
|
569 void ReleaseIncrementally(nsTArray<nsISupports *> &array); |
|
570 |
|
571 static const char* const mStrings[IDX_TOTAL_COUNT]; |
|
572 jsid mStrIDs[IDX_TOTAL_COUNT]; |
|
573 jsval mStrJSVals[IDX_TOTAL_COUNT]; |
|
574 |
|
575 XPCJSContextStack* mJSContextStack; |
|
576 XPCCallContext* mCallContext; |
|
577 AutoMarkingPtr* mAutoRoots; |
|
578 jsid mResolveName; |
|
579 XPCWrappedNative* mResolvingWrapper; |
|
580 JSObject2WrappedJSMap* mWrappedJSMap; |
|
581 IID2WrappedJSClassMap* mWrappedJSClassMap; |
|
582 IID2NativeInterfaceMap* mIID2NativeInterfaceMap; |
|
583 ClassInfo2NativeSetMap* mClassInfo2NativeSetMap; |
|
584 NativeSetMap* mNativeSetMap; |
|
585 IID2ThisTranslatorMap* mThisTranslatorMap; |
|
586 XPCNativeScriptableSharedMap* mNativeScriptableSharedMap; |
|
587 XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap; |
|
588 XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap; |
|
589 bool mGCIsRunning; |
|
590 nsTArray<nsXPCWrappedJS*> mWrappedJSToReleaseArray; |
|
591 nsTArray<nsISupports*> mNativesToReleaseArray; |
|
592 bool mDoingFinalization; |
|
593 XPCRootSetElem *mVariantRoots; |
|
594 XPCRootSetElem *mWrappedJSRoots; |
|
595 XPCRootSetElem *mObjectHolderRoots; |
|
596 nsTArray<xpcGCCallback> extraGCCallbacks; |
|
597 nsTArray<xpcContextCallback> extraContextCallbacks; |
|
598 nsRefPtr<WatchdogManager> mWatchdogManager; |
|
599 JS::GCSliceCallback mPrevGCSliceCallback; |
|
600 JS::PersistentRootedObject mJunkScope; |
|
601 JS::PersistentRootedObject mCompilationScope; |
|
602 nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer; |
|
603 |
|
604 mozilla::TimeStamp mSlowScriptCheckpoint; |
|
605 |
|
606 #define XPCCCX_STRING_CACHE_SIZE 2 |
|
607 |
|
608 mozilla::Maybe<nsString> mScratchStrings[XPCCCX_STRING_CACHE_SIZE]; |
|
609 |
|
610 friend class Watchdog; |
|
611 friend class AutoLockWatchdog; |
|
612 friend class XPCIncrementalReleaseRunnable; |
|
613 }; |
|
614 |
|
615 /***************************************************************************/ |
|
616 /***************************************************************************/ |
|
617 // XPCContext is mostly a dumb class to hold JSContext specific data and |
|
618 // maps that let us find wrappers created for the given JSContext. |
|
619 |
|
620 // no virtuals |
|
621 class XPCContext |
|
622 { |
|
623 friend class XPCJSRuntime; |
|
624 public: |
|
625 static XPCContext* GetXPCContext(JSContext* aJSContext) |
|
626 { |
|
627 MOZ_ASSERT(JS_GetSecondContextPrivate(aJSContext), "should already have XPCContext"); |
|
628 return static_cast<XPCContext *>(JS_GetSecondContextPrivate(aJSContext)); |
|
629 } |
|
630 |
|
631 XPCJSRuntime* GetRuntime() const {return mRuntime;} |
|
632 JSContext* GetJSContext() const {return mJSContext;} |
|
633 |
|
634 enum LangType {LANG_UNKNOWN, LANG_JS, LANG_NATIVE}; |
|
635 |
|
636 LangType GetCallingLangType() const |
|
637 { |
|
638 return mCallingLangType; |
|
639 } |
|
640 LangType SetCallingLangType(LangType lt) |
|
641 { |
|
642 LangType tmp = mCallingLangType; |
|
643 mCallingLangType = lt; |
|
644 return tmp; |
|
645 } |
|
646 bool CallerTypeIsJavaScript() const |
|
647 { |
|
648 return LANG_JS == mCallingLangType; |
|
649 } |
|
650 bool CallerTypeIsNative() const |
|
651 { |
|
652 return LANG_NATIVE == mCallingLangType; |
|
653 } |
|
654 bool CallerTypeIsKnown() const |
|
655 { |
|
656 return LANG_UNKNOWN != mCallingLangType; |
|
657 } |
|
658 |
|
659 nsresult GetException(nsIException** e) |
|
660 { |
|
661 nsCOMPtr<nsIException> rval = mException; |
|
662 rval.forget(e); |
|
663 return NS_OK; |
|
664 } |
|
665 void SetException(nsIException* e) |
|
666 { |
|
667 mException = e; |
|
668 } |
|
669 |
|
670 nsresult GetLastResult() {return mLastResult;} |
|
671 void SetLastResult(nsresult rc) {mLastResult = rc;} |
|
672 |
|
673 nsresult GetPendingResult() {return mPendingResult;} |
|
674 void SetPendingResult(nsresult rc) {mPendingResult = rc;} |
|
675 |
|
676 void DebugDump(int16_t depth); |
|
677 void AddScope(PRCList *scope) { PR_INSERT_AFTER(scope, &mScopes); } |
|
678 void RemoveScope(PRCList *scope) { PR_REMOVE_LINK(scope); } |
|
679 |
|
680 void MarkErrorUnreported() { mErrorUnreported = true; } |
|
681 void ClearUnreportedError() { mErrorUnreported = false; } |
|
682 bool WasErrorReported() { return !mErrorUnreported; } |
|
683 |
|
684 ~XPCContext(); |
|
685 |
|
686 private: |
|
687 XPCContext(); // no implementation |
|
688 XPCContext(XPCJSRuntime* aRuntime, JSContext* aJSContext); |
|
689 |
|
690 static XPCContext* newXPCContext(XPCJSRuntime* aRuntime, |
|
691 JSContext* aJSContext); |
|
692 private: |
|
693 XPCJSRuntime* mRuntime; |
|
694 JSContext* mJSContext; |
|
695 nsresult mLastResult; |
|
696 nsresult mPendingResult; |
|
697 nsCOMPtr<nsIException> mException; |
|
698 LangType mCallingLangType; |
|
699 bool mErrorUnreported; |
|
700 |
|
701 // A linked list of scopes to notify when we are destroyed. |
|
702 PRCList mScopes; |
|
703 }; |
|
704 |
|
705 /***************************************************************************/ |
|
706 |
|
707 #define NATIVE_CALLER XPCContext::LANG_NATIVE |
|
708 #define JS_CALLER XPCContext::LANG_JS |
|
709 |
|
710 // No virtuals |
|
711 // XPCCallContext is ALWAYS declared as a local variable in some function; |
|
712 // i.e. instance lifetime is always controled by some C++ function returning. |
|
713 // |
|
714 // These things are created frequently in many places. We *intentionally* do |
|
715 // not inialialize all members in order to save on construction overhead. |
|
716 // Some constructor pass more valid params than others. We init what must be |
|
717 // init'd and leave other members undefined. In debug builds the accessors |
|
718 // use a CHECK_STATE macro to track whether or not the object is in a valid |
|
719 // state to answer the question a caller might be asking. As long as this |
|
720 // class is maintained correctly it can do its job without a bunch of added |
|
721 // overhead from useless initializations and non-DEBUG error checking. |
|
722 // |
|
723 // Note that most accessors are inlined. |
|
724 |
|
725 class MOZ_STACK_CLASS XPCCallContext : public nsAXPCNativeCallContext |
|
726 { |
|
727 public: |
|
728 NS_IMETHOD GetCallee(nsISupports **aResult); |
|
729 NS_IMETHOD GetCalleeMethodIndex(uint16_t *aResult); |
|
730 NS_IMETHOD GetCalleeWrapper(nsIXPConnectWrappedNative **aResult); |
|
731 NS_IMETHOD GetJSContext(JSContext **aResult); |
|
732 NS_IMETHOD GetArgc(uint32_t *aResult); |
|
733 NS_IMETHOD GetArgvPtr(jsval **aResult); |
|
734 NS_IMETHOD GetCalleeInterface(nsIInterfaceInfo **aResult); |
|
735 NS_IMETHOD GetCalleeClassInfo(nsIClassInfo **aResult); |
|
736 NS_IMETHOD GetPreviousCallContext(nsAXPCNativeCallContext **aResult); |
|
737 NS_IMETHOD GetLanguage(uint16_t *aResult); |
|
738 |
|
739 enum {NO_ARGS = (unsigned) -1}; |
|
740 |
|
741 static JSContext* GetDefaultJSContext(); |
|
742 |
|
743 XPCCallContext(XPCContext::LangType callerLanguage, |
|
744 JSContext* cx, |
|
745 JS::HandleObject obj = JS::NullPtr(), |
|
746 JS::HandleObject funobj = JS::NullPtr(), |
|
747 JS::HandleId id = JSID_VOIDHANDLE, |
|
748 unsigned argc = NO_ARGS, |
|
749 jsval *argv = nullptr, |
|
750 jsval *rval = nullptr); |
|
751 |
|
752 virtual ~XPCCallContext(); |
|
753 |
|
754 inline bool IsValid() const ; |
|
755 |
|
756 inline XPCJSRuntime* GetRuntime() const ; |
|
757 inline XPCContext* GetXPCContext() const ; |
|
758 inline JSContext* GetJSContext() const ; |
|
759 inline bool GetContextPopRequired() const ; |
|
760 inline XPCContext::LangType GetCallerLanguage() const ; |
|
761 inline XPCContext::LangType GetPrevCallerLanguage() const ; |
|
762 inline XPCCallContext* GetPrevCallContext() const ; |
|
763 |
|
764 inline JSObject* GetFlattenedJSObject() const ; |
|
765 inline nsISupports* GetIdentityObject() const ; |
|
766 inline XPCWrappedNative* GetWrapper() const ; |
|
767 inline XPCWrappedNativeProto* GetProto() const ; |
|
768 |
|
769 inline bool CanGetTearOff() const ; |
|
770 inline XPCWrappedNativeTearOff* GetTearOff() const ; |
|
771 |
|
772 inline XPCNativeScriptableInfo* GetScriptableInfo() const ; |
|
773 inline bool CanGetSet() const ; |
|
774 inline XPCNativeSet* GetSet() const ; |
|
775 inline bool CanGetInterface() const ; |
|
776 inline XPCNativeInterface* GetInterface() const ; |
|
777 inline XPCNativeMember* GetMember() const ; |
|
778 inline bool HasInterfaceAndMember() const ; |
|
779 inline jsid GetName() const ; |
|
780 inline bool GetStaticMemberIsLocal() const ; |
|
781 inline unsigned GetArgc() const ; |
|
782 inline jsval* GetArgv() const ; |
|
783 inline jsval* GetRetVal() const ; |
|
784 |
|
785 inline uint16_t GetMethodIndex() const ; |
|
786 inline void SetMethodIndex(uint16_t index) ; |
|
787 |
|
788 inline jsid GetResolveName() const; |
|
789 inline jsid SetResolveName(JS::HandleId name); |
|
790 |
|
791 inline XPCWrappedNative* GetResolvingWrapper() const; |
|
792 inline XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w); |
|
793 |
|
794 inline void SetRetVal(jsval val); |
|
795 |
|
796 void SetName(jsid name); |
|
797 void SetArgsAndResultPtr(unsigned argc, jsval *argv, jsval *rval); |
|
798 void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member, |
|
799 bool isSetter); |
|
800 |
|
801 nsresult CanCallNow(); |
|
802 |
|
803 void SystemIsBeingShutDown(); |
|
804 |
|
805 operator JSContext*() const {return GetJSContext();} |
|
806 |
|
807 private: |
|
808 |
|
809 // no copy ctor or assignment allowed |
|
810 XPCCallContext(const XPCCallContext& r); // not implemented |
|
811 XPCCallContext& operator= (const XPCCallContext& r); // not implemented |
|
812 |
|
813 XPCWrappedNative* UnwrapThisIfAllowed(JS::HandleObject obj, JS::HandleObject fun, |
|
814 unsigned argc); |
|
815 |
|
816 private: |
|
817 // posible values for mState |
|
818 enum State { |
|
819 INIT_FAILED, |
|
820 SYSTEM_SHUTDOWN, |
|
821 HAVE_CONTEXT, |
|
822 HAVE_OBJECT, |
|
823 HAVE_NAME, |
|
824 HAVE_ARGS, |
|
825 READY_TO_CALL, |
|
826 CALL_DONE |
|
827 }; |
|
828 |
|
829 #ifdef DEBUG |
|
830 inline void CHECK_STATE(int s) const {MOZ_ASSERT(mState >= s, "bad state");} |
|
831 #else |
|
832 #define CHECK_STATE(s) ((void)0) |
|
833 #endif |
|
834 |
|
835 private: |
|
836 JSAutoRequest mAr; |
|
837 State mState; |
|
838 |
|
839 nsRefPtr<nsXPConnect> mXPC; |
|
840 |
|
841 XPCContext* mXPCContext; |
|
842 JSContext* mJSContext; |
|
843 |
|
844 XPCContext::LangType mCallerLanguage; |
|
845 |
|
846 // ctor does not necessarily init the following. BEWARE! |
|
847 |
|
848 XPCContext::LangType mPrevCallerLanguage; |
|
849 |
|
850 XPCCallContext* mPrevCallContext; |
|
851 |
|
852 JS::RootedObject mFlattenedJSObject; |
|
853 XPCWrappedNative* mWrapper; |
|
854 XPCWrappedNativeTearOff* mTearOff; |
|
855 |
|
856 XPCNativeScriptableInfo* mScriptableInfo; |
|
857 |
|
858 XPCNativeSet* mSet; |
|
859 XPCNativeInterface* mInterface; |
|
860 XPCNativeMember* mMember; |
|
861 |
|
862 JS::RootedId mName; |
|
863 bool mStaticMemberIsLocal; |
|
864 |
|
865 unsigned mArgc; |
|
866 jsval* mArgv; |
|
867 jsval* mRetVal; |
|
868 |
|
869 uint16_t mMethodIndex; |
|
870 }; |
|
871 |
|
872 /*************************************************************************** |
|
873 **************************************************************************** |
|
874 * |
|
875 * Core classes for wrapped native objects for use from JavaScript... |
|
876 * |
|
877 **************************************************************************** |
|
878 ***************************************************************************/ |
|
879 |
|
880 // These are the various JSClasses and callbacks whose use that required |
|
881 // visibility from more than one .cpp file. |
|
882 |
|
883 struct XPCWrappedNativeJSClass; |
|
884 extern const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass; |
|
885 extern const js::Class XPC_WN_NoMods_WithCall_Proto_JSClass; |
|
886 extern const js::Class XPC_WN_NoMods_NoCall_Proto_JSClass; |
|
887 extern const js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass; |
|
888 extern const js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass; |
|
889 extern const js::Class XPC_WN_Tearoff_JSClass; |
|
890 extern const js::Class XPC_WN_NoHelper_Proto_JSClass; |
|
891 |
|
892 extern bool |
|
893 XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp); |
|
894 |
|
895 extern bool |
|
896 XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp); |
|
897 |
|
898 extern bool |
|
899 XPC_WN_JSOp_Enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op, |
|
900 JS::MutableHandleValue statep, JS::MutableHandleId idp); |
|
901 |
|
902 extern JSObject* |
|
903 XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj); |
|
904 |
|
905 // Macros to initialize Object or Function like XPC_WN classes |
|
906 #define XPC_WN_WithCall_ObjectOps \ |
|
907 { \ |
|
908 nullptr, /* lookupGeneric */ \ |
|
909 nullptr, /* lookupProperty */ \ |
|
910 nullptr, /* lookupElement */ \ |
|
911 nullptr, /* defineGeneric */ \ |
|
912 nullptr, /* defineProperty */ \ |
|
913 nullptr, /* defineElement */ \ |
|
914 nullptr, /* getGeneric */ \ |
|
915 nullptr, /* getProperty */ \ |
|
916 nullptr, /* getElement */ \ |
|
917 nullptr, /* setGeneric */ \ |
|
918 nullptr, /* setProperty */ \ |
|
919 nullptr, /* setElement */ \ |
|
920 nullptr, /* getGenericAttributes */ \ |
|
921 nullptr, /* setGenericAttributes */ \ |
|
922 nullptr, /* deleteProperty */ \ |
|
923 nullptr, /* deleteElement */ \ |
|
924 nullptr, nullptr, /* watch/unwatch */ \ |
|
925 nullptr, /* slice */ \ |
|
926 XPC_WN_JSOp_Enumerate, \ |
|
927 XPC_WN_JSOp_ThisObject, \ |
|
928 } |
|
929 |
|
930 #define XPC_WN_NoCall_ObjectOps \ |
|
931 { \ |
|
932 nullptr, /* lookupGeneric */ \ |
|
933 nullptr, /* lookupProperty */ \ |
|
934 nullptr, /* lookupElement */ \ |
|
935 nullptr, /* defineGeneric */ \ |
|
936 nullptr, /* defineProperty */ \ |
|
937 nullptr, /* defineElement */ \ |
|
938 nullptr, /* getGeneric */ \ |
|
939 nullptr, /* getProperty */ \ |
|
940 nullptr, /* getElement */ \ |
|
941 nullptr, /* setGeneric */ \ |
|
942 nullptr, /* setProperty */ \ |
|
943 nullptr, /* setElement */ \ |
|
944 nullptr, /* getGenericAttributes */ \ |
|
945 nullptr, /* setGenericAttributes */ \ |
|
946 nullptr, /* deleteProperty */ \ |
|
947 nullptr, /* deleteElement */ \ |
|
948 nullptr, nullptr, /* watch/unwatch */ \ |
|
949 nullptr, /* slice */ \ |
|
950 XPC_WN_JSOp_Enumerate, \ |
|
951 XPC_WN_JSOp_ThisObject, \ |
|
952 } |
|
953 |
|
954 // Maybe this macro should check for class->enumerate == |
|
955 // XPC_WN_Shared_Proto_Enumerate or something rather than checking for |
|
956 // 4 classes? |
|
957 static inline bool IS_PROTO_CLASS(const js::Class *clazz) |
|
958 { |
|
959 return clazz == &XPC_WN_NoMods_WithCall_Proto_JSClass || |
|
960 clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass || |
|
961 clazz == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || |
|
962 clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass; |
|
963 } |
|
964 |
|
965 /***************************************************************************/ |
|
966 // XPCWrappedNativeScope is one-to-one with a JS global object. |
|
967 |
|
968 class nsXPCComponentsBase; |
|
969 class XPCWrappedNativeScope : public PRCList |
|
970 { |
|
971 public: |
|
972 |
|
973 static XPCWrappedNativeScope* |
|
974 GetNewOrUsed(JSContext *cx, JS::HandleObject aGlobal); |
|
975 |
|
976 XPCJSRuntime* |
|
977 GetRuntime() const {return XPCJSRuntime::Get();} |
|
978 |
|
979 Native2WrappedNativeMap* |
|
980 GetWrappedNativeMap() const {return mWrappedNativeMap;} |
|
981 |
|
982 ClassInfo2WrappedNativeProtoMap* |
|
983 GetWrappedNativeProtoMap() const {return mWrappedNativeProtoMap;} |
|
984 |
|
985 nsXPCComponentsBase* |
|
986 GetComponents() const {return mComponents;} |
|
987 |
|
988 // Forces the creation of a privileged |Components| object, even in |
|
989 // content scopes. This will crash if used outside of automation. |
|
990 void |
|
991 ForcePrivilegedComponents(); |
|
992 |
|
993 bool AttachComponentsObject(JSContext *aCx); |
|
994 |
|
995 // Returns the JS object reflection of the Components object. |
|
996 bool |
|
997 GetComponentsJSObject(JS::MutableHandleObject obj); |
|
998 |
|
999 JSObject* |
|
1000 GetGlobalJSObject() const { |
|
1001 JS::ExposeObjectToActiveJS(mGlobalJSObject); |
|
1002 return mGlobalJSObject; |
|
1003 } |
|
1004 |
|
1005 JSObject* |
|
1006 GetGlobalJSObjectPreserveColor() const {return mGlobalJSObject;} |
|
1007 |
|
1008 nsIPrincipal* |
|
1009 GetPrincipal() const { |
|
1010 JSCompartment *c = js::GetObjectCompartment(mGlobalJSObject); |
|
1011 return nsJSPrincipals::get(JS_GetCompartmentPrincipals(c)); |
|
1012 } |
|
1013 |
|
1014 JSObject* |
|
1015 GetExpandoChain(JS::HandleObject target); |
|
1016 |
|
1017 bool |
|
1018 SetExpandoChain(JSContext *cx, JS::HandleObject target, JS::HandleObject chain); |
|
1019 |
|
1020 void RemoveWrappedNativeProtos(); |
|
1021 |
|
1022 static void |
|
1023 SystemIsBeingShutDown(); |
|
1024 |
|
1025 static void |
|
1026 TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt); |
|
1027 |
|
1028 void TraceInside(JSTracer *trc) { |
|
1029 MOZ_ASSERT(mGlobalJSObject); |
|
1030 mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject"); |
|
1031 if (mXBLScope) |
|
1032 mXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope"); |
|
1033 if (mXrayExpandos.initialized()) |
|
1034 mXrayExpandos.trace(trc); |
|
1035 } |
|
1036 |
|
1037 static void |
|
1038 SuspectAllWrappers(XPCJSRuntime* rt, nsCycleCollectionNoteRootCallback &cb); |
|
1039 |
|
1040 static void |
|
1041 StartFinalizationPhaseOfGC(JSFreeOp *fop, XPCJSRuntime* rt); |
|
1042 |
|
1043 static void |
|
1044 FinishedFinalizationPhaseOfGC(); |
|
1045 |
|
1046 static void |
|
1047 MarkAllWrappedNativesAndProtos(); |
|
1048 |
|
1049 #ifdef DEBUG |
|
1050 static void |
|
1051 ASSERT_NoInterfaceSetsAreMarked(); |
|
1052 #endif |
|
1053 |
|
1054 static void |
|
1055 SweepAllWrappedNativeTearOffs(); |
|
1056 |
|
1057 static void |
|
1058 DebugDumpAllScopes(int16_t depth); |
|
1059 |
|
1060 void |
|
1061 DebugDump(int16_t depth); |
|
1062 |
|
1063 struct ScopeSizeInfo { |
|
1064 ScopeSizeInfo(mozilla::MallocSizeOf mallocSizeOf) |
|
1065 : mMallocSizeOf(mallocSizeOf), |
|
1066 mScopeAndMapSize(0), |
|
1067 mProtoAndIfaceCacheSize(0) |
|
1068 {} |
|
1069 |
|
1070 mozilla::MallocSizeOf mMallocSizeOf; |
|
1071 size_t mScopeAndMapSize; |
|
1072 size_t mProtoAndIfaceCacheSize; |
|
1073 }; |
|
1074 |
|
1075 static void |
|
1076 AddSizeOfAllScopesIncludingThis(ScopeSizeInfo* scopeSizeInfo); |
|
1077 |
|
1078 void |
|
1079 AddSizeOfIncludingThis(ScopeSizeInfo* scopeSizeInfo); |
|
1080 |
|
1081 bool |
|
1082 IsValid() const {return mRuntime != nullptr;} |
|
1083 |
|
1084 static bool |
|
1085 IsDyingScope(XPCWrappedNativeScope *scope); |
|
1086 |
|
1087 static void InitStatics() { gScopes = nullptr; gDyingScopes = nullptr; } |
|
1088 |
|
1089 XPCContext *GetContext() { return mContext; } |
|
1090 void ClearContext() { mContext = nullptr; } |
|
1091 |
|
1092 typedef js::HashSet<JSObject *, |
|
1093 js::PointerHasher<JSObject *, 3>, |
|
1094 js::SystemAllocPolicy> DOMExpandoSet; |
|
1095 |
|
1096 bool RegisterDOMExpandoObject(JSObject *expando) { |
|
1097 // Expandos are proxy objects, and proxies are always tenured. |
|
1098 JS::AssertGCThingMustBeTenured(expando); |
|
1099 if (!mDOMExpandoSet) { |
|
1100 mDOMExpandoSet = new DOMExpandoSet(); |
|
1101 mDOMExpandoSet->init(8); |
|
1102 } |
|
1103 return mDOMExpandoSet->put(expando); |
|
1104 } |
|
1105 void RemoveDOMExpandoObject(JSObject *expando) { |
|
1106 if (mDOMExpandoSet) |
|
1107 mDOMExpandoSet->remove(expando); |
|
1108 } |
|
1109 |
|
1110 // Gets the appropriate scope object for XBL in this scope. The context |
|
1111 // must be same-compartment with the global upon entering, and the scope |
|
1112 // object is wrapped into the compartment of the global. |
|
1113 JSObject *EnsureXBLScope(JSContext *cx); |
|
1114 |
|
1115 XPCWrappedNativeScope(JSContext *cx, JS::HandleObject aGlobal); |
|
1116 |
|
1117 nsAutoPtr<JSObject2JSObjectMap> mWaiverWrapperMap; |
|
1118 |
|
1119 bool IsXBLScope() { return mIsXBLScope; } |
|
1120 bool AllowXBLScope(); |
|
1121 bool UseXBLScope() { return mUseXBLScope; } |
|
1122 |
|
1123 protected: |
|
1124 virtual ~XPCWrappedNativeScope(); |
|
1125 |
|
1126 static void KillDyingScopes(); |
|
1127 |
|
1128 XPCWrappedNativeScope(); // not implemented |
|
1129 |
|
1130 private: |
|
1131 static XPCWrappedNativeScope* gScopes; |
|
1132 static XPCWrappedNativeScope* gDyingScopes; |
|
1133 |
|
1134 XPCJSRuntime* mRuntime; |
|
1135 Native2WrappedNativeMap* mWrappedNativeMap; |
|
1136 ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap; |
|
1137 nsRefPtr<nsXPCComponentsBase> mComponents; |
|
1138 XPCWrappedNativeScope* mNext; |
|
1139 // The JS global object for this scope. If non-null, this will be the |
|
1140 // default parent for the XPCWrappedNatives that have us as the scope, |
|
1141 // unless a PreCreate hook overrides it. Note that this _may_ be null (see |
|
1142 // constructor). |
|
1143 JS::ObjectPtr mGlobalJSObject; |
|
1144 |
|
1145 // XBL Scope. This is is a lazily-created sandbox for non-system scopes. |
|
1146 // EnsureXBLScope() decides whether it needs to be created or not. |
|
1147 // This reference is wrapped into the compartment of mGlobalJSObject. |
|
1148 JS::ObjectPtr mXBLScope; |
|
1149 |
|
1150 XPCContext* mContext; |
|
1151 |
|
1152 nsAutoPtr<DOMExpandoSet> mDOMExpandoSet; |
|
1153 |
|
1154 JS::WeakMapPtr<JSObject*, JSObject*> mXrayExpandos; |
|
1155 |
|
1156 bool mIsXBLScope; |
|
1157 |
|
1158 // For remote XUL domains, we run all XBL in the content scope for compat |
|
1159 // reasons (though we sometimes pref this off for automation). We separately |
|
1160 // track the result of this decision (mAllowXBLScope), from the decision |
|
1161 // of whether to actually _use_ an XBL scope (mUseXBLScope), which depends |
|
1162 // on the type of global and whether the compartment is system principal |
|
1163 // or not. |
|
1164 // |
|
1165 // This distinction is useful primarily because, if true, we know that we |
|
1166 // have no way of distinguishing XBL script from content script for the |
|
1167 // given scope. In these (unsupported) situations, we just always claim to |
|
1168 // be XBL. |
|
1169 bool mAllowXBLScope; |
|
1170 bool mUseXBLScope; |
|
1171 }; |
|
1172 |
|
1173 /***************************************************************************/ |
|
1174 // XPCNativeMember represents a single idl declared method, attribute or |
|
1175 // constant. |
|
1176 |
|
1177 // Tight. No virtual methods. Can be bitwise copied (until any resolution done). |
|
1178 |
|
1179 class XPCNativeMember |
|
1180 { |
|
1181 public: |
|
1182 static bool GetCallInfo(JSObject* funobj, |
|
1183 XPCNativeInterface** pInterface, |
|
1184 XPCNativeMember** pMember); |
|
1185 |
|
1186 jsid GetName() const {return mName;} |
|
1187 |
|
1188 uint16_t GetIndex() const {return mIndex;} |
|
1189 |
|
1190 bool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface, |
|
1191 jsval* pval) |
|
1192 {MOZ_ASSERT(IsConstant(), |
|
1193 "Only call this if you're sure this is a constant!"); |
|
1194 return Resolve(ccx, iface, JS::NullPtr(), pval);} |
|
1195 |
|
1196 bool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface, |
|
1197 JS::HandleObject parent, jsval* pval); |
|
1198 |
|
1199 bool IsMethod() const |
|
1200 {return 0 != (mFlags & METHOD);} |
|
1201 |
|
1202 bool IsConstant() const |
|
1203 {return 0 != (mFlags & CONSTANT);} |
|
1204 |
|
1205 bool IsAttribute() const |
|
1206 {return 0 != (mFlags & GETTER);} |
|
1207 |
|
1208 bool IsWritableAttribute() const |
|
1209 {return 0 != (mFlags & SETTER_TOO);} |
|
1210 |
|
1211 bool IsReadOnlyAttribute() const |
|
1212 {return IsAttribute() && !IsWritableAttribute();} |
|
1213 |
|
1214 |
|
1215 void SetName(jsid a) {mName = a;} |
|
1216 |
|
1217 void SetMethod(uint16_t index) |
|
1218 {mFlags = METHOD; mIndex = index;} |
|
1219 |
|
1220 void SetConstant(uint16_t index) |
|
1221 {mFlags = CONSTANT; mIndex = index;} |
|
1222 |
|
1223 void SetReadOnlyAttribute(uint16_t index) |
|
1224 {mFlags = GETTER; mIndex = index;} |
|
1225 |
|
1226 void SetWritableAttribute() |
|
1227 {MOZ_ASSERT(mFlags == GETTER,"bad"); mFlags = GETTER | SETTER_TOO;} |
|
1228 |
|
1229 /* default ctor - leave random contents */ |
|
1230 XPCNativeMember() {MOZ_COUNT_CTOR(XPCNativeMember);} |
|
1231 ~XPCNativeMember() {MOZ_COUNT_DTOR(XPCNativeMember);} |
|
1232 |
|
1233 private: |
|
1234 bool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface, |
|
1235 JS::HandleObject parent, jsval *vp); |
|
1236 |
|
1237 enum { |
|
1238 METHOD = 0x01, |
|
1239 CONSTANT = 0x02, |
|
1240 GETTER = 0x04, |
|
1241 SETTER_TOO = 0x08 |
|
1242 }; |
|
1243 |
|
1244 private: |
|
1245 // our only data... |
|
1246 jsid mName; |
|
1247 uint16_t mIndex; |
|
1248 uint16_t mFlags; |
|
1249 }; |
|
1250 |
|
1251 /***************************************************************************/ |
|
1252 // XPCNativeInterface represents a single idl declared interface. This is |
|
1253 // primarily the set of XPCNativeMembers. |
|
1254 |
|
1255 // Tight. No virtual methods. |
|
1256 |
|
1257 class XPCNativeInterface |
|
1258 { |
|
1259 public: |
|
1260 static XPCNativeInterface* GetNewOrUsed(const nsIID* iid); |
|
1261 static XPCNativeInterface* GetNewOrUsed(nsIInterfaceInfo* info); |
|
1262 static XPCNativeInterface* GetNewOrUsed(const char* name); |
|
1263 static XPCNativeInterface* GetISupports(); |
|
1264 |
|
1265 inline nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo.get();} |
|
1266 inline jsid GetName() const {return mName;} |
|
1267 |
|
1268 inline const nsIID* GetIID() const; |
|
1269 inline const char* GetNameString() const; |
|
1270 inline XPCNativeMember* FindMember(jsid name) const; |
|
1271 |
|
1272 inline bool HasAncestor(const nsIID* iid) const; |
|
1273 |
|
1274 uint16_t GetMemberCount() const { |
|
1275 return mMemberCount; |
|
1276 } |
|
1277 XPCNativeMember* GetMemberAt(uint16_t i) { |
|
1278 MOZ_ASSERT(i < mMemberCount, "bad index"); |
|
1279 return &mMembers[i]; |
|
1280 } |
|
1281 |
|
1282 void DebugDump(int16_t depth); |
|
1283 |
|
1284 #define XPC_NATIVE_IFACE_MARK_FLAG ((uint16_t)JS_BIT(15)) // only high bit of 16 is set |
|
1285 |
|
1286 void Mark() { |
|
1287 mMarked = 1; |
|
1288 } |
|
1289 |
|
1290 void Unmark() { |
|
1291 mMarked = 0; |
|
1292 } |
|
1293 |
|
1294 bool IsMarked() const { |
|
1295 return mMarked != 0; |
|
1296 } |
|
1297 |
|
1298 // NOP. This is just here to make the AutoMarkingPtr code compile. |
|
1299 inline void TraceJS(JSTracer* trc) {} |
|
1300 inline void AutoTrace(JSTracer* trc) {} |
|
1301 |
|
1302 static void DestroyInstance(XPCNativeInterface* inst); |
|
1303 |
|
1304 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
1305 |
|
1306 protected: |
|
1307 static XPCNativeInterface* NewInstance(nsIInterfaceInfo* aInfo); |
|
1308 |
|
1309 XPCNativeInterface(); // not implemented |
|
1310 XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName) |
|
1311 : mInfo(aInfo), mName(aName), mMemberCount(0), mMarked(0) |
|
1312 { |
|
1313 MOZ_COUNT_CTOR(XPCNativeInterface); |
|
1314 } |
|
1315 ~XPCNativeInterface() { |
|
1316 MOZ_COUNT_DTOR(XPCNativeInterface); |
|
1317 } |
|
1318 |
|
1319 void* operator new(size_t, void* p) CPP_THROW_NEW {return p;} |
|
1320 |
|
1321 XPCNativeInterface(const XPCNativeInterface& r); // not implemented |
|
1322 XPCNativeInterface& operator= (const XPCNativeInterface& r); // not implemented |
|
1323 |
|
1324 private: |
|
1325 nsCOMPtr<nsIInterfaceInfo> mInfo; |
|
1326 jsid mName; |
|
1327 uint16_t mMemberCount : 15; |
|
1328 uint16_t mMarked : 1; |
|
1329 XPCNativeMember mMembers[1]; // always last - object sized for array |
|
1330 }; |
|
1331 |
|
1332 /***************************************************************************/ |
|
1333 // XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap. |
|
1334 |
|
1335 class XPCNativeSetKey |
|
1336 { |
|
1337 public: |
|
1338 XPCNativeSetKey(XPCNativeSet* BaseSet = nullptr, |
|
1339 XPCNativeInterface* Addition = nullptr, |
|
1340 uint16_t Position = 0) |
|
1341 : mIsAKey(IS_A_KEY), mPosition(Position), mBaseSet(BaseSet), |
|
1342 mAddition(Addition) {} |
|
1343 ~XPCNativeSetKey() {} |
|
1344 |
|
1345 XPCNativeSet* GetBaseSet() const {return mBaseSet;} |
|
1346 XPCNativeInterface* GetAddition() const {return mAddition;} |
|
1347 uint16_t GetPosition() const {return mPosition;} |
|
1348 |
|
1349 // This is a fun little hack... |
|
1350 // We build these keys only on the stack. We use them for lookup in |
|
1351 // NativeSetMap. Becasue we don't want to pay the cost of cloning a key and |
|
1352 // sticking it into the hashtable, when the XPCNativeSet actually |
|
1353 // gets added to the table the 'key' in the table is a pointer to the |
|
1354 // set itself and not this key. Our key compare function expects to get |
|
1355 // a key and a set. When we do external lookups in the map we pass in one |
|
1356 // of these keys and our compare function gets passed a key and a set. |
|
1357 // (see compare_NativeKeyToSet in xpcmaps.cpp). This is all well and good. |
|
1358 // Except, when the table decides to resize itself. Then it tries to use |
|
1359 // our compare function with the 'keys' that are in the hashtable (which are |
|
1360 // really XPCNativeSet objects and not XPCNativeSetKey objects! |
|
1361 // |
|
1362 // So, the hack is to have the compare function assume it is getting a |
|
1363 // XPCNativeSetKey pointer and call this IsAKey method. If that fails then |
|
1364 // it realises that it really has a XPCNativeSet pointer and deals with that |
|
1365 // fact. This is safe because we know that both of these classes have no |
|
1366 // virtual methods and their first data member is a uint16_t. We are |
|
1367 // confident that XPCNativeSet->mMemberCount will never be 0xffff. |
|
1368 |
|
1369 bool IsAKey() const {return mIsAKey == IS_A_KEY;} |
|
1370 |
|
1371 enum {IS_A_KEY = 0xffff}; |
|
1372 |
|
1373 // Allow shallow copy |
|
1374 |
|
1375 private: |
|
1376 uint16_t mIsAKey; // must be first data member |
|
1377 uint16_t mPosition; |
|
1378 XPCNativeSet* mBaseSet; |
|
1379 XPCNativeInterface* mAddition; |
|
1380 }; |
|
1381 |
|
1382 /***************************************************************************/ |
|
1383 // XPCNativeSet represents an ordered collection of XPCNativeInterface pointers. |
|
1384 |
|
1385 class XPCNativeSet |
|
1386 { |
|
1387 public: |
|
1388 static XPCNativeSet* GetNewOrUsed(const nsIID* iid); |
|
1389 static XPCNativeSet* GetNewOrUsed(nsIClassInfo* classInfo); |
|
1390 static XPCNativeSet* GetNewOrUsed(XPCNativeSet* otherSet, |
|
1391 XPCNativeInterface* newInterface, |
|
1392 uint16_t position); |
|
1393 |
|
1394 // This generates a union set. |
|
1395 // |
|
1396 // If preserveFirstSetOrder is true, the elements from |firstSet| come first, |
|
1397 // followed by any non-duplicate items from |secondSet|. If false, the same |
|
1398 // algorithm is applied; but if we detect that |secondSet| is a superset of |
|
1399 // |firstSet|, we return |secondSet| without worrying about whether the |
|
1400 // ordering might differ from |firstSet|. |
|
1401 static XPCNativeSet* GetNewOrUsed(XPCNativeSet* firstSet, |
|
1402 XPCNativeSet* secondSet, |
|
1403 bool preserveFirstSetOrder); |
|
1404 |
|
1405 static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo); |
|
1406 |
|
1407 inline bool FindMember(jsid name, XPCNativeMember** pMember, |
|
1408 uint16_t* pInterfaceIndex) const; |
|
1409 |
|
1410 inline bool FindMember(jsid name, XPCNativeMember** pMember, |
|
1411 XPCNativeInterface** pInterface) const; |
|
1412 |
|
1413 inline bool FindMember(jsid name, |
|
1414 XPCNativeMember** pMember, |
|
1415 XPCNativeInterface** pInterface, |
|
1416 XPCNativeSet* protoSet, |
|
1417 bool* pIsLocal) const; |
|
1418 |
|
1419 inline bool HasInterface(XPCNativeInterface* aInterface) const; |
|
1420 inline bool HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const; |
|
1421 inline bool HasInterfaceWithAncestor(const nsIID* iid) const; |
|
1422 |
|
1423 inline XPCNativeInterface* FindInterfaceWithIID(const nsIID& iid) const; |
|
1424 |
|
1425 inline XPCNativeInterface* FindNamedInterface(jsid name) const; |
|
1426 |
|
1427 uint16_t GetMemberCount() const { |
|
1428 return mMemberCount; |
|
1429 } |
|
1430 uint16_t GetInterfaceCount() const { |
|
1431 return mInterfaceCount; |
|
1432 } |
|
1433 XPCNativeInterface **GetInterfaceArray() { |
|
1434 return mInterfaces; |
|
1435 } |
|
1436 |
|
1437 XPCNativeInterface* GetInterfaceAt(uint16_t i) |
|
1438 {MOZ_ASSERT(i < mInterfaceCount, "bad index"); return mInterfaces[i];} |
|
1439 |
|
1440 inline bool MatchesSetUpToInterface(const XPCNativeSet* other, |
|
1441 XPCNativeInterface* iface) const; |
|
1442 |
|
1443 #define XPC_NATIVE_SET_MARK_FLAG ((uint16_t)JS_BIT(15)) // only high bit of 16 is set |
|
1444 |
|
1445 inline void Mark(); |
|
1446 |
|
1447 // NOP. This is just here to make the AutoMarkingPtr code compile. |
|
1448 inline void TraceJS(JSTracer* trc) {} |
|
1449 inline void AutoTrace(JSTracer* trc) {} |
|
1450 |
|
1451 private: |
|
1452 void MarkSelfOnly() { |
|
1453 mMarked = 1; |
|
1454 } |
|
1455 |
|
1456 public: |
|
1457 void Unmark() { |
|
1458 mMarked = 0; |
|
1459 } |
|
1460 bool IsMarked() const { |
|
1461 return !!mMarked; |
|
1462 } |
|
1463 |
|
1464 #ifdef DEBUG |
|
1465 inline void ASSERT_NotMarked(); |
|
1466 #endif |
|
1467 |
|
1468 void DebugDump(int16_t depth); |
|
1469 |
|
1470 static void DestroyInstance(XPCNativeSet* inst); |
|
1471 |
|
1472 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
1473 |
|
1474 protected: |
|
1475 static XPCNativeSet* NewInstance(XPCNativeInterface** array, |
|
1476 uint16_t count); |
|
1477 static XPCNativeSet* NewInstanceMutate(XPCNativeSet* otherSet, |
|
1478 XPCNativeInterface* newInterface, |
|
1479 uint16_t position); |
|
1480 XPCNativeSet() |
|
1481 : mMemberCount(0), mInterfaceCount(0), mMarked(0) |
|
1482 { |
|
1483 MOZ_COUNT_CTOR(XPCNativeSet); |
|
1484 } |
|
1485 ~XPCNativeSet() { |
|
1486 MOZ_COUNT_DTOR(XPCNativeSet); |
|
1487 } |
|
1488 void* operator new(size_t, void* p) CPP_THROW_NEW {return p;} |
|
1489 |
|
1490 private: |
|
1491 uint16_t mMemberCount; |
|
1492 uint16_t mInterfaceCount : 15; |
|
1493 uint16_t mMarked : 1; |
|
1494 XPCNativeInterface* mInterfaces[1]; // always last - object sized for array |
|
1495 }; |
|
1496 |
|
1497 /***************************************************************************/ |
|
1498 // XPCNativeScriptableFlags is a wrapper class that holds the flags returned |
|
1499 // from calls to nsIXPCScriptable::GetScriptableFlags(). It has convenience |
|
1500 // methods to check for particular bitflags. Since we also use this class as |
|
1501 // a member of the gc'd class XPCNativeScriptableShared, this class holds the |
|
1502 // bit and exposes the inlined methods to support marking. |
|
1503 |
|
1504 #define XPC_WN_SJSFLAGS_MARK_FLAG JS_BIT(31) // only high bit of 32 is set |
|
1505 |
|
1506 class XPCNativeScriptableFlags |
|
1507 { |
|
1508 private: |
|
1509 uint32_t mFlags; |
|
1510 |
|
1511 public: |
|
1512 |
|
1513 XPCNativeScriptableFlags(uint32_t flags = 0) : mFlags(flags) {} |
|
1514 |
|
1515 uint32_t GetFlags() const {return mFlags & ~XPC_WN_SJSFLAGS_MARK_FLAG;} |
|
1516 void SetFlags(uint32_t flags) {mFlags = flags;} |
|
1517 |
|
1518 operator uint32_t() const {return GetFlags();} |
|
1519 |
|
1520 XPCNativeScriptableFlags(const XPCNativeScriptableFlags& r) |
|
1521 {mFlags = r.GetFlags();} |
|
1522 |
|
1523 XPCNativeScriptableFlags& operator= (const XPCNativeScriptableFlags& r) |
|
1524 {mFlags = r.GetFlags(); return *this;} |
|
1525 |
|
1526 void Mark() {mFlags |= XPC_WN_SJSFLAGS_MARK_FLAG;} |
|
1527 void Unmark() {mFlags &= ~XPC_WN_SJSFLAGS_MARK_FLAG;} |
|
1528 bool IsMarked() const {return 0 != (mFlags & XPC_WN_SJSFLAGS_MARK_FLAG);} |
|
1529 |
|
1530 #ifdef GET_IT |
|
1531 #undef GET_IT |
|
1532 #endif |
|
1533 #define GET_IT(f_) const {return 0 != (mFlags & nsIXPCScriptable:: f_ );} |
|
1534 |
|
1535 bool WantPreCreate() GET_IT(WANT_PRECREATE) |
|
1536 bool WantCreate() GET_IT(WANT_CREATE) |
|
1537 bool WantPostCreate() GET_IT(WANT_POSTCREATE) |
|
1538 bool WantAddProperty() GET_IT(WANT_ADDPROPERTY) |
|
1539 bool WantDelProperty() GET_IT(WANT_DELPROPERTY) |
|
1540 bool WantGetProperty() GET_IT(WANT_GETPROPERTY) |
|
1541 bool WantSetProperty() GET_IT(WANT_SETPROPERTY) |
|
1542 bool WantEnumerate() GET_IT(WANT_ENUMERATE) |
|
1543 bool WantNewEnumerate() GET_IT(WANT_NEWENUMERATE) |
|
1544 bool WantNewResolve() GET_IT(WANT_NEWRESOLVE) |
|
1545 bool WantConvert() GET_IT(WANT_CONVERT) |
|
1546 bool WantFinalize() GET_IT(WANT_FINALIZE) |
|
1547 bool WantCall() GET_IT(WANT_CALL) |
|
1548 bool WantConstruct() GET_IT(WANT_CONSTRUCT) |
|
1549 bool WantHasInstance() GET_IT(WANT_HASINSTANCE) |
|
1550 bool WantOuterObject() GET_IT(WANT_OUTER_OBJECT) |
|
1551 bool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY) |
|
1552 bool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY) |
|
1553 bool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY) |
|
1554 bool DontEnumStaticProps() GET_IT(DONT_ENUM_STATIC_PROPS) |
|
1555 bool DontEnumQueryInterface() GET_IT(DONT_ENUM_QUERY_INTERFACE) |
|
1556 bool DontAskInstanceForScriptable() GET_IT(DONT_ASK_INSTANCE_FOR_SCRIPTABLE) |
|
1557 bool ClassInfoInterfacesOnly() GET_IT(CLASSINFO_INTERFACES_ONLY) |
|
1558 bool AllowPropModsDuringResolve() GET_IT(ALLOW_PROP_MODS_DURING_RESOLVE) |
|
1559 bool AllowPropModsToPrototype() GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE) |
|
1560 bool IsGlobalObject() GET_IT(IS_GLOBAL_OBJECT) |
|
1561 bool DontReflectInterfaceNames() GET_IT(DONT_REFLECT_INTERFACE_NAMES) |
|
1562 |
|
1563 #undef GET_IT |
|
1564 }; |
|
1565 |
|
1566 /***************************************************************************/ |
|
1567 |
|
1568 // XPCNativeScriptableShared is used to hold the JSClass and the |
|
1569 // associated scriptable flags for XPCWrappedNatives. These are shared across |
|
1570 // the runtime and are garbage collected by xpconnect. We *used* to just store |
|
1571 // this inside the XPCNativeScriptableInfo (usually owned by instances of |
|
1572 // XPCWrappedNativeProto. This had two problems... It was wasteful, and it |
|
1573 // was a big problem when wrappers are reparented to different scopes (and |
|
1574 // thus different protos (the DOM does this). |
|
1575 |
|
1576 // We maintain the invariant that every JSClass for which ext.isWrappedNative |
|
1577 // is true is a contained in an instance of this struct, and can thus be cast |
|
1578 // to it. |
|
1579 struct XPCWrappedNativeJSClass |
|
1580 { |
|
1581 js::Class base; |
|
1582 uint32_t interfacesBitmap; |
|
1583 }; |
|
1584 |
|
1585 class XPCNativeScriptableShared |
|
1586 { |
|
1587 public: |
|
1588 const XPCNativeScriptableFlags& GetFlags() const {return mFlags;} |
|
1589 uint32_t GetInterfacesBitmap() const |
|
1590 {return mJSClass.interfacesBitmap;} |
|
1591 const JSClass* GetJSClass() |
|
1592 {return Jsvalify(&mJSClass.base);} |
|
1593 |
|
1594 XPCNativeScriptableShared(uint32_t aFlags, char* aName, |
|
1595 uint32_t interfacesBitmap) |
|
1596 : mFlags(aFlags) |
|
1597 {memset(&mJSClass, 0, sizeof(mJSClass)); |
|
1598 mJSClass.base.name = aName; // take ownership |
|
1599 mJSClass.interfacesBitmap = interfacesBitmap; |
|
1600 MOZ_COUNT_CTOR(XPCNativeScriptableShared);} |
|
1601 |
|
1602 ~XPCNativeScriptableShared() |
|
1603 {if (mJSClass.base.name)nsMemory::Free((void*)mJSClass.base.name); |
|
1604 MOZ_COUNT_DTOR(XPCNativeScriptableShared);} |
|
1605 |
|
1606 char* TransferNameOwnership() |
|
1607 {char* name=(char*)mJSClass.base.name; mJSClass.base.name = nullptr; |
|
1608 return name;} |
|
1609 |
|
1610 void PopulateJSClass(); |
|
1611 |
|
1612 void Mark() {mFlags.Mark();} |
|
1613 void Unmark() {mFlags.Unmark();} |
|
1614 bool IsMarked() const {return mFlags.IsMarked();} |
|
1615 |
|
1616 private: |
|
1617 XPCNativeScriptableFlags mFlags; |
|
1618 XPCWrappedNativeJSClass mJSClass; |
|
1619 }; |
|
1620 |
|
1621 /***************************************************************************/ |
|
1622 // XPCNativeScriptableInfo is used to hold the nsIXPCScriptable state for a |
|
1623 // given class or instance. |
|
1624 |
|
1625 class XPCNativeScriptableInfo |
|
1626 { |
|
1627 public: |
|
1628 static XPCNativeScriptableInfo* |
|
1629 Construct(const XPCNativeScriptableCreateInfo* sci); |
|
1630 |
|
1631 nsIXPCScriptable* |
|
1632 GetCallback() const {return mCallback;} |
|
1633 |
|
1634 const XPCNativeScriptableFlags& |
|
1635 GetFlags() const {return mShared->GetFlags();} |
|
1636 |
|
1637 uint32_t |
|
1638 GetInterfacesBitmap() const {return mShared->GetInterfacesBitmap();} |
|
1639 |
|
1640 const JSClass* |
|
1641 GetJSClass() {return mShared->GetJSClass();} |
|
1642 |
|
1643 XPCNativeScriptableShared* |
|
1644 GetScriptableShared() {return mShared;} |
|
1645 |
|
1646 void |
|
1647 SetCallback(nsIXPCScriptable* s) {mCallback = s;} |
|
1648 void |
|
1649 SetCallback(already_AddRefed<nsIXPCScriptable>&& s) {mCallback = s;} |
|
1650 |
|
1651 void |
|
1652 SetScriptableShared(XPCNativeScriptableShared* shared) {mShared = shared;} |
|
1653 |
|
1654 void Mark() { |
|
1655 if (mShared) |
|
1656 mShared->Mark(); |
|
1657 } |
|
1658 |
|
1659 void TraceJS(JSTracer *trc) {} |
|
1660 void AutoTrace(JSTracer *trc) {} |
|
1661 |
|
1662 protected: |
|
1663 XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nullptr, |
|
1664 XPCNativeScriptableShared* shared = nullptr) |
|
1665 : mCallback(scriptable), mShared(shared) |
|
1666 {MOZ_COUNT_CTOR(XPCNativeScriptableInfo);} |
|
1667 public: |
|
1668 ~XPCNativeScriptableInfo() {MOZ_COUNT_DTOR(XPCNativeScriptableInfo);} |
|
1669 private: |
|
1670 |
|
1671 // disable copy ctor and assignment |
|
1672 XPCNativeScriptableInfo(const XPCNativeScriptableInfo& r); // not implemented |
|
1673 XPCNativeScriptableInfo& operator= (const XPCNativeScriptableInfo& r); // not implemented |
|
1674 |
|
1675 private: |
|
1676 nsCOMPtr<nsIXPCScriptable> mCallback; |
|
1677 XPCNativeScriptableShared* mShared; |
|
1678 }; |
|
1679 |
|
1680 /***************************************************************************/ |
|
1681 // XPCNativeScriptableCreateInfo is used in creating new wrapper and protos. |
|
1682 // it abstracts out the scriptable interface pointer and the flags. After |
|
1683 // creation these are factored differently using XPCNativeScriptableInfo. |
|
1684 |
|
1685 class MOZ_STACK_CLASS XPCNativeScriptableCreateInfo |
|
1686 { |
|
1687 public: |
|
1688 |
|
1689 XPCNativeScriptableCreateInfo(const XPCNativeScriptableInfo& si) |
|
1690 : mCallback(si.GetCallback()), mFlags(si.GetFlags()), |
|
1691 mInterfacesBitmap(si.GetInterfacesBitmap()) {} |
|
1692 |
|
1693 XPCNativeScriptableCreateInfo(already_AddRefed<nsIXPCScriptable>&& callback, |
|
1694 XPCNativeScriptableFlags flags, |
|
1695 uint32_t interfacesBitmap) |
|
1696 : mCallback(callback), mFlags(flags), |
|
1697 mInterfacesBitmap(interfacesBitmap) {} |
|
1698 |
|
1699 XPCNativeScriptableCreateInfo() |
|
1700 : mFlags(0), mInterfacesBitmap(0) {} |
|
1701 |
|
1702 |
|
1703 nsIXPCScriptable* |
|
1704 GetCallback() const {return mCallback;} |
|
1705 |
|
1706 const XPCNativeScriptableFlags& |
|
1707 GetFlags() const {return mFlags;} |
|
1708 |
|
1709 uint32_t |
|
1710 GetInterfacesBitmap() const {return mInterfacesBitmap;} |
|
1711 |
|
1712 void |
|
1713 SetCallback(already_AddRefed<nsIXPCScriptable>&& callback) |
|
1714 {mCallback = callback;} |
|
1715 |
|
1716 void |
|
1717 SetFlags(const XPCNativeScriptableFlags& flags) {mFlags = flags;} |
|
1718 |
|
1719 void |
|
1720 SetInterfacesBitmap(uint32_t interfacesBitmap) |
|
1721 {mInterfacesBitmap = interfacesBitmap;} |
|
1722 |
|
1723 private: |
|
1724 nsCOMPtr<nsIXPCScriptable> mCallback; |
|
1725 XPCNativeScriptableFlags mFlags; |
|
1726 uint32_t mInterfacesBitmap; |
|
1727 }; |
|
1728 |
|
1729 /***********************************************/ |
|
1730 // XPCWrappedNativeProto hold the additional shared wrapper data |
|
1731 // for XPCWrappedNative whose native objects expose nsIClassInfo. |
|
1732 |
|
1733 class XPCWrappedNativeProto |
|
1734 { |
|
1735 public: |
|
1736 static XPCWrappedNativeProto* |
|
1737 GetNewOrUsed(XPCWrappedNativeScope* scope, |
|
1738 nsIClassInfo* classInfo, |
|
1739 const XPCNativeScriptableCreateInfo* scriptableCreateInfo, |
|
1740 bool callPostCreatePrototype = true); |
|
1741 |
|
1742 XPCWrappedNativeScope* |
|
1743 GetScope() const {return mScope;} |
|
1744 |
|
1745 XPCJSRuntime* |
|
1746 GetRuntime() const {return mScope->GetRuntime();} |
|
1747 |
|
1748 JSObject* |
|
1749 GetJSProtoObject() const { |
|
1750 JS::ExposeObjectToActiveJS(mJSProtoObject); |
|
1751 return mJSProtoObject; |
|
1752 } |
|
1753 |
|
1754 nsIClassInfo* |
|
1755 GetClassInfo() const {return mClassInfo;} |
|
1756 |
|
1757 XPCNativeSet* |
|
1758 GetSet() const {return mSet;} |
|
1759 |
|
1760 XPCNativeScriptableInfo* |
|
1761 GetScriptableInfo() {return mScriptableInfo;} |
|
1762 |
|
1763 uint32_t |
|
1764 GetClassInfoFlags() const {return mClassInfoFlags;} |
|
1765 |
|
1766 #ifdef GET_IT |
|
1767 #undef GET_IT |
|
1768 #endif |
|
1769 #define GET_IT(f_) const {return !!(mClassInfoFlags & nsIClassInfo:: f_ );} |
|
1770 |
|
1771 bool ClassIsSingleton() GET_IT(SINGLETON) |
|
1772 bool ClassIsDOMObject() GET_IT(DOM_OBJECT) |
|
1773 bool ClassIsPluginObject() GET_IT(PLUGIN_OBJECT) |
|
1774 |
|
1775 #undef GET_IT |
|
1776 |
|
1777 void SetScriptableInfo(XPCNativeScriptableInfo* si) |
|
1778 {MOZ_ASSERT(!mScriptableInfo, "leak here!"); mScriptableInfo = si;} |
|
1779 |
|
1780 bool CallPostCreatePrototype(); |
|
1781 void JSProtoObjectFinalized(js::FreeOp *fop, JSObject *obj); |
|
1782 |
|
1783 void SystemIsBeingShutDown(); |
|
1784 |
|
1785 void DebugDump(int16_t depth); |
|
1786 |
|
1787 void TraceSelf(JSTracer *trc) { |
|
1788 if (mJSProtoObject) |
|
1789 mJSProtoObject.trace(trc, "XPCWrappedNativeProto::mJSProtoObject"); |
|
1790 } |
|
1791 |
|
1792 void TraceInside(JSTracer *trc) { |
|
1793 if (JS_IsGCMarkingTracer(trc)) { |
|
1794 mSet->Mark(); |
|
1795 if (mScriptableInfo) |
|
1796 mScriptableInfo->Mark(); |
|
1797 } |
|
1798 |
|
1799 GetScope()->TraceInside(trc); |
|
1800 } |
|
1801 |
|
1802 void TraceJS(JSTracer *trc) { |
|
1803 TraceSelf(trc); |
|
1804 TraceInside(trc); |
|
1805 } |
|
1806 |
|
1807 void WriteBarrierPre(JSRuntime* rt) |
|
1808 { |
|
1809 if (JS::IsIncrementalBarrierNeeded(rt) && mJSProtoObject) |
|
1810 mJSProtoObject.writeBarrierPre(rt); |
|
1811 } |
|
1812 |
|
1813 // NOP. This is just here to make the AutoMarkingPtr code compile. |
|
1814 inline void AutoTrace(JSTracer* trc) {} |
|
1815 |
|
1816 // Yes, we *do* need to mark the mScriptableInfo in both cases. |
|
1817 void Mark() const |
|
1818 {mSet->Mark(); |
|
1819 if (mScriptableInfo) mScriptableInfo->Mark();} |
|
1820 |
|
1821 #ifdef DEBUG |
|
1822 void ASSERT_SetNotMarked() const {mSet->ASSERT_NotMarked();} |
|
1823 #endif |
|
1824 |
|
1825 ~XPCWrappedNativeProto(); |
|
1826 |
|
1827 protected: |
|
1828 // disable copy ctor and assignment |
|
1829 XPCWrappedNativeProto(const XPCWrappedNativeProto& r); // not implemented |
|
1830 XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r); // not implemented |
|
1831 |
|
1832 // hide ctor |
|
1833 XPCWrappedNativeProto(XPCWrappedNativeScope* Scope, |
|
1834 nsIClassInfo* ClassInfo, |
|
1835 uint32_t ClassInfoFlags, |
|
1836 XPCNativeSet* Set); |
|
1837 |
|
1838 bool Init(const XPCNativeScriptableCreateInfo* scriptableCreateInfo, |
|
1839 bool callPostCreatePrototype); |
|
1840 |
|
1841 private: |
|
1842 #ifdef DEBUG |
|
1843 static int32_t gDEBUG_LiveProtoCount; |
|
1844 #endif |
|
1845 |
|
1846 private: |
|
1847 XPCWrappedNativeScope* mScope; |
|
1848 JS::ObjectPtr mJSProtoObject; |
|
1849 nsCOMPtr<nsIClassInfo> mClassInfo; |
|
1850 uint32_t mClassInfoFlags; |
|
1851 XPCNativeSet* mSet; |
|
1852 XPCNativeScriptableInfo* mScriptableInfo; |
|
1853 }; |
|
1854 |
|
1855 /***********************************************/ |
|
1856 // XPCWrappedNativeTearOff represents the info needed to make calls to one |
|
1857 // interface on the underlying native object of a XPCWrappedNative. |
|
1858 |
|
1859 class XPCWrappedNativeTearOff |
|
1860 { |
|
1861 public: |
|
1862 bool IsAvailable() const {return mInterface == nullptr;} |
|
1863 bool IsReserved() const {return mInterface == (XPCNativeInterface*)1;} |
|
1864 bool IsValid() const {return !IsAvailable() && !IsReserved();} |
|
1865 void SetReserved() {mInterface = (XPCNativeInterface*)1;} |
|
1866 |
|
1867 XPCNativeInterface* GetInterface() const {return mInterface;} |
|
1868 nsISupports* GetNative() const {return mNative;} |
|
1869 JSObject* GetJSObject(); |
|
1870 JSObject* GetJSObjectPreserveColor() const; |
|
1871 void SetInterface(XPCNativeInterface* Interface) {mInterface = Interface;} |
|
1872 void SetNative(nsISupports* Native) {mNative = Native;} |
|
1873 void SetJSObject(JSObject* JSObj); |
|
1874 |
|
1875 void JSObjectFinalized() {SetJSObject(nullptr);} |
|
1876 |
|
1877 XPCWrappedNativeTearOff() |
|
1878 : mInterface(nullptr), mNative(nullptr), mJSObject(nullptr) {} |
|
1879 ~XPCWrappedNativeTearOff(); |
|
1880 |
|
1881 // NOP. This is just here to make the AutoMarkingPtr code compile. |
|
1882 inline void TraceJS(JSTracer* trc) {} |
|
1883 inline void AutoTrace(JSTracer* trc) {} |
|
1884 |
|
1885 void Mark() {mJSObject = (JSObject*)(intptr_t(mJSObject) | 1);} |
|
1886 void Unmark() {mJSObject = (JSObject*)(intptr_t(mJSObject) & ~1);} |
|
1887 bool IsMarked() const {return !!(intptr_t(mJSObject) & 1);} |
|
1888 |
|
1889 private: |
|
1890 XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) MOZ_DELETE; |
|
1891 XPCWrappedNativeTearOff& operator= (const XPCWrappedNativeTearOff& r) MOZ_DELETE; |
|
1892 |
|
1893 private: |
|
1894 XPCNativeInterface* mInterface; |
|
1895 nsISupports* mNative; |
|
1896 JSObject* mJSObject; |
|
1897 }; |
|
1898 |
|
1899 /***********************************************/ |
|
1900 // XPCWrappedNativeTearOffChunk is a collections of XPCWrappedNativeTearOff |
|
1901 // objects. It lets us allocate a set of XPCWrappedNativeTearOff objects and |
|
1902 // link the sets - rather than only having the option of linking single |
|
1903 // XPCWrappedNativeTearOff objects. |
|
1904 // |
|
1905 // The value of XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK can be tuned at buildtime |
|
1906 // to balance between the code of allocations of additional chunks and the waste |
|
1907 // of space for ununsed XPCWrappedNativeTearOff objects. |
|
1908 |
|
1909 #define XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK 1 |
|
1910 |
|
1911 class XPCWrappedNativeTearOffChunk |
|
1912 { |
|
1913 friend class XPCWrappedNative; |
|
1914 private: |
|
1915 XPCWrappedNativeTearOffChunk() : mNextChunk(nullptr) {} |
|
1916 ~XPCWrappedNativeTearOffChunk() {delete mNextChunk;} |
|
1917 |
|
1918 private: |
|
1919 XPCWrappedNativeTearOff mTearOffs[XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK]; |
|
1920 XPCWrappedNativeTearOffChunk* mNextChunk; |
|
1921 }; |
|
1922 |
|
1923 void *xpc_GetJSPrivate(JSObject *obj); |
|
1924 |
|
1925 /***************************************************************************/ |
|
1926 // XPCWrappedNative the wrapper around one instance of a native xpcom object |
|
1927 // to be used from JavaScript. |
|
1928 |
|
1929 class XPCWrappedNative : public nsIXPConnectWrappedNative |
|
1930 { |
|
1931 public: |
|
1932 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
1933 NS_DECL_NSIXPCONNECTJSOBJECTHOLDER |
|
1934 NS_DECL_NSIXPCONNECTWRAPPEDNATIVE |
|
1935 |
|
1936 NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative) |
|
1937 |
|
1938 nsIPrincipal* GetObjectPrincipal() const; |
|
1939 |
|
1940 bool |
|
1941 IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); } |
|
1942 |
|
1943 #define XPC_SCOPE_WORD(s) (intptr_t(s)) |
|
1944 #define XPC_SCOPE_MASK (intptr_t(0x3)) |
|
1945 #define XPC_SCOPE_TAG (intptr_t(0x1)) |
|
1946 #define XPC_WRAPPER_EXPIRED (intptr_t(0x2)) |
|
1947 |
|
1948 static inline bool |
|
1949 IsTaggedScope(XPCWrappedNativeScope* s) |
|
1950 {return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;} |
|
1951 |
|
1952 static inline XPCWrappedNativeScope* |
|
1953 TagScope(XPCWrappedNativeScope* s) |
|
1954 {MOZ_ASSERT(!IsTaggedScope(s), "bad pointer!"); |
|
1955 return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) | XPC_SCOPE_TAG);} |
|
1956 |
|
1957 static inline XPCWrappedNativeScope* |
|
1958 UnTagScope(XPCWrappedNativeScope* s) |
|
1959 {return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) & ~XPC_SCOPE_TAG);} |
|
1960 |
|
1961 inline bool |
|
1962 IsWrapperExpired() const |
|
1963 {return XPC_SCOPE_WORD(mMaybeScope) & XPC_WRAPPER_EXPIRED;} |
|
1964 |
|
1965 bool |
|
1966 HasProto() const {return !IsTaggedScope(mMaybeScope);} |
|
1967 |
|
1968 XPCWrappedNativeProto* |
|
1969 GetProto() const |
|
1970 {return HasProto() ? |
|
1971 (XPCWrappedNativeProto*) |
|
1972 (XPC_SCOPE_WORD(mMaybeProto) & ~XPC_SCOPE_MASK) : nullptr;} |
|
1973 |
|
1974 void SetProto(XPCWrappedNativeProto* p); |
|
1975 |
|
1976 XPCWrappedNativeScope* |
|
1977 GetScope() const |
|
1978 {return GetProto() ? GetProto()->GetScope() : |
|
1979 (XPCWrappedNativeScope*) |
|
1980 (XPC_SCOPE_WORD(mMaybeScope) & ~XPC_SCOPE_MASK);} |
|
1981 |
|
1982 nsISupports* |
|
1983 GetIdentityObject() const {return mIdentity;} |
|
1984 |
|
1985 /** |
|
1986 * This getter clears the gray bit before handing out the JSObject which |
|
1987 * means that the object is guaranteed to be kept alive past the next CC. |
|
1988 */ |
|
1989 JSObject* |
|
1990 GetFlatJSObject() const |
|
1991 { |
|
1992 JS::ExposeObjectToActiveJS(mFlatJSObject); |
|
1993 return mFlatJSObject; |
|
1994 } |
|
1995 |
|
1996 /** |
|
1997 * This getter does not change the color of the JSObject meaning that the |
|
1998 * object returned is not guaranteed to be kept alive past the next CC. |
|
1999 * |
|
2000 * This should only be called if you are certain that the return value won't |
|
2001 * be passed into a JS API function and that it won't be stored without |
|
2002 * being rooted (or otherwise signaling the stored value to the CC). |
|
2003 */ |
|
2004 JSObject* |
|
2005 GetFlatJSObjectPreserveColor() const {return mFlatJSObject;} |
|
2006 |
|
2007 XPCNativeSet* |
|
2008 GetSet() const {return mSet;} |
|
2009 |
|
2010 void |
|
2011 SetSet(XPCNativeSet* set) {mSet = set;} |
|
2012 |
|
2013 static XPCWrappedNative* Get(JSObject *obj) { |
|
2014 MOZ_ASSERT(IS_WN_REFLECTOR(obj)); |
|
2015 return (XPCWrappedNative*)js::GetObjectPrivate(obj); |
|
2016 } |
|
2017 |
|
2018 private: |
|
2019 inline void |
|
2020 ExpireWrapper() |
|
2021 {mMaybeScope = (XPCWrappedNativeScope*) |
|
2022 (XPC_SCOPE_WORD(mMaybeScope) | XPC_WRAPPER_EXPIRED);} |
|
2023 |
|
2024 public: |
|
2025 |
|
2026 XPCNativeScriptableInfo* |
|
2027 GetScriptableInfo() const {return mScriptableInfo;} |
|
2028 |
|
2029 nsIXPCScriptable* // call this wrong and you deserve to crash |
|
2030 GetScriptableCallback() const {return mScriptableInfo->GetCallback();} |
|
2031 |
|
2032 nsIClassInfo* |
|
2033 GetClassInfo() const {return IsValid() && HasProto() ? |
|
2034 GetProto()->GetClassInfo() : nullptr;} |
|
2035 |
|
2036 bool |
|
2037 HasMutatedSet() const {return IsValid() && |
|
2038 (!HasProto() || |
|
2039 GetSet() != GetProto()->GetSet());} |
|
2040 |
|
2041 XPCJSRuntime* |
|
2042 GetRuntime() const {XPCWrappedNativeScope* scope = GetScope(); |
|
2043 return scope ? scope->GetRuntime() : nullptr;} |
|
2044 |
|
2045 static nsresult |
|
2046 WrapNewGlobal(xpcObjectHelper &nativeHelper, |
|
2047 nsIPrincipal *principal, bool initStandardClasses, |
|
2048 JS::CompartmentOptions& aOptions, |
|
2049 XPCWrappedNative **wrappedGlobal); |
|
2050 |
|
2051 static nsresult |
|
2052 GetNewOrUsed(xpcObjectHelper& helper, |
|
2053 XPCWrappedNativeScope* Scope, |
|
2054 XPCNativeInterface* Interface, |
|
2055 XPCWrappedNative** wrapper); |
|
2056 |
|
2057 public: |
|
2058 static nsresult |
|
2059 GetUsedOnly(nsISupports* Object, |
|
2060 XPCWrappedNativeScope* Scope, |
|
2061 XPCNativeInterface* Interface, |
|
2062 XPCWrappedNative** wrapper); |
|
2063 |
|
2064 static nsresult |
|
2065 ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope, |
|
2066 XPCWrappedNativeScope* aNewScope, |
|
2067 JS::HandleObject aNewParent, |
|
2068 nsISupports* aCOMObj); |
|
2069 |
|
2070 nsresult RescueOrphans(); |
|
2071 |
|
2072 void FlatJSObjectFinalized(); |
|
2073 |
|
2074 void SystemIsBeingShutDown(); |
|
2075 |
|
2076 enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER}; |
|
2077 |
|
2078 static bool CallMethod(XPCCallContext& ccx, |
|
2079 CallMode mode = CALL_METHOD); |
|
2080 |
|
2081 static bool GetAttribute(XPCCallContext& ccx) |
|
2082 {return CallMethod(ccx, CALL_GETTER);} |
|
2083 |
|
2084 static bool SetAttribute(XPCCallContext& ccx) |
|
2085 {return CallMethod(ccx, CALL_SETTER);} |
|
2086 |
|
2087 inline bool HasInterfaceNoQI(const nsIID& iid); |
|
2088 |
|
2089 XPCWrappedNativeTearOff* LocateTearOff(XPCNativeInterface* aInterface); |
|
2090 XPCWrappedNativeTearOff* FindTearOff(XPCNativeInterface* aInterface, |
|
2091 bool needJSObject = false, |
|
2092 nsresult* pError = nullptr); |
|
2093 void Mark() const |
|
2094 { |
|
2095 mSet->Mark(); |
|
2096 if (mScriptableInfo) mScriptableInfo->Mark(); |
|
2097 if (HasProto()) GetProto()->Mark(); |
|
2098 } |
|
2099 |
|
2100 // Yes, we *do* need to mark the mScriptableInfo in both cases. |
|
2101 inline void TraceInside(JSTracer *trc) { |
|
2102 if (JS_IsGCMarkingTracer(trc)) { |
|
2103 mSet->Mark(); |
|
2104 if (mScriptableInfo) |
|
2105 mScriptableInfo->Mark(); |
|
2106 } |
|
2107 if (HasProto()) |
|
2108 GetProto()->TraceSelf(trc); |
|
2109 else |
|
2110 GetScope()->TraceInside(trc); |
|
2111 if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject)) |
|
2112 { |
|
2113 xpc::TraceXPCGlobal(trc, mFlatJSObject); |
|
2114 } |
|
2115 } |
|
2116 |
|
2117 void TraceJS(JSTracer *trc) { |
|
2118 TraceInside(trc); |
|
2119 } |
|
2120 |
|
2121 void TraceSelf(JSTracer *trc) { |
|
2122 // If this got called, we're being kept alive by someone who really |
|
2123 // needs us alive and whole. Do not let our mFlatJSObject go away. |
|
2124 // This is the only time we should be tracing our mFlatJSObject, |
|
2125 // normally somebody else is doing that. Be careful not to trace the |
|
2126 // bogus INVALID_OBJECT value we can have during init, though. |
|
2127 if (mFlatJSObject) { |
|
2128 JS_CallTenuredObjectTracer(trc, &mFlatJSObject, |
|
2129 "XPCWrappedNative::mFlatJSObject"); |
|
2130 } |
|
2131 } |
|
2132 |
|
2133 static void Trace(JSTracer *trc, JSObject *obj); |
|
2134 |
|
2135 void AutoTrace(JSTracer *trc) { |
|
2136 TraceSelf(trc); |
|
2137 } |
|
2138 |
|
2139 #ifdef DEBUG |
|
2140 void ASSERT_SetsNotMarked() const |
|
2141 {mSet->ASSERT_NotMarked(); |
|
2142 if (HasProto()){GetProto()->ASSERT_SetNotMarked();}} |
|
2143 #endif |
|
2144 |
|
2145 inline void SweepTearOffs(); |
|
2146 |
|
2147 // Returns a string that shuld be free'd using JS_smprintf_free (or null). |
|
2148 char* ToString(XPCWrappedNativeTearOff* to = nullptr) const; |
|
2149 |
|
2150 static void GatherProtoScriptableCreateInfo(nsIClassInfo* classInfo, |
|
2151 XPCNativeScriptableCreateInfo& sciProto); |
|
2152 |
|
2153 bool HasExternalReference() const {return mRefCnt > 1;} |
|
2154 |
|
2155 void NoteTearoffs(nsCycleCollectionTraversalCallback& cb); |
|
2156 |
|
2157 // Make ctor and dtor protected (rather than private) to placate nsCOMPtr. |
|
2158 protected: |
|
2159 XPCWrappedNative(); // not implemented |
|
2160 |
|
2161 // This ctor is used if this object will have a proto. |
|
2162 XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity, |
|
2163 XPCWrappedNativeProto* aProto); |
|
2164 |
|
2165 // This ctor is used if this object will NOT have a proto. |
|
2166 XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity, |
|
2167 XPCWrappedNativeScope* aScope, |
|
2168 XPCNativeSet* aSet); |
|
2169 |
|
2170 virtual ~XPCWrappedNative(); |
|
2171 void Destroy(); |
|
2172 |
|
2173 void UpdateScriptableInfo(XPCNativeScriptableInfo *si); |
|
2174 |
|
2175 private: |
|
2176 enum { |
|
2177 // Flags bits for mFlatJSObject: |
|
2178 FLAT_JS_OBJECT_VALID = JS_BIT(0) |
|
2179 }; |
|
2180 |
|
2181 private: |
|
2182 |
|
2183 bool Init(JS::HandleObject parent, const XPCNativeScriptableCreateInfo* sci); |
|
2184 bool FinishInit(); |
|
2185 |
|
2186 bool ExtendSet(XPCNativeInterface* aInterface); |
|
2187 |
|
2188 nsresult InitTearOff(XPCWrappedNativeTearOff* aTearOff, |
|
2189 XPCNativeInterface* aInterface, |
|
2190 bool needJSObject); |
|
2191 |
|
2192 bool InitTearOffJSObject(XPCWrappedNativeTearOff* to); |
|
2193 |
|
2194 public: |
|
2195 static const XPCNativeScriptableCreateInfo& GatherScriptableCreateInfo(nsISupports* obj, |
|
2196 nsIClassInfo* classInfo, |
|
2197 XPCNativeScriptableCreateInfo& sciProto, |
|
2198 XPCNativeScriptableCreateInfo& sciWrapper); |
|
2199 |
|
2200 private: |
|
2201 union |
|
2202 { |
|
2203 XPCWrappedNativeScope* mMaybeScope; |
|
2204 XPCWrappedNativeProto* mMaybeProto; |
|
2205 }; |
|
2206 XPCNativeSet* mSet; |
|
2207 JS::TenuredHeap<JSObject*> mFlatJSObject; |
|
2208 XPCNativeScriptableInfo* mScriptableInfo; |
|
2209 XPCWrappedNativeTearOffChunk mFirstChunk; |
|
2210 }; |
|
2211 |
|
2212 /*************************************************************************** |
|
2213 **************************************************************************** |
|
2214 * |
|
2215 * Core classes for wrapped JSObject for use from native code... |
|
2216 * |
|
2217 **************************************************************************** |
|
2218 ***************************************************************************/ |
|
2219 |
|
2220 // this interfaces exists so we can refcount nsXPCWrappedJSClass |
|
2221 // {2453EBA0-A9B8-11d2-BA64-00805F8A5DD7} |
|
2222 #define NS_IXPCONNECT_WRAPPED_JS_CLASS_IID \ |
|
2223 { 0x2453eba0, 0xa9b8, 0x11d2, \ |
|
2224 { 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } } |
|
2225 |
|
2226 class nsIXPCWrappedJSClass : public nsISupports |
|
2227 { |
|
2228 public: |
|
2229 NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPCONNECT_WRAPPED_JS_CLASS_IID) |
|
2230 NS_IMETHOD DebugDump(int16_t depth) = 0; |
|
2231 }; |
|
2232 |
|
2233 NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPCWrappedJSClass, |
|
2234 NS_IXPCONNECT_WRAPPED_JS_CLASS_IID) |
|
2235 |
|
2236 /*************************/ |
|
2237 // nsXPCWrappedJSClass represents the sharable factored out common code and |
|
2238 // data for nsXPCWrappedJS instances for the same interface type. |
|
2239 |
|
2240 class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass |
|
2241 { |
|
2242 // all the interface method declarations... |
|
2243 NS_DECL_ISUPPORTS |
|
2244 NS_IMETHOD DebugDump(int16_t depth); |
|
2245 public: |
|
2246 |
|
2247 static already_AddRefed<nsXPCWrappedJSClass> |
|
2248 GetNewOrUsed(JSContext* cx, |
|
2249 REFNSIID aIID); |
|
2250 |
|
2251 REFNSIID GetIID() const {return mIID;} |
|
2252 XPCJSRuntime* GetRuntime() const {return mRuntime;} |
|
2253 nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;} |
|
2254 const char* GetInterfaceName(); |
|
2255 |
|
2256 static bool IsWrappedJS(nsISupports* aPtr); |
|
2257 |
|
2258 NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID, |
|
2259 void** aInstancePtr); |
|
2260 |
|
2261 JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj); |
|
2262 |
|
2263 NS_IMETHOD CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex, |
|
2264 const XPTMethodDescriptor* info, |
|
2265 nsXPTCMiniVariant* params); |
|
2266 |
|
2267 JSObject* CallQueryInterfaceOnJSObject(JSContext* cx, |
|
2268 JSObject* jsobj, REFNSIID aIID); |
|
2269 |
|
2270 static nsresult BuildPropertyEnumerator(XPCCallContext& ccx, |
|
2271 JSObject* aJSObj, |
|
2272 nsISimpleEnumerator** aEnumerate); |
|
2273 |
|
2274 static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx, |
|
2275 JSObject* aJSObj, |
|
2276 const nsAString& aName, |
|
2277 nsIVariant** aResult); |
|
2278 |
|
2279 virtual ~nsXPCWrappedJSClass(); |
|
2280 |
|
2281 static nsresult CheckForException(XPCCallContext & ccx, |
|
2282 const char * aPropertyName, |
|
2283 const char * anInterfaceName, |
|
2284 bool aForceReport); |
|
2285 private: |
|
2286 nsXPCWrappedJSClass(); // not implemented |
|
2287 nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID, |
|
2288 nsIInterfaceInfo* aInfo); |
|
2289 |
|
2290 bool IsReflectable(uint16_t i) const |
|
2291 {return (bool)(mDescriptors[i/32] & (1 << (i%32)));} |
|
2292 void SetReflectable(uint16_t i, bool b) |
|
2293 {if (b) mDescriptors[i/32] |= (1 << (i%32)); |
|
2294 else mDescriptors[i/32] &= ~(1 << (i%32));} |
|
2295 |
|
2296 bool GetArraySizeFromParam(JSContext* cx, |
|
2297 const XPTMethodDescriptor* method, |
|
2298 const nsXPTParamInfo& param, |
|
2299 uint16_t methodIndex, |
|
2300 uint8_t paramIndex, |
|
2301 nsXPTCMiniVariant* params, |
|
2302 uint32_t* result); |
|
2303 |
|
2304 bool GetInterfaceTypeFromParam(JSContext* cx, |
|
2305 const XPTMethodDescriptor* method, |
|
2306 const nsXPTParamInfo& param, |
|
2307 uint16_t methodIndex, |
|
2308 const nsXPTType& type, |
|
2309 nsXPTCMiniVariant* params, |
|
2310 nsID* result); |
|
2311 |
|
2312 void CleanupPointerArray(const nsXPTType& datum_type, |
|
2313 uint32_t array_count, |
|
2314 void** arrayp); |
|
2315 |
|
2316 void CleanupPointerTypeObject(const nsXPTType& type, |
|
2317 void** pp); |
|
2318 |
|
2319 private: |
|
2320 XPCJSRuntime* mRuntime; |
|
2321 nsCOMPtr<nsIInterfaceInfo> mInfo; |
|
2322 char* mName; |
|
2323 nsIID mIID; |
|
2324 uint32_t* mDescriptors; |
|
2325 }; |
|
2326 |
|
2327 /*************************/ |
|
2328 // nsXPCWrappedJS is a wrapper for a single JSObject for use from native code. |
|
2329 // nsXPCWrappedJS objects are chained together to represent the various |
|
2330 // interface on the single underlying (possibly aggregate) JSObject. |
|
2331 |
|
2332 class nsXPCWrappedJS : protected nsAutoXPTCStub, |
|
2333 public nsIXPConnectWrappedJS, |
|
2334 public nsSupportsWeakReference, |
|
2335 public nsIPropertyBag, |
|
2336 public XPCRootSetElem |
|
2337 { |
|
2338 public: |
|
2339 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
2340 NS_DECL_NSIXPCONNECTJSOBJECTHOLDER |
|
2341 NS_DECL_NSIXPCONNECTWRAPPEDJS |
|
2342 NS_DECL_NSISUPPORTSWEAKREFERENCE |
|
2343 NS_DECL_NSIPROPERTYBAG |
|
2344 |
|
2345 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS) |
|
2346 |
|
2347 NS_IMETHOD CallMethod(uint16_t methodIndex, |
|
2348 const XPTMethodDescriptor *info, |
|
2349 nsXPTCMiniVariant* params); |
|
2350 |
|
2351 /* |
|
2352 * This is rarely called directly. Instead one usually calls |
|
2353 * XPCConvert::JSObject2NativeInterface which will handles cases where the |
|
2354 * JS object is already a wrapped native or a DOM object. |
|
2355 */ |
|
2356 |
|
2357 static nsresult |
|
2358 GetNewOrUsed(JS::HandleObject aJSObj, |
|
2359 REFNSIID aIID, |
|
2360 nsXPCWrappedJS** wrapper); |
|
2361 |
|
2362 nsISomeInterface* GetXPTCStub() { return mXPTCStub; } |
|
2363 |
|
2364 /** |
|
2365 * This getter does not change the color of the JSObject meaning that the |
|
2366 * object returned is not guaranteed to be kept alive past the next CC. |
|
2367 * |
|
2368 * This should only be called if you are certain that the return value won't |
|
2369 * be passed into a JS API function and that it won't be stored without |
|
2370 * being rooted (or otherwise signaling the stored value to the CC). |
|
2371 */ |
|
2372 JSObject* GetJSObjectPreserveColor() const {return mJSObj;} |
|
2373 |
|
2374 nsXPCWrappedJSClass* GetClass() const {return mClass;} |
|
2375 REFNSIID GetIID() const {return GetClass()->GetIID();} |
|
2376 nsXPCWrappedJS* GetRootWrapper() const {return mRoot;} |
|
2377 nsXPCWrappedJS* GetNextWrapper() const {return mNext;} |
|
2378 |
|
2379 nsXPCWrappedJS* Find(REFNSIID aIID); |
|
2380 nsXPCWrappedJS* FindInherited(REFNSIID aIID); |
|
2381 nsXPCWrappedJS* FindOrFindInherited(REFNSIID aIID) { |
|
2382 nsXPCWrappedJS* wrapper = Find(aIID); |
|
2383 if (wrapper) |
|
2384 return wrapper; |
|
2385 return FindInherited(aIID); |
|
2386 } |
|
2387 |
|
2388 bool IsRootWrapper() const {return mRoot == this;} |
|
2389 bool IsValid() const {return mJSObj != nullptr;} |
|
2390 void SystemIsBeingShutDown(); |
|
2391 |
|
2392 // These two methods are used by JSObject2WrappedJSMap::FindDyingJSObjects |
|
2393 // to find non-rooting wrappers for dying JS objects. See the top of |
|
2394 // XPCWrappedJS.cpp for more details. |
|
2395 bool IsSubjectToFinalization() const {return IsValid() && mRefCnt == 1;} |
|
2396 bool IsObjectAboutToBeFinalized() {return JS_IsAboutToBeFinalized(&mJSObj);} |
|
2397 |
|
2398 bool IsAggregatedToNative() const {return mRoot->mOuter != nullptr;} |
|
2399 nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;} |
|
2400 void SetAggregatedNativeObject(nsISupports *aNative) { |
|
2401 MOZ_ASSERT(aNative); |
|
2402 if (mRoot->mOuter) { |
|
2403 MOZ_ASSERT(mRoot->mOuter == aNative, |
|
2404 "Only one aggregated native can be set"); |
|
2405 return; |
|
2406 } |
|
2407 mRoot->mOuter = aNative; |
|
2408 } |
|
2409 |
|
2410 void TraceJS(JSTracer* trc); |
|
2411 static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize); |
|
2412 |
|
2413 virtual ~nsXPCWrappedJS(); |
|
2414 protected: |
|
2415 nsXPCWrappedJS(); // not implemented |
|
2416 nsXPCWrappedJS(JSContext* cx, |
|
2417 JSObject* aJSObj, |
|
2418 nsXPCWrappedJSClass* aClass, |
|
2419 nsXPCWrappedJS* root); |
|
2420 |
|
2421 bool CanSkip(); |
|
2422 void Destroy(); |
|
2423 void Unlink(); |
|
2424 |
|
2425 private: |
|
2426 JS::Heap<JSObject*> mJSObj; |
|
2427 nsRefPtr<nsXPCWrappedJSClass> mClass; |
|
2428 nsXPCWrappedJS* mRoot; // If mRoot != this, it is an owning pointer. |
|
2429 nsXPCWrappedJS* mNext; |
|
2430 nsCOMPtr<nsISupports> mOuter; // only set in root |
|
2431 }; |
|
2432 |
|
2433 /***************************************************************************/ |
|
2434 |
|
2435 class XPCJSObjectHolder : public nsIXPConnectJSObjectHolder, |
|
2436 public XPCRootSetElem |
|
2437 { |
|
2438 public: |
|
2439 // all the interface method declarations... |
|
2440 NS_DECL_ISUPPORTS |
|
2441 NS_DECL_NSIXPCONNECTJSOBJECTHOLDER |
|
2442 |
|
2443 // non-interface implementation |
|
2444 |
|
2445 public: |
|
2446 static XPCJSObjectHolder* newHolder(JSObject* obj); |
|
2447 |
|
2448 virtual ~XPCJSObjectHolder(); |
|
2449 |
|
2450 void TraceJS(JSTracer *trc); |
|
2451 static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize); |
|
2452 |
|
2453 private: |
|
2454 XPCJSObjectHolder(JSObject* obj); |
|
2455 XPCJSObjectHolder(); // not implemented |
|
2456 |
|
2457 JS::Heap<JSObject*> mJSObj; |
|
2458 }; |
|
2459 |
|
2460 /*************************************************************************** |
|
2461 **************************************************************************** |
|
2462 * |
|
2463 * All manner of utility classes follow... |
|
2464 * |
|
2465 **************************************************************************** |
|
2466 ***************************************************************************/ |
|
2467 |
|
2468 class xpcProperty : public nsIProperty |
|
2469 { |
|
2470 public: |
|
2471 NS_DECL_ISUPPORTS |
|
2472 NS_DECL_NSIPROPERTY |
|
2473 |
|
2474 xpcProperty(const char16_t* aName, uint32_t aNameLen, nsIVariant* aValue); |
|
2475 virtual ~xpcProperty() {} |
|
2476 |
|
2477 private: |
|
2478 nsString mName; |
|
2479 nsCOMPtr<nsIVariant> mValue; |
|
2480 }; |
|
2481 |
|
2482 /***************************************************************************/ |
|
2483 // class here just for static methods |
|
2484 class XPCConvert |
|
2485 { |
|
2486 public: |
|
2487 static bool IsMethodReflectable(const XPTMethodDescriptor& info); |
|
2488 |
|
2489 /** |
|
2490 * Convert a native object into a jsval. |
|
2491 * |
|
2492 * @param d [out] the resulting jsval |
|
2493 * @param s the native object we're working with |
|
2494 * @param type the type of object that s is |
|
2495 * @param iid the interface of s that we want |
|
2496 * @param scope the default scope to put on the new JSObject's parent |
|
2497 * chain |
|
2498 * @param pErr [out] relevant error code, if any. |
|
2499 */ |
|
2500 |
|
2501 static bool NativeData2JS(JS::MutableHandleValue d, |
|
2502 const void* s, const nsXPTType& type, |
|
2503 const nsID* iid, nsresult* pErr); |
|
2504 |
|
2505 static bool JSData2Native(void* d, JS::HandleValue s, |
|
2506 const nsXPTType& type, |
|
2507 bool useAllocator, const nsID* iid, |
|
2508 nsresult* pErr); |
|
2509 |
|
2510 /** |
|
2511 * Convert a native nsISupports into a JSObject. |
|
2512 * |
|
2513 * @param dest [out] the resulting JSObject |
|
2514 * @param src the native object we're working with |
|
2515 * @param iid the interface of src that we want (may be null) |
|
2516 * @param Interface the interface of src that we want |
|
2517 * @param cache the wrapper cache for src (may be null, in which case src |
|
2518 * will be QI'ed to get the cache) |
|
2519 * @param allowNativeWrapper if true, this method may wrap the resulting |
|
2520 * JSObject in an XPCNativeWrapper and return that, as needed. |
|
2521 * @param pErr [out] relevant error code, if any. |
|
2522 * @param src_is_identity optional performance hint. Set to true only |
|
2523 * if src is the identity pointer. |
|
2524 */ |
|
2525 static bool NativeInterface2JSObject(JS::MutableHandleValue d, |
|
2526 nsIXPConnectJSObjectHolder** dest, |
|
2527 xpcObjectHelper& aHelper, |
|
2528 const nsID* iid, |
|
2529 XPCNativeInterface** Interface, |
|
2530 bool allowNativeWrapper, |
|
2531 nsresult* pErr); |
|
2532 |
|
2533 static bool GetNativeInterfaceFromJSObject(void** dest, JSObject* src, |
|
2534 const nsID* iid, |
|
2535 nsresult* pErr); |
|
2536 static bool JSObject2NativeInterface(void** dest, JS::HandleObject src, |
|
2537 const nsID* iid, |
|
2538 nsISupports* aOuter, |
|
2539 nsresult* pErr); |
|
2540 static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface); |
|
2541 |
|
2542 /** |
|
2543 * Convert a native array into a jsval. |
|
2544 * |
|
2545 * @param d [out] the resulting jsval |
|
2546 * @param s the native array we're working with |
|
2547 * @param type the type of objects in the array |
|
2548 * @param iid the interface of each object in the array that we want |
|
2549 * @param count the number of items in the array |
|
2550 * @param scope the default scope to put on the new JSObjects' parent chain |
|
2551 * @param pErr [out] relevant error code, if any. |
|
2552 */ |
|
2553 static bool NativeArray2JS(JS::MutableHandleValue d, const void** s, |
|
2554 const nsXPTType& type, const nsID* iid, |
|
2555 uint32_t count, nsresult* pErr); |
|
2556 |
|
2557 static bool JSArray2Native(void** d, JS::HandleValue s, |
|
2558 uint32_t count, const nsXPTType& type, |
|
2559 const nsID* iid, nsresult* pErr); |
|
2560 |
|
2561 static bool JSTypedArray2Native(void** d, |
|
2562 JSObject* jsarray, |
|
2563 uint32_t count, |
|
2564 const nsXPTType& type, |
|
2565 nsresult* pErr); |
|
2566 |
|
2567 static bool NativeStringWithSize2JS(JS::MutableHandleValue d, const void* s, |
|
2568 const nsXPTType& type, |
|
2569 uint32_t count, |
|
2570 nsresult* pErr); |
|
2571 |
|
2572 static bool JSStringWithSize2Native(void* d, JS::HandleValue s, |
|
2573 uint32_t count, const nsXPTType& type, |
|
2574 nsresult* pErr); |
|
2575 |
|
2576 static nsresult JSValToXPCException(JS::MutableHandleValue s, |
|
2577 const char* ifaceName, |
|
2578 const char* methodName, |
|
2579 nsIException** exception); |
|
2580 |
|
2581 static nsresult JSErrorToXPCException(const char* message, |
|
2582 const char* ifaceName, |
|
2583 const char* methodName, |
|
2584 const JSErrorReport* report, |
|
2585 nsIException** exception); |
|
2586 |
|
2587 static nsresult ConstructException(nsresult rv, const char* message, |
|
2588 const char* ifaceName, |
|
2589 const char* methodName, |
|
2590 nsISupports* data, |
|
2591 nsIException** exception, |
|
2592 JSContext* cx, |
|
2593 jsval *jsExceptionPtr); |
|
2594 |
|
2595 private: |
|
2596 XPCConvert(); // not implemented |
|
2597 |
|
2598 }; |
|
2599 |
|
2600 /***************************************************************************/ |
|
2601 // code for throwing exceptions into JS |
|
2602 |
|
2603 class nsXPCException; |
|
2604 |
|
2605 class XPCThrower |
|
2606 { |
|
2607 public: |
|
2608 static void Throw(nsresult rv, JSContext* cx); |
|
2609 static void Throw(nsresult rv, XPCCallContext& ccx); |
|
2610 static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx); |
|
2611 static void ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx); |
|
2612 static bool SetVerbosity(bool state) |
|
2613 {bool old = sVerbose; sVerbose = state; return old;} |
|
2614 |
|
2615 static bool CheckForPendingException(nsresult result, JSContext *cx); |
|
2616 |
|
2617 private: |
|
2618 static void Verbosify(XPCCallContext& ccx, |
|
2619 char** psz, bool own); |
|
2620 |
|
2621 private: |
|
2622 static bool sVerbose; |
|
2623 }; |
|
2624 |
|
2625 /***************************************************************************/ |
|
2626 |
|
2627 class nsXPCException |
|
2628 { |
|
2629 public: |
|
2630 static bool NameAndFormatForNSResult(nsresult rv, |
|
2631 const char** name, |
|
2632 const char** format); |
|
2633 |
|
2634 static const void* IterateNSResults(nsresult* rv, |
|
2635 const char** name, |
|
2636 const char** format, |
|
2637 const void** iterp); |
|
2638 |
|
2639 static uint32_t GetNSResultCount(); |
|
2640 }; |
|
2641 |
|
2642 /***************************************************************************/ |
|
2643 /* |
|
2644 * nsJSID implements nsIJSID. It is also used by nsJSIID and nsJSCID as a |
|
2645 * member (as a hidden implementaion detail) to which they delegate many calls. |
|
2646 */ |
|
2647 |
|
2648 // Initialization is done on demand, and calling the destructor below is always |
|
2649 // safe. |
|
2650 extern void xpc_DestroyJSxIDClassObjects(); |
|
2651 |
|
2652 class nsJSID : public nsIJSID |
|
2653 { |
|
2654 public: |
|
2655 NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID) |
|
2656 |
|
2657 NS_DECL_ISUPPORTS |
|
2658 NS_DECL_NSIJSID |
|
2659 |
|
2660 bool InitWithName(const nsID& id, const char *nameString); |
|
2661 bool SetName(const char* name); |
|
2662 void SetNameToNoString() |
|
2663 {MOZ_ASSERT(!mName, "name already set"); mName = gNoString;} |
|
2664 bool NameIsSet() const {return nullptr != mName;} |
|
2665 const nsID& ID() const {return mID;} |
|
2666 bool IsValid() const {return !mID.Equals(GetInvalidIID());} |
|
2667 |
|
2668 static already_AddRefed<nsJSID> NewID(const char* str); |
|
2669 static already_AddRefed<nsJSID> NewID(const nsID& id); |
|
2670 |
|
2671 nsJSID(); |
|
2672 virtual ~nsJSID(); |
|
2673 protected: |
|
2674 |
|
2675 void Reset(); |
|
2676 const nsID& GetInvalidIID() const; |
|
2677 |
|
2678 protected: |
|
2679 static char gNoString[]; |
|
2680 nsID mID; |
|
2681 char* mNumber; |
|
2682 char* mName; |
|
2683 }; |
|
2684 |
|
2685 // nsJSIID |
|
2686 |
|
2687 class nsJSIID : public nsIJSIID, |
|
2688 public nsIXPCScriptable |
|
2689 { |
|
2690 public: |
|
2691 NS_DECL_ISUPPORTS |
|
2692 |
|
2693 // we manually delagate these to nsJSID |
|
2694 NS_DECL_NSIJSID |
|
2695 |
|
2696 // we implement the rest... |
|
2697 NS_DECL_NSIJSIID |
|
2698 NS_DECL_NSIXPCSCRIPTABLE |
|
2699 |
|
2700 static already_AddRefed<nsJSIID> NewID(nsIInterfaceInfo* aInfo); |
|
2701 |
|
2702 nsJSIID(nsIInterfaceInfo* aInfo); |
|
2703 nsJSIID(); // not implemented |
|
2704 virtual ~nsJSIID(); |
|
2705 |
|
2706 private: |
|
2707 nsCOMPtr<nsIInterfaceInfo> mInfo; |
|
2708 }; |
|
2709 |
|
2710 // nsJSCID |
|
2711 |
|
2712 class nsJSCID : public nsIJSCID, public nsIXPCScriptable |
|
2713 { |
|
2714 public: |
|
2715 NS_DECL_ISUPPORTS |
|
2716 |
|
2717 // we manually delagate these to nsJSID |
|
2718 NS_DECL_NSIJSID |
|
2719 |
|
2720 // we implement the rest... |
|
2721 NS_DECL_NSIJSCID |
|
2722 NS_DECL_NSIXPCSCRIPTABLE |
|
2723 |
|
2724 static already_AddRefed<nsJSCID> NewID(const char* str); |
|
2725 |
|
2726 nsJSCID(); |
|
2727 virtual ~nsJSCID(); |
|
2728 |
|
2729 private: |
|
2730 void ResolveName(); |
|
2731 |
|
2732 private: |
|
2733 nsJSID mDetails; |
|
2734 }; |
|
2735 |
|
2736 |
|
2737 /***************************************************************************/ |
|
2738 // XPCJSContextStack is not actually an xpcom object, but xpcom calls are |
|
2739 // delegated to it as an implementation detail. |
|
2740 struct XPCJSContextInfo { |
|
2741 XPCJSContextInfo(JSContext* aCx) : |
|
2742 cx(aCx), |
|
2743 savedFrameChain(false) |
|
2744 {} |
|
2745 JSContext* cx; |
|
2746 |
|
2747 // Whether the frame chain was saved |
|
2748 bool savedFrameChain; |
|
2749 }; |
|
2750 |
|
2751 namespace xpc { |
|
2752 |
|
2753 // These functions are used in a few places where a callback model makes it |
|
2754 // impossible to push a JSContext using one of our stack-scoped classes. We |
|
2755 // depend on those stack-scoped classes to maintain nsIScriptContext |
|
2756 // invariants, so these functions may only be used of the context is not |
|
2757 // associated with an nsJSContext/nsIScriptContext. |
|
2758 bool PushJSContextNoScriptContext(JSContext *aCx); |
|
2759 void PopJSContextNoScriptContext(); |
|
2760 |
|
2761 } /* namespace xpc */ |
|
2762 |
|
2763 class XPCJSContextStack |
|
2764 { |
|
2765 public: |
|
2766 XPCJSContextStack(XPCJSRuntime *aRuntime) |
|
2767 : mRuntime(aRuntime) |
|
2768 , mSafeJSContext(nullptr) |
|
2769 , mSafeJSContextGlobal(aRuntime->Runtime(), nullptr) |
|
2770 { } |
|
2771 |
|
2772 virtual ~XPCJSContextStack(); |
|
2773 |
|
2774 uint32_t Count() |
|
2775 { |
|
2776 return mStack.Length(); |
|
2777 } |
|
2778 |
|
2779 JSContext *Peek() |
|
2780 { |
|
2781 return mStack.IsEmpty() ? nullptr : mStack[mStack.Length() - 1].cx; |
|
2782 } |
|
2783 |
|
2784 JSContext *InitSafeJSContext(); |
|
2785 JSContext *GetSafeJSContext(); |
|
2786 JSObject *GetSafeJSContextGlobal(); |
|
2787 bool HasJSContext(JSContext *cx); |
|
2788 |
|
2789 const InfallibleTArray<XPCJSContextInfo>* GetStack() |
|
2790 { return &mStack; } |
|
2791 |
|
2792 private: |
|
2793 friend class mozilla::AutoCxPusher; |
|
2794 friend bool xpc::PushJSContextNoScriptContext(JSContext *aCx);; |
|
2795 friend void xpc::PopJSContextNoScriptContext(); |
|
2796 |
|
2797 // We make these private so that stack manipulation can only happen |
|
2798 // through one of the above friends. |
|
2799 JSContext *Pop(); |
|
2800 bool Push(JSContext *cx); |
|
2801 |
|
2802 AutoInfallibleTArray<XPCJSContextInfo, 16> mStack; |
|
2803 XPCJSRuntime* mRuntime; |
|
2804 JSContext* mSafeJSContext; |
|
2805 JS::PersistentRootedObject mSafeJSContextGlobal; |
|
2806 }; |
|
2807 |
|
2808 /***************************************************************************/ |
|
2809 // 'Components' object implementations. nsXPCComponentsBase has the |
|
2810 // less-privileged stuff that we're willing to expose to XBL. |
|
2811 |
|
2812 class nsXPCComponentsBase : public nsIXPCComponentsBase |
|
2813 { |
|
2814 public: |
|
2815 NS_DECL_ISUPPORTS |
|
2816 NS_DECL_NSIXPCCOMPONENTSBASE |
|
2817 |
|
2818 public: |
|
2819 void SystemIsBeingShutDown() { ClearMembers(); } |
|
2820 virtual ~nsXPCComponentsBase(); |
|
2821 |
|
2822 XPCWrappedNativeScope *GetScope() { return mScope; } |
|
2823 |
|
2824 protected: |
|
2825 nsXPCComponentsBase(XPCWrappedNativeScope* aScope); |
|
2826 virtual void ClearMembers(); |
|
2827 |
|
2828 XPCWrappedNativeScope* mScope; |
|
2829 |
|
2830 // Unprivileged members from nsIXPCComponentsBase. |
|
2831 nsRefPtr<nsXPCComponents_Interfaces> mInterfaces; |
|
2832 nsRefPtr<nsXPCComponents_InterfacesByID> mInterfacesByID; |
|
2833 nsRefPtr<nsXPCComponents_Results> mResults; |
|
2834 |
|
2835 friend class XPCWrappedNativeScope; |
|
2836 }; |
|
2837 |
|
2838 class nsXPCComponents : public nsXPCComponentsBase, |
|
2839 public nsIXPCComponents |
|
2840 { |
|
2841 public: |
|
2842 NS_DECL_ISUPPORTS |
|
2843 NS_FORWARD_NSIXPCCOMPONENTSBASE(nsXPCComponentsBase::) |
|
2844 NS_DECL_NSIXPCCOMPONENTS |
|
2845 |
|
2846 protected: |
|
2847 nsXPCComponents(XPCWrappedNativeScope* aScope); |
|
2848 virtual ~nsXPCComponents(); |
|
2849 virtual void ClearMembers() MOZ_OVERRIDE; |
|
2850 |
|
2851 // Privileged members added by nsIXPCComponents. |
|
2852 nsRefPtr<nsXPCComponents_Classes> mClasses; |
|
2853 nsRefPtr<nsXPCComponents_ClassesByID> mClassesByID; |
|
2854 nsRefPtr<nsXPCComponents_ID> mID; |
|
2855 nsRefPtr<nsXPCComponents_Exception> mException; |
|
2856 nsRefPtr<nsXPCComponents_Constructor> mConstructor; |
|
2857 nsRefPtr<nsXPCComponents_Utils> mUtils; |
|
2858 |
|
2859 friend class XPCWrappedNativeScope; |
|
2860 }; |
|
2861 |
|
2862 |
|
2863 /***************************************************************************/ |
|
2864 |
|
2865 extern JSObject* |
|
2866 xpc_NewIDObject(JSContext *cx, JS::HandleObject jsobj, const nsID& aID); |
|
2867 |
|
2868 extern const nsID* |
|
2869 xpc_JSObjectToID(JSContext *cx, JSObject* obj); |
|
2870 |
|
2871 extern bool |
|
2872 xpc_JSObjectIsID(JSContext *cx, JSObject* obj); |
|
2873 |
|
2874 /***************************************************************************/ |
|
2875 // in XPCDebug.cpp |
|
2876 |
|
2877 extern bool |
|
2878 xpc_DumpJSStack(JSContext* cx, bool showArgs, bool showLocals, |
|
2879 bool showThisProps); |
|
2880 |
|
2881 // Return a newly-allocated string containing a representation of the |
|
2882 // current JS stack. It is the *caller's* responsibility to free this |
|
2883 // string with JS_smprintf_free(). |
|
2884 extern char* |
|
2885 xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals, |
|
2886 bool showThisProps); |
|
2887 |
|
2888 extern bool |
|
2889 xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text); |
|
2890 |
|
2891 extern bool |
|
2892 xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt); |
|
2893 |
|
2894 /***************************************************************************/ |
|
2895 |
|
2896 // Definition of nsScriptError, defined here because we lack a place to put |
|
2897 // XPCOM objects associated with the JavaScript engine. |
|
2898 class nsScriptError : public nsIScriptError { |
|
2899 public: |
|
2900 nsScriptError(); |
|
2901 |
|
2902 virtual ~nsScriptError(); |
|
2903 |
|
2904 // TODO - do something reasonable on getting null from these babies. |
|
2905 |
|
2906 NS_DECL_THREADSAFE_ISUPPORTS |
|
2907 NS_DECL_NSICONSOLEMESSAGE |
|
2908 NS_DECL_NSISCRIPTERROR |
|
2909 |
|
2910 private: |
|
2911 nsString mMessage; |
|
2912 nsString mSourceName; |
|
2913 uint32_t mLineNumber; |
|
2914 nsString mSourceLine; |
|
2915 uint32_t mColumnNumber; |
|
2916 uint32_t mFlags; |
|
2917 nsCString mCategory; |
|
2918 uint64_t mOuterWindowID; |
|
2919 uint64_t mInnerWindowID; |
|
2920 int64_t mTimeStamp; |
|
2921 bool mIsFromPrivateWindow; |
|
2922 }; |
|
2923 |
|
2924 /****************************************************************************** |
|
2925 * Handles pre/post script processing and the setting/resetting the error |
|
2926 * reporter |
|
2927 */ |
|
2928 class MOZ_STACK_CLASS AutoScriptEvaluate |
|
2929 { |
|
2930 public: |
|
2931 /** |
|
2932 * Saves the JSContext as well as initializing our state |
|
2933 * @param cx The JSContext, this can be null, we don't do anything then |
|
2934 */ |
|
2935 AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
|
2936 : mJSContext(cx), mErrorReporterSet(false), mEvaluated(false) { |
|
2937 MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
|
2938 } |
|
2939 |
|
2940 /** |
|
2941 * Does the pre script evaluation and sets the error reporter if given |
|
2942 * This function should only be called once, and will assert if called |
|
2943 * more than once |
|
2944 * @param errorReporter the error reporter callback function to set |
|
2945 */ |
|
2946 |
|
2947 bool StartEvaluating(JS::HandleObject scope, JSErrorReporter errorReporter = nullptr); |
|
2948 |
|
2949 /** |
|
2950 * Does the post script evaluation and resets the error reporter |
|
2951 */ |
|
2952 ~AutoScriptEvaluate(); |
|
2953 private: |
|
2954 JSContext* mJSContext; |
|
2955 mozilla::Maybe<JS::AutoSaveExceptionState> mState; |
|
2956 bool mErrorReporterSet; |
|
2957 bool mEvaluated; |
|
2958 mozilla::Maybe<JSAutoCompartment> mAutoCompartment; |
|
2959 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
|
2960 |
|
2961 // No copying or assignment allowed |
|
2962 AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE; |
|
2963 AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE; |
|
2964 }; |
|
2965 |
|
2966 /***************************************************************************/ |
|
2967 class MOZ_STACK_CLASS AutoResolveName |
|
2968 { |
|
2969 public: |
|
2970 AutoResolveName(XPCCallContext& ccx, JS::HandleId name |
|
2971 MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : |
|
2972 mOld(ccx, XPCJSRuntime::Get()->SetResolveName(name)) |
|
2973 #ifdef DEBUG |
|
2974 ,mCheck(ccx, name) |
|
2975 #endif |
|
2976 { |
|
2977 MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
|
2978 } |
|
2979 ~AutoResolveName() |
|
2980 { |
|
2981 #ifdef DEBUG |
|
2982 jsid old = |
|
2983 #endif |
|
2984 XPCJSRuntime::Get()->SetResolveName(mOld); |
|
2985 MOZ_ASSERT(old == mCheck, "Bad Nesting!"); |
|
2986 } |
|
2987 |
|
2988 private: |
|
2989 JS::RootedId mOld; |
|
2990 #ifdef DEBUG |
|
2991 JS::RootedId mCheck; |
|
2992 #endif |
|
2993 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
|
2994 }; |
|
2995 |
|
2996 /***************************************************************************/ |
|
2997 // AutoMarkingPtr is the base class for the various AutoMarking pointer types |
|
2998 // below. This system allows us to temporarily protect instances of our garbage |
|
2999 // collected types after they are constructed but before they are safely |
|
3000 // attached to other rooted objects. |
|
3001 // This base class has pure virtual support for marking. |
|
3002 |
|
3003 class AutoMarkingPtr |
|
3004 { |
|
3005 public: |
|
3006 AutoMarkingPtr(JSContext* cx) { |
|
3007 mRoot = XPCJSRuntime::Get()->GetAutoRootsAdr(); |
|
3008 mNext = *mRoot; |
|
3009 *mRoot = this; |
|
3010 } |
|
3011 |
|
3012 virtual ~AutoMarkingPtr() { |
|
3013 if (mRoot) { |
|
3014 MOZ_ASSERT(*mRoot == this); |
|
3015 *mRoot = mNext; |
|
3016 } |
|
3017 } |
|
3018 |
|
3019 void TraceJSAll(JSTracer* trc) { |
|
3020 for (AutoMarkingPtr *cur = this; cur; cur = cur->mNext) |
|
3021 cur->TraceJS(trc); |
|
3022 } |
|
3023 |
|
3024 void MarkAfterJSFinalizeAll() { |
|
3025 for (AutoMarkingPtr *cur = this; cur; cur = cur->mNext) |
|
3026 cur->MarkAfterJSFinalize(); |
|
3027 } |
|
3028 |
|
3029 protected: |
|
3030 virtual void TraceJS(JSTracer* trc) = 0; |
|
3031 virtual void MarkAfterJSFinalize() = 0; |
|
3032 |
|
3033 private: |
|
3034 AutoMarkingPtr** mRoot; |
|
3035 AutoMarkingPtr* mNext; |
|
3036 }; |
|
3037 |
|
3038 template<class T> |
|
3039 class TypedAutoMarkingPtr : public AutoMarkingPtr |
|
3040 { |
|
3041 public: |
|
3042 TypedAutoMarkingPtr(JSContext* cx) : AutoMarkingPtr(cx), mPtr(nullptr) {} |
|
3043 TypedAutoMarkingPtr(JSContext* cx, T* ptr) : AutoMarkingPtr(cx), mPtr(ptr) {} |
|
3044 |
|
3045 T* get() const { return mPtr; } |
|
3046 operator T *() const { return mPtr; } |
|
3047 T* operator->() const { return mPtr; } |
|
3048 |
|
3049 TypedAutoMarkingPtr<T>& operator =(T* ptr) { mPtr = ptr; return *this; } |
|
3050 |
|
3051 protected: |
|
3052 virtual void TraceJS(JSTracer* trc) |
|
3053 { |
|
3054 if (mPtr) { |
|
3055 mPtr->TraceJS(trc); |
|
3056 mPtr->AutoTrace(trc); |
|
3057 } |
|
3058 } |
|
3059 |
|
3060 virtual void MarkAfterJSFinalize() |
|
3061 { |
|
3062 if (mPtr) |
|
3063 mPtr->Mark(); |
|
3064 } |
|
3065 |
|
3066 private: |
|
3067 T* mPtr; |
|
3068 }; |
|
3069 |
|
3070 typedef TypedAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtr; |
|
3071 typedef TypedAutoMarkingPtr<XPCNativeSet> AutoMarkingNativeSetPtr; |
|
3072 typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr; |
|
3073 typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr; |
|
3074 typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr; |
|
3075 typedef TypedAutoMarkingPtr<XPCNativeScriptableInfo> AutoMarkingNativeScriptableInfoPtr; |
|
3076 |
|
3077 template<class T> |
|
3078 class ArrayAutoMarkingPtr : public AutoMarkingPtr |
|
3079 { |
|
3080 public: |
|
3081 ArrayAutoMarkingPtr(JSContext* cx) |
|
3082 : AutoMarkingPtr(cx), mPtr(nullptr), mCount(0) {} |
|
3083 ArrayAutoMarkingPtr(JSContext* cx, T** ptr, uint32_t count, bool clear) |
|
3084 : AutoMarkingPtr(cx), mPtr(ptr), mCount(count) |
|
3085 { |
|
3086 if (!mPtr) mCount = 0; |
|
3087 else if (clear) memset(mPtr, 0, mCount*sizeof(T*)); |
|
3088 } |
|
3089 |
|
3090 T** get() const { return mPtr; } |
|
3091 operator T **() const { return mPtr; } |
|
3092 T** operator->() const { return mPtr; } |
|
3093 |
|
3094 ArrayAutoMarkingPtr<T>& operator =(const ArrayAutoMarkingPtr<T> &other) |
|
3095 { |
|
3096 mPtr = other.mPtr; |
|
3097 mCount = other.mCount; |
|
3098 return *this; |
|
3099 } |
|
3100 |
|
3101 protected: |
|
3102 virtual void TraceJS(JSTracer* trc) |
|
3103 { |
|
3104 for (uint32_t i = 0; i < mCount; i++) { |
|
3105 if (mPtr[i]) { |
|
3106 mPtr[i]->TraceJS(trc); |
|
3107 mPtr[i]->AutoTrace(trc); |
|
3108 } |
|
3109 } |
|
3110 } |
|
3111 |
|
3112 virtual void MarkAfterJSFinalize() |
|
3113 { |
|
3114 for (uint32_t i = 0; i < mCount; i++) { |
|
3115 if (mPtr[i]) |
|
3116 mPtr[i]->Mark(); |
|
3117 } |
|
3118 } |
|
3119 |
|
3120 private: |
|
3121 T** mPtr; |
|
3122 uint32_t mCount; |
|
3123 }; |
|
3124 |
|
3125 typedef ArrayAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtrArrayPtr; |
|
3126 |
|
3127 /***************************************************************************/ |
|
3128 namespace xpc { |
|
3129 // Allocates a string that grants all access ("AllAccess") |
|
3130 char * |
|
3131 CloneAllAccess(); |
|
3132 |
|
3133 // Returns access if wideName is in list |
|
3134 char * |
|
3135 CheckAccessList(const char16_t *wideName, const char *const list[]); |
|
3136 } /* namespace xpc */ |
|
3137 |
|
3138 /***************************************************************************/ |
|
3139 // in xpcvariant.cpp... |
|
3140 |
|
3141 // {1809FD50-91E8-11d5-90F9-0010A4E73D9A} |
|
3142 #define XPCVARIANT_IID \ |
|
3143 {0x1809fd50, 0x91e8, 0x11d5, \ |
|
3144 { 0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } } |
|
3145 |
|
3146 // {DC524540-487E-4501-9AC7-AAA784B17C1C} |
|
3147 #define XPCVARIANT_CID \ |
|
3148 {0xdc524540, 0x487e, 0x4501, \ |
|
3149 { 0x9a, 0xc7, 0xaa, 0xa7, 0x84, 0xb1, 0x7c, 0x1c } } |
|
3150 |
|
3151 class XPCVariant : public nsIVariant |
|
3152 { |
|
3153 public: |
|
3154 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
3155 NS_DECL_NSIVARIANT |
|
3156 NS_DECL_CYCLE_COLLECTION_CLASS(XPCVariant) |
|
3157 |
|
3158 // If this class ever implements nsIWritableVariant, take special care with |
|
3159 // the case when mJSVal is JSVAL_STRING, since we don't own the data in |
|
3160 // that case. |
|
3161 |
|
3162 // We #define and iid so that out module local code can use QI to detect |
|
3163 // if a given nsIVariant is in fact an XPCVariant. |
|
3164 NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID) |
|
3165 |
|
3166 static already_AddRefed<XPCVariant> newVariant(JSContext* cx, jsval aJSVal); |
|
3167 |
|
3168 /** |
|
3169 * This getter clears the gray bit before handing out the jsval if the jsval |
|
3170 * represents a JSObject. That means that the object is guaranteed to be |
|
3171 * kept alive past the next CC. |
|
3172 */ |
|
3173 jsval GetJSVal() const { |
|
3174 if (!JSVAL_IS_PRIMITIVE(mJSVal)) |
|
3175 JS::ExposeObjectToActiveJS(&mJSVal.toObject()); |
|
3176 return mJSVal; |
|
3177 } |
|
3178 |
|
3179 /** |
|
3180 * This getter does not change the color of the jsval (if it represents a |
|
3181 * JSObject) meaning that the value returned is not guaranteed to be kept |
|
3182 * alive past the next CC. |
|
3183 * |
|
3184 * This should only be called if you are certain that the return value won't |
|
3185 * be passed into a JS API function and that it won't be stored without |
|
3186 * being rooted (or otherwise signaling the stored value to the CC). |
|
3187 */ |
|
3188 jsval GetJSValPreserveColor() const {return mJSVal;} |
|
3189 |
|
3190 XPCVariant(JSContext* cx, jsval aJSVal); |
|
3191 |
|
3192 /** |
|
3193 * Convert a variant into a jsval. |
|
3194 * |
|
3195 * @param ccx the context for the whole procedure |
|
3196 * @param variant the variant to convert |
|
3197 * @param scope the default scope to put on the new JSObject's parent chain |
|
3198 * @param pErr [out] relevant error code, if any. |
|
3199 * @param pJSVal [out] the resulting jsval. |
|
3200 */ |
|
3201 static bool VariantDataToJS(nsIVariant* variant, |
|
3202 nsresult* pErr, JS::MutableHandleValue pJSVal); |
|
3203 |
|
3204 bool IsPurple() |
|
3205 { |
|
3206 return mRefCnt.IsPurple(); |
|
3207 } |
|
3208 |
|
3209 void RemovePurple() |
|
3210 { |
|
3211 mRefCnt.RemovePurple(); |
|
3212 } |
|
3213 |
|
3214 void SetCCGeneration(uint32_t aGen) |
|
3215 { |
|
3216 mCCGeneration = aGen; |
|
3217 } |
|
3218 |
|
3219 uint32_t CCGeneration() { return mCCGeneration; } |
|
3220 protected: |
|
3221 virtual ~XPCVariant() { } |
|
3222 |
|
3223 bool InitializeData(JSContext* cx); |
|
3224 |
|
3225 protected: |
|
3226 nsDiscriminatedUnion mData; |
|
3227 JS::Heap<JS::Value> mJSVal; |
|
3228 bool mReturnRawObject : 1; |
|
3229 uint32_t mCCGeneration : 31; |
|
3230 }; |
|
3231 |
|
3232 NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID) |
|
3233 |
|
3234 class XPCTraceableVariant: public XPCVariant, |
|
3235 public XPCRootSetElem |
|
3236 { |
|
3237 public: |
|
3238 XPCTraceableVariant(JSContext* cx, jsval aJSVal) |
|
3239 : XPCVariant(cx, aJSVal) |
|
3240 { |
|
3241 nsXPConnect::GetRuntimeInstance()->AddVariantRoot(this); |
|
3242 } |
|
3243 |
|
3244 virtual ~XPCTraceableVariant(); |
|
3245 |
|
3246 void TraceJS(JSTracer* trc); |
|
3247 static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize); |
|
3248 }; |
|
3249 |
|
3250 /***************************************************************************/ |
|
3251 // Utilities |
|
3252 |
|
3253 inline void * |
|
3254 xpc_GetJSPrivate(JSObject *obj) |
|
3255 { |
|
3256 return js::GetObjectPrivate(obj); |
|
3257 } |
|
3258 |
|
3259 inline JSContext * |
|
3260 xpc_GetSafeJSContext() |
|
3261 { |
|
3262 return XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContext(); |
|
3263 } |
|
3264 |
|
3265 namespace xpc { |
|
3266 |
|
3267 // JSNatives to expose atob and btoa in various non-DOM XPConnect scopes. |
|
3268 bool |
|
3269 Atob(JSContext *cx, unsigned argc, jsval *vp); |
|
3270 |
|
3271 bool |
|
3272 Btoa(JSContext *cx, unsigned argc, jsval *vp); |
|
3273 |
|
3274 |
|
3275 // Helper function that creates a JSFunction that wraps a native function that |
|
3276 // forwards the call to the original 'callable'. If the 'doclone' argument is |
|
3277 // set, it also structure clones non-native arguments for extra security. |
|
3278 bool |
|
3279 NewFunctionForwarder(JSContext *cx, JS::HandleId id, JS::HandleObject callable, |
|
3280 bool doclone, JS::MutableHandleValue vp); |
|
3281 |
|
3282 bool |
|
3283 NewFunctionForwarder(JSContext *cx, JS::HandleObject callable, |
|
3284 bool doclone, JS::MutableHandleValue vp); |
|
3285 |
|
3286 // Old fashioned xpc error reporter. Try to use JS_ReportError instead. |
|
3287 nsresult |
|
3288 ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval); |
|
3289 |
|
3290 struct GlobalProperties { |
|
3291 GlobalProperties(bool aPromise) { |
|
3292 mozilla::PodZero(this); |
|
3293 Promise = true; |
|
3294 } |
|
3295 bool Parse(JSContext *cx, JS::HandleObject obj); |
|
3296 bool Define(JSContext *cx, JS::HandleObject obj); |
|
3297 bool Promise : 1; |
|
3298 bool indexedDB : 1; |
|
3299 bool XMLHttpRequest : 1; |
|
3300 bool TextDecoder : 1; |
|
3301 bool TextEncoder : 1; |
|
3302 bool URL : 1; |
|
3303 bool atob : 1; |
|
3304 bool btoa : 1; |
|
3305 }; |
|
3306 |
|
3307 // Infallible. |
|
3308 already_AddRefed<nsIXPCComponents_utils_Sandbox> |
|
3309 NewSandboxConstructor(); |
|
3310 |
|
3311 // Returns true if class of 'obj' is SandboxClass. |
|
3312 bool |
|
3313 IsSandbox(JSObject *obj); |
|
3314 |
|
3315 class MOZ_STACK_CLASS OptionsBase { |
|
3316 public: |
|
3317 OptionsBase(JSContext *cx = xpc_GetSafeJSContext(), |
|
3318 JSObject *options = nullptr) |
|
3319 : mCx(cx) |
|
3320 , mObject(cx, options) |
|
3321 { } |
|
3322 |
|
3323 virtual bool Parse() = 0; |
|
3324 |
|
3325 protected: |
|
3326 bool ParseValue(const char *name, JS::MutableHandleValue prop, bool *found = nullptr); |
|
3327 bool ParseBoolean(const char *name, bool *prop); |
|
3328 bool ParseObject(const char *name, JS::MutableHandleObject prop); |
|
3329 bool ParseString(const char *name, nsCString &prop); |
|
3330 bool ParseString(const char *name, nsString &prop); |
|
3331 bool ParseId(const char* name, JS::MutableHandleId id); |
|
3332 |
|
3333 JSContext *mCx; |
|
3334 JS::RootedObject mObject; |
|
3335 }; |
|
3336 |
|
3337 class MOZ_STACK_CLASS SandboxOptions : public OptionsBase { |
|
3338 public: |
|
3339 SandboxOptions(JSContext *cx = xpc_GetSafeJSContext(), |
|
3340 JSObject *options = nullptr) |
|
3341 : OptionsBase(cx, options) |
|
3342 , wantXrays(true) |
|
3343 , wantComponents(true) |
|
3344 , wantExportHelpers(false) |
|
3345 , proto(cx) |
|
3346 , sameZoneAs(cx) |
|
3347 , invisibleToDebugger(false) |
|
3348 , discardSource(false) |
|
3349 , globalProperties(true) |
|
3350 , metadata(cx) |
|
3351 { } |
|
3352 |
|
3353 virtual bool Parse(); |
|
3354 |
|
3355 bool wantXrays; |
|
3356 bool wantComponents; |
|
3357 bool wantExportHelpers; |
|
3358 JS::RootedObject proto; |
|
3359 nsCString sandboxName; |
|
3360 JS::RootedObject sameZoneAs; |
|
3361 bool invisibleToDebugger; |
|
3362 bool discardSource; |
|
3363 GlobalProperties globalProperties; |
|
3364 JS::RootedValue metadata; |
|
3365 |
|
3366 protected: |
|
3367 bool ParseGlobalProperties(); |
|
3368 }; |
|
3369 |
|
3370 class MOZ_STACK_CLASS CreateObjectInOptions : public OptionsBase { |
|
3371 public: |
|
3372 CreateObjectInOptions(JSContext *cx = xpc_GetSafeJSContext(), |
|
3373 JSObject* options = nullptr) |
|
3374 : OptionsBase(cx, options) |
|
3375 , defineAs(cx, JSID_VOID) |
|
3376 { } |
|
3377 |
|
3378 virtual bool Parse() { return ParseId("defineAs", &defineAs); }; |
|
3379 |
|
3380 JS::RootedId defineAs; |
|
3381 }; |
|
3382 |
|
3383 class MOZ_STACK_CLASS ExportOptions : public OptionsBase { |
|
3384 public: |
|
3385 ExportOptions(JSContext *cx = xpc_GetSafeJSContext(), |
|
3386 JSObject* options = nullptr) |
|
3387 : OptionsBase(cx, options) |
|
3388 , defineAs(cx, JSID_VOID) |
|
3389 { } |
|
3390 |
|
3391 virtual bool Parse() { return ParseId("defineAs", &defineAs); }; |
|
3392 |
|
3393 JS::RootedId defineAs; |
|
3394 }; |
|
3395 |
|
3396 JSObject * |
|
3397 CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal, |
|
3398 JS::CompartmentOptions& aOptions); |
|
3399 |
|
3400 bool |
|
3401 InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal, |
|
3402 uint32_t aFlags); |
|
3403 |
|
3404 // Helper for creating a sandbox object to use for evaluating |
|
3405 // untrusted code completely separated from all other code in the |
|
3406 // system using EvalInSandbox(). Takes the JSContext on which to |
|
3407 // do setup etc on, puts the sandbox object in *vp (which must be |
|
3408 // rooted by the caller), and uses the principal that's either |
|
3409 // directly passed in prinOrSop or indirectly as an |
|
3410 // nsIScriptObjectPrincipal holding the principal. If no principal is |
|
3411 // reachable through prinOrSop, a new null principal will be created |
|
3412 // and used. |
|
3413 nsresult |
|
3414 CreateSandboxObject(JSContext *cx, JS::MutableHandleValue vp, nsISupports *prinOrSop, |
|
3415 xpc::SandboxOptions& options); |
|
3416 // Helper for evaluating scripts in a sandbox object created with |
|
3417 // CreateSandboxObject(). The caller is responsible of ensuring |
|
3418 // that *rval doesn't get collected during the call or usage after the |
|
3419 // call. This helper will use filename and lineNo for error reporting, |
|
3420 // and if no filename is provided it will use the codebase from the |
|
3421 // principal and line number 1 as a fallback. if returnStringOnly is |
|
3422 // true, then the result in *rval, or the exception in cx->exception |
|
3423 // will be coerced into strings. If an exception is thrown converting |
|
3424 // an exception to a string, evalInSandbox will return an NS_ERROR_* |
|
3425 // result, and cx->exception will be empty. |
|
3426 nsresult |
|
3427 EvalInSandbox(JSContext *cx, JS::HandleObject sandbox, const nsAString& source, |
|
3428 const nsACString& filename, int32_t lineNo, |
|
3429 JSVersion jsVersion, bool returnStringOnly, |
|
3430 JS::MutableHandleValue rval); |
|
3431 |
|
3432 // Helper for retrieving metadata stored in a reserved slot. The metadata |
|
3433 // is set during the sandbox creation using the "metadata" option. |
|
3434 nsresult |
|
3435 GetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg, |
|
3436 JS::MutableHandleValue rval); |
|
3437 |
|
3438 nsresult |
|
3439 SetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg, |
|
3440 JS::HandleValue metadata); |
|
3441 |
|
3442 bool |
|
3443 CreateObjectIn(JSContext *cx, JS::HandleValue vobj, CreateObjectInOptions &options, |
|
3444 JS::MutableHandleValue rval); |
|
3445 |
|
3446 bool |
|
3447 EvalInWindow(JSContext *cx, const nsAString &source, JS::HandleObject scope, |
|
3448 JS::MutableHandleValue rval); |
|
3449 |
|
3450 bool |
|
3451 ExportFunction(JSContext *cx, JS::HandleValue vscope, JS::HandleValue vfunction, |
|
3452 JS::HandleValue voptions, JS::MutableHandleValue rval); |
|
3453 |
|
3454 bool |
|
3455 CloneInto(JSContext *cx, JS::HandleValue vobj, JS::HandleValue vscope, |
|
3456 JS::HandleValue voptions, JS::MutableHandleValue rval); |
|
3457 |
|
3458 } /* namespace xpc */ |
|
3459 |
|
3460 |
|
3461 /***************************************************************************/ |
|
3462 // Inlined utilities. |
|
3463 |
|
3464 inline bool |
|
3465 xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid id); |
|
3466 |
|
3467 inline jsid |
|
3468 GetRTIdByIndex(JSContext *cx, unsigned index); |
|
3469 |
|
3470 namespace xpc { |
|
3471 |
|
3472 class CompartmentPrivate |
|
3473 { |
|
3474 public: |
|
3475 enum LocationHint { |
|
3476 LocationHintRegular, |
|
3477 LocationHintAddon |
|
3478 }; |
|
3479 |
|
3480 CompartmentPrivate(JSCompartment *c) |
|
3481 : wantXrays(false) |
|
3482 , universalXPConnectEnabled(false) |
|
3483 , adoptedNode(false) |
|
3484 , donatedNode(false) |
|
3485 , scriptability(c) |
|
3486 , scope(nullptr) |
|
3487 { |
|
3488 MOZ_COUNT_CTOR(xpc::CompartmentPrivate); |
|
3489 } |
|
3490 |
|
3491 ~CompartmentPrivate(); |
|
3492 |
|
3493 bool wantXrays; |
|
3494 |
|
3495 // This is only ever set during mochitest runs when enablePrivilege is called. |
|
3496 // It's intended as a temporary stopgap measure until we can finish ripping out |
|
3497 // enablePrivilege. Once set, this value is never unset (i.e., it doesn't follow |
|
3498 // the old scoping rules of enablePrivilege). Using it is inherently unsafe. |
|
3499 bool universalXPConnectEnabled; |
|
3500 |
|
3501 // for telemetry. See bug 928476. |
|
3502 bool adoptedNode; |
|
3503 bool donatedNode; |
|
3504 |
|
3505 // The scriptability of this compartment. |
|
3506 Scriptability scriptability; |
|
3507 |
|
3508 // Our XPCWrappedNativeScope. This is non-null if and only if this is an |
|
3509 // XPConnect compartment. |
|
3510 XPCWrappedNativeScope *scope; |
|
3511 |
|
3512 const nsACString& GetLocation() { |
|
3513 if (location.IsEmpty() && locationURI) { |
|
3514 if (NS_FAILED(locationURI->GetSpec(location))) |
|
3515 location = NS_LITERAL_CSTRING("<unknown location>"); |
|
3516 } |
|
3517 return location; |
|
3518 } |
|
3519 bool GetLocationURI(nsIURI **aURI) { |
|
3520 return GetLocationURI(LocationHintRegular, aURI); |
|
3521 } |
|
3522 bool GetLocationURI(LocationHint aLocationHint, nsIURI **aURI) { |
|
3523 if (locationURI) { |
|
3524 nsCOMPtr<nsIURI> rval = locationURI; |
|
3525 rval.forget(aURI); |
|
3526 return true; |
|
3527 } |
|
3528 return TryParseLocationURI(aLocationHint, aURI); |
|
3529 } |
|
3530 void SetLocation(const nsACString& aLocation) { |
|
3531 if (aLocation.IsEmpty()) |
|
3532 return; |
|
3533 if (!location.IsEmpty() || locationURI) |
|
3534 return; |
|
3535 location = aLocation; |
|
3536 } |
|
3537 void SetLocationURI(nsIURI *aLocationURI) { |
|
3538 if (!aLocationURI) |
|
3539 return; |
|
3540 if (locationURI) |
|
3541 return; |
|
3542 locationURI = aLocationURI; |
|
3543 } |
|
3544 |
|
3545 private: |
|
3546 nsCString location; |
|
3547 nsCOMPtr<nsIURI> locationURI; |
|
3548 |
|
3549 bool TryParseLocationURI(LocationHint aType, nsIURI** aURI); |
|
3550 }; |
|
3551 |
|
3552 CompartmentPrivate* |
|
3553 EnsureCompartmentPrivate(JSObject *obj); |
|
3554 |
|
3555 CompartmentPrivate* |
|
3556 EnsureCompartmentPrivate(JSCompartment *c); |
|
3557 |
|
3558 inline CompartmentPrivate* |
|
3559 GetCompartmentPrivate(JSCompartment *compartment) |
|
3560 { |
|
3561 MOZ_ASSERT(compartment); |
|
3562 void *priv = JS_GetCompartmentPrivate(compartment); |
|
3563 return static_cast<CompartmentPrivate*>(priv); |
|
3564 } |
|
3565 |
|
3566 inline CompartmentPrivate* |
|
3567 GetCompartmentPrivate(JSObject *object) |
|
3568 { |
|
3569 MOZ_ASSERT(object); |
|
3570 JSCompartment *compartment = js::GetObjectCompartment(object); |
|
3571 |
|
3572 MOZ_ASSERT(compartment); |
|
3573 return GetCompartmentPrivate(compartment); |
|
3574 } |
|
3575 |
|
3576 bool IsUniversalXPConnectEnabled(JSCompartment *compartment); |
|
3577 bool IsUniversalXPConnectEnabled(JSContext *cx); |
|
3578 bool EnableUniversalXPConnect(JSContext *cx); |
|
3579 |
|
3580 // This returns null if and only if it is called on an object in a non-XPConnect |
|
3581 // compartment. |
|
3582 inline XPCWrappedNativeScope* |
|
3583 GetObjectScope(JSObject *obj) |
|
3584 { |
|
3585 return EnsureCompartmentPrivate(obj)->scope; |
|
3586 } |
|
3587 |
|
3588 // This returns null if a scope doesn't already exist. |
|
3589 XPCWrappedNativeScope* MaybeGetObjectScope(JSObject *obj); |
|
3590 |
|
3591 extern bool gDebugMode; |
|
3592 extern bool gDesiredDebugMode; |
|
3593 |
|
3594 extern const JSClass SafeJSContextGlobalClass; |
|
3595 |
|
3596 JSObject* NewOutObject(JSContext* cx, JSObject* scope); |
|
3597 bool IsOutObject(JSContext* cx, JSObject* obj); |
|
3598 |
|
3599 nsresult HasInstance(JSContext *cx, JS::HandleObject objArg, const nsID *iid, bool *bp); |
|
3600 |
|
3601 /** |
|
3602 * Define quick stubs on the given object, @a proto. |
|
3603 * |
|
3604 * @param cx |
|
3605 * A context. Requires request. |
|
3606 * @param proto |
|
3607 * The (newly created) prototype object for a DOM class. The JS half |
|
3608 * of an XPCWrappedNativeProto. |
|
3609 * @param flags |
|
3610 * Property flags for the quick stub properties--should be either |
|
3611 * JSPROP_ENUMERATE or 0. |
|
3612 * @param interfaceCount |
|
3613 * The number of interfaces the class implements. |
|
3614 * @param interfaceArray |
|
3615 * The interfaces the class implements; interfaceArray and |
|
3616 * interfaceCount are like what nsIClassInfo.getInterfaces returns. |
|
3617 */ |
|
3618 bool |
|
3619 DOM_DefineQuickStubs(JSContext *cx, JSObject *proto, uint32_t flags, |
|
3620 uint32_t interfaceCount, const nsIID **interfaceArray); |
|
3621 |
|
3622 nsIPrincipal *GetObjectPrincipal(JSObject *obj); |
|
3623 |
|
3624 } // namespace xpc |
|
3625 |
|
3626 namespace mozilla { |
|
3627 namespace dom { |
|
3628 extern bool |
|
3629 DefineStaticJSVals(JSContext *cx); |
|
3630 } // namespace dom |
|
3631 } // namespace mozilla |
|
3632 |
|
3633 bool |
|
3634 xpc_LocalizeRuntime(JSRuntime *rt); |
|
3635 void |
|
3636 xpc_DelocalizeRuntime(JSRuntime *rt); |
|
3637 |
|
3638 /***************************************************************************/ |
|
3639 // Inlines use the above - include last. |
|
3640 |
|
3641 #include "XPCInlines.h" |
|
3642 |
|
3643 /***************************************************************************/ |
|
3644 // Maps have inlines that use the above - include last. |
|
3645 |
|
3646 #include "XPCMaps.h" |
|
3647 |
|
3648 /***************************************************************************/ |
|
3649 |
|
3650 #endif /* xpcprivate_h___ */ |