LCOV - code coverage report
Current view: top level - js/xpconnect/src - nsXPConnect.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 147 532 27.6 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.13-14-ga5dd952