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 : /* High level class and public functions implementation. */
8 :
9 : #include "mozilla/Assertions.h"
10 : #include "mozilla/Base64.h"
11 : #include "mozilla/Likely.h"
12 : #include "mozilla/Unused.h"
13 :
14 : #include "xpcprivate.h"
15 : #include "XPCWrapper.h"
16 : #include "jsfriendapi.h"
17 : #include "js/ProfilingStack.h"
18 : #include "GeckoProfiler.h"
19 : #include "nsJSEnvironment.h"
20 : #include "nsThreadUtils.h"
21 : #include "nsDOMJSUtils.h"
22 :
23 : #include "WrapperFactory.h"
24 : #include "AccessCheck.h"
25 :
26 : #include "mozilla/dom/BindingUtils.h"
27 : #include "mozilla/dom/DOMException.h"
28 : #include "mozilla/dom/DOMPrefs.h"
29 : #include "mozilla/dom/Exceptions.h"
30 : #include "mozilla/dom/Promise.h"
31 : #include "mozilla/dom/ResolveSystemBinding.h"
32 :
33 : #include "nsDOMMutationObserver.h"
34 : #include "nsICycleCollectorListener.h"
35 : #include "nsIObjectInputStream.h"
36 : #include "nsIObjectOutputStream.h"
37 : #include "nsScriptSecurityManager.h"
38 : #include "nsIPermissionManager.h"
39 : #include "nsIScriptError.h"
40 : #include "nsContentUtils.h"
41 : #include "nsScriptError.h"
42 :
43 : using namespace mozilla;
44 : using namespace mozilla::dom;
45 : using namespace xpc;
46 : using namespace JS;
47 :
48 121480 : NS_IMPL_ISUPPORTS(nsXPConnect, nsIXPConnect)
49 :
50 : nsXPConnect* nsXPConnect::gSelf = nullptr;
51 : bool nsXPConnect::gOnceAliveNowDead = false;
52 :
53 : // Global cache of the default script security manager (QI'd to
54 : // nsIScriptSecurityManager) and the system principal.
55 : nsIScriptSecurityManager* nsXPConnect::gScriptSecurityManager = nullptr;
56 : nsIPrincipal* nsXPConnect::gSystemPrincipal = nullptr;
57 :
58 : const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1";
59 : const char XPC_EXCEPTION_CONTRACTID[] = "@mozilla.org/js/xpc/Exception;1";
60 : const char XPC_CONSOLE_CONTRACTID[] = "@mozilla.org/consoleservice;1";
61 : const char XPC_SCRIPT_ERROR_CONTRACTID[] = "@mozilla.org/scripterror;1";
62 : const char XPC_ID_CONTRACTID[] = "@mozilla.org/js/xpc/ID;1";
63 : const char XPC_XPCONNECT_CONTRACTID[] = "@mozilla.org/js/xpc/XPConnect;1";
64 :
65 : /***************************************************************************/
66 :
67 : // This global should be used very sparingly: only to create and destroy
68 : // nsXPConnect and when creating a new cooperative (non-primary) XPCJSContext.
69 : static XPCJSContext* gPrimaryContext;
70 :
71 0 : nsXPConnect::nsXPConnect()
72 3 : : mShuttingDown(false)
73 : {
74 1 : XPCJSContext::InitTLS();
75 :
76 0 : #ifdef MOZ_GECKO_PROFILER
77 : JS::SetProfilingThreadCallbacks(profiler_register_thread, profiler_unregister_thread);
78 1 : #endif
79 0 :
80 0 : XPCJSContext* xpccx = XPCJSContext::NewXPCJSContext(nullptr);
81 : if (!xpccx) {
82 1 : MOZ_CRASH("Couldn't create XPCJSContext.");
83 0 : }
84 1 : gPrimaryContext = xpccx;
85 : mRuntime = xpccx->Runtime();
86 0 : }
87 :
88 0 : nsXPConnect::~nsXPConnect()
89 : {
90 0 : MOZ_ASSERT(XPCJSContext::Get() == gPrimaryContext);
91 :
92 : mRuntime->DeleteSingletonScopes();
93 :
94 : // In order to clean up everything properly, we need to GC twice: once now,
95 : // to clean anything that can go away on its own (like the Junk Scope, which
96 : // we unrooted above), and once after forcing a bunch of shutdown in
97 : // XPConnect, to clean the stuff we forcibly disconnected. The forced
98 0 : // shutdown code defaults to leaking in a number of situations, so we can't
99 : // get by with only the second GC. :-(
100 0 : mRuntime->GarbageCollect(JS::gcreason::XPCONNECT_SHUTDOWN);
101 0 :
102 0 : mShuttingDown = true;
103 : XPCWrappedNativeScope::SystemIsBeingShutDown();
104 : mRuntime->SystemIsBeingShutDown();
105 :
106 : // The above causes us to clean up a bunch of XPConnect data structures,
107 : // after which point we need to GC to clean everything up. We need to do
108 0 : // this before deleting the XPCJSContext, because doing so destroys the
109 : // maps that our finalize callback depends on.
110 0 : mRuntime->GarbageCollect(JS::gcreason::XPCONNECT_SHUTDOWN);
111 0 :
112 : NS_RELEASE(gSystemPrincipal);
113 : gScriptSecurityManager = nullptr;
114 0 :
115 : // shutdown the logging system
116 0 : XPC_LOG_FINISH();
117 :
118 0 : delete gPrimaryContext;
119 0 :
120 0 : MOZ_ASSERT(gSelf == this);
121 0 : gSelf = nullptr;
122 : gOnceAliveNowDead = true;
123 : }
124 :
125 1 : // static
126 : void
127 : nsXPConnect::InitStatics()
128 : {
129 : #ifdef NS_BUILD_REFCNT_LOGGING
130 0 : // These functions are used for reporting leaks, so we register them as early
131 : // as possible to avoid missing any classes' creations.
132 : js::SetLogCtorDtorFunctions(NS_LogCtor, NS_LogDtor);
133 1 : #endif
134 1 :
135 : gSelf = new nsXPConnect();
136 : gOnceAliveNowDead = false;
137 :
138 0 : // Initial extra ref to keep the singleton alive
139 : // balanced by explicit call to ReleaseXPConnectSingleton()
140 : NS_ADDREF(gSelf);
141 0 :
142 1 : // Fire up the SSM.
143 0 : nsScriptSecurityManager::InitStatics();
144 0 : gScriptSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
145 : gScriptSecurityManager->GetSystemPrincipal(&gSystemPrincipal);
146 0 : MOZ_RELEASE_ASSERT(gSystemPrincipal);
147 1 :
148 0 : JSContext* cx = XPCJSContext::Get()->Context();
149 1 : if (!JS::InitSelfHostedCode(cx))
150 0 : MOZ_CRASH("InitSelfHostedCode failed");
151 : if (!gSelf->mRuntime->InitializeStrings(cx))
152 : MOZ_CRASH("InitializeStrings failed");
153 1 :
154 0 : // Initialize our singleton scopes.
155 : gSelf->mRuntime->InitSingletonScopes();
156 : }
157 0 :
158 : already_AddRefed<nsXPConnect>
159 0 : nsXPConnect::GetSingleton()
160 : {
161 : return do_AddRef(nsXPConnect::XPConnect());
162 : }
163 :
164 0 : // static
165 : void
166 0 : nsXPConnect::ReleaseXPConnectSingleton()
167 0 : {
168 : nsXPConnect* xpc = gSelf;
169 0 : if (xpc) {
170 : nsrefcnt cnt;
171 0 : NS_RELEASE2(xpc, cnt);
172 : }
173 : }
174 :
175 0 : // static
176 : XPCJSRuntime*
177 22241 : nsXPConnect::GetRuntimeInstance()
178 22241 : {
179 : MOZ_RELEASE_ASSERT(NS_IsMainThread());
180 : return gSelf->mRuntime;
181 : }
182 :
183 365 : // static
184 : bool
185 365 : nsXPConnect::IsISupportsDescendant(const nsXPTInterfaceInfo* info)
186 : {
187 : return info && info->HasAncestor(NS_GET_IID(nsISupports));
188 : }
189 0 :
190 : void
191 0 : xpc::ErrorBase::Init(JSErrorBase* aReport)
192 0 : {
193 : if (!aReport->filename)
194 0 : mFileName.SetIsVoid(true);
195 : else
196 2 : CopyASCIItoUTF16(aReport->filename, mFileName);
197 2 :
198 0 : mLineNumber = aReport->lineno;
199 : mColumn = aReport->column;
200 : }
201 0 :
202 : void
203 0 : xpc::ErrorNote::Init(JSErrorNotes::Note* aNote)
204 : {
205 0 : xpc::ErrorBase::Init(aNote);
206 0 :
207 : ErrorNoteToMessageString(aNote, mErrorMsg);
208 : }
209 0 :
210 : void
211 : xpc::ErrorReport::Init(JSErrorReport* aReport, const char* aToStringResult,
212 0 : bool aIsChrome, uint64_t aWindowID)
213 1 : {
214 0 : xpc::ErrorBase::Init(aReport);
215 0 : mCategory = aIsChrome ? NS_LITERAL_CSTRING("chrome javascript")
216 : : NS_LITERAL_CSTRING("content javascript");
217 2 : mWindowID = aWindowID;
218 2 :
219 0 : ErrorReportToMessageString(aReport, mErrorMsg);
220 : if (mErrorMsg.IsEmpty() && aToStringResult) {
221 : AppendUTF8toUTF16(aToStringResult, mErrorMsg);
222 0 : }
223 0 :
224 : mSourceLine.Assign(aReport->linebuf(), aReport->linebufLength());
225 0 : const JSErrorFormatString* efs = js::GetErrorMessage(nullptr, aReport->errorNumber);
226 0 :
227 : if (efs == nullptr) {
228 0 : mErrorMsgName.AssignASCII("");
229 : } else {
230 : mErrorMsgName.AssignASCII(efs->name);
231 0 : }
232 0 :
233 : mFlags = aReport->flags;
234 4 : mIsMuted = aReport->isMuted;
235 0 :
236 : if (aReport->notes) {
237 : if (!mNotes.SetLength(aReport->notes->length(), fallible))
238 0 : return;
239 0 :
240 0 : size_t i = 0;
241 0 : for (auto&& note : *aReport->notes) {
242 : mNotes.ElementAt(i).Init(note.get());
243 : i++;
244 : }
245 : }
246 : }
247 0 :
248 : void
249 : xpc::ErrorReport::Init(JSContext* aCx, mozilla::dom::Exception* aException,
250 0 : bool aIsChrome, uint64_t aWindowID)
251 0 : {
252 0 : mCategory = aIsChrome ? NS_LITERAL_CSTRING("chrome javascript")
253 : : NS_LITERAL_CSTRING("content javascript");
254 0 : mWindowID = aWindowID;
255 :
256 0 : aException->GetErrorMessage(mErrorMsg);
257 0 :
258 0 : aException->GetFilename(aCx, mFileName);
259 : if (mFileName.IsEmpty()) {
260 0 : mFileName.SetIsVoid(true);
261 0 : }
262 : mLineNumber = aException->LineNumber(aCx);
263 0 : mColumn = aException->ColumnNumber();
264 0 :
265 : mFlags = JSREPORT_EXCEPTION;
266 : }
267 :
268 : static LazyLogModule gJSDiagnostics("JSDiagnostics");
269 0 :
270 : void
271 0 : xpc::ErrorBase::AppendErrorDetailsTo(nsCString& error)
272 0 : {
273 0 : error.Append(NS_LossyConvertUTF16toASCII(mFileName));
274 1 : error.AppendLiteral(", line ");
275 2 : error.AppendInt(mLineNumber, 10);
276 0 : error.AppendLiteral(": ");
277 : error.Append(NS_LossyConvertUTF16toASCII(mErrorMsg));
278 : }
279 0 :
280 : void
281 0 : xpc::ErrorNote::LogToStderr()
282 0 : {
283 : if (!DOMPrefs::DumpEnabled())
284 0 : return;
285 0 :
286 0 : nsAutoCString error;
287 : error.AssignLiteral("JavaScript note: ");
288 0 : AppendErrorDetailsTo(error);
289 0 :
290 : fprintf(stderr, "%s\n", error.get());
291 : fflush(stderr);
292 : }
293 1 :
294 : void
295 0 : xpc::ErrorReport::LogToStderr()
296 0 : {
297 : if (!DOMPrefs::DumpEnabled())
298 0 : return;
299 0 :
300 0 : nsAutoCString error;
301 0 : error.AssignLiteral("JavaScript ");
302 0 : if (JSREPORT_IS_STRICT(mFlags))
303 0 : error.AppendLiteral("strict ");
304 : if (JSREPORT_IS_WARNING(mFlags))
305 0 : error.AppendLiteral("warning: ");
306 0 : else
307 : error.AppendLiteral("error: ");
308 0 : AppendErrorDetailsTo(error);
309 0 :
310 : fprintf(stderr, "%s\n", error.get());
311 2 : fflush(stderr);
312 0 :
313 0 : for (size_t i = 0, len = mNotes.Length(); i < len; i++) {
314 : ErrorNote& note = mNotes[i];
315 : note.LogToStderr();
316 : }
317 : }
318 0 :
319 : void
320 0 : xpc::ErrorReport::LogToConsole()
321 1 : {
322 : LogToConsoleWithStack(nullptr);
323 1 : }
324 : void
325 1 : xpc::ErrorReport::LogToConsoleWithStack(JS::HandleObject aStack)
326 : {
327 1 : LogToStderr();
328 :
329 : MOZ_LOG(gJSDiagnostics,
330 : JSREPORT_IS_WARNING(mFlags) ? LogLevel::Warning : LogLevel::Error,
331 : ("file %s, line %u\n%s", NS_LossyConvertUTF16toASCII(mFileName).get(),
332 : mLineNumber, NS_LossyConvertUTF16toASCII(mErrorMsg).get()));
333 :
334 : // Log to the console. We do this last so that we can simply return if
335 : // there's no console service without affecting the other reporting
336 0 : // mechanisms.
337 0 : nsCOMPtr<nsIConsoleService> consoleService =
338 : do_GetService(NS_CONSOLESERVICE_CONTRACTID);
339 2 : NS_ENSURE_TRUE_VOID(consoleService);
340 1 :
341 : RefPtr<nsScriptErrorBase> errorObject;
342 : if (mWindowID && aStack) {
343 : // Only set stack on messages related to a document
344 : // As we cache messages in the console service,
345 0 : // we have to ensure not leaking them after the related
346 : // context is destroyed and we only track document lifecycle for now.
347 1 : errorObject = new nsScriptErrorWithStack(aStack);
348 : } else {
349 1 : errorObject = new nsScriptError();
350 : }
351 0 : errorObject->SetErrorMessageName(mErrorMsgName);
352 :
353 0 : nsresult rv = errorObject->InitWithWindowID(mErrorMsg, mFileName, mSourceLine,
354 0 : mLineNumber, mColumn, mFlags,
355 : mCategory, mWindowID);
356 0 : NS_ENSURE_SUCCESS_VOID(rv);
357 0 :
358 : for (size_t i = 0, len = mNotes.Length(); i < len; i++) {
359 0 : ErrorNote& note = mNotes[i];
360 0 :
361 0 : nsScriptErrorNote* noteObject = new nsScriptErrorNote();
362 0 : noteObject->Init(note.mErrorMsg, note.mFileName,
363 : note.mLineNumber, note.mColumn);
364 : errorObject->AddNote(noteObject);
365 2 : }
366 :
367 : consoleService->LogMessage(errorObject);
368 :
369 : }
370 :
371 0 : /* static */
372 : void
373 : xpc::ErrorNote::ErrorNoteToMessageString(JSErrorNotes::Note* aNote,
374 0 : nsAString& aString)
375 0 : {
376 0 : aString.Truncate();
377 0 : if (aNote->message())
378 : aString.Append(NS_ConvertUTF8toUTF16(aNote->message().c_str()));
379 : }
380 :
381 0 : /* static */
382 : void
383 : xpc::ErrorReport::ErrorReportToMessageString(JSErrorReport* aReport,
384 0 : nsAString& aString)
385 0 : {
386 0 : aString.Truncate();
387 2 : if (aReport->message()) {
388 0 : JSFlatString* name = js::GetErrorTypeName(CycleCollectedJSContext::Get()->Context(), aReport->exnType);
389 2 : if (name) {
390 : AssignJSFlatString(aString, name);
391 4 : aString.AppendLiteral(": ");
392 : }
393 2 : aString.Append(NS_ConvertUTF8toUTF16(aReport->message().c_str()));
394 : }
395 : }
396 :
397 : /***************************************************************************/
398 :
399 0 :
400 : void
401 : xpc_TryUnmarkWrappedGrayObject(nsISupports* aWrappedJS)
402 : {
403 0 : // QIing to nsIXPConnectWrappedJSUnmarkGray may have side effects!
404 : nsCOMPtr<nsIXPConnectWrappedJSUnmarkGray> wjsug =
405 0 : do_QueryInterface(aWrappedJS);
406 : Unused << wjsug;
407 0 : MOZ_ASSERT(!wjsug, "One should never be able to QI to "
408 : "nsIXPConnectWrappedJSUnmarkGray successfully!");
409 : }
410 :
411 : /***************************************************************************/
412 : /***************************************************************************/
413 : // nsIXPConnect interface methods...
414 0 :
415 : template<typename T>
416 0 : static inline T UnexpectedFailure(T rv)
417 0 : {
418 : NS_ERROR("This is not supposed to fail!");
419 : return rv;
420 : }
421 0 :
422 : void
423 18 : xpc::TraceXPCGlobal(JSTracer* trc, JSObject* obj)
424 18 : {
425 : if (js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL)
426 : mozilla::dom::TraceProtoAndIfaceCache(trc, obj);
427 :
428 : // We might be called from a GC during the creation of a global, before we've
429 0 : // been able to set up the compartment private or the XPCWrappedNativeScope,
430 18 : // so we need to null-check those.
431 18 : xpc::RealmPrivate* realmPrivate = xpc::RealmPrivate::Get(obj);
432 18 : if (realmPrivate && realmPrivate->scope)
433 : realmPrivate->scope->TraceInside(trc);
434 : }
435 :
436 :
437 : namespace xpc {
438 0 :
439 : JSObject*
440 : CreateGlobalObject(JSContext* cx, const JSClass* clasp, nsIPrincipal* principal,
441 0 : JS::RealmOptions& aOptions)
442 20 : {
443 : MOZ_ASSERT(NS_IsMainThread(), "using a principal off the main thread?");
444 20 : MOZ_ASSERT(principal);
445 :
446 : MOZ_RELEASE_ASSERT(principal != nsContentUtils::GetNullSubjectPrincipal(),
447 : "The null subject principal is getting inherited - fix that!");
448 40 :
449 0 : RootedObject global(cx,
450 20 : JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal),
451 : JS::DontFireOnNewGlobalHook, aOptions));
452 60 : if (!global)
453 : return nullptr;
454 : JSAutoRealm ar(cx, global);
455 :
456 40 : // The constructor automatically attaches the scope to the compartment private
457 : // of |global|.
458 20 : (void) new XPCWrappedNativeScope(cx, global);
459 :
460 : if (clasp->flags & JSCLASS_DOM_GLOBAL) {
461 : #ifdef DEBUG
462 : // Verify that the right trace hook is called. Note that this doesn't
463 : // work right for wrapped globals, since the tracing situation there is
464 : // more complicated. Manual inspection shows that they do the right
465 : // thing. Also note that we only check this for JSCLASS_DOM_GLOBAL
466 0 : // classes because xpc::TraceXPCGlobal won't call
467 : // TraceProtoAndIfaceCache unless that flag is set.
468 18 : if (!((const js::Class*)clasp)->isWrappedNative())
469 18 : {
470 18 : VerifyTraceProtoAndIfaceCacheCalledTracer trc(cx);
471 : TraceChildren(&trc, GCCellPtr(global.get()));
472 : MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
473 : }
474 0 : #endif
475 38 :
476 0 : const char* className = clasp->name;
477 19 : AllocateProtoAndIfaceCache(global,
478 : (strcmp(className, "Window") == 0 ||
479 0 : strcmp(className, "ChromeWindow") == 0)
480 : ? ProtoAndIfaceCache::WindowLike
481 : : ProtoAndIfaceCache::NonWindowLike);
482 20 : }
483 :
484 : return global;
485 : }
486 0 :
487 : void
488 : InitGlobalObjectOptions(JS::RealmOptions& aOptions,
489 0 : nsIPrincipal* aPrincipal)
490 19 : {
491 : bool shouldDiscardSystemSource = ShouldDiscardSystemSource();
492 19 : bool extraWarningsForSystemJS = ExtraWarningsForSystemJS();
493 :
494 0 : bool isSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
495 :
496 24 : if (isSystem) {
497 0 : // Make sure [SecureContext] APIs are visible:
498 : aOptions.creationOptions().setSecureContext(true);
499 : aOptions.creationOptions().setClampAndJitterTime(false);
500 0 : }
501 0 :
502 : if (shouldDiscardSystemSource) {
503 0 : bool discardSource = isSystem;
504 :
505 : aOptions.behaviors().setDiscardSource(discardSource);
506 19 : }
507 0 :
508 0 : if (extraWarningsForSystemJS) {
509 : if (isSystem)
510 0 : aOptions.behaviors().extraWarningsOverride().set(true);
511 : }
512 : }
513 19 :
514 : bool
515 : InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal, uint32_t aFlags)
516 : {
517 0 : // Immediately enter the global's realm so that everything we create
518 : // ends up there.
519 : JSAutoRealm ar(aJSContext, aGlobal);
520 38 :
521 : // Stuff coming through this path always ends up as a DOM global.
522 0 : MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL);
523 :
524 24 : if (!(aFlags & xpc::OMIT_COMPONENTS_OBJECT)) {
525 12 : // XPCCallContext gives us an active request needed to save/restore.
526 0 : if (!RealmPrivate::Get(aGlobal)->scope->AttachComponentsObject(aJSContext) ||
527 : !XPCNativeWrapper::AttachNewConstructorObject(aJSContext, aGlobal)) {
528 : return UnexpectedFailure(false);
529 : }
530 19 : }
531 4 :
532 : if (!(aFlags & xpc::DONT_FIRE_ONNEWGLOBALHOOK))
533 : JS_FireOnNewGlobalObject(aJSContext, aGlobal);
534 :
535 : return true;
536 : }
537 1 :
538 : nsresult
539 : InitClassesWithNewWrappedGlobal(JSContext* aJSContext,
540 : nsISupports* aCOMObj,
541 : nsIPrincipal* aPrincipal,
542 : uint32_t aFlags,
543 : JS::RealmOptions& aOptions,
544 1 : MutableHandleObject aNewGlobal)
545 1 : {
546 : MOZ_ASSERT(aJSContext, "bad param");
547 : MOZ_ASSERT(aCOMObj, "bad param");
548 :
549 1 : // We pass null for the 'extra' pointer during global object creation, so
550 : // we need to have a principal.
551 1 : MOZ_ASSERT(aPrincipal);
552 :
553 : if (!SystemBindingInitIds(aJSContext)) {
554 : return NS_ERROR_FAILURE;
555 1 : }
556 :
557 : InitGlobalObjectOptions(aOptions, aPrincipal);
558 :
559 1 : // Call into XPCWrappedNative to make a new global object, scope, and global
560 0 : // prototype.
561 0 : xpcObjectHelper helper(aCOMObj);
562 : MOZ_ASSERT(helper.GetScriptableFlags() & XPC_SCRIPTABLE_IS_GLOBAL_OBJECT);
563 0 : RefPtr<XPCWrappedNative> wrappedGlobal;
564 1 : nsresult rv =
565 2 : XPCWrappedNative::WrapNewGlobal(helper, aPrincipal,
566 0 : aFlags & xpc::INIT_JS_STANDARD_CLASSES,
567 : aOptions, getter_AddRefs(wrappedGlobal));
568 : NS_ENSURE_SUCCESS(rv, rv);
569 0 :
570 1 : // Grab a copy of the global and enter its compartment.
571 : RootedObject global(aJSContext, wrappedGlobal->GetFlatJSObject());
572 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
573 0 :
574 : if (!InitGlobalObject(aJSContext, global, aFlags))
575 1 : return UnexpectedFailure(NS_ERROR_FAILURE);
576 1 :
577 : aNewGlobal.set(global);
578 : return NS_OK;
579 : }
580 :
581 : } // namespace xpc
582 1668 :
583 : static nsresult
584 : NativeInterface2JSObject(HandleObject aScope,
585 : nsISupports* aCOMObj,
586 : nsWrapperCache* aCache,
587 : const nsIID * aIID,
588 : bool aAllowWrapping,
589 3336 : MutableHandleValue aVal)
590 0 : {
591 : AutoJSContext cx;
592 : JSAutoRealm ar(cx, aScope);
593 3336 :
594 0 : nsresult rv;
595 0 : xpcObjectHelper helper(aCOMObj, aCache);
596 : if (!XPCConvert::NativeInterface2JSObject(aVal, helper, aIID, aAllowWrapping, &rv))
597 1668 : return rv;
598 :
599 : MOZ_ASSERT(aAllowWrapping || !xpc::WrapperFactory::IsXrayWrapper(&aVal.toObject()),
600 : "Shouldn't be returning a xray wrapper here");
601 :
602 : return NS_OK;
603 : }
604 595 :
605 : NS_IMETHODIMP
606 : nsXPConnect::WrapNative(JSContext * aJSContext,
607 : JSObject * aScopeArg,
608 : nsISupports* aCOMObj,
609 : const nsIID & aIID,
610 595 : JSObject** aRetVal)
611 0 : {
612 0 : MOZ_ASSERT(aJSContext, "bad param");
613 : MOZ_ASSERT(aScopeArg, "bad param");
614 0 : MOZ_ASSERT(aCOMObj, "bad param");
615 0 :
616 1785 : RootedObject aScope(aJSContext, aScopeArg);
617 595 : RootedValue v(aJSContext);
618 0 : nsresult rv = NativeInterface2JSObject(aScope, aCOMObj, nullptr, &aIID,
619 : true, &v);
620 : if (NS_FAILED(rv))
621 0 : return rv;
622 :
623 : if (!v.isObjectOrNull())
624 595 : return NS_ERROR_FAILURE;
625 595 :
626 : *aRetVal = v.toObjectOrNull();
627 : return NS_OK;
628 : }
629 1073 :
630 : NS_IMETHODIMP
631 : nsXPConnect::WrapNativeToJSVal(JSContext* aJSContext,
632 : JSObject* aScopeArg,
633 : nsISupports* aCOMObj,
634 : nsWrapperCache* aCache,
635 : const nsIID* aIID,
636 : bool aAllowWrapping,
637 1073 : MutableHandleValue aVal)
638 0 : {
639 0 : MOZ_ASSERT(aJSContext, "bad param");
640 : MOZ_ASSERT(aScopeArg, "bad param");
641 2146 : MOZ_ASSERT(aCOMObj, "bad param");
642 3219 :
643 2146 : RootedObject aScope(aJSContext, aScopeArg);
644 : return NativeInterface2JSObject(aScope, aCOMObj, aCache, aIID,
645 : aAllowWrapping, aVal);
646 : }
647 32 :
648 : NS_IMETHODIMP
649 : nsXPConnect::WrapJS(JSContext * aJSContext,
650 : JSObject * aJSObjArg,
651 : const nsIID & aIID,
652 32 : void * *result)
653 0 : {
654 32 : MOZ_ASSERT(aJSContext, "bad param");
655 : MOZ_ASSERT(aJSObjArg, "bad param");
656 0 : MOZ_ASSERT(result, "bad param");
657 :
658 0 : *result = nullptr;
659 0 :
660 : RootedObject aJSObj(aJSContext, aJSObjArg);
661 1 : JSAutoRealm ar(aJSContext, aJSObj);
662 32 :
663 : nsresult rv = NS_ERROR_UNEXPECTED;
664 0 : if (!XPCConvert::JSObject2NativeInterface(result, aJSObj,
665 : &aIID, nullptr, &rv))
666 : return rv;
667 : return NS_OK;
668 : }
669 0 :
670 : NS_IMETHODIMP
671 : nsXPConnect::JSValToVariant(JSContext* cx,
672 : HandleValue aJSVal,
673 0 : nsIVariant** aResult)
674 : {
675 0 : MOZ_ASSERT(aResult, "bad param");
676 0 :
677 0 : RefPtr<XPCVariant> variant = XPCVariant::newVariant(cx, aJSVal);
678 : variant.forget(aResult);
679 : NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
680 :
681 : return NS_OK;
682 : }
683 14 :
684 : NS_IMETHODIMP
685 : nsXPConnect::WrapJSAggregatedToNative(nsISupports* aOuter,
686 : JSContext* aJSContext,
687 : JSObject* aJSObjArg,
688 : const nsIID& aIID,
689 0 : void** result)
690 14 : {
691 0 : MOZ_ASSERT(aOuter, "bad param");
692 14 : MOZ_ASSERT(aJSContext, "bad param");
693 : MOZ_ASSERT(aJSObjArg, "bad param");
694 14 : MOZ_ASSERT(result, "bad param");
695 :
696 28 : *result = nullptr;
697 :
698 28 : RootedObject aJSObj(aJSContext, aJSObjArg);
699 : nsresult rv;
700 0 : if (!XPCConvert::JSObject2NativeInterface(result, aJSObj,
701 : &aIID, aOuter, &rv))
702 : return rv;
703 : return NS_OK;
704 : }
705 71 :
706 : NS_IMETHODIMP
707 : nsXPConnect::GetWrappedNativeOfJSObject(JSContext * aJSContext,
708 : JSObject * aJSObjArg,
709 71 : nsIXPConnectWrappedNative** _retval)
710 0 : {
711 0 : MOZ_ASSERT(aJSContext, "bad param");
712 : MOZ_ASSERT(aJSObjArg, "bad param");
713 0 : MOZ_ASSERT(_retval, "bad param");
714 0 :
715 142 : RootedObject aJSObj(aJSContext, aJSObjArg);
716 0 : aJSObj = js::CheckedUnwrap(aJSObj, /* stopAtWindowProxy = */ false);
717 0 : if (!aJSObj || !IS_WN_REFLECTOR(aJSObj)) {
718 : *_retval = nullptr;
719 : return NS_ERROR_FAILURE;
720 142 : }
721 71 :
722 : RefPtr<XPCWrappedNative> temp = XPCWrappedNative::Get(aJSObj);
723 : temp.forget(_retval);
724 : return NS_OK;
725 : }
726 0 :
727 : already_AddRefed<nsISupports>
728 : xpc::UnwrapReflectorToISupports(JSObject* reflector)
729 751 : {
730 751 : // Unwrap security wrappers, if allowed.
731 : reflector = js::CheckedUnwrap(reflector, /* stopAtWindowProxy = */ false);
732 : if (!reflector)
733 : return nullptr;
734 751 :
735 0 : // Try XPCWrappedNatives.
736 0 : if (IS_WN_REFLECTOR(reflector)) {
737 : XPCWrappedNative* wn = XPCWrappedNative::Get(reflector);
738 1334 : if (!wn)
739 667 : return nullptr;
740 : nsCOMPtr<nsISupports> native = wn->Native();
741 : return native.forget();
742 : }
743 :
744 : // Try DOM objects. This QI without taking a ref first is safe, because
745 : // this if non-null our thing will definitely be a DOM object, and we know
746 168 : // their QI to nsISupports doesn't do anything weird.
747 84 : nsCOMPtr<nsISupports> canonical =
748 : do_QueryInterface(mozilla::dom::UnwrapDOMObjectToISupports(reflector));
749 : return canonical.forget();
750 : }
751 0 :
752 : NS_IMETHODIMP
753 : nsXPConnect::CreateSandbox(JSContext* cx, nsIPrincipal* principal,
754 0 : JSObject** _retval)
755 : {
756 0 : *_retval = nullptr;
757 0 :
758 0 : RootedValue rval(cx);
759 0 : SandboxOptions options;
760 : nsresult rv = CreateSandboxObject(cx, &rval, principal, options);
761 : MOZ_ASSERT(NS_FAILED(rv) || !rval.isPrimitive(),
762 0 : "Bad return value from xpc_CreateSandboxObject()!");
763 0 :
764 : if (NS_SUCCEEDED(rv) && !rval.isPrimitive()) {
765 : *_retval = rval.toObjectOrNull();
766 0 : }
767 :
768 : return rv;
769 : }
770 0 :
771 : NS_IMETHODIMP
772 : nsXPConnect::EvalInSandboxObject(const nsAString& source, const char* filename,
773 : JSContext* cx, JSObject* sandboxArg,
774 0 : MutableHandleValue rval)
775 : {
776 : if (!sandboxArg)
777 0 : return NS_ERROR_INVALID_ARG;
778 0 :
779 0 : RootedObject sandbox(cx, sandboxArg);
780 0 : nsCString filenameStr;
781 : if (filename) {
782 0 : filenameStr.Assign(filename);
783 : } else {
784 0 : filenameStr = NS_LITERAL_CSTRING("x-bogus://XPConnect/Sandbox");
785 : }
786 : return EvalInSandbox(cx, sandbox, source, filenameStr, 1, rval);
787 : }
788 0 :
789 : NS_IMETHODIMP
790 : nsXPConnect::GetWrappedNativePrototype(JSContext* aJSContext,
791 : JSObject* aScopeArg,
792 : nsIClassInfo* aClassInfo,
793 0 : JSObject** aRetVal)
794 0 : {
795 : RootedObject aScope(aJSContext, aScopeArg);
796 0 : JSAutoRealm ar(aJSContext, aScope);
797 0 :
798 0 : XPCWrappedNativeScope* scope = ObjectScope(aScope);
799 : if (!scope)
800 : return UnexpectedFailure(NS_ERROR_FAILURE);
801 0 :
802 : nsCOMPtr<nsIXPCScriptable> scrProto =
803 0 : XPCWrappedNative::GatherProtoScriptable(aClassInfo);
804 0 :
805 0 : AutoMarkingWrappedNativeProtoPtr proto(aJSContext);
806 0 : proto = XPCWrappedNativeProto::GetNewOrUsed(scope, aClassInfo, scrProto);
807 : if (!proto)
808 0 : return UnexpectedFailure(NS_ERROR_FAILURE);
809 0 :
810 0 : JSObject* protoObj = proto->GetJSProtoObject();
811 : if (!protoObj)
812 0 : return UnexpectedFailure(NS_ERROR_FAILURE);
813 :
814 0 : *aRetVal = protoObj;
815 :
816 : return NS_OK;
817 : }
818 0 :
819 : NS_IMETHODIMP
820 : nsXPConnect::DebugDump(int16_t depth)
821 0 : {
822 0 : #ifdef DEBUG
823 0 : depth-- ;
824 0 : XPC_LOG_ALWAYS(("nsXPConnect @ %p with mRefCnt = %" PRIuPTR, this, mRefCnt.get()));
825 0 : XPC_LOG_INDENT();
826 0 : XPC_LOG_ALWAYS(("gSelf @ %p", gSelf));
827 0 : XPC_LOG_ALWAYS(("gOnceAliveNowDead is %d", (int)gOnceAliveNowDead));
828 : XPCWrappedNativeScope::DebugDumpAllScopes(depth);
829 0 : XPC_LOG_OUTDENT();
830 : #endif
831 : return NS_OK;
832 : }
833 0 :
834 : NS_IMETHODIMP
835 : nsXPConnect::DebugDumpObject(nsISupports* p, int16_t depth)
836 0 : {
837 : #ifdef DEBUG
838 0 : if (!depth)
839 0 : return NS_OK;
840 : if (!p) {
841 : XPC_LOG_ALWAYS(("*** Cound not dump object with NULL address"));
842 : return NS_OK;
843 0 : }
844 0 :
845 0 : nsCOMPtr<nsIXPConnect> xpc;
846 0 : nsCOMPtr<nsIXPCWrappedJSClass> wjsc;
847 : nsCOMPtr<nsIXPConnectWrappedNative> wn;
848 0 : nsCOMPtr<nsIXPConnectWrappedJS> wjs;
849 :
850 0 : if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnect),
851 0 : getter_AddRefs(xpc)))) {
852 0 : XPC_LOG_ALWAYS(("Dumping a nsIXPConnect..."));
853 : xpc->DebugDump(depth);
854 0 : } else if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPCWrappedJSClass),
855 0 : getter_AddRefs(wjsc)))) {
856 0 : XPC_LOG_ALWAYS(("Dumping a nsIXPCWrappedJSClass..."));
857 : wjsc->DebugDump(depth);
858 0 : } else if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnectWrappedNative),
859 0 : getter_AddRefs(wn)))) {
860 0 : XPC_LOG_ALWAYS(("Dumping a nsIXPConnectWrappedNative..."));
861 : wn->DebugDump(depth);
862 0 : } else if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnectWrappedJS),
863 0 : getter_AddRefs(wjs)))) {
864 : XPC_LOG_ALWAYS(("Dumping a nsIXPConnectWrappedJS..."));
865 0 : wjs->DebugDump(depth);
866 : } else {
867 : XPC_LOG_ALWAYS(("*** Could not dump the nsISupports @ %p", p));
868 : }
869 : #endif
870 : return NS_OK;
871 : }
872 0 :
873 : NS_IMETHODIMP
874 : nsXPConnect::DebugDumpJSStack(bool showArgs,
875 : bool showLocals,
876 0 : bool showThisProps)
877 : {
878 0 : xpc_DumpJSStack(showArgs, showLocals, showThisProps);
879 :
880 : return NS_OK;
881 : }
882 0 :
883 : NS_IMETHODIMP
884 : nsXPConnect::VariantToJS(JSContext* ctx, JSObject* scopeArg, nsIVariant* value,
885 0 : MutableHandleValue _retval)
886 0 : {
887 0 : MOZ_ASSERT(ctx, "bad param");
888 : MOZ_ASSERT(scopeArg, "bad param");
889 0 : MOZ_ASSERT(value, "bad param");
890 0 :
891 : RootedObject scope(ctx, scopeArg);
892 0 : MOZ_ASSERT(js::IsObjectInContextCompartment(scope, ctx));
893 0 :
894 0 : nsresult rv = NS_OK;
895 0 : if (!XPCVariant::VariantDataToJS(value, &rv, _retval)) {
896 : if (NS_FAILED(rv))
897 : return rv;
898 :
899 : return NS_ERROR_FAILURE;
900 : }
901 : return NS_OK;
902 : }
903 0 :
904 : NS_IMETHODIMP
905 0 : nsXPConnect::JSToVariant(JSContext* ctx, HandleValue value, nsIVariant** _retval)
906 0 : {
907 : MOZ_ASSERT(ctx, "bad param");
908 15 : MOZ_ASSERT(_retval, "bad param");
909 5 :
910 0 : RefPtr<XPCVariant> variant = XPCVariant::newVariant(ctx, value);
911 : variant.forget(_retval);
912 : if (!(*_retval))
913 5 : return NS_ERROR_FAILURE;
914 :
915 : return NS_OK;
916 : }
917 :
918 : namespace xpc {
919 0 :
920 : bool
921 0 : Base64Encode(JSContext* cx, HandleValue val, MutableHandleValue out)
922 : {
923 0 : MOZ_ASSERT(cx);
924 0 :
925 : nsAutoCString encodedString;
926 : if (!ConvertJSValueToByteString(cx, val, false, encodedString)) {
927 : return false;
928 0 : }
929 0 :
930 0 : nsAutoCString result;
931 0 : if (NS_FAILED(mozilla::Base64Encode(encodedString, result))) {
932 : JS_ReportErrorASCII(cx, "Failed to encode base64 data!");
933 : return false;
934 0 : }
935 0 :
936 : JSString* str = JS_NewStringCopyN(cx, result.get(), result.Length());
937 : if (!str)
938 0 : return false;
939 0 :
940 : out.setString(str);
941 : return true;
942 : }
943 0 :
944 : bool
945 0 : Base64Decode(JSContext* cx, HandleValue val, MutableHandleValue out)
946 : {
947 0 : MOZ_ASSERT(cx);
948 0 :
949 : nsAutoCString encodedString;
950 : if (!ConvertJSValueToByteString(cx, val, false, encodedString)) {
951 : return false;
952 0 : }
953 0 :
954 0 : nsAutoCString result;
955 0 : if (NS_FAILED(mozilla::Base64Decode(encodedString, result))) {
956 : JS_ReportErrorASCII(cx, "Failed to decode base64 string!");
957 : return false;
958 0 : }
959 0 :
960 : JSString* str = JS_NewStringCopyN(cx, result.get(), result.Length());
961 : if (!str)
962 0 : return false;
963 0 :
964 : out.setString(str);
965 : return true;
966 : }
967 0 :
968 : void
969 23 : SetLocationForGlobal(JSObject* global, const nsACString& location)
970 23 : {
971 0 : MOZ_ASSERT(global);
972 : RealmPrivate::Get(global)->SetLocation(location);
973 : }
974 0 :
975 : void
976 14 : SetLocationForGlobal(JSObject* global, nsIURI* locationURI)
977 14 : {
978 14 : MOZ_ASSERT(global);
979 : RealmPrivate::Get(global)->SetLocationURI(locationURI);
980 : }
981 :
982 : } // namespace xpc
983 786 :
984 : static nsresult
985 : WriteScriptOrFunction(nsIObjectOutputStream* stream, JSContext* cx,
986 : JSScript* scriptArg, HandleObject functionObj)
987 0 : {
988 : // Exactly one of script or functionObj must be given
989 0 : MOZ_ASSERT(!scriptArg != !functionObj);
990 786 :
991 1566 : RootedScript script(cx, scriptArg);
992 0 : if (!script) {
993 : RootedFunction fun(cx, JS_GetObjectFunction(functionObj));
994 : script.set(JS_GetFunctionScript(cx, fun));
995 786 : }
996 786 :
997 786 : uint8_t flags = 0; // We don't have flags anymore.
998 : nsresult rv = stream->Write8(flags);
999 : if (NS_FAILED(rv))
1000 : return rv;
1001 0 :
1002 :
1003 : TranscodeBuffer buffer;
1004 0 : TranscodeResult code;
1005 783 : {
1006 : if (functionObj)
1007 0 : code = EncodeInterpretedFunction(cx, buffer, functionObj);
1008 : else
1009 : code = EncodeScript(cx, buffer, script);
1010 1 : }
1011 0 :
1012 : if (code != TranscodeResult_Ok) {
1013 0 : if ((code & TranscodeResult_Failure) != 0)
1014 0 : return NS_ERROR_FAILURE;
1015 0 : MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
1016 : JS_ClearPendingException(cx);
1017 : return NS_ERROR_OUT_OF_MEMORY;
1018 0 : }
1019 0 :
1020 : size_t size = buffer.length();
1021 786 : if (size > UINT32_MAX)
1022 786 : return NS_ERROR_FAILURE;
1023 786 : rv = stream->Write32(size);
1024 : if (NS_SUCCEEDED(rv))
1025 : rv = stream->WriteBytes(reinterpret_cast<char*>(buffer.begin()), size);
1026 :
1027 : return rv;
1028 : }
1029 0 :
1030 : static nsresult
1031 : ReadScriptOrFunction(nsIObjectInputStream* stream, JSContext* cx,
1032 : JSScript** scriptp, JSObject** functionObjp)
1033 0 : {
1034 : // Exactly one of script or functionObj must be given
1035 : MOZ_ASSERT(!scriptp != !functionObjp);
1036 0 :
1037 0 : uint8_t flags;
1038 : nsresult rv = stream->Read8(&flags);
1039 : if (NS_FAILED(rv))
1040 : return rv;
1041 :
1042 : // We don't serialize mutedError-ness of scripts, which is fine as long as
1043 0 : // we only serialize system and XUL-y things. We can detect this by checking
1044 : // where the caller wants us to deserialize.
1045 : MOZ_RELEASE_ASSERT(nsContentUtils::IsSystemCaller(cx) ||
1046 : CurrentGlobalOrNull(cx) == xpc::CompilationScope());
1047 0 :
1048 0 : uint32_t size;
1049 : rv = stream->Read32(&size);
1050 : if (NS_FAILED(rv))
1051 : return rv;
1052 0 :
1053 0 : char* data;
1054 : rv = stream->ReadBytes(size, &data);
1055 : if (NS_FAILED(rv))
1056 0 : return rv;
1057 0 :
1058 : TranscodeBuffer buffer;
1059 : buffer.replaceRawBuffer(reinterpret_cast<uint8_t*>(data), size);
1060 :
1061 0 : {
1062 0 : TranscodeResult code;
1063 0 : if (scriptp) {
1064 0 : Rooted<JSScript*> script(cx);
1065 0 : code = DecodeScript(cx, buffer, &script);
1066 : if (code == TranscodeResult_Ok)
1067 0 : *scriptp = script.get();
1068 0 : } else {
1069 0 : Rooted<JSFunction*> funobj(cx);
1070 0 : code = DecodeInterpretedFunction(cx, buffer, &funobj);
1071 : if (code == TranscodeResult_Ok)
1072 : *functionObjp = JS_GetFunctionObject(funobj.get());
1073 0 : }
1074 0 :
1075 : if (code != TranscodeResult_Ok) {
1076 0 : if ((code & TranscodeResult_Failure) != 0)
1077 0 : return NS_ERROR_FAILURE;
1078 0 : MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
1079 : JS_ClearPendingException(cx);
1080 : return NS_ERROR_OUT_OF_MEMORY;
1081 : }
1082 : }
1083 :
1084 : return rv;
1085 : }
1086 3 :
1087 : NS_IMETHODIMP
1088 3 : nsXPConnect::WriteScript(nsIObjectOutputStream* stream, JSContext* cx, JSScript* script)
1089 : {
1090 : return WriteScriptOrFunction(stream, cx, script, nullptr);
1091 : }
1092 0 :
1093 : NS_IMETHODIMP
1094 0 : nsXPConnect::ReadScript(nsIObjectInputStream* stream, JSContext* cx, JSScript** scriptp)
1095 : {
1096 : return ReadScriptOrFunction(stream, cx, scriptp, nullptr);
1097 : }
1098 0 :
1099 : NS_IMETHODIMP
1100 1566 : nsXPConnect::WriteFunction(nsIObjectOutputStream* stream, JSContext* cx, JSObject* functionObjArg)
1101 1566 : {
1102 : RootedObject functionObj(cx, functionObjArg);
1103 : return WriteScriptOrFunction(stream, cx, nullptr, functionObj);
1104 : }
1105 0 :
1106 : NS_IMETHODIMP
1107 0 : nsXPConnect::ReadFunction(nsIObjectInputStream* stream, JSContext* cx, JSObject** functionObjp)
1108 : {
1109 : return ReadScriptOrFunction(stream, cx, nullptr, functionObjp);
1110 : }
1111 :
1112 : /* These are here to be callable from a debugger */
1113 : extern "C" {
1114 0 :
1115 : MOZ_EXPORT void
1116 0 : DumpJSStack()
1117 0 : {
1118 : xpc_DumpJSStack(true, true, false);
1119 : }
1120 0 :
1121 : MOZ_EXPORT void
1122 : DumpCompleteHeap()
1123 0 : {
1124 0 : nsCOMPtr<nsICycleCollectorListener> listener =
1125 0 : do_CreateInstance("@mozilla.org/cycle-collector-logger;1");
1126 0 : if (!listener) {
1127 : NS_WARNING("Failed to create CC logger");
1128 : return;
1129 0 : }
1130 0 :
1131 0 : nsCOMPtr<nsICycleCollectorListener> alltracesListener;
1132 0 : listener->AllTraces(getter_AddRefs(alltracesListener));
1133 0 : if (!alltracesListener) {
1134 : NS_WARNING("Failed to get all traces logger");
1135 : return;
1136 0 : }
1137 :
1138 : nsJSContext::CycleCollectNow(alltracesListener);
1139 : }
1140 :
1141 : } // extern "C"
1142 :
1143 : namespace xpc {
1144 0 :
1145 : bool
1146 0 : Atob(JSContext* cx, unsigned argc, Value* vp)
1147 0 : {
1148 : CallArgs args = CallArgsFromVp(argc, vp);
1149 : if (!args.length())
1150 0 : return true;
1151 :
1152 : return xpc::Base64Decode(cx, args[0], args.rval());
1153 : }
1154 0 :
1155 : bool
1156 0 : Btoa(JSContext* cx, unsigned argc, Value* vp)
1157 0 : {
1158 : CallArgs args = CallArgsFromVp(argc, vp);
1159 : if (!args.length())
1160 0 : return true;
1161 :
1162 : return xpc::Base64Encode(cx, args[0], args.rval());
1163 : }
1164 0 :
1165 : bool
1166 0 : IsXrayWrapper(JSObject* obj)
1167 : {
1168 : return WrapperFactory::IsXrayWrapper(obj);
1169 : }
1170 :
1171 : } // namespace xpc
1172 :
1173 : namespace mozilla {
1174 : namespace dom {
1175 0 :
1176 : bool
1177 0 : IsChromeOrXBL(JSContext* cx, JSObject* /* unused */)
1178 401 : {
1179 401 : MOZ_ASSERT(NS_IsMainThread());
1180 802 : JS::Realm* realm = JS::GetCurrentRealmOrNull(cx);
1181 : MOZ_ASSERT(realm);
1182 : JS::Compartment* c = JS::GetCompartmentForRealm(realm);
1183 :
1184 : // For remote XUL, we run XBL in the XUL scope. Given that we care about
1185 : // compat and not security for remote XUL, we just always claim to be XBL.
1186 : //
1187 : // Note that, for performance, we don't check AllowXULXBLForPrincipal here,
1188 401 : // and instead rely on the fact that AllowContentXBLScope() only returns false in
1189 : // remote XUL situations.
1190 : return AccessCheck::isChrome(c) || IsContentXBLCompartment(c) || !AllowContentXBLScope(realm);
1191 : }
1192 :
1193 : extern bool IsCurrentThreadRunningChromeWorker();
1194 0 :
1195 : bool
1196 1 : ThreadSafeIsChromeOrXBL(JSContext* cx, JSObject* obj)
1197 10 : {
1198 : if (NS_IsMainThread()) {
1199 0 : return IsChromeOrXBL(cx, obj);
1200 : }
1201 : return IsCurrentThreadRunningChromeWorker();
1202 : }
1203 :
1204 : } // namespace dom
1205 : } // namespace mozilla
1206 0 :
1207 : void
1208 0 : xpc::CreateCooperativeContext()
1209 0 : {
1210 0 : MOZ_ASSERT(gPrimaryContext);
1211 : XPCJSContext::NewXPCJSContext(gPrimaryContext);
1212 : }
1213 0 :
1214 : void
1215 0 : xpc::DestroyCooperativeContext()
1216 0 : {
1217 0 : MOZ_ASSERT(XPCJSContext::Get() != gPrimaryContext);
1218 : delete XPCJSContext::Get();
1219 : }
1220 0 :
1221 : void
1222 0 : xpc::YieldCooperativeContext()
1223 0 : {
1224 : JS_YieldCooperativeContext(XPCJSContext::Get()->Context());
1225 : }
1226 0 :
1227 : void
1228 : xpc::ResumeCooperativeContext()
1229 : {
1230 : JS_ResumeCooperativeContext(XPCJSContext::Get()->Context());
1231 : }
|