Line data Source code
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 can have pointers from XPCWrappedNativeProto and
62 : * XPCWrappedNative (since C++ objects can have scriptable info without having
63 : * class info).
64 : */
65 :
66 : /* All the XPConnect private declarations - only include locally. */
67 :
68 : #ifndef xpcprivate_h___
69 : #define xpcprivate_h___
70 :
71 : #include "mozilla/Alignment.h"
72 : #include "mozilla/ArrayUtils.h"
73 : #include "mozilla/Assertions.h"
74 : #include "mozilla/Atomics.h"
75 : #include "mozilla/Attributes.h"
76 : #include "mozilla/CycleCollectedJSContext.h"
77 : #include "mozilla/CycleCollectedJSRuntime.h"
78 : #include "mozilla/DebugOnly.h"
79 : #include "mozilla/GuardObjects.h"
80 : #include "mozilla/Maybe.h"
81 : #include "mozilla/MemoryReporting.h"
82 : #include "mozilla/Preferences.h"
83 : #include "mozilla/TimeStamp.h"
84 : #include "mozilla/UniquePtr.h"
85 :
86 : #include "mozilla/dom/ScriptSettings.h"
87 :
88 : #include <math.h>
89 : #include <stdint.h>
90 : #include <stdlib.h>
91 : #include <string.h>
92 :
93 : #include "xpcpublic.h"
94 : #include "js/TracingAPI.h"
95 : #include "js/WeakMapPtr.h"
96 : #include "PLDHashTable.h"
97 : #include "nscore.h"
98 : #include "nsXPCOM.h"
99 : #include "nsAutoPtr.h"
100 : #include "nsCycleCollectionParticipant.h"
101 : #include "nsDebug.h"
102 : #include "nsISupports.h"
103 : #include "nsIServiceManager.h"
104 : #include "nsIClassInfoImpl.h"
105 : #include "nsIComponentManager.h"
106 : #include "nsIComponentRegistrar.h"
107 : #include "nsISupportsPrimitives.h"
108 : #include "nsMemory.h"
109 : #include "nsIXPConnect.h"
110 : #include "nsIInterfaceInfo.h"
111 : #include "nsIXPCScriptable.h"
112 : #include "nsIObserver.h"
113 : #include "nsWeakReference.h"
114 : #include "nsCOMPtr.h"
115 : #include "nsXPTCUtils.h"
116 : #include "xptinfo.h"
117 : #include "XPCForwards.h"
118 : #include "XPCLog.h"
119 : #include "xpccomponents.h"
120 : #include "xpcexception.h"
121 : #include "xpcjsid.h"
122 : #include "prenv.h"
123 : #include "prcvar.h"
124 : #include "nsString.h"
125 : #include "nsReadableUtils.h"
126 : #include "nsXPIDLString.h"
127 :
128 : #include "MainThreadUtils.h"
129 :
130 : #include "nsIConsoleService.h"
131 : #include "nsIException.h"
132 :
133 : #include "nsVariant.h"
134 : #include "nsIPropertyBag.h"
135 : #include "nsIProperty.h"
136 : #include "nsCOMArray.h"
137 : #include "nsTArray.h"
138 : #include "nsBaseHashtable.h"
139 : #include "nsHashKeys.h"
140 : #include "nsWrapperCache.h"
141 : #include "nsStringBuffer.h"
142 : #include "nsDataHashtable.h"
143 : #include "nsDeque.h"
144 :
145 : #include "nsIScriptSecurityManager.h"
146 :
147 : #include "nsIPrincipal.h"
148 : #include "nsJSPrincipals.h"
149 : #include "nsIScriptObjectPrincipal.h"
150 : #include "xpcObjectHelper.h"
151 :
152 : #include "SandboxPrivate.h"
153 : #include "BackstagePass.h"
154 : #include "nsAXPCNativeCallContext.h"
155 :
156 : #ifdef XP_WIN
157 : // Nasty MS defines
158 : #ifdef GetClassInfo
159 : #undef GetClassInfo
160 : #endif
161 : #ifdef GetClassName
162 : #undef GetClassName
163 : #endif
164 : #endif /* XP_WIN */
165 :
166 : /***************************************************************************/
167 : // default initial sizes for maps (hashtables)
168 :
169 : #define XPC_JS_MAP_LENGTH 32
170 : #define XPC_JS_CLASS_MAP_LENGTH 32
171 :
172 : #define XPC_NATIVE_MAP_LENGTH 8
173 : #define XPC_NATIVE_PROTO_MAP_LENGTH 8
174 : #define XPC_DYING_NATIVE_PROTO_MAP_LENGTH 8
175 : #define XPC_NATIVE_INTERFACE_MAP_LENGTH 32
176 : #define XPC_NATIVE_SET_MAP_LENGTH 32
177 : #define XPC_THIS_TRANSLATOR_MAP_LENGTH 4
178 : #define XPC_WRAPPER_MAP_LENGTH 8
179 :
180 : /***************************************************************************/
181 : // data declarations...
182 : extern const char XPC_CONTEXT_STACK_CONTRACTID[];
183 : extern const char XPC_EXCEPTION_CONTRACTID[];
184 : extern const char XPC_CONSOLE_CONTRACTID[];
185 : extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
186 : extern const char XPC_ID_CONTRACTID[];
187 : extern const char XPC_XPCONNECT_CONTRACTID[];
188 :
189 : /***************************************************************************/
190 : // Useful macros...
191 :
192 : #define XPC_STRING_GETTER_BODY(dest, src) \
193 : NS_ENSURE_ARG_POINTER(dest); \
194 : char* result; \
195 : if (src) \
196 : result = (char*) nsMemory::Clone(src, \
197 : sizeof(char)*(strlen(src)+1)); \
198 : else \
199 : result = nullptr; \
200 : *dest = result; \
201 : return (result || !src) ? NS_OK : NS_ERROR_OUT_OF_MEMORY
202 :
203 : // If IS_WN_CLASS for the JSClass of an object is true, the object is a
204 : // wrappednative wrapper, holding the XPCWrappedNative in its private slot.
205 127179 : static inline bool IS_WN_CLASS(const js::Class* clazz)
206 : {
207 127179 : return clazz->isWrappedNative();
208 : }
209 :
210 86280 : static inline bool IS_WN_REFLECTOR(JSObject* obj)
211 : {
212 86280 : return IS_WN_CLASS(js::GetObjectClass(obj));
213 : }
214 :
215 : /***************************************************************************
216 : ****************************************************************************
217 : *
218 : * Core runtime and context classes...
219 : *
220 : ****************************************************************************
221 : ***************************************************************************/
222 :
223 : // We have a general rule internally that getters that return addref'd interface
224 : // pointer generally do so using an 'out' parm. When interface pointers are
225 : // returned as function call result values they are not addref'd. Exceptions
226 : // to this rule are noted explicitly.
227 :
228 : class nsXPConnect final : public nsIXPConnect
229 : {
230 : public:
231 : // all the interface method declarations...
232 : NS_DECL_ISUPPORTS
233 : NS_DECL_NSIXPCONNECT
234 :
235 : // non-interface implementation
236 : public:
237 : // These get non-addref'd pointers
238 55055 : static nsXPConnect* XPConnect()
239 : {
240 : // Do a release-mode assert that we're not doing anything significant in
241 : // XPConnect off the main thread. If you're an extension developer hitting
242 : // this, you need to change your code. See bug 716167.
243 55055 : if (!MOZ_LIKELY(NS_IsMainThread()))
244 0 : MOZ_CRASH();
245 :
246 55055 : return gSelf;
247 : }
248 :
249 : static XPCJSRuntime* GetRuntimeInstance();
250 :
251 : static bool IsISupportsDescendant(nsIInterfaceInfo* info);
252 :
253 8712 : static nsIScriptSecurityManager* SecurityManager()
254 : {
255 8712 : MOZ_ASSERT(NS_IsMainThread());
256 8712 : MOZ_ASSERT(gScriptSecurityManager);
257 8712 : return gScriptSecurityManager;
258 : }
259 :
260 32260 : static nsIPrincipal* SystemPrincipal()
261 : {
262 32260 : MOZ_ASSERT(NS_IsMainThread());
263 32260 : MOZ_ASSERT(gSystemPrincipal);
264 32260 : return gSystemPrincipal;
265 : }
266 :
267 : // This returns an AddRef'd pointer. It does not do this with an 'out' param
268 : // only because this form is required by the generic module macro:
269 : // NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
270 : static nsXPConnect* GetSingleton();
271 :
272 : // Called by module code in dll startup
273 : static void InitStatics();
274 : // Called by module code on dll shutdown.
275 : static void ReleaseXPConnectSingleton();
276 :
277 1 : bool IsShuttingDown() const {return mShuttingDown;}
278 :
279 : nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
280 : nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
281 :
282 : virtual nsIPrincipal* GetPrincipal(JSObject* obj,
283 : bool allowShortCircuit) const override;
284 :
285 : void RecordTraversal(void* p, nsISupports* s);
286 : virtual char* DebugPrintJSStack(bool showArgs,
287 : bool showLocals,
288 : bool showThisProps) override;
289 :
290 : protected:
291 : virtual ~nsXPConnect();
292 :
293 : nsXPConnect();
294 :
295 : private:
296 : // Singleton instance
297 : static nsXPConnect* gSelf;
298 : static bool gOnceAliveNowDead;
299 :
300 : XPCJSRuntime* mRuntime;
301 : bool mShuttingDown;
302 :
303 : public:
304 : static nsIScriptSecurityManager* gScriptSecurityManager;
305 : static nsIPrincipal* gSystemPrincipal;
306 : };
307 :
308 : /***************************************************************************/
309 :
310 : class XPCRootSetElem
311 : {
312 : public:
313 941 : XPCRootSetElem()
314 941 : {
315 : #ifdef DEBUG
316 941 : mNext = nullptr;
317 941 : mSelfp = nullptr;
318 : #endif
319 941 : }
320 :
321 142 : ~XPCRootSetElem()
322 142 : {
323 142 : MOZ_ASSERT(!mNext, "Must be unlinked");
324 142 : MOZ_ASSERT(!mSelfp, "Must be unlinked");
325 142 : }
326 :
327 481 : inline XPCRootSetElem* GetNextRoot() { return mNext; }
328 : void AddToRootSet(XPCRootSetElem** listHead);
329 : void RemoveFromRootSet();
330 :
331 : private:
332 : XPCRootSetElem* mNext;
333 : XPCRootSetElem** mSelfp;
334 : };
335 :
336 : /***************************************************************************/
337 :
338 : // In the current xpconnect system there can only be one XPCJSContext.
339 : // So, xpconnect can only be used on one JSContext within the process.
340 :
341 : class WatchdogManager;
342 :
343 : enum WatchdogTimestampCategory
344 : {
345 : TimestampContextStateChange = 0,
346 : TimestampWatchdogWakeup,
347 : TimestampWatchdogHibernateStart,
348 : TimestampWatchdogHibernateStop,
349 : TimestampCount
350 : };
351 :
352 : class AsyncFreeSnowWhite;
353 :
354 : template <class StringType>
355 6 : class ShortLivedStringBuffer
356 : {
357 : public:
358 2481 : StringType* Create()
359 : {
360 3403 : for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
361 3207 : if (!mStrings[i]) {
362 2285 : mStrings[i].emplace();
363 2285 : return mStrings[i].ptr();
364 : }
365 : }
366 :
367 : // All our internal string wrappers are used, allocate a new string.
368 196 : return new StringType();
369 : }
370 :
371 2480 : void Destroy(StringType* string)
372 : {
373 3402 : for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
374 3206 : if (mStrings[i] && mStrings[i].ptr() == string) {
375 : // One of our internal strings is no longer in use, mark
376 : // it as such and free its data.
377 2284 : mStrings[i].reset();
378 2284 : return;
379 : }
380 : }
381 :
382 : // We're done with a string that's not one of our internal
383 : // strings, delete it.
384 196 : delete string;
385 : }
386 :
387 0 : ~ShortLivedStringBuffer()
388 : {
389 : #ifdef DEBUG
390 0 : for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
391 0 : MOZ_ASSERT(!mStrings[i], "Short lived string still in use");
392 : }
393 : #endif
394 0 : }
395 :
396 : private:
397 : mozilla::Maybe<StringType> mStrings[2];
398 : };
399 :
400 : class XPCJSContext final : public mozilla::CycleCollectedJSContext
401 : {
402 : public:
403 : static void InitTLS();
404 : static XPCJSContext* NewXPCJSContext(XPCJSContext* aPrimaryContext);
405 : static XPCJSContext* Get();
406 :
407 : XPCJSRuntime* Runtime() const;
408 :
409 : mozilla::CycleCollectedJSRuntime* CreateRuntime(JSContext* aCx) override;
410 :
411 16 : XPCCallContext* GetCallContext() const {return mCallContext;}
412 98262 : XPCCallContext* SetCallContext(XPCCallContext* ccx)
413 98262 : {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
414 :
415 2505 : jsid GetResolveName() const {return mResolveName;}
416 44412 : jsid SetResolveName(jsid name)
417 44412 : {jsid old = mResolveName; mResolveName = name; return old;}
418 :
419 1408 : XPCWrappedNative* GetResolvingWrapper() const {return mResolvingWrapper;}
420 6138 : XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w)
421 6138 : {XPCWrappedNative* old = mResolvingWrapper;
422 6138 : mResolvingWrapper = w; return old;}
423 :
424 : bool JSContextInitialized(JSContext* cx);
425 :
426 : virtual void BeforeProcessTask(bool aMightBlock) override;
427 : virtual void AfterProcessTask(uint32_t aNewRecursionDepth) override;
428 :
429 : ~XPCJSContext();
430 :
431 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
432 :
433 23259 : AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;}
434 :
435 1357 : nsresult GetPendingResult() { return mPendingResult; }
436 1357 : void SetPendingResult(nsresult rv) { mPendingResult = rv; }
437 :
438 : PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
439 :
440 : static void ActivityCallback(void* arg, bool active);
441 : static bool InterruptCallback(JSContext* cx);
442 :
443 : // Mapping of often used strings to jsid atoms that live 'forever'.
444 : //
445 : // To add a new string: add to this list and to XPCJSRuntime::mStrings
446 : // at the top of XPCJSRuntime.cpp
447 : enum {
448 : IDX_CONSTRUCTOR = 0 ,
449 : IDX_TO_STRING ,
450 : IDX_TO_SOURCE ,
451 : IDX_LAST_RESULT ,
452 : IDX_RETURN_CODE ,
453 : IDX_VALUE ,
454 : IDX_QUERY_INTERFACE ,
455 : IDX_COMPONENTS ,
456 : IDX_WRAPPED_JSOBJECT ,
457 : IDX_OBJECT ,
458 : IDX_FUNCTION ,
459 : IDX_PROTOTYPE ,
460 : IDX_CREATE_INSTANCE ,
461 : IDX_ITEM ,
462 : IDX_PROTO ,
463 : IDX_ITERATOR ,
464 : IDX_EXPOSEDPROPS ,
465 : IDX_EVAL ,
466 : IDX_CONTROLLERS ,
467 : IDX_CONTROLLERS_CLASS ,
468 : IDX_REALFRAMEELEMENT ,
469 : IDX_LENGTH ,
470 : IDX_NAME ,
471 : IDX_UNDEFINED ,
472 : IDX_EMPTYSTRING ,
473 : IDX_FILENAME ,
474 : IDX_LINENUMBER ,
475 : IDX_COLUMNNUMBER ,
476 : IDX_STACK ,
477 : IDX_MESSAGE ,
478 : IDX_LASTINDEX ,
479 : IDX_TOTAL_COUNT // just a count of the above
480 : };
481 :
482 : inline JS::HandleId GetStringID(unsigned index) const;
483 : inline const char* GetStringName(unsigned index) const;
484 :
485 : ShortLivedStringBuffer<nsString> mScratchStrings;
486 : ShortLivedStringBuffer<nsCString> mScratchCStrings;
487 :
488 : private:
489 : XPCJSContext();
490 :
491 : MOZ_IS_CLASS_INIT
492 : nsresult Initialize(XPCJSContext* aPrimaryContext);
493 :
494 : XPCCallContext* mCallContext;
495 : AutoMarkingPtr* mAutoRoots;
496 : jsid mResolveName;
497 : XPCWrappedNative* mResolvingWrapper;
498 : RefPtr<WatchdogManager> mWatchdogManager;
499 :
500 : // If we spend too much time running JS code in an event handler, then we
501 : // want to show the slow script UI. The timeout T is controlled by prefs. We
502 : // invoke the interrupt callback once after T/2 seconds and set
503 : // mSlowScriptSecondHalf to true. After another T/2 seconds, we invoke the
504 : // interrupt callback again. Since mSlowScriptSecondHalf is now true, it
505 : // shows the slow script UI. The reason we invoke the callback twice is to
506 : // ensure that putting the computer to sleep while running a script doesn't
507 : // cause the UI to be shown. If the laptop goes to sleep during one of the
508 : // timeout periods, the script still has the other T/2 seconds to complete
509 : // before the slow script UI is shown.
510 : bool mSlowScriptSecondHalf;
511 :
512 : // mSlowScriptCheckpoint is set to the time when:
513 : // 1. We started processing the current event, or
514 : // 2. mSlowScriptSecondHalf was set to true
515 : // (whichever comes later). We use it to determine whether the interrupt
516 : // callback needs to do anything.
517 : mozilla::TimeStamp mSlowScriptCheckpoint;
518 : // Accumulates total time we actually waited for telemetry
519 : mozilla::TimeDuration mSlowScriptActualWait;
520 : bool mTimeoutAccumulated;
521 :
522 : // mPendingResult is used to implement Components.returnCode. Only really
523 : // meaningful while calling through XPCWrappedJS.
524 : nsresult mPendingResult;
525 :
526 : friend class XPCJSRuntime;
527 : friend class Watchdog;
528 : friend class AutoLockWatchdog;
529 : };
530 :
531 : class XPCJSRuntime final : public mozilla::CycleCollectedJSRuntime
532 : {
533 : public:
534 : static XPCJSRuntime* Get();
535 :
536 : void RemoveWrappedJS(nsXPCWrappedJS* wrapper);
537 : void AssertInvalidWrappedJSNotInTable(nsXPCWrappedJS* wrapper) const;
538 :
539 1851 : JSObject2WrappedJSMap* GetMultiCompartmentWrappedJSMap() const
540 1851 : {return mWrappedJSMap;}
541 :
542 1532 : IID2WrappedJSClassMap* GetWrappedJSClassMap() const
543 1532 : {return mWrappedJSClassMap;}
544 :
545 16953 : IID2NativeInterfaceMap* GetIID2NativeInterfaceMap() const
546 16953 : {return mIID2NativeInterfaceMap;}
547 :
548 1824 : ClassInfo2NativeSetMap* GetClassInfo2NativeSetMap() const
549 1824 : {return mClassInfo2NativeSetMap;}
550 :
551 3013 : NativeSetMap* GetNativeSetMap() const
552 3013 : {return mNativeSetMap;}
553 :
554 47 : IID2ThisTranslatorMap* GetThisTranslatorMap() const
555 47 : {return mThisTranslatorMap;}
556 :
557 0 : XPCWrappedNativeProtoMap* GetDyingWrappedNativeProtoMap() const
558 0 : {return mDyingWrappedNativeProtoMap;}
559 :
560 : bool InitializeStrings(JSContext* cx);
561 :
562 : virtual bool
563 : DescribeCustomObjects(JSObject* aObject, const js::Class* aClasp,
564 : char (&aName)[72]) const override;
565 : virtual bool
566 : NoteCustomGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj,
567 : nsCycleCollectionTraversalCallback& aCb) const override;
568 :
569 : /**
570 : * Infrastructure for classes that need to defer part of the finalization
571 : * until after the GC has run, for example for objects that we don't want to
572 : * destroy during the GC.
573 : */
574 :
575 : public:
576 0 : bool GetDoingFinalization() const {return mDoingFinalization;}
577 :
578 30076 : JS::HandleId GetStringID(unsigned index) const
579 : {
580 30076 : MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
581 : // fromMarkedLocation() is safe because the string is interned.
582 30076 : return JS::HandleId::fromMarkedLocation(&mStrIDs[index]);
583 : }
584 : JS::HandleValue GetStringJSVal(unsigned index) const
585 : {
586 : MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
587 : // fromMarkedLocation() is safe because the string is interned.
588 : return JS::HandleValue::fromMarkedLocation(&mStrJSVals[index]);
589 : }
590 3 : const char* GetStringName(unsigned index) const
591 : {
592 3 : MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
593 3 : return mStrings[index];
594 : }
595 :
596 : virtual bool UsefulToMergeZones() const override;
597 : void TraceNativeBlackRoots(JSTracer* trc) override;
598 : void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) override;
599 : void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& cb) override;
600 : void UnmarkSkippableJSHolders();
601 : void PrepareForForgetSkippable() override;
602 : void BeginCycleCollectionCallback() override;
603 : void EndCycleCollectionCallback(mozilla::CycleCollectorResults& aResults) override;
604 : void DispatchDeferredDeletion(bool aContinuation, bool aPurge = false) override;
605 :
606 : void CustomGCCallback(JSGCStatus status) override;
607 : void CustomOutOfMemoryCallback() override;
608 : void OnLargeAllocationFailure();
609 : static void GCSliceCallback(JSContext* cx,
610 : JS::GCProgress progress,
611 : const JS::GCDescription& desc);
612 : static void DoCycleCollectionCallback(JSContext* cx);
613 : static void FinalizeCallback(JSFreeOp* fop,
614 : JSFinalizeStatus status,
615 : bool isZoneGC,
616 : void* data);
617 : static void WeakPointerZonesCallback(JSContext* cx, void* data);
618 : static void WeakPointerCompartmentCallback(JSContext* cx, JSCompartment* comp, void* data);
619 :
620 : inline void AddVariantRoot(XPCTraceableVariant* variant);
621 : inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
622 :
623 : void DebugDump(int16_t depth);
624 :
625 8007 : bool GCIsRunning() const {return mGCIsRunning;}
626 :
627 : ~XPCJSRuntime();
628 :
629 : void AddGCCallback(xpcGCCallback cb);
630 : void RemoveGCCallback(xpcGCCallback cb);
631 :
632 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
633 :
634 284 : JSObject* UnprivilegedJunkScope() { return mUnprivilegedJunkScope; }
635 66 : JSObject* PrivilegedJunkScope() { return mPrivilegedJunkScope; }
636 3774 : JSObject* CompilationScope() { return mCompilationScope; }
637 :
638 : void InitSingletonScopes();
639 : void DeleteSingletonScopes();
640 :
641 : private:
642 : explicit XPCJSRuntime(JSContext* aCx);
643 :
644 : MOZ_IS_CLASS_INIT
645 : void Initialize(JSContext* cx);
646 : void Shutdown(JSContext* cx) override;
647 :
648 : void ReleaseIncrementally(nsTArray<nsISupports*>& array);
649 :
650 : static const char* const mStrings[XPCJSContext::IDX_TOTAL_COUNT];
651 : jsid mStrIDs[XPCJSContext::IDX_TOTAL_COUNT];
652 : JS::Value mStrJSVals[XPCJSContext::IDX_TOTAL_COUNT];
653 :
654 : JSObject2WrappedJSMap* mWrappedJSMap;
655 : IID2WrappedJSClassMap* mWrappedJSClassMap;
656 : IID2NativeInterfaceMap* mIID2NativeInterfaceMap;
657 : ClassInfo2NativeSetMap* mClassInfo2NativeSetMap;
658 : NativeSetMap* mNativeSetMap;
659 : IID2ThisTranslatorMap* mThisTranslatorMap;
660 : XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
661 : bool mGCIsRunning;
662 : nsTArray<nsISupports*> mNativesToReleaseArray;
663 : bool mDoingFinalization;
664 : XPCRootSetElem* mVariantRoots;
665 : XPCRootSetElem* mWrappedJSRoots;
666 : nsTArray<xpcGCCallback> extraGCCallbacks;
667 : JS::GCSliceCallback mPrevGCSliceCallback;
668 : JS::DoCycleCollectionCallback mPrevDoCycleCollectionCallback;
669 : JS::PersistentRootedObject mUnprivilegedJunkScope;
670 : JS::PersistentRootedObject mPrivilegedJunkScope;
671 : JS::PersistentRootedObject mCompilationScope;
672 : RefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
673 :
674 : friend class XPCJSContext;
675 : friend class XPCIncrementalReleaseRunnable;
676 : };
677 :
678 : inline JS::HandleId
679 24252 : XPCJSContext::GetStringID(unsigned index) const
680 : {
681 24252 : return Runtime()->GetStringID(index);
682 : }
683 :
684 : inline const char*
685 3 : XPCJSContext::GetStringName(unsigned index) const
686 : {
687 3 : return Runtime()->GetStringName(index);
688 : }
689 :
690 : /***************************************************************************/
691 :
692 : // No virtuals
693 : // XPCCallContext is ALWAYS declared as a local variable in some function;
694 : // i.e. instance lifetime is always controled by some C++ function returning.
695 : //
696 : // These things are created frequently in many places. We *intentionally* do
697 : // not inialialize all members in order to save on construction overhead.
698 : // Some constructor pass more valid params than others. We init what must be
699 : // init'd and leave other members undefined. In debug builds the accessors
700 : // use a CHECK_STATE macro to track whether or not the object is in a valid
701 : // state to answer the question a caller might be asking. As long as this
702 : // class is maintained correctly it can do its job without a bunch of added
703 : // overhead from useless initializations and non-DEBUG error checking.
704 : //
705 : // Note that most accessors are inlined.
706 :
707 : class MOZ_STACK_CLASS XPCCallContext final : public nsAXPCNativeCallContext
708 : {
709 : public:
710 : NS_IMETHOD GetCallee(nsISupports** aResult);
711 : NS_IMETHOD GetCalleeMethodIndex(uint16_t* aResult);
712 : NS_IMETHOD GetJSContext(JSContext** aResult);
713 : NS_IMETHOD GetArgc(uint32_t* aResult);
714 : NS_IMETHOD GetArgvPtr(JS::Value** aResult);
715 : NS_IMETHOD GetCalleeInterface(nsIInterfaceInfo** aResult);
716 : NS_IMETHOD GetCalleeClassInfo(nsIClassInfo** aResult);
717 : NS_IMETHOD GetPreviousCallContext(nsAXPCNativeCallContext** aResult);
718 :
719 : enum {NO_ARGS = (unsigned) -1};
720 :
721 : explicit XPCCallContext(JSContext* cx,
722 : JS::HandleObject obj = nullptr,
723 : JS::HandleObject funobj = nullptr,
724 : JS::HandleId id = JSID_VOIDHANDLE,
725 : unsigned argc = NO_ARGS,
726 : JS::Value* argv = nullptr,
727 : JS::Value* rval = nullptr);
728 :
729 : virtual ~XPCCallContext();
730 :
731 : inline bool IsValid() const ;
732 :
733 : inline XPCJSContext* GetContext() const ;
734 : inline JSContext* GetJSContext() const ;
735 : inline bool GetContextPopRequired() const ;
736 : inline XPCCallContext* GetPrevCallContext() const ;
737 :
738 : inline JSObject* GetFlattenedJSObject() const ;
739 : inline nsISupports* GetIdentityObject() const ;
740 : inline XPCWrappedNative* GetWrapper() const ;
741 : inline XPCWrappedNativeProto* GetProto() const ;
742 :
743 : inline bool CanGetTearOff() const ;
744 : inline XPCWrappedNativeTearOff* GetTearOff() const ;
745 :
746 : inline nsIXPCScriptable* GetScriptable() const ;
747 : inline bool CanGetSet() const ;
748 : inline XPCNativeSet* GetSet() const ;
749 : inline bool CanGetInterface() const ;
750 : inline XPCNativeInterface* GetInterface() const ;
751 : inline XPCNativeMember* GetMember() const ;
752 : inline bool HasInterfaceAndMember() const ;
753 : inline jsid GetName() const ;
754 : inline bool GetStaticMemberIsLocal() const ;
755 : inline unsigned GetArgc() const ;
756 : inline JS::Value* GetArgv() const ;
757 : inline JS::Value* GetRetVal() const ;
758 :
759 : inline uint16_t GetMethodIndex() const ;
760 : inline void SetMethodIndex(uint16_t index) ;
761 :
762 : inline jsid GetResolveName() const;
763 : inline jsid SetResolveName(JS::HandleId name);
764 :
765 : inline XPCWrappedNative* GetResolvingWrapper() const;
766 : inline XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w);
767 :
768 : inline void SetRetVal(const JS::Value& val);
769 :
770 : void SetName(jsid name);
771 : void SetArgsAndResultPtr(unsigned argc, JS::Value* argv, JS::Value* rval);
772 : void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
773 : bool isSetter);
774 :
775 : nsresult CanCallNow();
776 :
777 : void SystemIsBeingShutDown();
778 :
779 82585 : operator JSContext*() const {return GetJSContext();}
780 :
781 : private:
782 :
783 : // no copy ctor or assignment allowed
784 : XPCCallContext(const XPCCallContext& r) = delete;
785 : XPCCallContext& operator= (const XPCCallContext& r) = delete;
786 :
787 : private:
788 : // posible values for mState
789 : enum State {
790 : INIT_FAILED,
791 : SYSTEM_SHUTDOWN,
792 : HAVE_CONTEXT,
793 : HAVE_OBJECT,
794 : HAVE_NAME,
795 : HAVE_ARGS,
796 : READY_TO_CALL,
797 : CALL_DONE
798 : };
799 :
800 : #ifdef DEBUG
801 420186 : inline void CHECK_STATE(int s) const {MOZ_ASSERT(mState >= s, "bad state");}
802 : #else
803 : #define CHECK_STATE(s) ((void)0)
804 : #endif
805 :
806 : private:
807 : JSAutoRequest mAr;
808 : State mState;
809 :
810 : RefPtr<nsXPConnect> mXPC;
811 :
812 : XPCJSContext* mXPCJSContext;
813 : JSContext* mJSContext;
814 :
815 : // ctor does not necessarily init the following. BEWARE!
816 :
817 : XPCCallContext* mPrevCallContext;
818 :
819 : XPCWrappedNative* mWrapper;
820 : XPCWrappedNativeTearOff* mTearOff;
821 :
822 : nsCOMPtr<nsIXPCScriptable> mScriptable;
823 :
824 : RefPtr<XPCNativeSet> mSet;
825 : RefPtr<XPCNativeInterface> mInterface;
826 : XPCNativeMember* mMember;
827 :
828 : JS::RootedId mName;
829 : bool mStaticMemberIsLocal;
830 :
831 : unsigned mArgc;
832 : JS::Value* mArgv;
833 : JS::Value* mRetVal;
834 :
835 : uint16_t mMethodIndex;
836 : };
837 :
838 : /***************************************************************************
839 : ****************************************************************************
840 : *
841 : * Core classes for wrapped native objects for use from JavaScript...
842 : *
843 : ****************************************************************************
844 : ***************************************************************************/
845 :
846 : // These are the various JSClasses and callbacks whose use that required
847 : // visibility from more than one .cpp file.
848 :
849 : extern const js::Class XPC_WN_NoHelper_JSClass;
850 : extern const js::Class XPC_WN_NoMods_Proto_JSClass;
851 : extern const js::Class XPC_WN_ModsAllowed_Proto_JSClass;
852 : extern const js::Class XPC_WN_Tearoff_JSClass;
853 : #define XPC_WN_TEAROFF_RESERVED_SLOTS 1
854 : #define XPC_WN_TEAROFF_FLAT_OBJECT_SLOT 0
855 : extern const js::Class XPC_WN_NoHelper_Proto_JSClass;
856 :
857 : extern bool
858 : XPC_WN_CallMethod(JSContext* cx, unsigned argc, JS::Value* vp);
859 :
860 : extern bool
861 : XPC_WN_GetterSetter(JSContext* cx, unsigned argc, JS::Value* vp);
862 :
863 : // Maybe this macro should check for class->enumerate ==
864 : // XPC_WN_Shared_Proto_Enumerate or something rather than checking for
865 : // 4 classes?
866 0 : static inline bool IS_PROTO_CLASS(const js::Class* clazz)
867 : {
868 0 : return clazz == &XPC_WN_NoMods_Proto_JSClass ||
869 0 : clazz == &XPC_WN_ModsAllowed_Proto_JSClass;
870 : }
871 :
872 : typedef js::HashSet<size_t,
873 : js::DefaultHasher<size_t>,
874 : js::SystemAllocPolicy> InterpositionWhitelist;
875 :
876 0 : struct InterpositionWhitelistPair {
877 : nsIAddonInterposition* interposition;
878 : InterpositionWhitelist whitelist;
879 : };
880 :
881 : typedef nsTArray<InterpositionWhitelistPair> InterpositionWhitelistArray;
882 :
883 : /***************************************************************************/
884 : // XPCWrappedNativeScope is one-to-one with a JS global object.
885 :
886 : class nsIAddonInterposition;
887 : class nsXPCComponentsBase;
888 : class XPCWrappedNativeScope final
889 : {
890 : public:
891 :
892 : XPCJSRuntime*
893 8007 : GetRuntime() const {return XPCJSRuntime::Get();}
894 :
895 : Native2WrappedNativeMap*
896 13718 : GetWrappedNativeMap() const {return mWrappedNativeMap;}
897 :
898 : ClassInfo2WrappedNativeProtoMap*
899 4378 : GetWrappedNativeProtoMap() const {return mWrappedNativeProtoMap;}
900 :
901 : nsXPCComponentsBase*
902 10 : GetComponents() const {return mComponents;}
903 :
904 : // Forces the creation of a privileged |Components| object, even in
905 : // content scopes. This will crash if used outside of automation.
906 : void
907 : ForcePrivilegedComponents();
908 :
909 : bool AttachComponentsObject(JSContext* aCx);
910 :
911 : // Returns the JS object reflection of the Components object.
912 : bool
913 : GetComponentsJSObject(JS::MutableHandleObject obj);
914 :
915 : JSObject*
916 10769 : GetGlobalJSObject() const {
917 10769 : return mGlobalJSObject;
918 : }
919 :
920 : JSObject*
921 24462 : GetGlobalJSObjectPreserveColor() const {return mGlobalJSObject.unbarrieredGet();}
922 :
923 : nsIPrincipal*
924 801 : GetPrincipal() const {
925 801 : JSCompartment* c = js::GetObjectCompartment(mGlobalJSObject);
926 801 : return nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
927 : }
928 :
929 : JSObject*
930 : GetExpandoChain(JS::HandleObject target);
931 :
932 : bool
933 : SetExpandoChain(JSContext* cx, JS::HandleObject target, JS::HandleObject chain);
934 :
935 : static void
936 : SystemIsBeingShutDown();
937 :
938 : static void
939 : TraceWrappedNativesInAllScopes(JSTracer* trc);
940 :
941 34 : void TraceSelf(JSTracer* trc) {
942 34 : MOZ_ASSERT(mGlobalJSObject);
943 34 : mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject");
944 34 : }
945 :
946 26 : void TraceInside(JSTracer* trc) {
947 26 : if (mContentXBLScope)
948 0 : mContentXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope");
949 26 : for (size_t i = 0; i < mAddonScopes.Length(); i++)
950 0 : mAddonScopes[i].trace(trc, "XPCWrappedNativeScope::mAddonScopes");
951 26 : if (mXrayExpandos.initialized())
952 0 : mXrayExpandos.trace(trc);
953 26 : }
954 :
955 : static void
956 : SuspectAllWrappers(nsCycleCollectionNoteRootCallback& cb);
957 :
958 : static void
959 : SweepAllWrappedNativeTearOffs();
960 :
961 : static void
962 : UpdateWeakPointersInAllScopesAfterGC();
963 :
964 : void
965 : UpdateWeakPointersAfterGC();
966 :
967 : static void
968 : KillDyingScopes();
969 :
970 : static void
971 : DebugDumpAllScopes(int16_t depth);
972 :
973 : void
974 : DebugDump(int16_t depth);
975 :
976 : struct ScopeSizeInfo {
977 0 : explicit ScopeSizeInfo(mozilla::MallocSizeOf mallocSizeOf)
978 0 : : mMallocSizeOf(mallocSizeOf),
979 : mScopeAndMapSize(0),
980 0 : mProtoAndIfaceCacheSize(0)
981 0 : {}
982 :
983 : mozilla::MallocSizeOf mMallocSizeOf;
984 : size_t mScopeAndMapSize;
985 : size_t mProtoAndIfaceCacheSize;
986 : };
987 :
988 : static void
989 : AddSizeOfAllScopesIncludingThis(ScopeSizeInfo* scopeSizeInfo);
990 :
991 : void
992 : AddSizeOfIncludingThis(ScopeSizeInfo* scopeSizeInfo);
993 :
994 : static bool
995 : IsDyingScope(XPCWrappedNativeScope* scope);
996 :
997 : typedef js::HashMap<JSAddonId*,
998 : nsCOMPtr<nsIAddonInterposition>,
999 : js::PointerHasher<JSAddonId*, 3>,
1000 : js::SystemAllocPolicy> InterpositionMap;
1001 :
1002 : typedef js::HashSet<JSAddonId*,
1003 : js::PointerHasher<JSAddonId*, 3>,
1004 : js::SystemAllocPolicy> AddonSet;
1005 :
1006 : // Gets the appropriate scope object for XBL in this scope. The context
1007 : // must be same-compartment with the global upon entering, and the scope
1008 : // object is wrapped into the compartment of the global.
1009 : JSObject* EnsureContentXBLScope(JSContext* cx);
1010 :
1011 : JSObject* EnsureAddonScope(JSContext* cx, JSAddonId* addonId);
1012 :
1013 : XPCWrappedNativeScope(JSContext* cx, JS::HandleObject aGlobal);
1014 :
1015 : nsAutoPtr<JSObject2JSObjectMap> mWaiverWrapperMap;
1016 :
1017 3627 : bool IsContentXBLScope() { return mIsContentXBLScope; }
1018 : bool AllowContentXBLScope();
1019 868 : bool UseContentXBLScope() { return mUseContentXBLScope; }
1020 1 : void ClearContentXBLScope() { mContentXBLScope = nullptr; }
1021 :
1022 3716 : bool IsAddonScope() { return mIsAddonScope; }
1023 :
1024 12063 : bool HasInterposition() { return mInterposition; }
1025 : nsCOMPtr<nsIAddonInterposition> GetInterposition();
1026 :
1027 : static bool SetAddonInterposition(JSContext* cx,
1028 : JSAddonId* addonId,
1029 : nsIAddonInterposition* interp);
1030 :
1031 : static InterpositionWhitelist* GetInterpositionWhitelist(nsIAddonInterposition* interposition);
1032 : static bool UpdateInterpositionWhitelist(JSContext* cx,
1033 : nsIAddonInterposition* interposition);
1034 :
1035 0 : void SetAddonCallInterposition() { mHasCallInterpositions = true; }
1036 0 : bool HasCallInterposition() { return mHasCallInterpositions; };
1037 :
1038 : static bool AllowCPOWsInAddon(JSContext* cx, JSAddonId* addonId, bool allow);
1039 :
1040 : protected:
1041 : virtual ~XPCWrappedNativeScope();
1042 :
1043 : XPCWrappedNativeScope() = delete;
1044 :
1045 : private:
1046 0 : class ClearInterpositionsObserver final : public nsIObserver {
1047 0 : ~ClearInterpositionsObserver() {}
1048 :
1049 : public:
1050 : NS_DECL_ISUPPORTS
1051 : NS_DECL_NSIOBSERVER
1052 : };
1053 :
1054 : static XPCWrappedNativeScope* gScopes;
1055 : static XPCWrappedNativeScope* gDyingScopes;
1056 :
1057 : static bool gShutdownObserverInitialized;
1058 : static InterpositionMap* gInterpositionMap;
1059 : static AddonSet* gAllowCPOWAddonSet;
1060 :
1061 : static InterpositionWhitelistArray* gInterpositionWhitelists;
1062 :
1063 : Native2WrappedNativeMap* mWrappedNativeMap;
1064 : ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap;
1065 : RefPtr<nsXPCComponentsBase> mComponents;
1066 : XPCWrappedNativeScope* mNext;
1067 : // The JS global object for this scope. If non-null, this will be the
1068 : // default parent for the XPCWrappedNatives that have us as the scope,
1069 : // unless a PreCreate hook overrides it. Note that this _may_ be null (see
1070 : // constructor).
1071 : JS::ObjectPtr mGlobalJSObject;
1072 :
1073 : // XBL Scope. This is is a lazily-created sandbox for non-system scopes.
1074 : // EnsureContentXBLScope() decides whether it needs to be created or not.
1075 : // This reference is wrapped into the compartment of mGlobalJSObject.
1076 : JS::ObjectPtr mContentXBLScope;
1077 :
1078 : // Lazily created sandboxes for addon code.
1079 : nsTArray<JS::ObjectPtr> mAddonScopes;
1080 :
1081 : // This is a service that will be use to interpose on some property accesses on
1082 : // objects from other scope, for add-on compatibility reasons.
1083 : nsCOMPtr<nsIAddonInterposition> mInterposition;
1084 :
1085 : // If this flag is set, we intercept function calls on vanilla JS function objects
1086 : // from this scope if the caller scope has mInterposition set.
1087 : bool mHasCallInterpositions;
1088 :
1089 : JS::WeakMapPtr<JSObject*, JSObject*> mXrayExpandos;
1090 :
1091 : bool mIsContentXBLScope;
1092 : bool mIsAddonScope;
1093 :
1094 : // For remote XUL domains, we run all XBL in the content scope for compat
1095 : // reasons (though we sometimes pref this off for automation). We separately
1096 : // track the result of this decision (mAllowContentXBLScope), from the decision
1097 : // of whether to actually _use_ an XBL scope (mUseContentXBLScope), which depends
1098 : // on the type of global and whether the compartment is system principal
1099 : // or not.
1100 : //
1101 : // This distinction is useful primarily because, if true, we know that we
1102 : // have no way of distinguishing XBL script from content script for the
1103 : // given scope. In these (unsupported) situations, we just always claim to
1104 : // be XBL.
1105 : bool mAllowContentXBLScope;
1106 : bool mUseContentXBLScope;
1107 : };
1108 :
1109 : /***************************************************************************/
1110 : // Slots we use for our functions
1111 : #define XPC_FUNCTION_NATIVE_MEMBER_SLOT 0
1112 : #define XPC_FUNCTION_PARENT_OBJECT_SLOT 1
1113 :
1114 : /***************************************************************************/
1115 : // XPCNativeMember represents a single idl declared method, attribute or
1116 : // constant.
1117 :
1118 : // Tight. No virtual methods. Can be bitwise copied (until any resolution done).
1119 :
1120 : class XPCNativeMember final
1121 : {
1122 : public:
1123 : static bool GetCallInfo(JSObject* funobj,
1124 : RefPtr<XPCNativeInterface>* pInterface,
1125 : XPCNativeMember** pMember);
1126 :
1127 137145 : jsid GetName() const {return mName;}
1128 :
1129 16233 : uint16_t GetIndex() const {return mIndex;}
1130 :
1131 199 : bool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
1132 : JS::Value* pval)
1133 199 : {MOZ_ASSERT(IsConstant(),
1134 : "Only call this if you're sure this is a constant!");
1135 199 : return Resolve(ccx, iface, nullptr, pval);}
1136 :
1137 : bool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface,
1138 : JS::HandleObject parent, JS::Value* pval);
1139 :
1140 6354 : bool IsMethod() const
1141 6354 : {return 0 != (mFlags & METHOD);}
1142 :
1143 13536 : bool IsConstant() const
1144 13536 : {return 0 != (mFlags & CONSTANT);}
1145 :
1146 1926 : bool IsAttribute() const
1147 1926 : {return 0 != (mFlags & GETTER);}
1148 :
1149 1964 : bool IsWritableAttribute() const
1150 1964 : {return 0 != (mFlags & SETTER_TOO);}
1151 :
1152 550 : bool IsReadOnlyAttribute() const
1153 550 : {return IsAttribute() && !IsWritableAttribute();}
1154 :
1155 :
1156 13315 : void SetName(jsid a) {mName = a;}
1157 :
1158 7597 : void SetMethod(uint16_t index)
1159 7597 : {mFlags = METHOD; mIndex = index;}
1160 :
1161 3815 : void SetConstant(uint16_t index)
1162 3815 : {mFlags = CONSTANT; mIndex = index;}
1163 :
1164 1903 : void SetReadOnlyAttribute(uint16_t index)
1165 1903 : {mFlags = GETTER; mIndex = index;}
1166 :
1167 550 : void SetWritableAttribute()
1168 550 : {MOZ_ASSERT(mFlags == GETTER,"bad"); mFlags = GETTER | SETTER_TOO;}
1169 :
1170 13315 : static uint16_t GetMaxIndexInInterface()
1171 13315 : {return (1<<12) - 1;}
1172 :
1173 : inline XPCNativeInterface* GetInterface() const;
1174 :
1175 13315 : void SetIndexInInterface(uint16_t index)
1176 13315 : {mIndexInInterface = index;}
1177 :
1178 : /* default ctor - leave random contents */
1179 40187 : XPCNativeMember() {MOZ_COUNT_CTOR(XPCNativeMember);}
1180 39919 : ~XPCNativeMember() {MOZ_COUNT_DTOR(XPCNativeMember);}
1181 :
1182 : private:
1183 : bool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
1184 : JS::HandleObject parent, JS::Value* vp);
1185 :
1186 : enum {
1187 : METHOD = 0x01,
1188 : CONSTANT = 0x02,
1189 : GETTER = 0x04,
1190 : SETTER_TOO = 0x08
1191 : // If you add a flag here, you may need to make mFlags wider and either
1192 : // make mIndexInInterface narrower (and adjust
1193 : // XPCNativeInterface::NewInstance accordingly) or make this object
1194 : // bigger.
1195 : };
1196 :
1197 : private:
1198 : // our only data...
1199 : jsid mName;
1200 : uint16_t mIndex;
1201 : // mFlags needs to be wide enogh to hold the flags in the above enum.
1202 : uint16_t mFlags : 4;
1203 : // mIndexInInterface is the index of this in our XPCNativeInterface's
1204 : // mMembers. In theory our XPCNativeInterface could have as many as 2^15-1
1205 : // members (since mMemberCount is 15-bit) but in practice we prevent
1206 : // creation of XPCNativeInterfaces which have more than 2^12 members.
1207 : // If the width of this field changes, update GetMaxIndexInInterface.
1208 : uint16_t mIndexInInterface : 12;
1209 : } JS_HAZ_NON_GC_POINTER; // Only stores a pinned string
1210 :
1211 : /***************************************************************************/
1212 : // XPCNativeInterface represents a single idl declared interface. This is
1213 : // primarily the set of XPCNativeMembers.
1214 :
1215 : // Tight. No virtual methods.
1216 :
1217 : class XPCNativeInterface final
1218 : {
1219 : public:
1220 99850 : NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeInterface,
1221 : DestroyInstance(this))
1222 :
1223 : static already_AddRefed<XPCNativeInterface> GetNewOrUsed(const nsIID* iid);
1224 : static already_AddRefed<XPCNativeInterface> GetNewOrUsed(nsIInterfaceInfo* info);
1225 : static already_AddRefed<XPCNativeInterface> GetNewOrUsed(const char* name);
1226 : static already_AddRefed<XPCNativeInterface> GetISupports();
1227 :
1228 13576 : inline nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo.get();}
1229 21517 : inline jsid GetName() const {return mName;}
1230 :
1231 : inline const nsIID* GetIID() const;
1232 : inline const char* GetNameString() const;
1233 : inline XPCNativeMember* FindMember(jsid name) const;
1234 :
1235 : inline bool HasAncestor(const nsIID* iid) const;
1236 : static inline size_t OffsetOfMembers();
1237 :
1238 992 : uint16_t GetMemberCount() const {
1239 992 : return mMemberCount;
1240 : }
1241 132 : XPCNativeMember* GetMemberAt(uint16_t i) {
1242 132 : MOZ_ASSERT(i < mMemberCount, "bad index");
1243 132 : return &mMembers[i];
1244 : }
1245 :
1246 : void DebugDump(int16_t depth);
1247 :
1248 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
1249 :
1250 : protected:
1251 : static already_AddRefed<XPCNativeInterface> NewInstance(nsIInterfaceInfo* aInfo);
1252 :
1253 : XPCNativeInterface() = delete;
1254 1825 : XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName)
1255 1825 : : mInfo(aInfo), mName(aName), mMemberCount(0)
1256 1825 : {}
1257 : ~XPCNativeInterface();
1258 :
1259 1825 : void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
1260 :
1261 : XPCNativeInterface(const XPCNativeInterface& r) = delete;
1262 : XPCNativeInterface& operator= (const XPCNativeInterface& r) = delete;
1263 :
1264 : static void DestroyInstance(XPCNativeInterface* inst);
1265 :
1266 : private:
1267 : nsCOMPtr<nsIInterfaceInfo> mInfo;
1268 : jsid mName;
1269 : uint16_t mMemberCount;
1270 : XPCNativeMember mMembers[1]; // always last - object sized for array
1271 : };
1272 :
1273 : /***************************************************************************/
1274 : // XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap.
1275 : // It represents a new XPCNativeSet we are considering constructing, without
1276 : // requiring that the set actually be built.
1277 :
1278 : class MOZ_STACK_CLASS XPCNativeSetKey final
1279 : {
1280 : public:
1281 : // This represents an existing set |baseSet|.
1282 1316 : explicit XPCNativeSetKey(XPCNativeSet* baseSet)
1283 1316 : : mBaseSet(baseSet), mAddition(nullptr)
1284 : {
1285 1316 : MOZ_ASSERT(baseSet);
1286 1316 : }
1287 :
1288 : // This represents a new set containing only nsISupports and
1289 : // |addition|.
1290 1707 : explicit XPCNativeSetKey(XPCNativeInterface* addition)
1291 1707 : : mBaseSet(nullptr), mAddition(addition)
1292 : {
1293 1707 : MOZ_ASSERT(addition);
1294 1707 : }
1295 :
1296 : // This represents the existing set |baseSet| with the interface
1297 : // |addition| inserted after existing interfaces. |addition| must
1298 : // not already be present in |baseSet|.
1299 : explicit XPCNativeSetKey(XPCNativeSet* baseSet,
1300 : XPCNativeInterface* addition);
1301 3258 : ~XPCNativeSetKey() {}
1302 :
1303 2706 : XPCNativeSet* GetBaseSet() const {return mBaseSet;}
1304 2649 : XPCNativeInterface* GetAddition() const {return mAddition;}
1305 :
1306 : PLDHashNumber Hash() const;
1307 :
1308 : // Allow shallow copy
1309 :
1310 : private:
1311 : RefPtr<XPCNativeSet> mBaseSet;
1312 : RefPtr<XPCNativeInterface> mAddition;
1313 : };
1314 :
1315 : /***************************************************************************/
1316 : // XPCNativeSet represents an ordered collection of XPCNativeInterface pointers.
1317 :
1318 : class XPCNativeSet final
1319 : {
1320 : public:
1321 51906 : NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeSet,
1322 : DestroyInstance(this))
1323 :
1324 : static already_AddRefed<XPCNativeSet> GetNewOrUsed(const nsIID* iid);
1325 : static already_AddRefed<XPCNativeSet> GetNewOrUsed(nsIClassInfo* classInfo);
1326 : static already_AddRefed<XPCNativeSet> GetNewOrUsed(XPCNativeSetKey* key);
1327 :
1328 : // This generates a union set.
1329 : //
1330 : // If preserveFirstSetOrder is true, the elements from |firstSet| come first,
1331 : // followed by any non-duplicate items from |secondSet|. If false, the same
1332 : // algorithm is applied; but if we detect that |secondSet| is a superset of
1333 : // |firstSet|, we return |secondSet| without worrying about whether the
1334 : // ordering might differ from |firstSet|.
1335 : static already_AddRefed<XPCNativeSet> GetNewOrUsed(XPCNativeSet* firstSet,
1336 : XPCNativeSet* secondSet,
1337 : bool preserveFirstSetOrder);
1338 :
1339 : static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
1340 :
1341 : inline bool FindMember(jsid name, XPCNativeMember** pMember,
1342 : uint16_t* pInterfaceIndex) const;
1343 :
1344 : inline bool FindMember(jsid name, XPCNativeMember** pMember,
1345 : RefPtr<XPCNativeInterface>* pInterface) const;
1346 :
1347 : inline bool FindMember(JS::HandleId name,
1348 : XPCNativeMember** pMember,
1349 : RefPtr<XPCNativeInterface>* pInterface,
1350 : XPCNativeSet* protoSet,
1351 : bool* pIsLocal) const;
1352 :
1353 : inline bool HasInterface(XPCNativeInterface* aInterface) const;
1354 : inline bool HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const;
1355 : inline bool HasInterfaceWithAncestor(const nsIID* iid) const;
1356 :
1357 : inline XPCNativeInterface* FindInterfaceWithIID(const nsIID& iid) const;
1358 :
1359 : inline XPCNativeInterface* FindNamedInterface(jsid name) const;
1360 :
1361 57 : uint16_t GetMemberCount() const {
1362 57 : return mMemberCount;
1363 : }
1364 5631 : uint16_t GetInterfaceCount() const {
1365 5631 : return mInterfaceCount;
1366 : }
1367 3357 : XPCNativeInterface** GetInterfaceArray() {
1368 3357 : return mInterfaces;
1369 : }
1370 :
1371 1519 : XPCNativeInterface* GetInterfaceAt(uint16_t i)
1372 1519 : {MOZ_ASSERT(i < mInterfaceCount, "bad index"); return mInterfaces[i];}
1373 :
1374 : inline bool MatchesSetUpToInterface(const XPCNativeSet* other,
1375 : XPCNativeInterface* iface) const;
1376 :
1377 : void DebugDump(int16_t depth);
1378 :
1379 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
1380 :
1381 : protected:
1382 : static already_AddRefed<XPCNativeSet> NewInstance(nsTArray<RefPtr<XPCNativeInterface>>&& array);
1383 : static already_AddRefed<XPCNativeSet> NewInstanceMutate(XPCNativeSetKey* key);
1384 :
1385 940 : XPCNativeSet()
1386 940 : : mMemberCount(0), mInterfaceCount(0)
1387 940 : {}
1388 : ~XPCNativeSet();
1389 940 : void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
1390 :
1391 : static void DestroyInstance(XPCNativeSet* inst);
1392 :
1393 : private:
1394 : uint16_t mMemberCount;
1395 : uint16_t mInterfaceCount;
1396 : // Always last - object sized for array.
1397 : // These are strong references.
1398 : XPCNativeInterface* mInterfaces[1];
1399 : };
1400 :
1401 : /***********************************************/
1402 : // XPCWrappedNativeProto hold the additional shared wrapper data
1403 : // for XPCWrappedNative whose native objects expose nsIClassInfo.
1404 :
1405 : class XPCWrappedNativeProto final
1406 : {
1407 : public:
1408 : static XPCWrappedNativeProto*
1409 : GetNewOrUsed(XPCWrappedNativeScope* scope,
1410 : nsIClassInfo* classInfo,
1411 : nsIXPCScriptable* scriptable,
1412 : bool callPostCreatePrototype = true);
1413 :
1414 : XPCWrappedNativeScope*
1415 4092 : GetScope() const {return mScope;}
1416 :
1417 : XPCJSRuntime*
1418 0 : GetRuntime() const {return mScope->GetRuntime();}
1419 :
1420 : JSObject*
1421 4638 : GetJSProtoObject() const { return mJSProtoObject; }
1422 :
1423 : JSObject*
1424 0 : GetJSProtoObjectPreserveColor() const { return mJSProtoObject.unbarrieredGet(); }
1425 :
1426 : nsIClassInfo*
1427 5905 : GetClassInfo() const {return mClassInfo;}
1428 :
1429 : XPCNativeSet*
1430 28285 : GetSet() const {return mSet;}
1431 :
1432 : nsIXPCScriptable*
1433 3891 : GetScriptable() const { return mScriptable; }
1434 :
1435 : bool CallPostCreatePrototype();
1436 : void JSProtoObjectFinalized(js::FreeOp* fop, JSObject* obj);
1437 : void JSProtoObjectMoved(JSObject* obj, const JSObject* old);
1438 :
1439 : void SystemIsBeingShutDown();
1440 :
1441 : void DebugDump(int16_t depth);
1442 :
1443 173 : void TraceSelf(JSTracer* trc) {
1444 173 : if (mJSProtoObject)
1445 173 : mJSProtoObject.trace(trc, "XPCWrappedNativeProto::mJSProtoObject");
1446 173 : }
1447 :
1448 24 : void TraceInside(JSTracer* trc) {
1449 24 : GetScope()->TraceSelf(trc);
1450 24 : }
1451 :
1452 0 : void TraceJS(JSTracer* trc) {
1453 0 : TraceSelf(trc);
1454 0 : TraceInside(trc);
1455 0 : }
1456 :
1457 : void WriteBarrierPre(JSContext* cx)
1458 : {
1459 : if (JS::IsIncrementalBarrierNeeded(cx) && mJSProtoObject)
1460 : mJSProtoObject.writeBarrierPre(cx);
1461 : }
1462 :
1463 : // NOP. This is just here to make the AutoMarkingPtr code compile.
1464 0 : void Mark() const {}
1465 0 : inline void AutoTrace(JSTracer* trc) {}
1466 :
1467 : ~XPCWrappedNativeProto();
1468 :
1469 : protected:
1470 : // disable copy ctor and assignment
1471 : XPCWrappedNativeProto(const XPCWrappedNativeProto& r) = delete;
1472 : XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r) = delete;
1473 :
1474 : // hide ctor
1475 : XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
1476 : nsIClassInfo* ClassInfo,
1477 : already_AddRefed<XPCNativeSet>&& Set);
1478 :
1479 : bool Init(nsIXPCScriptable* scriptable, bool callPostCreatePrototype);
1480 :
1481 : private:
1482 : #ifdef DEBUG
1483 : static int32_t gDEBUG_LiveProtoCount;
1484 : #endif
1485 :
1486 : private:
1487 : XPCWrappedNativeScope* mScope;
1488 : JS::ObjectPtr mJSProtoObject;
1489 : nsCOMPtr<nsIClassInfo> mClassInfo;
1490 : RefPtr<XPCNativeSet> mSet;
1491 : nsCOMPtr<nsIXPCScriptable> mScriptable;
1492 : };
1493 :
1494 : /***********************************************/
1495 : // XPCWrappedNativeTearOff represents the info needed to make calls to one
1496 : // interface on the underlying native object of a XPCWrappedNative.
1497 :
1498 : class XPCWrappedNativeTearOff final
1499 : {
1500 : public:
1501 18093 : bool IsAvailable() const {return mInterface == nullptr;}
1502 : bool IsReserved() const {return mInterface == (XPCNativeInterface*)1;}
1503 : bool IsValid() const {return !IsAvailable() && !IsReserved();}
1504 7716 : void SetReserved() {mInterface = (XPCNativeInterface*)1;}
1505 :
1506 42708 : XPCNativeInterface* GetInterface() const {return mInterface;}
1507 11998 : nsISupports* GetNative() const {return mNative;}
1508 : JSObject* GetJSObject();
1509 : JSObject* GetJSObjectPreserveColor() const;
1510 7716 : void SetInterface(XPCNativeInterface* Interface) {mInterface = Interface;}
1511 7707 : void SetNative(nsISupports* Native) {mNative = Native;}
1512 0 : already_AddRefed<nsISupports> TakeNative() { return mNative.forget(); }
1513 : void SetJSObject(JSObject* JSObj);
1514 :
1515 0 : void JSObjectFinalized() {SetJSObject(nullptr);}
1516 : void JSObjectMoved(JSObject* obj, const JSObject* old);
1517 :
1518 7716 : XPCWrappedNativeTearOff()
1519 7716 : : mInterface(nullptr), mJSObject(nullptr)
1520 : {
1521 7716 : MOZ_COUNT_CTOR(XPCWrappedNativeTearOff);
1522 7716 : }
1523 : ~XPCWrappedNativeTearOff();
1524 :
1525 : // NOP. This is just here to make the AutoMarkingPtr code compile.
1526 0 : inline void TraceJS(JSTracer* trc) {}
1527 0 : inline void AutoTrace(JSTracer* trc) {}
1528 :
1529 0 : void Mark() {mJSObject.setFlags(1);}
1530 7719 : void Unmark() {mJSObject.unsetFlags(1);}
1531 0 : bool IsMarked() const {return mJSObject.hasFlag(1);}
1532 :
1533 2005 : XPCWrappedNativeTearOff* AddTearOff()
1534 : {
1535 2005 : MOZ_ASSERT(!mNextTearOff);
1536 2005 : mNextTearOff = mozilla::MakeUnique<XPCWrappedNativeTearOff>();
1537 2005 : return mNextTearOff.get();
1538 : }
1539 :
1540 18093 : XPCWrappedNativeTearOff* GetNextTearOff() {return mNextTearOff.get();}
1541 :
1542 : private:
1543 : XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) = delete;
1544 : XPCWrappedNativeTearOff& operator= (const XPCWrappedNativeTearOff& r) = delete;
1545 :
1546 : private:
1547 : XPCNativeInterface* mInterface;
1548 : // mNative is an nsRefPtr not an nsCOMPtr because it may not be the canonical
1549 : // nsISupports pointer.
1550 : RefPtr<nsISupports> mNative;
1551 : JS::TenuredHeap<JSObject*> mJSObject;
1552 : mozilla::UniquePtr<XPCWrappedNativeTearOff> mNextTearOff;
1553 : };
1554 :
1555 :
1556 : /***************************************************************************/
1557 : // XPCWrappedNative the wrapper around one instance of a native xpcom object
1558 : // to be used from JavaScript.
1559 :
1560 : class XPCWrappedNative final : public nsIXPConnectWrappedNative
1561 : {
1562 : public:
1563 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
1564 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
1565 : NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
1566 :
1567 48048 : NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
1568 :
1569 : nsIPrincipal* GetObjectPrincipal() const;
1570 :
1571 : bool
1572 62850 : IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); }
1573 :
1574 : #define XPC_SCOPE_WORD(s) (intptr_t(s))
1575 : #define XPC_SCOPE_MASK (intptr_t(0x3))
1576 : #define XPC_SCOPE_TAG (intptr_t(0x1))
1577 : #define XPC_WRAPPER_EXPIRED (intptr_t(0x2))
1578 :
1579 : static inline bool
1580 69797 : IsTaggedScope(XPCWrappedNativeScope* s)
1581 69797 : {return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;}
1582 :
1583 : static inline XPCWrappedNativeScope*
1584 1333 : TagScope(XPCWrappedNativeScope* s)
1585 1333 : {MOZ_ASSERT(!IsTaggedScope(s), "bad pointer!");
1586 1333 : return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) | XPC_SCOPE_TAG);}
1587 :
1588 : static inline XPCWrappedNativeScope*
1589 : UnTagScope(XPCWrappedNativeScope* s)
1590 : {return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) & ~XPC_SCOPE_TAG);}
1591 :
1592 : inline bool
1593 2 : IsWrapperExpired() const
1594 2 : {return XPC_SCOPE_WORD(mMaybeScope) & XPC_WRAPPER_EXPIRED;}
1595 :
1596 : bool
1597 68464 : HasProto() const {return !IsTaggedScope(mMaybeScope);}
1598 :
1599 : XPCWrappedNativeProto*
1600 32083 : GetProto() const
1601 62648 : {return HasProto() ?
1602 : (XPCWrappedNativeProto*)
1603 62648 : (XPC_SCOPE_WORD(mMaybeProto) & ~XPC_SCOPE_MASK) : nullptr;}
1604 :
1605 : XPCWrappedNativeScope*
1606 1695 : GetScope() const
1607 3213 : {return GetProto() ? GetProto()->GetScope() :
1608 : (XPCWrappedNativeScope*)
1609 3213 : (XPC_SCOPE_WORD(mMaybeScope) & ~XPC_SCOPE_MASK);}
1610 :
1611 : nsISupports*
1612 17937 : GetIdentityObject() const {return mIdentity;}
1613 :
1614 : /**
1615 : * This getter clears the gray bit before handing out the JSObject which
1616 : * means that the object is guaranteed to be kept alive past the next CC.
1617 : */
1618 33427 : JSObject* GetFlatJSObject() const { return mFlatJSObject; }
1619 :
1620 : /**
1621 : * This getter does not change the color of the JSObject meaning that the
1622 : * object returned is not guaranteed to be kept alive past the next CC.
1623 : *
1624 : * This should only be called if you are certain that the return value won't
1625 : * be passed into a JS API function and that it won't be stored without
1626 : * being rooted (or otherwise signaling the stored value to the CC).
1627 : */
1628 : JSObject*
1629 0 : GetFlatJSObjectPreserveColor() const {
1630 0 : return mFlatJSObject.unbarrieredGetPtr();
1631 : }
1632 :
1633 : XPCNativeSet*
1634 43169 : GetSet() const {return mSet;}
1635 :
1636 : void
1637 2768 : SetSet(already_AddRefed<XPCNativeSet> set) {mSet = set;}
1638 :
1639 50779 : static XPCWrappedNative* Get(JSObject* obj) {
1640 50779 : MOZ_ASSERT(IS_WN_REFLECTOR(obj));
1641 50779 : return (XPCWrappedNative*)js::GetObjectPrivate(obj);
1642 : }
1643 :
1644 : private:
1645 : inline void
1646 0 : ExpireWrapper()
1647 0 : {mMaybeScope = (XPCWrappedNativeScope*)
1648 0 : (XPC_SCOPE_WORD(mMaybeScope) | XPC_WRAPPER_EXPIRED);}
1649 :
1650 : public:
1651 :
1652 : nsIXPCScriptable*
1653 59460 : GetScriptable() const { return mScriptable; }
1654 :
1655 : nsIClassInfo*
1656 13616 : GetClassInfo() const {return IsValid() && HasProto() ?
1657 13616 : GetProto()->GetClassInfo() : nullptr;}
1658 :
1659 : bool
1660 36230 : HasMutatedSet() const {return IsValid() &&
1661 35632 : (!HasProto() ||
1662 35632 : GetSet() != GetProto()->GetSet());}
1663 :
1664 : XPCJSRuntime*
1665 0 : GetRuntime() const {XPCWrappedNativeScope* scope = GetScope();
1666 0 : return scope ? scope->GetRuntime() : nullptr;}
1667 :
1668 : static nsresult
1669 : WrapNewGlobal(xpcObjectHelper& nativeHelper,
1670 : nsIPrincipal* principal, bool initStandardClasses,
1671 : JS::CompartmentOptions& aOptions,
1672 : XPCWrappedNative** wrappedGlobal);
1673 :
1674 : static nsresult
1675 : GetNewOrUsed(xpcObjectHelper& helper,
1676 : XPCWrappedNativeScope* Scope,
1677 : XPCNativeInterface* Interface,
1678 : XPCWrappedNative** wrapper);
1679 :
1680 : static nsresult
1681 : GetUsedOnly(nsISupports* Object,
1682 : XPCWrappedNativeScope* Scope,
1683 : XPCNativeInterface* Interface,
1684 : XPCWrappedNative** wrapper);
1685 :
1686 : void FlatJSObjectFinalized();
1687 : void FlatJSObjectMoved(JSObject* obj, const JSObject* old);
1688 :
1689 : void SystemIsBeingShutDown();
1690 :
1691 : enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
1692 :
1693 : static bool CallMethod(XPCCallContext& ccx,
1694 : CallMode mode = CALL_METHOD);
1695 :
1696 2865 : static bool GetAttribute(XPCCallContext& ccx)
1697 2865 : {return CallMethod(ccx, CALL_GETTER);}
1698 :
1699 38 : static bool SetAttribute(XPCCallContext& ccx)
1700 38 : {return CallMethod(ccx, CALL_SETTER);}
1701 :
1702 : inline bool HasInterfaceNoQI(const nsIID& iid);
1703 :
1704 : XPCWrappedNativeTearOff* FindTearOff(XPCNativeInterface* aInterface,
1705 : bool needJSObject = false,
1706 : nsresult* pError = nullptr);
1707 : XPCWrappedNativeTearOff* FindTearOff(const nsIID& iid);
1708 :
1709 0 : void Mark() const {}
1710 :
1711 183 : inline void TraceInside(JSTracer* trc) {
1712 183 : if (HasProto())
1713 173 : GetProto()->TraceSelf(trc);
1714 : else
1715 10 : GetScope()->TraceSelf(trc);
1716 :
1717 183 : JSObject* obj = mFlatJSObject.unbarrieredGetPtr();
1718 183 : if (obj && JS_IsGlobalObject(obj)) {
1719 0 : xpc::TraceXPCGlobal(trc, obj);
1720 : }
1721 183 : }
1722 :
1723 0 : void TraceJS(JSTracer* trc) {
1724 0 : TraceInside(trc);
1725 0 : }
1726 :
1727 2 : void TraceSelf(JSTracer* trc) {
1728 : // If this got called, we're being kept alive by someone who really
1729 : // needs us alive and whole. Do not let our mFlatJSObject go away.
1730 : // This is the only time we should be tracing our mFlatJSObject,
1731 : // normally somebody else is doing that.
1732 2 : JS::TraceEdge(trc, &mFlatJSObject, "XPCWrappedNative::mFlatJSObject");
1733 2 : }
1734 :
1735 : static void Trace(JSTracer* trc, JSObject* obj);
1736 :
1737 0 : void AutoTrace(JSTracer* trc) {
1738 0 : TraceSelf(trc);
1739 0 : }
1740 :
1741 : inline void SweepTearOffs();
1742 :
1743 : // Returns a string that shuld be free'd using JS_smprintf_free (or null).
1744 : char* ToString(XPCWrappedNativeTearOff* to = nullptr) const;
1745 :
1746 : static nsIXPCScriptable* GatherProtoScriptable(nsIClassInfo* classInfo);
1747 :
1748 4476 : bool HasExternalReference() const {return mRefCnt > 1;}
1749 :
1750 : void Suspect(nsCycleCollectionNoteRootCallback& cb);
1751 : void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
1752 :
1753 : // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
1754 : protected:
1755 : XPCWrappedNative() = delete;
1756 :
1757 : // This ctor is used if this object will have a proto.
1758 : XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
1759 : XPCWrappedNativeProto* aProto);
1760 :
1761 : // This ctor is used if this object will NOT have a proto.
1762 : XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
1763 : XPCWrappedNativeScope* aScope,
1764 : already_AddRefed<XPCNativeSet>&& aSet);
1765 :
1766 : virtual ~XPCWrappedNative();
1767 : void Destroy();
1768 :
1769 : private:
1770 : enum {
1771 : // Flags bits for mFlatJSObject:
1772 : FLAT_JS_OBJECT_VALID = JS_BIT(0)
1773 : };
1774 :
1775 : bool Init(nsIXPCScriptable* scriptable);
1776 : bool FinishInit();
1777 :
1778 : bool ExtendSet(XPCNativeInterface* aInterface);
1779 :
1780 : nsresult InitTearOff(XPCWrappedNativeTearOff* aTearOff,
1781 : XPCNativeInterface* aInterface,
1782 : bool needJSObject);
1783 :
1784 : bool InitTearOffJSObject(XPCWrappedNativeTearOff* to);
1785 :
1786 : public:
1787 : static void GatherScriptable(nsISupports* obj,
1788 : nsIClassInfo* classInfo,
1789 : nsIXPCScriptable** scrProto,
1790 : nsIXPCScriptable** scrWrapper);
1791 :
1792 : private:
1793 : union
1794 : {
1795 : XPCWrappedNativeScope* mMaybeScope;
1796 : XPCWrappedNativeProto* mMaybeProto;
1797 : };
1798 : RefPtr<XPCNativeSet> mSet;
1799 : JS::TenuredHeap<JSObject*> mFlatJSObject;
1800 : nsCOMPtr<nsIXPCScriptable> mScriptable;
1801 : XPCWrappedNativeTearOff mFirstTearOff;
1802 : };
1803 :
1804 : /***************************************************************************
1805 : ****************************************************************************
1806 : *
1807 : * Core classes for wrapped JSObject for use from native code...
1808 : *
1809 : ****************************************************************************
1810 : ***************************************************************************/
1811 :
1812 : // this interfaces exists so we can refcount nsXPCWrappedJSClass
1813 : // {2453EBA0-A9B8-11d2-BA64-00805F8A5DD7}
1814 : #define NS_IXPCONNECT_WRAPPED_JS_CLASS_IID \
1815 : { 0x2453eba0, 0xa9b8, 0x11d2, \
1816 : { 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
1817 :
1818 92 : class nsIXPCWrappedJSClass : public nsISupports
1819 : {
1820 : public:
1821 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
1822 : NS_IMETHOD DebugDump(int16_t depth) = 0;
1823 : };
1824 :
1825 : NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPCWrappedJSClass,
1826 : NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
1827 :
1828 : /*************************/
1829 : // nsXPCWrappedJSClass represents the sharable factored out common code and
1830 : // data for nsXPCWrappedJS instances for the same interface type.
1831 :
1832 : class nsXPCWrappedJSClass final : public nsIXPCWrappedJSClass
1833 : {
1834 : // all the interface method declarations...
1835 : NS_DECL_ISUPPORTS
1836 : NS_IMETHOD DebugDump(int16_t depth) override;
1837 : public:
1838 :
1839 : static already_AddRefed<nsXPCWrappedJSClass>
1840 : GetNewOrUsed(JSContext* cx,
1841 : REFNSIID aIID,
1842 : bool allowNonScriptable = false);
1843 :
1844 3875 : REFNSIID GetIID() const {return mIID;}
1845 976 : XPCJSRuntime* GetRuntime() const {return mRuntime;}
1846 1057 : nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
1847 : const char* GetInterfaceName();
1848 :
1849 : static bool IsWrappedJS(nsISupports* aPtr);
1850 :
1851 : NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
1852 : void** aInstancePtr);
1853 :
1854 : JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj);
1855 :
1856 : NS_IMETHOD CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
1857 : const XPTMethodDescriptor* info,
1858 : nsXPTCMiniVariant* params);
1859 :
1860 : JSObject* CallQueryInterfaceOnJSObject(JSContext* cx,
1861 : JSObject* jsobj, REFNSIID aIID);
1862 :
1863 : static nsresult BuildPropertyEnumerator(XPCCallContext& ccx,
1864 : JSObject* aJSObj,
1865 : nsISimpleEnumerator** aEnumerate);
1866 :
1867 : static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
1868 : JSObject* aJSObj,
1869 : const nsAString& aName,
1870 : nsIVariant** aResult);
1871 :
1872 : private:
1873 : // aSyntheticException, if not null, is the exception we should be using.
1874 : // If null, look for an exception on the JSContext hanging off the
1875 : // XPCCallContext.
1876 : static nsresult CheckForException(XPCCallContext & ccx,
1877 : mozilla::dom::AutoEntryScript& aes,
1878 : const char * aPropertyName,
1879 : const char * anInterfaceName,
1880 : nsIException* aSyntheticException = nullptr);
1881 : virtual ~nsXPCWrappedJSClass();
1882 :
1883 : nsXPCWrappedJSClass() = delete;
1884 : nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID,
1885 : nsIInterfaceInfo* aInfo);
1886 :
1887 679 : bool IsReflectable(uint16_t i) const
1888 679 : {return (bool)(mDescriptors[i/32] & (1 << (i%32)));}
1889 679 : void SetReflectable(uint16_t i, bool b)
1890 679 : {if (b) mDescriptors[i/32] |= (1 << (i%32));
1891 184 : else mDescriptors[i/32] &= ~(1 << (i%32));}
1892 :
1893 : bool GetArraySizeFromParam(JSContext* cx,
1894 : const XPTMethodDescriptor* method,
1895 : const nsXPTParamInfo& param,
1896 : uint16_t methodIndex,
1897 : uint8_t paramIndex,
1898 : nsXPTCMiniVariant* params,
1899 : uint32_t* result) const;
1900 :
1901 : bool GetInterfaceTypeFromParam(JSContext* cx,
1902 : const XPTMethodDescriptor* method,
1903 : const nsXPTParamInfo& param,
1904 : uint16_t methodIndex,
1905 : const nsXPTType& type,
1906 : nsXPTCMiniVariant* params,
1907 : nsID* result) const;
1908 :
1909 : static void CleanupPointerArray(const nsXPTType& datum_type,
1910 : uint32_t array_count,
1911 : void** arrayp);
1912 :
1913 : static void CleanupPointerTypeObject(const nsXPTType& type,
1914 : void** pp);
1915 :
1916 : void CleanupOutparams(JSContext* cx, uint16_t methodIndex, const nsXPTMethodInfo* info,
1917 : nsXPTCMiniVariant* nativeParams, bool inOutOnly, uint8_t n) const;
1918 :
1919 : private:
1920 : XPCJSRuntime* mRuntime;
1921 : nsCOMPtr<nsIInterfaceInfo> mInfo;
1922 : char* mName;
1923 : nsIID mIID;
1924 : uint32_t* mDescriptors;
1925 : };
1926 :
1927 : /*************************/
1928 : // nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
1929 : // nsXPCWrappedJS objects are chained together to represent the various
1930 : // interface on the single underlying (possibly aggregate) JSObject.
1931 :
1932 : class nsXPCWrappedJS final : protected nsAutoXPTCStub,
1933 : public nsIXPConnectWrappedJSUnmarkGray,
1934 : public nsSupportsWeakReference,
1935 : public nsIPropertyBag,
1936 : public XPCRootSetElem
1937 : {
1938 : public:
1939 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
1940 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
1941 : NS_DECL_NSIXPCONNECTWRAPPEDJS
1942 : NS_DECL_NSIXPCONNECTWRAPPEDJSUNMARKGRAY
1943 : NS_DECL_NSISUPPORTSWEAKREFERENCE
1944 : NS_DECL_NSIPROPERTYBAG
1945 :
1946 16122 : NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
1947 :
1948 : NS_IMETHOD CallMethod(uint16_t methodIndex,
1949 : const XPTMethodDescriptor* info,
1950 : nsXPTCMiniVariant* params) override;
1951 :
1952 : /*
1953 : * This is rarely called directly. Instead one usually calls
1954 : * XPCConvert::JSObject2NativeInterface which will handles cases where the
1955 : * JS object is already a wrapped native or a DOM object.
1956 : */
1957 :
1958 : static nsresult
1959 : GetNewOrUsed(JS::HandleObject aJSObj,
1960 : REFNSIID aIID,
1961 : nsXPCWrappedJS** wrapper);
1962 :
1963 1680 : nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
1964 :
1965 : /**
1966 : * This getter does not change the color of the JSObject meaning that the
1967 : * object returned is not guaranteed to be kept alive past the next CC.
1968 : *
1969 : * This should only be called if you are certain that the return value won't
1970 : * be passed into a JS API function and that it won't be stored without
1971 : * being rooted (or otherwise signaling the stored value to the CC).
1972 : */
1973 1574 : JSObject* GetJSObjectPreserveColor() const { return mJSObj.unbarrieredGet(); }
1974 :
1975 : // Returns true if the wrapper chain contains references to multiple
1976 : // compartments. If the wrapper chain contains references to multiple
1977 : // compartments, then it must be registered on the XPCJSContext. Otherwise,
1978 : // it should be registered in the CompartmentPrivate for the compartment of
1979 : // the root's JS object. This will only return correct results when called
1980 : // on the root wrapper and will assert if not called on a root wrapper.
1981 : bool IsMultiCompartment() const;
1982 :
1983 4941 : nsXPCWrappedJSClass* GetClass() const {return mClass;}
1984 2819 : REFNSIID GetIID() const {return GetClass()->GetIID();}
1985 111 : nsXPCWrappedJS* GetRootWrapper() const {return mRoot;}
1986 0 : nsXPCWrappedJS* GetNextWrapper() const {return mNext;}
1987 :
1988 : nsXPCWrappedJS* Find(REFNSIID aIID);
1989 : nsXPCWrappedJS* FindInherited(REFNSIID aIID);
1990 2535 : nsXPCWrappedJS* FindOrFindInherited(REFNSIID aIID) {
1991 2535 : nsXPCWrappedJS* wrapper = Find(aIID);
1992 2535 : if (wrapper)
1993 2137 : return wrapper;
1994 398 : return FindInherited(aIID);
1995 : }
1996 :
1997 2932 : bool IsRootWrapper() const { return mRoot == this; }
1998 6262 : bool IsValid() const { return bool(mJSObj); }
1999 : void SystemIsBeingShutDown();
2000 :
2001 : // These two methods are used by JSObject2WrappedJSMap::FindDyingJSObjects
2002 : // to find non-rooting wrappers for dying JS objects. See the top of
2003 : // XPCWrappedJS.cpp for more details.
2004 0 : bool IsSubjectToFinalization() const {return IsValid() && mRefCnt == 1;}
2005 0 : void UpdateObjectPointerAfterGC() {JS_UpdateWeakPointerAfterGC(&mJSObj);}
2006 :
2007 66 : bool IsAggregatedToNative() const {return mRoot->mOuter != nullptr;}
2008 2123 : nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
2009 18 : void SetAggregatedNativeObject(nsISupports* aNative) {
2010 18 : MOZ_ASSERT(aNative);
2011 18 : if (mRoot->mOuter) {
2012 2 : MOZ_ASSERT(mRoot->mOuter == aNative,
2013 : "Only one aggregated native can be set");
2014 2 : return;
2015 : }
2016 16 : mRoot->mOuter = aNative;
2017 : }
2018 :
2019 : void TraceJS(JSTracer* trc);
2020 :
2021 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
2022 :
2023 : virtual ~nsXPCWrappedJS();
2024 : protected:
2025 : nsXPCWrappedJS() = delete;
2026 : nsXPCWrappedJS(JSContext* cx,
2027 : JSObject* aJSObj,
2028 : nsXPCWrappedJSClass* aClass,
2029 : nsXPCWrappedJS* root,
2030 : nsresult* rv);
2031 :
2032 : bool CanSkip();
2033 : void Destroy();
2034 : void Unlink();
2035 :
2036 : private:
2037 1394 : JSCompartment* Compartment() const {
2038 1394 : return js::GetObjectCompartment(mJSObj.unbarrieredGet());
2039 : }
2040 :
2041 : JS::Heap<JSObject*> mJSObj;
2042 : RefPtr<nsXPCWrappedJSClass> mClass;
2043 : nsXPCWrappedJS* mRoot; // If mRoot != this, it is an owning pointer.
2044 : nsXPCWrappedJS* mNext;
2045 : nsCOMPtr<nsISupports> mOuter; // only set in root
2046 : };
2047 :
2048 : /***************************************************************************/
2049 :
2050 : class XPCJSObjectHolder final : public nsIXPConnectJSObjectHolder
2051 : {
2052 : public:
2053 : // all the interface method declarations...
2054 : NS_DECL_ISUPPORTS
2055 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
2056 :
2057 : // non-interface implementation
2058 :
2059 : public:
2060 : XPCJSObjectHolder(JSContext* cx, JSObject* obj);
2061 :
2062 : private:
2063 0 : virtual ~XPCJSObjectHolder() {}
2064 : XPCJSObjectHolder() = delete;
2065 :
2066 : JS::PersistentRooted<JSObject*> mJSObj;
2067 : };
2068 :
2069 : /***************************************************************************
2070 : ****************************************************************************
2071 : *
2072 : * All manner of utility classes follow...
2073 : *
2074 : ****************************************************************************
2075 : ***************************************************************************/
2076 :
2077 : class xpcProperty : public nsIProperty
2078 : {
2079 : public:
2080 : NS_DECL_ISUPPORTS
2081 : NS_DECL_NSIPROPERTY
2082 :
2083 : xpcProperty(const char16_t* aName, uint32_t aNameLen, nsIVariant* aValue);
2084 :
2085 : private:
2086 0 : virtual ~xpcProperty() {}
2087 :
2088 : nsString mName;
2089 : nsCOMPtr<nsIVariant> mValue;
2090 : };
2091 :
2092 : /***************************************************************************/
2093 : // class here just for static methods
2094 : class XPCConvert
2095 : {
2096 : public:
2097 : static bool IsMethodReflectable(const XPTMethodDescriptor& info);
2098 :
2099 : /**
2100 : * Convert a native object into a JS::Value.
2101 : *
2102 : * @param d [out] the resulting JS::Value
2103 : * @param s the native object we're working with
2104 : * @param type the type of object that s is
2105 : * @param iid the interface of s that we want
2106 : * @param scope the default scope to put on the new JSObject's parent
2107 : * chain
2108 : * @param pErr [out] relevant error code, if any.
2109 : */
2110 :
2111 : static bool NativeData2JS(JS::MutableHandleValue d,
2112 : const void* s, const nsXPTType& type,
2113 : const nsID* iid, nsresult* pErr);
2114 :
2115 : static bool JSData2Native(void* d, JS::HandleValue s,
2116 : const nsXPTType& type,
2117 : const nsID* iid,
2118 : nsresult* pErr);
2119 :
2120 : /**
2121 : * Convert a native nsISupports into a JSObject.
2122 : *
2123 : * @param dest [out] the resulting JSObject
2124 : * @param src the native object we're working with
2125 : * @param iid the interface of src that we want (may be null)
2126 : * @param cache the wrapper cache for src (may be null, in which case src
2127 : * will be QI'ed to get the cache)
2128 : * @param allowNativeWrapper if true, this method may wrap the resulting
2129 : * JSObject in an XPCNativeWrapper and return that, as needed.
2130 : * @param pErr [out] relevant error code, if any.
2131 : * @param src_is_identity optional performance hint. Set to true only
2132 : * if src is the identity pointer.
2133 : */
2134 : static bool NativeInterface2JSObject(JS::MutableHandleValue d,
2135 : nsIXPConnectJSObjectHolder** dest,
2136 : xpcObjectHelper& aHelper,
2137 : const nsID* iid,
2138 : bool allowNativeWrapper,
2139 : nsresult* pErr);
2140 :
2141 : static bool GetNativeInterfaceFromJSObject(void** dest, JSObject* src,
2142 : const nsID* iid,
2143 : nsresult* pErr);
2144 : static bool JSObject2NativeInterface(void** dest, JS::HandleObject src,
2145 : const nsID* iid,
2146 : nsISupports* aOuter,
2147 : nsresult* pErr);
2148 :
2149 : // Note - This return the XPCWrappedNative, rather than the native itself,
2150 : // for the WN case. You probably want UnwrapReflectorToISupports.
2151 : static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
2152 :
2153 : /**
2154 : * Convert a native array into a JS::Value.
2155 : *
2156 : * @param d [out] the resulting JS::Value
2157 : * @param s the native array we're working with
2158 : * @param type the type of objects in the array
2159 : * @param iid the interface of each object in the array that we want
2160 : * @param count the number of items in the array
2161 : * @param scope the default scope to put on the new JSObjects' parent chain
2162 : * @param pErr [out] relevant error code, if any.
2163 : */
2164 : static bool NativeArray2JS(JS::MutableHandleValue d, const void** s,
2165 : const nsXPTType& type, const nsID* iid,
2166 : uint32_t count, nsresult* pErr);
2167 :
2168 : static bool JSArray2Native(void** d, JS::HandleValue s,
2169 : uint32_t count, const nsXPTType& type,
2170 : const nsID* iid, nsresult* pErr);
2171 :
2172 : static bool JSTypedArray2Native(void** d,
2173 : JSObject* jsarray,
2174 : uint32_t count,
2175 : const nsXPTType& type,
2176 : nsresult* pErr);
2177 :
2178 : static bool NativeStringWithSize2JS(JS::MutableHandleValue d, const void* s,
2179 : const nsXPTType& type,
2180 : uint32_t count,
2181 : nsresult* pErr);
2182 :
2183 : static bool JSStringWithSize2Native(void* d, JS::HandleValue s,
2184 : uint32_t count, const nsXPTType& type,
2185 : nsresult* pErr);
2186 :
2187 : static nsresult JSValToXPCException(JS::MutableHandleValue s,
2188 : const char* ifaceName,
2189 : const char* methodName,
2190 : nsIException** exception);
2191 :
2192 : static nsresult ConstructException(nsresult rv, const char* message,
2193 : const char* ifaceName,
2194 : const char* methodName,
2195 : nsISupports* data,
2196 : nsIException** exception,
2197 : JSContext* cx,
2198 : JS::Value* jsExceptionPtr);
2199 :
2200 : private:
2201 : XPCConvert() = delete;
2202 :
2203 : };
2204 :
2205 : /***************************************************************************/
2206 : // code for throwing exceptions into JS
2207 :
2208 : class nsXPCException;
2209 :
2210 : class XPCThrower
2211 : {
2212 : public:
2213 : static void Throw(nsresult rv, JSContext* cx);
2214 : static void Throw(nsresult rv, XPCCallContext& ccx);
2215 : static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
2216 : static void ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx);
2217 : static bool SetVerbosity(bool state)
2218 : {bool old = sVerbose; sVerbose = state; return old;}
2219 :
2220 : static bool CheckForPendingException(nsresult result, JSContext* cx);
2221 :
2222 : private:
2223 : static void Verbosify(XPCCallContext& ccx,
2224 : char** psz, bool own);
2225 :
2226 : private:
2227 : static bool sVerbose;
2228 : };
2229 :
2230 : /***************************************************************************/
2231 :
2232 : class nsXPCException
2233 : {
2234 : public:
2235 : static bool NameAndFormatForNSResult(nsresult rv,
2236 : const char** name,
2237 : const char** format);
2238 :
2239 : static const void* IterateNSResults(nsresult* rv,
2240 : const char** name,
2241 : const char** format,
2242 : const void** iterp);
2243 :
2244 : static uint32_t GetNSResultCount();
2245 : };
2246 :
2247 : /***************************************************************************/
2248 : /*
2249 : * nsJSID implements nsIJSID. It is also used by nsJSIID and nsJSCID as a
2250 : * member (as a hidden implementaion detail) to which they delegate many calls.
2251 : */
2252 :
2253 : // Initialization is done on demand, and calling the destructor below is always
2254 : // safe.
2255 : extern void xpc_DestroyJSxIDClassObjects();
2256 :
2257 : class nsJSID final : public nsIJSID
2258 : {
2259 : public:
2260 78 : NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID)
2261 :
2262 : NS_DECL_ISUPPORTS
2263 : NS_DECL_NSIJSID
2264 :
2265 : bool InitWithName(const nsID& id, const char* nameString);
2266 : bool SetName(const char* name);
2267 0 : void SetNameToNoString()
2268 0 : {MOZ_ASSERT(!mName, "name already set"); mName = const_cast<char*>(gNoString);}
2269 0 : bool NameIsSet() const {return nullptr != mName;}
2270 662 : const nsID& ID() const {return mID;}
2271 331 : bool IsValid() const {return !mID.Equals(GetInvalidIID());}
2272 :
2273 : static already_AddRefed<nsJSID> NewID(const char* str);
2274 : static already_AddRefed<nsJSID> NewID(const nsID& id);
2275 :
2276 : nsJSID();
2277 :
2278 : void Reset();
2279 : const nsID& GetInvalidIID() const;
2280 :
2281 : protected:
2282 : virtual ~nsJSID();
2283 : static const char gNoString[];
2284 : nsID mID;
2285 : char* mNumber;
2286 : char* mName;
2287 : };
2288 :
2289 :
2290 : // nsJSIID
2291 :
2292 : class nsJSIID : public nsIJSIID,
2293 : public nsIXPCScriptable
2294 : {
2295 : public:
2296 : NS_DECL_ISUPPORTS
2297 :
2298 : // we manually delegate these to nsJSID
2299 : NS_DECL_NSIJSID
2300 :
2301 : // we implement the rest...
2302 : NS_DECL_NSIJSIID
2303 : NS_DECL_NSIXPCSCRIPTABLE
2304 :
2305 : static already_AddRefed<nsJSIID> NewID(nsIInterfaceInfo* aInfo);
2306 :
2307 : explicit nsJSIID(nsIInterfaceInfo* aInfo);
2308 : nsJSIID() = delete;
2309 :
2310 : private:
2311 : virtual ~nsJSIID();
2312 :
2313 : nsCOMPtr<nsIInterfaceInfo> mInfo;
2314 : };
2315 :
2316 : // nsJSCID
2317 :
2318 : class nsJSCID : public nsIJSCID, public nsIXPCScriptable
2319 : {
2320 : public:
2321 : NS_DECL_ISUPPORTS
2322 :
2323 : // we manually delegate these to nsJSID
2324 : NS_DECL_NSIJSID
2325 :
2326 : // we implement the rest...
2327 : NS_DECL_NSIJSCID
2328 : NS_DECL_NSIXPCSCRIPTABLE
2329 :
2330 : static already_AddRefed<nsJSCID> NewID(const char* str);
2331 :
2332 : nsJSCID();
2333 :
2334 : private:
2335 : virtual ~nsJSCID();
2336 :
2337 : void ResolveName();
2338 :
2339 : private:
2340 : RefPtr<nsJSID> mDetails;
2341 : };
2342 :
2343 :
2344 : /***************************************************************************/
2345 : // 'Components' object implementations. nsXPCComponentsBase has the
2346 : // less-privileged stuff that we're willing to expose to XBL.
2347 :
2348 : class nsXPCComponentsBase : public nsIXPCComponentsBase
2349 : {
2350 : public:
2351 : NS_DECL_ISUPPORTS
2352 : NS_DECL_NSIXPCCOMPONENTSBASE
2353 :
2354 : public:
2355 0 : void SystemIsBeingShutDown() { ClearMembers(); }
2356 :
2357 562 : XPCWrappedNativeScope* GetScope() { return mScope; }
2358 :
2359 : protected:
2360 : virtual ~nsXPCComponentsBase();
2361 :
2362 : explicit nsXPCComponentsBase(XPCWrappedNativeScope* aScope);
2363 : virtual void ClearMembers();
2364 :
2365 : XPCWrappedNativeScope* mScope;
2366 :
2367 : // Unprivileged members from nsIXPCComponentsBase.
2368 : RefPtr<nsXPCComponents_Interfaces> mInterfaces;
2369 : RefPtr<nsXPCComponents_InterfacesByID> mInterfacesByID;
2370 : RefPtr<nsXPCComponents_Results> mResults;
2371 :
2372 : friend class XPCWrappedNativeScope;
2373 : };
2374 :
2375 : class nsXPCComponents : public nsXPCComponentsBase,
2376 : public nsIXPCComponents
2377 : {
2378 : public:
2379 : NS_DECL_ISUPPORTS_INHERITED
2380 613 : NS_FORWARD_NSIXPCCOMPONENTSBASE(nsXPCComponentsBase::)
2381 : NS_DECL_NSIXPCCOMPONENTS
2382 :
2383 : protected:
2384 : explicit nsXPCComponents(XPCWrappedNativeScope* aScope);
2385 : virtual ~nsXPCComponents();
2386 : virtual void ClearMembers() override;
2387 :
2388 : // Privileged members added by nsIXPCComponents.
2389 : RefPtr<nsXPCComponents_Classes> mClasses;
2390 : RefPtr<nsXPCComponents_ClassesByID> mClassesByID;
2391 : RefPtr<nsXPCComponents_ID> mID;
2392 : RefPtr<nsXPCComponents_Exception> mException;
2393 : RefPtr<nsXPCComponents_Constructor> mConstructor;
2394 : RefPtr<nsXPCComponents_Utils> mUtils;
2395 :
2396 : friend class XPCWrappedNativeScope;
2397 : };
2398 :
2399 :
2400 : /***************************************************************************/
2401 :
2402 : extern JSObject*
2403 : xpc_NewIDObject(JSContext* cx, JS::HandleObject jsobj, const nsID& aID);
2404 :
2405 : extern const nsID*
2406 : xpc_JSObjectToID(JSContext* cx, JSObject* obj);
2407 :
2408 : extern bool
2409 : xpc_JSObjectIsID(JSContext* cx, JSObject* obj);
2410 :
2411 : /***************************************************************************/
2412 : // in XPCDebug.cpp
2413 :
2414 : extern bool
2415 : xpc_DumpJSStack(bool showArgs, bool showLocals, bool showThisProps);
2416 :
2417 : // Return a newly-allocated string containing a representation of the
2418 : // current JS stack.
2419 : extern JS::UniqueChars
2420 : xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
2421 : bool showThisProps);
2422 :
2423 : /******************************************************************************
2424 : * Handles pre/post script processing.
2425 : */
2426 : class MOZ_RAII AutoScriptEvaluate
2427 : {
2428 : public:
2429 : /**
2430 : * Saves the JSContext as well as initializing our state
2431 : * @param cx The JSContext, this can be null, we don't do anything then
2432 : */
2433 2341 : explicit AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
2434 2341 : : mJSContext(cx), mEvaluated(false) {
2435 2341 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
2436 2341 : }
2437 :
2438 : /**
2439 : * Does the pre script evaluation.
2440 : * This function should only be called once, and will assert if called
2441 : * more than once
2442 : */
2443 :
2444 : bool StartEvaluating(JS::HandleObject scope);
2445 :
2446 : /**
2447 : * Does the post script evaluation.
2448 : */
2449 : ~AutoScriptEvaluate();
2450 : private:
2451 : JSContext* mJSContext;
2452 : mozilla::Maybe<JS::AutoSaveExceptionState> mState;
2453 : bool mEvaluated;
2454 : mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
2455 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
2456 :
2457 : // No copying or assignment allowed
2458 : AutoScriptEvaluate(const AutoScriptEvaluate&) = delete;
2459 : AutoScriptEvaluate & operator =(const AutoScriptEvaluate&) = delete;
2460 : };
2461 :
2462 : /***************************************************************************/
2463 : class MOZ_RAII AutoResolveName
2464 : {
2465 : public:
2466 2876 : AutoResolveName(XPCCallContext& ccx, JS::HandleId name
2467 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
2468 2876 : : mContext(ccx.GetContext())
2469 5752 : , mOld(ccx, mContext->SetResolveName(name))
2470 : #ifdef DEBUG
2471 8628 : , mCheck(ccx, name)
2472 : #endif
2473 : {
2474 2876 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
2475 2876 : }
2476 :
2477 2876 : ~AutoResolveName()
2478 2876 : {
2479 : mozilla::DebugOnly<jsid> old =
2480 5752 : mContext->SetResolveName(mOld);
2481 2876 : MOZ_ASSERT(old == mCheck, "Bad Nesting!");
2482 2876 : }
2483 :
2484 : private:
2485 : XPCJSContext* mContext;
2486 : JS::RootedId mOld;
2487 : #ifdef DEBUG
2488 : JS::RootedId mCheck;
2489 : #endif
2490 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
2491 : };
2492 :
2493 : /***************************************************************************/
2494 : // AutoMarkingPtr is the base class for the various AutoMarking pointer types
2495 : // below. This system allows us to temporarily protect instances of our garbage
2496 : // collected types after they are constructed but before they are safely
2497 : // attached to other rooted objects.
2498 : // This base class has pure virtual support for marking.
2499 :
2500 : class AutoMarkingPtr
2501 : {
2502 : public:
2503 23259 : explicit AutoMarkingPtr(JSContext* cx) {
2504 23259 : mRoot = XPCJSContext::Get()->GetAutoRootsAdr();
2505 23259 : mNext = *mRoot;
2506 23259 : *mRoot = this;
2507 23259 : }
2508 :
2509 46518 : virtual ~AutoMarkingPtr() {
2510 23259 : if (mRoot) {
2511 23259 : MOZ_ASSERT(*mRoot == this);
2512 23259 : *mRoot = mNext;
2513 : }
2514 23259 : }
2515 :
2516 0 : void TraceJSAll(JSTracer* trc) {
2517 0 : for (AutoMarkingPtr* cur = this; cur; cur = cur->mNext)
2518 0 : cur->TraceJS(trc);
2519 0 : }
2520 :
2521 0 : void MarkAfterJSFinalizeAll() {
2522 0 : for (AutoMarkingPtr* cur = this; cur; cur = cur->mNext)
2523 0 : cur->MarkAfterJSFinalize();
2524 0 : }
2525 :
2526 : protected:
2527 : virtual void TraceJS(JSTracer* trc) = 0;
2528 : virtual void MarkAfterJSFinalize() = 0;
2529 :
2530 : private:
2531 : AutoMarkingPtr** mRoot;
2532 : AutoMarkingPtr* mNext;
2533 : };
2534 :
2535 : template<class T>
2536 23258 : class TypedAutoMarkingPtr : public AutoMarkingPtr
2537 : {
2538 : public:
2539 9829 : explicit TypedAutoMarkingPtr(JSContext* cx) : AutoMarkingPtr(cx), mPtr(nullptr) {}
2540 13430 : TypedAutoMarkingPtr(JSContext* cx, T* ptr) : AutoMarkingPtr(cx), mPtr(ptr) {}
2541 :
2542 0 : T* get() const { return mPtr; }
2543 20640 : operator T*() const { return mPtr; }
2544 1824 : T* operator->() const { return mPtr; }
2545 :
2546 10320 : TypedAutoMarkingPtr<T>& operator =(T* ptr) { mPtr = ptr; return *this; }
2547 :
2548 : protected:
2549 0 : virtual void TraceJS(JSTracer* trc)
2550 : {
2551 0 : if (mPtr) {
2552 0 : mPtr->TraceJS(trc);
2553 0 : mPtr->AutoTrace(trc);
2554 : }
2555 0 : }
2556 :
2557 0 : virtual void MarkAfterJSFinalize()
2558 : {
2559 0 : if (mPtr)
2560 0 : mPtr->Mark();
2561 0 : }
2562 :
2563 : private:
2564 : T* mPtr;
2565 : };
2566 :
2567 : typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr;
2568 : typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr;
2569 : typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
2570 :
2571 : /***************************************************************************/
2572 : namespace xpc {
2573 : // Allocates a string that grants all access ("AllAccess")
2574 : char*
2575 : CloneAllAccess();
2576 :
2577 : // Returns access if wideName is in list
2578 : char*
2579 : CheckAccessList(const char16_t* wideName, const char* const list[]);
2580 : } /* namespace xpc */
2581 :
2582 : /***************************************************************************/
2583 : // in xpcvariant.cpp...
2584 :
2585 : // {1809FD50-91E8-11d5-90F9-0010A4E73D9A}
2586 : #define XPCVARIANT_IID \
2587 : {0x1809fd50, 0x91e8, 0x11d5, \
2588 : { 0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
2589 :
2590 : // {DC524540-487E-4501-9AC7-AAA784B17C1C}
2591 : #define XPCVARIANT_CID \
2592 : {0xdc524540, 0x487e, 0x4501, \
2593 : { 0x9a, 0xc7, 0xaa, 0xa7, 0x84, 0xb1, 0x7c, 0x1c } }
2594 :
2595 : class XPCVariant : public nsIVariant
2596 : {
2597 : public:
2598 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
2599 : NS_DECL_NSIVARIANT
2600 36 : NS_DECL_CYCLE_COLLECTION_CLASS(XPCVariant)
2601 :
2602 : // If this class ever implements nsIWritableVariant, take special care with
2603 : // the case when mJSVal is JSVAL_STRING, since we don't own the data in
2604 : // that case.
2605 :
2606 : // We #define and iid so that out module local code can use QI to detect
2607 : // if a given nsIVariant is in fact an XPCVariant.
2608 : NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
2609 :
2610 : static already_AddRefed<XPCVariant> newVariant(JSContext* cx, const JS::Value& aJSVal);
2611 :
2612 : /**
2613 : * This getter clears the gray bit before handing out the Value if the Value
2614 : * represents a JSObject. That means that the object is guaranteed to be
2615 : * kept alive past the next CC.
2616 : */
2617 3 : JS::Value GetJSVal() const {
2618 3 : return mJSVal;
2619 : }
2620 :
2621 : /**
2622 : * This getter does not change the color of the Value (if it represents a
2623 : * JSObject) meaning that the value returned is not guaranteed to be kept
2624 : * alive past the next CC.
2625 : *
2626 : * This should only be called if you are certain that the return value won't
2627 : * be passed into a JS API function and that it won't be stored without
2628 : * being rooted (or otherwise signaling the stored value to the CC).
2629 : */
2630 4 : JS::Value GetJSValPreserveColor() const { return mJSVal.unbarrieredGet(); }
2631 :
2632 : XPCVariant(JSContext* cx, const JS::Value& aJSVal);
2633 :
2634 : /**
2635 : * Convert a variant into a JS::Value.
2636 : *
2637 : * @param ccx the context for the whole procedure
2638 : * @param variant the variant to convert
2639 : * @param scope the default scope to put on the new JSObject's parent chain
2640 : * @param pErr [out] relevant error code, if any.
2641 : * @param pJSVal [out] the resulting jsval.
2642 : */
2643 : static bool VariantDataToJS(nsIVariant* variant,
2644 : nsresult* pErr, JS::MutableHandleValue pJSVal);
2645 :
2646 0 : bool IsPurple()
2647 : {
2648 0 : return mRefCnt.IsPurple();
2649 : }
2650 :
2651 0 : void RemovePurple()
2652 : {
2653 0 : mRefCnt.RemovePurple();
2654 0 : }
2655 :
2656 0 : void SetCCGeneration(uint32_t aGen)
2657 : {
2658 0 : mCCGeneration = aGen;
2659 0 : }
2660 :
2661 0 : uint32_t CCGeneration() { return mCCGeneration; }
2662 : protected:
2663 5 : virtual ~XPCVariant() { }
2664 :
2665 : bool InitializeData(JSContext* cx);
2666 :
2667 : protected:
2668 : nsDiscriminatedUnion mData;
2669 : JS::Heap<JS::Value> mJSVal;
2670 : bool mReturnRawObject : 1;
2671 : uint32_t mCCGeneration : 31;
2672 : };
2673 :
2674 : NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID)
2675 :
2676 : class XPCTraceableVariant: public XPCVariant,
2677 : public XPCRootSetElem
2678 : {
2679 : public:
2680 2 : XPCTraceableVariant(JSContext* cx, const JS::Value& aJSVal)
2681 2 : : XPCVariant(cx, aJSVal)
2682 : {
2683 2 : nsXPConnect::GetRuntimeInstance()->AddVariantRoot(this);
2684 2 : }
2685 :
2686 : virtual ~XPCTraceableVariant();
2687 :
2688 : void TraceJS(JSTracer* trc);
2689 : };
2690 :
2691 : /***************************************************************************/
2692 : // Utilities
2693 :
2694 : inline void*
2695 5034 : xpc_GetJSPrivate(JSObject* obj)
2696 : {
2697 5034 : return js::GetObjectPrivate(obj);
2698 : }
2699 :
2700 : inline JSContext*
2701 9 : xpc_GetSafeJSContext()
2702 : {
2703 9 : return XPCJSContext::Get()->Context();
2704 : }
2705 :
2706 : namespace xpc {
2707 :
2708 : JSAddonId*
2709 : NewAddonId(JSContext* cx, const nsACString& id);
2710 :
2711 : // JSNatives to expose atob and btoa in various non-DOM XPConnect scopes.
2712 : bool
2713 : Atob(JSContext* cx, unsigned argc, JS::Value* vp);
2714 :
2715 : bool
2716 : Btoa(JSContext* cx, unsigned argc, JS::Value* vp);
2717 :
2718 : // Helper function that creates a JSFunction that wraps a native function that
2719 : // forwards the call to the original 'callable'.
2720 : class FunctionForwarderOptions;
2721 : bool
2722 : NewFunctionForwarder(JSContext* cx, JS::HandleId id, JS::HandleObject callable,
2723 : FunctionForwarderOptions& options, JS::MutableHandleValue vp);
2724 :
2725 : // Old fashioned xpc error reporter. Try to use JS_ReportError instead.
2726 : nsresult
2727 : ThrowAndFail(nsresult errNum, JSContext* cx, bool* retval);
2728 :
2729 : struct GlobalProperties {
2730 45 : GlobalProperties() {
2731 45 : mozilla::PodZero(this);
2732 :
2733 45 : }
2734 : bool Parse(JSContext* cx, JS::HandleObject obj);
2735 : bool DefineInXPCComponents(JSContext* cx, JS::HandleObject obj);
2736 : bool DefineInSandbox(JSContext* cx, JS::HandleObject obj);
2737 : bool CSS : 1;
2738 : bool indexedDB : 1;
2739 : bool XMLHttpRequest : 1;
2740 : bool TextDecoder : 1;
2741 : bool TextEncoder : 1;
2742 : bool URL : 1;
2743 : bool URLSearchParams : 1;
2744 : bool atob : 1;
2745 : bool btoa : 1;
2746 : bool Blob : 1;
2747 : bool Directory : 1;
2748 : bool File : 1;
2749 : bool crypto : 1;
2750 : bool rtcIdentityProvider : 1;
2751 : bool fetch : 1;
2752 : bool caches : 1;
2753 : bool fileReader: 1;
2754 : bool messageChannel: 1;
2755 : private:
2756 : bool Define(JSContext* cx, JS::HandleObject obj);
2757 : };
2758 :
2759 : // Infallible.
2760 : already_AddRefed<nsIXPCComponents_utils_Sandbox>
2761 : NewSandboxConstructor();
2762 :
2763 : // Returns true if class of 'obj' is SandboxClass.
2764 : bool
2765 : IsSandbox(JSObject* obj);
2766 :
2767 62 : class MOZ_STACK_CLASS OptionsBase {
2768 : public:
2769 62 : explicit OptionsBase(JSContext* cx = xpc_GetSafeJSContext(),
2770 : JSObject* options = nullptr)
2771 62 : : mCx(cx)
2772 62 : , mObject(cx, options)
2773 62 : { }
2774 :
2775 : virtual bool Parse() = 0;
2776 :
2777 : protected:
2778 : bool ParseValue(const char* name, JS::MutableHandleValue prop, bool* found = nullptr);
2779 : bool ParseBoolean(const char* name, bool* prop);
2780 : bool ParseObject(const char* name, JS::MutableHandleObject prop);
2781 : bool ParseJSString(const char* name, JS::MutableHandleString prop);
2782 : bool ParseString(const char* name, nsCString& prop);
2783 : bool ParseString(const char* name, nsString& prop);
2784 : bool ParseId(const char* name, JS::MutableHandleId id);
2785 : bool ParseUInt32(const char* name, uint32_t* prop);
2786 :
2787 : JSContext* mCx;
2788 : JS::RootedObject mObject;
2789 : };
2790 :
2791 25 : class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
2792 : public:
2793 25 : explicit SandboxOptions(JSContext* cx = xpc_GetSafeJSContext(),
2794 : JSObject* options = nullptr)
2795 25 : : OptionsBase(cx, options)
2796 : , wantXrays(true)
2797 : , allowWaivers(true)
2798 : , wantComponents(true)
2799 : , wantExportHelpers(false)
2800 : , isWebExtensionContentScript(false)
2801 : , waiveInterposition(false)
2802 : , proto(cx)
2803 : , addonId(cx)
2804 : , writeToGlobalPrototype(false)
2805 : , sameZoneAs(cx)
2806 : , freshZone(false)
2807 : , invisibleToDebugger(false)
2808 : , discardSource(false)
2809 : , metadata(cx)
2810 : , userContextId(0)
2811 25 : , originAttributes(cx)
2812 25 : { }
2813 :
2814 : virtual bool Parse();
2815 :
2816 : bool wantXrays;
2817 : bool allowWaivers;
2818 : bool wantComponents;
2819 : bool wantExportHelpers;
2820 : bool isWebExtensionContentScript;
2821 : bool waiveInterposition;
2822 : JS::RootedObject proto;
2823 : nsCString sandboxName;
2824 : JS::RootedString addonId;
2825 : bool writeToGlobalPrototype;
2826 : JS::RootedObject sameZoneAs;
2827 : bool freshZone;
2828 : bool invisibleToDebugger;
2829 : bool discardSource;
2830 : GlobalProperties globalProperties;
2831 : JS::RootedValue metadata;
2832 : uint32_t userContextId;
2833 : JS::RootedObject originAttributes;
2834 :
2835 : protected:
2836 : bool ParseGlobalProperties();
2837 : };
2838 :
2839 0 : class MOZ_STACK_CLASS CreateObjectInOptions : public OptionsBase {
2840 : public:
2841 0 : explicit CreateObjectInOptions(JSContext* cx = xpc_GetSafeJSContext(),
2842 : JSObject* options = nullptr)
2843 0 : : OptionsBase(cx, options)
2844 0 : , defineAs(cx, JSID_VOID)
2845 0 : { }
2846 :
2847 0 : virtual bool Parse() { return ParseId("defineAs", &defineAs); }
2848 :
2849 : JS::RootedId defineAs;
2850 : };
2851 :
2852 0 : class MOZ_STACK_CLASS ExportFunctionOptions : public OptionsBase {
2853 : public:
2854 0 : explicit ExportFunctionOptions(JSContext* cx = xpc_GetSafeJSContext(),
2855 : JSObject* options = nullptr)
2856 0 : : OptionsBase(cx, options)
2857 : , defineAs(cx, JSID_VOID)
2858 0 : , allowCrossOriginArguments(false)
2859 0 : { }
2860 :
2861 0 : virtual bool Parse() {
2862 0 : return ParseId("defineAs", &defineAs) &&
2863 0 : ParseBoolean("allowCrossOriginArguments", &allowCrossOriginArguments);
2864 : }
2865 :
2866 : JS::RootedId defineAs;
2867 : bool allowCrossOriginArguments;
2868 : };
2869 :
2870 0 : class MOZ_STACK_CLASS FunctionForwarderOptions : public OptionsBase {
2871 : public:
2872 0 : explicit FunctionForwarderOptions(JSContext* cx = xpc_GetSafeJSContext(),
2873 : JSObject* options = nullptr)
2874 0 : : OptionsBase(cx, options)
2875 0 : , allowCrossOriginArguments(false)
2876 0 : { }
2877 :
2878 0 : JSObject* ToJSObject(JSContext* cx) {
2879 0 : JS::RootedObject obj(cx, JS_NewObjectWithGivenProto(cx, nullptr, nullptr));
2880 0 : if (!obj)
2881 0 : return nullptr;
2882 :
2883 0 : JS::RootedValue val(cx);
2884 0 : unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
2885 0 : val = JS::BooleanValue(allowCrossOriginArguments);
2886 0 : if (!JS_DefineProperty(cx, obj, "allowCrossOriginArguments", val, attrs))
2887 0 : return nullptr;
2888 :
2889 0 : return obj;
2890 : }
2891 :
2892 0 : virtual bool Parse() {
2893 0 : return ParseBoolean("allowCrossOriginArguments", &allowCrossOriginArguments);
2894 : }
2895 :
2896 : bool allowCrossOriginArguments;
2897 : };
2898 :
2899 4 : class MOZ_STACK_CLASS StackScopedCloneOptions : public OptionsBase {
2900 : public:
2901 4 : explicit StackScopedCloneOptions(JSContext* cx = xpc_GetSafeJSContext(),
2902 : JSObject* options = nullptr)
2903 4 : : OptionsBase(cx, options)
2904 : , wrapReflectors(false)
2905 : , cloneFunctions(false)
2906 4 : , deepFreeze(false)
2907 4 : { }
2908 :
2909 0 : virtual bool Parse() {
2910 0 : return ParseBoolean("wrapReflectors", &wrapReflectors) &&
2911 0 : ParseBoolean("cloneFunctions", &cloneFunctions) &&
2912 0 : ParseBoolean("deepFreeze", &deepFreeze);
2913 : }
2914 :
2915 : // When a reflector is encountered, wrap it rather than aborting the clone.
2916 : bool wrapReflectors;
2917 :
2918 : // When a function is encountered, clone it (exportFunction-style) rather than
2919 : // aborting the clone.
2920 : bool cloneFunctions;
2921 :
2922 : // If true, the resulting object is deep-frozen after being cloned.
2923 : bool deepFreeze;
2924 : };
2925 :
2926 : JSObject*
2927 : CreateGlobalObject(JSContext* cx, const JSClass* clasp, nsIPrincipal* principal,
2928 : JS::CompartmentOptions& aOptions);
2929 :
2930 : // Modify the provided compartment options, consistent with |aPrincipal| and
2931 : // with globally-cached values of various preferences.
2932 : //
2933 : // Call this function *before* |aOptions| is used to create the corresponding
2934 : // global object, as not all of the options it sets can be modified on an
2935 : // existing global object. (The type system should make this obvious, because
2936 : // you can't get a *mutable* JS::CompartmentOptions& from an existing global
2937 : // object.)
2938 : void
2939 : InitGlobalObjectOptions(JS::CompartmentOptions& aOptions,
2940 : nsIPrincipal* aPrincipal);
2941 :
2942 : // Finish initializing an already-created, not-yet-exposed-to-script global
2943 : // object. This will attach a Components object (if necessary) and call
2944 : // |JS_FireOnNewGlobalObject| (if necessary).
2945 : //
2946 : // If you must modify compartment options, see InitGlobalObjectOptions above.
2947 : bool
2948 : InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal,
2949 : uint32_t aFlags);
2950 :
2951 : // Helper for creating a sandbox object to use for evaluating
2952 : // untrusted code completely separated from all other code in the
2953 : // system using EvalInSandbox(). Takes the JSContext on which to
2954 : // do setup etc on, puts the sandbox object in *vp (which must be
2955 : // rooted by the caller), and uses the principal that's either
2956 : // directly passed in prinOrSop or indirectly as an
2957 : // nsIScriptObjectPrincipal holding the principal. If no principal is
2958 : // reachable through prinOrSop, a new null principal will be created
2959 : // and used.
2960 : nsresult
2961 : CreateSandboxObject(JSContext* cx, JS::MutableHandleValue vp, nsISupports* prinOrSop,
2962 : xpc::SandboxOptions& options);
2963 : // Helper for evaluating scripts in a sandbox object created with
2964 : // CreateSandboxObject(). The caller is responsible of ensuring
2965 : // that *rval doesn't get collected during the call or usage after the
2966 : // call. This helper will use filename and lineNo for error reporting,
2967 : // and if no filename is provided it will use the codebase from the
2968 : // principal and line number 1 as a fallback.
2969 : nsresult
2970 : EvalInSandbox(JSContext* cx, JS::HandleObject sandbox, const nsAString& source,
2971 : const nsACString& filename, int32_t lineNo,
2972 : JSVersion jsVersion, JS::MutableHandleValue rval);
2973 :
2974 : nsresult
2975 : GetSandboxAddonId(JSContext* cx, JS::HandleObject sandboxArg,
2976 : JS::MutableHandleValue rval);
2977 :
2978 : // Helper for retrieving metadata stored in a reserved slot. The metadata
2979 : // is set during the sandbox creation using the "metadata" option.
2980 : nsresult
2981 : GetSandboxMetadata(JSContext* cx, JS::HandleObject sandboxArg,
2982 : JS::MutableHandleValue rval);
2983 :
2984 : nsresult
2985 : SetSandboxMetadata(JSContext* cx, JS::HandleObject sandboxArg,
2986 : JS::HandleValue metadata);
2987 :
2988 : bool
2989 : CreateObjectIn(JSContext* cx, JS::HandleValue vobj, CreateObjectInOptions& options,
2990 : JS::MutableHandleValue rval);
2991 :
2992 : bool
2993 : EvalInWindow(JSContext* cx, const nsAString& source, JS::HandleObject scope,
2994 : JS::MutableHandleValue rval);
2995 :
2996 : bool
2997 : ExportFunction(JSContext* cx, JS::HandleValue vscope, JS::HandleValue vfunction,
2998 : JS::HandleValue voptions, JS::MutableHandleValue rval);
2999 :
3000 : bool
3001 : CloneInto(JSContext* cx, JS::HandleValue vobj, JS::HandleValue vscope,
3002 : JS::HandleValue voptions, JS::MutableHandleValue rval);
3003 :
3004 : bool
3005 : StackScopedClone(JSContext* cx, StackScopedCloneOptions& options, JS::MutableHandleValue val);
3006 :
3007 : } /* namespace xpc */
3008 :
3009 :
3010 : /***************************************************************************/
3011 : // Inlined utilities.
3012 :
3013 : inline bool
3014 : xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid id);
3015 :
3016 : inline jsid
3017 : GetJSIDByIndex(JSContext* cx, unsigned index);
3018 :
3019 : namespace xpc {
3020 :
3021 : enum WrapperDenialType {
3022 : WrapperDenialForXray = 0,
3023 : WrapperDenialForCOW,
3024 : WrapperDenialTypeCount
3025 : };
3026 : bool ReportWrapperDenial(JSContext* cx, JS::HandleId id, WrapperDenialType type, const char* reason);
3027 :
3028 : class CompartmentPrivate
3029 : {
3030 : public:
3031 : enum LocationHint {
3032 : LocationHintRegular,
3033 : LocationHintAddon
3034 : };
3035 :
3036 : explicit CompartmentPrivate(JSCompartment* c);
3037 :
3038 : ~CompartmentPrivate();
3039 :
3040 153444 : static CompartmentPrivate* Get(JSCompartment* compartment)
3041 : {
3042 153444 : MOZ_ASSERT(compartment);
3043 153444 : void* priv = JS_GetCompartmentPrivate(compartment);
3044 153444 : return static_cast<CompartmentPrivate*>(priv);
3045 : }
3046 :
3047 21737 : static CompartmentPrivate* Get(JSObject* object)
3048 : {
3049 21737 : JSCompartment* compartment = js::GetObjectCompartment(object);
3050 21737 : return Get(compartment);
3051 : }
3052 :
3053 : // Controls whether this compartment gets Xrays to same-origin. This behavior
3054 : // is deprecated, but is still the default for sandboxes for compatibity
3055 : // reasons.
3056 : bool wantXrays;
3057 :
3058 : // Controls whether this compartment is allowed to waive Xrays to content
3059 : // that it subsumes. This should generally be true, except in cases where we
3060 : // want to prevent code from depending on Xray Waivers (which might make it
3061 : // more portable to other browser architectures).
3062 : bool allowWaivers;
3063 :
3064 : // This flag is intended for a very specific use, internal to Gecko. It may
3065 : // go away or change behavior at any time. It should not be added to any
3066 : // documentation and it should not be used without consulting the XPConnect
3067 : // module owner.
3068 : bool writeToGlobalPrototype;
3069 :
3070 : // When writeToGlobalPrototype is true, we use this flag to temporarily
3071 : // disable the writeToGlobalPrototype behavior (when resolving standard
3072 : // classes, for example).
3073 : bool skipWriteToGlobalPrototype;
3074 :
3075 : // This scope corresponds to a WebExtension content script, and receives
3076 : // various bits of special compatibility behavior.
3077 : bool isWebExtensionContentScript;
3078 :
3079 : // Even if an add-on needs interposition, it does not necessary need it
3080 : // for every scope. If this flag is set we waive interposition for this
3081 : // scope.
3082 : bool waiveInterposition;
3083 :
3084 : // If CPOWs are disabled for browser code via the
3085 : // dom.ipc.cpows.forbid-unsafe-from-browser preferences, then only
3086 : // add-ons can use CPOWs. This flag allows a non-addon scope
3087 : // to opt into CPOWs. It's necessary for the implementation of
3088 : // RemoteAddonsParent.jsm.
3089 : bool allowCPOWs;
3090 :
3091 : // This is only ever set during mochitest runs when enablePrivilege is called.
3092 : // It's intended as a temporary stopgap measure until we can finish ripping out
3093 : // enablePrivilege. Once set, this value is never unset (i.e., it doesn't follow
3094 : // the old scoping rules of enablePrivilege).
3095 : //
3096 : // Using it in production is inherently unsafe.
3097 : bool universalXPConnectEnabled;
3098 :
3099 : // This is only ever set during mochitest runs when enablePrivilege is called.
3100 : // It allows the SpecialPowers scope to waive the normal chrome security
3101 : // wrappers and expose properties directly to content. This lets us avoid a
3102 : // bunch of overhead and complexity in our SpecialPowers automation glue.
3103 : //
3104 : // Using it in production is inherently unsafe.
3105 : bool forcePermissiveCOWs;
3106 :
3107 : // True if this compartment has been nuked. If true, any wrappers into or
3108 : // out of it should be considered invalid.
3109 : bool wasNuked;
3110 :
3111 : // Whether we've emitted a warning about a property that was filtered out
3112 : // by a security wrapper. See XrayWrapper.cpp.
3113 : bool wrapperDenialWarnings[WrapperDenialTypeCount];
3114 :
3115 : // The scriptability of this compartment.
3116 : Scriptability scriptability;
3117 :
3118 : // Our XPCWrappedNativeScope. This is non-null if and only if this is an
3119 : // XPConnect compartment.
3120 : XPCWrappedNativeScope* scope;
3121 :
3122 0 : const nsACString& GetLocation() {
3123 0 : if (location.IsEmpty() && locationURI) {
3124 :
3125 : nsCOMPtr<nsIXPConnectWrappedJS> jsLocationURI =
3126 0 : do_QueryInterface(locationURI);
3127 0 : if (jsLocationURI) {
3128 : // We cannot call into JS-implemented nsIURI objects, because
3129 : // we are iterating over the JS heap at this point.
3130 : location =
3131 0 : NS_LITERAL_CSTRING("<JS-implemented nsIURI location>");
3132 0 : } else if (NS_FAILED(locationURI->GetSpec(location))) {
3133 0 : location = NS_LITERAL_CSTRING("<unknown location>");
3134 : }
3135 : }
3136 0 : return location;
3137 : }
3138 : bool GetLocationURI(nsIURI** aURI) {
3139 : return GetLocationURI(LocationHintRegular, aURI);
3140 : }
3141 0 : bool GetLocationURI(LocationHint aLocationHint, nsIURI** aURI) {
3142 0 : if (locationURI) {
3143 0 : nsCOMPtr<nsIURI> rval = locationURI;
3144 0 : rval.forget(aURI);
3145 0 : return true;
3146 : }
3147 0 : return TryParseLocationURI(aLocationHint, aURI);
3148 : }
3149 285 : void SetLocation(const nsACString& aLocation) {
3150 285 : if (aLocation.IsEmpty())
3151 0 : return;
3152 285 : if (!location.IsEmpty() || locationURI)
3153 0 : return;
3154 285 : location = aLocation;
3155 : }
3156 7 : void SetLocationURI(nsIURI* aLocationURI) {
3157 7 : if (!aLocationURI)
3158 0 : return;
3159 7 : if (locationURI)
3160 0 : return;
3161 7 : locationURI = aLocationURI;
3162 : }
3163 :
3164 51288 : JSObject2WrappedJSMap* GetWrappedJSMap() const { return mWrappedJSMap; }
3165 : void UpdateWeakPointersAfterGC();
3166 :
3167 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
3168 :
3169 : private:
3170 : nsCString location;
3171 : nsCOMPtr<nsIURI> locationURI;
3172 : JSObject2WrappedJSMap* mWrappedJSMap;
3173 :
3174 : bool TryParseLocationURI(LocationHint aType, nsIURI** aURI);
3175 : };
3176 :
3177 : bool IsUniversalXPConnectEnabled(JSCompartment* compartment);
3178 : bool IsUniversalXPConnectEnabled(JSContext* cx);
3179 : bool EnableUniversalXPConnect(JSContext* cx);
3180 :
3181 : inline void
3182 2 : CrashIfNotInAutomation()
3183 : {
3184 2 : MOZ_RELEASE_ASSERT(IsInAutomation());
3185 2 : }
3186 :
3187 : inline XPCWrappedNativeScope*
3188 15039 : ObjectScope(JSObject* obj)
3189 : {
3190 15039 : return CompartmentPrivate::Get(obj)->scope;
3191 : }
3192 :
3193 : JSObject* NewOutObject(JSContext* cx);
3194 : bool IsOutObject(JSContext* cx, JSObject* obj);
3195 :
3196 : nsresult HasInstance(JSContext* cx, JS::HandleObject objArg, const nsID* iid, bool* bp);
3197 :
3198 : nsIPrincipal* GetObjectPrincipal(JSObject* obj);
3199 :
3200 : } // namespace xpc
3201 :
3202 : namespace mozilla {
3203 : namespace dom {
3204 : extern bool
3205 : DefineStaticJSVals(JSContext* cx);
3206 : } // namespace dom
3207 : } // namespace mozilla
3208 :
3209 : bool
3210 : xpc_LocalizeContext(JSContext* cx);
3211 : void
3212 : xpc_DelocalizeContext(JSContext* cx);
3213 :
3214 : /***************************************************************************/
3215 : // Inlines use the above - include last.
3216 :
3217 : #include "XPCInlines.h"
3218 :
3219 : /***************************************************************************/
3220 : // Maps have inlines that use the above - include last.
3221 :
3222 : #include "XPCMaps.h"
3223 :
3224 : /***************************************************************************/
3225 :
3226 : #endif /* xpcprivate_h___ */
|