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

Generated by: LCOV version 1.13