js/xpconnect/src/XPCJSContextStack.cpp

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     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/. */
     7 /* Implement global service to track stack of JSContext. */
     9 #include "xpcprivate.h"
    10 #include "XPCWrapper.h"
    11 #include "nsDOMJSUtils.h"
    12 #include "nsNullPrincipal.h"
    13 #include "mozilla/dom/BindingUtils.h"
    15 using namespace mozilla;
    16 using namespace JS;
    17 using namespace xpc;
    18 using mozilla::dom::DestroyProtoAndIfaceCache;
    20 /***************************************************************************/
    22 XPCJSContextStack::~XPCJSContextStack()
    23 {
    24     if (mSafeJSContext) {
    25         mSafeJSContextGlobal = nullptr;
    26         JS_DestroyContextNoGC(mSafeJSContext);
    27         mSafeJSContext = nullptr;
    28     }
    29 }
    31 JSContext*
    32 XPCJSContextStack::Pop()
    33 {
    34     MOZ_ASSERT(!mStack.IsEmpty());
    36     uint32_t idx = mStack.Length() - 1; // The thing we're popping
    38     JSContext *cx = mStack[idx].cx;
    40     mStack.RemoveElementAt(idx);
    41     if (idx == 0) {
    42         js::Debug_SetActiveJSContext(mRuntime->Runtime(), nullptr);
    43         return cx;
    44     }
    46     --idx; // Advance to new top of the stack
    48     XPCJSContextInfo &e = mStack[idx];
    49     if (e.cx && e.savedFrameChain) {
    50         // Pop() can be called outside any request for e.cx.
    51         JSAutoRequest ar(e.cx);
    52         JS_RestoreFrameChain(e.cx);
    53         e.savedFrameChain = false;
    54     }
    55     js::Debug_SetActiveJSContext(mRuntime->Runtime(), e.cx);
    56     return cx;
    57 }
    59 bool
    60 XPCJSContextStack::Push(JSContext *cx)
    61 {
    62     js::Debug_SetActiveJSContext(mRuntime->Runtime(), cx);
    63     if (mStack.Length() == 0) {
    64         mStack.AppendElement(cx);
    65         return true;
    66     }
    68     XPCJSContextInfo &e = mStack[mStack.Length() - 1];
    69     if (e.cx) {
    70         // The cx we're pushing is also stack-top. In general we still need to
    71         // call JS_SaveFrameChain here. But if that would put us in a
    72         // compartment that's same-origin with the current one, we can skip it.
    73         nsIScriptSecurityManager* ssm = XPCWrapper::GetSecurityManager();
    74         if ((e.cx == cx) && ssm) {
    75             // DOM JSContexts don't store their default compartment object on
    76             // the cx, so in those cases we need to fetch it via the scx
    77             // instead. And in some cases (i.e. the SafeJSContext), we have no
    78             // default compartment object at all.
    79             RootedObject defaultScope(cx, GetDefaultScopeFromJSContext(cx));
    80             if (defaultScope) {
    81                 nsIPrincipal *currentPrincipal =
    82                   GetCompartmentPrincipal(js::GetContextCompartment(cx));
    83                 nsIPrincipal *defaultPrincipal = GetObjectPrincipal(defaultScope);
    84                 if (currentPrincipal->Equals(defaultPrincipal)) {
    85                     mStack.AppendElement(cx);
    86                     return true;
    87                 }
    88             }
    89         }
    91         {
    92             // Push() can be called outside any request for e.cx.
    93             JSAutoRequest ar(e.cx);
    94             if (!JS_SaveFrameChain(e.cx))
    95                 return false;
    96             e.savedFrameChain = true;
    97         }
    98     }
   100     mStack.AppendElement(cx);
   101     return true;
   102 }
   104 bool
   105 XPCJSContextStack::HasJSContext(JSContext *cx)
   106 {
   107     for (uint32_t i = 0; i < mStack.Length(); i++)
   108         if (cx == mStack[i].cx)
   109             return true;
   110     return false;
   111 }
   113 static bool
   114 SafeGlobalResolve(JSContext *cx, HandleObject obj, HandleId id)
   115 {
   116     bool resolved;
   117     return JS_ResolveStandardClass(cx, obj, id, &resolved);
   118 }
   120 static void
   121 SafeFinalize(JSFreeOp *fop, JSObject* obj)
   122 {
   123     SandboxPrivate* sop =
   124         static_cast<SandboxPrivate*>(xpc_GetJSPrivate(obj));
   125     sop->ForgetGlobalObject();
   126     NS_IF_RELEASE(sop);
   127     DestroyProtoAndIfaceCache(obj);
   128 }
   130 const JSClass xpc::SafeJSContextGlobalClass = {
   131     "global_for_XPCJSContextStack_SafeJSContext",
   132     XPCONNECT_GLOBAL_FLAGS,
   133     JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   134     JS_EnumerateStub, SafeGlobalResolve, JS_ConvertStub, SafeFinalize,
   135     nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook
   136 };
   138 JSContext*
   139 XPCJSContextStack::GetSafeJSContext()
   140 {
   141     MOZ_ASSERT(mSafeJSContext);
   142     return mSafeJSContext;
   143 }
   145 JSObject*
   146 XPCJSContextStack::GetSafeJSContextGlobal()
   147 {
   148     MOZ_ASSERT(mSafeJSContextGlobal);
   149     return mSafeJSContextGlobal;
   150 }
   152 JSContext*
   153 XPCJSContextStack::InitSafeJSContext()
   154 {
   155     MOZ_ASSERT(!mSafeJSContext);
   157     // Start by getting the principal holder and principal for this
   158     // context.  If we can't manage that, don't bother with the rest.
   159     nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
   160     nsresult rv = principal->Init();
   161     if (NS_FAILED(rv))
   162         MOZ_CRASH();
   164     nsXPConnect* xpc = nsXPConnect::XPConnect();
   165     JSRuntime *rt = xpc->GetRuntime()->Runtime();
   166     if (!rt)
   167         MOZ_CRASH();
   169     mSafeJSContext = JS_NewContext(rt, 8192);
   170     if (!mSafeJSContext)
   171         MOZ_CRASH();
   172     JSAutoRequest req(mSafeJSContext);
   173     ContextOptionsRef(mSafeJSContext).setNoDefaultCompartmentObject(true);
   175     JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter);
   177     JS::CompartmentOptions options;
   178     options.setZone(JS::SystemZone)
   179            .setTrace(TraceXPCGlobal);
   180     mSafeJSContextGlobal = CreateGlobalObject(mSafeJSContext,
   181                                               &SafeJSContextGlobalClass,
   182                                               principal, options);
   183     if (!mSafeJSContextGlobal)
   184         MOZ_CRASH();
   186     // Note: make sure to set the private before calling
   187     // InitClasses
   188     nsRefPtr<SandboxPrivate> sp = new SandboxPrivate(principal, mSafeJSContextGlobal);
   189     JS_SetPrivate(mSafeJSContextGlobal, sp.forget().take());
   191     // After this point either glob is null and the
   192     // nsIScriptObjectPrincipal ownership is either handled by the
   193     // nsCOMPtr or dealt with, or we'll release in the finalize
   194     // hook.
   195     if (NS_FAILED(xpc->InitClasses(mSafeJSContext, mSafeJSContextGlobal)))
   196         MOZ_CRASH();
   198     JS::RootedObject glob(mSafeJSContext, mSafeJSContextGlobal);
   199     JS_FireOnNewGlobalObject(mSafeJSContext, glob);
   201     return mSafeJSContext;
   202 }

mercurial