LCOV - code coverage report
Current view: top level - js/xpconnect/src - XPCCallContext.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 79 139 56.8 %
Date: 2017-07-14 16:53:18 Functions: 6 17 35.3 %
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             : /* Call context. */
       8             : 
       9             : #include "xpcprivate.h"
      10             : #include "jswrapper.h"
      11             : #include "jsfriendapi.h"
      12             : #include "nsContentUtils.h"
      13             : 
      14             : using namespace mozilla;
      15             : using namespace xpc;
      16             : using namespace JS;
      17             : 
      18           0 : static inline bool IsTearoffClass(const js::Class* clazz)
      19             : {
      20           0 :     return clazz == &XPC_WN_Tearoff_JSClass;
      21             : }
      22             : 
      23       49131 : XPCCallContext::XPCCallContext(JSContext* cx,
      24             :                                HandleObject obj    /* = nullptr               */,
      25             :                                HandleObject funobj /* = nullptr               */,
      26             :                                HandleId name       /* = JSID_VOID             */,
      27             :                                unsigned argc       /* = NO_ARGS               */,
      28             :                                Value* argv         /* = nullptr               */,
      29       49131 :                                Value* rval         /* = nullptr               */)
      30             :     :   mAr(cx),
      31             :         mState(INIT_FAILED),
      32             :         mXPC(nsXPConnect::XPConnect()),
      33             :         mXPCJSContext(nullptr),
      34             :         mJSContext(cx),
      35             :         mWrapper(nullptr),
      36             :         mTearOff(nullptr),
      37       49131 :         mName(cx)
      38             : {
      39       49131 :     MOZ_ASSERT(cx);
      40       49131 :     MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
      41             : 
      42       49131 :     if (!mXPC)
      43           0 :         return;
      44             : 
      45       49131 :     mXPCJSContext = XPCJSContext::Get();
      46             : 
      47             :     // hook into call context chain.
      48       49131 :     mPrevCallContext = mXPCJSContext->SetCallContext(this);
      49             : 
      50       49131 :     mState = HAVE_CONTEXT;
      51             : 
      52       49131 :     if (!obj)
      53        9555 :         return;
      54             : 
      55       39576 :     mMethodIndex = 0xDEAD;
      56             : 
      57       39576 :     mState = HAVE_OBJECT;
      58             : 
      59       39576 :     mTearOff = nullptr;
      60             : 
      61       39576 :     JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
      62       39576 :     if (!unwrapped) {
      63           0 :         JS_ReportErrorASCII(mJSContext, "Permission denied to call method on |this|");
      64           0 :         mState = INIT_FAILED;
      65           0 :         return;
      66             :     }
      67       39576 :     const js::Class* clasp = js::GetObjectClass(unwrapped);
      68       39576 :     if (IS_WN_CLASS(clasp)) {
      69       39576 :         mWrapper = XPCWrappedNative::Get(unwrapped);
      70           0 :     } else if (IsTearoffClass(clasp)) {
      71           0 :         mTearOff = (XPCWrappedNativeTearOff*)js::GetObjectPrivate(unwrapped);
      72           0 :         mWrapper = XPCWrappedNative::Get(
      73             :           &js::GetReservedSlot(unwrapped,
      74           0 :                                XPC_WN_TEAROFF_FLAT_OBJECT_SLOT).toObject());
      75             :     }
      76       39576 :     if (mWrapper && !mTearOff) {
      77       39576 :         mScriptable = mWrapper->GetScriptable();
      78             :     }
      79             : 
      80       39576 :     if (!JSID_IS_VOID(name))
      81        3917 :         SetName(name);
      82             : 
      83       39576 :     if (argc != NO_ARGS)
      84       11287 :         SetArgsAndResultPtr(argc, argv, rval);
      85             : 
      86       39576 :     CHECK_STATE(HAVE_OBJECT);
      87             : }
      88             : 
      89             : void
      90        4769 : XPCCallContext::SetName(jsid name)
      91             : {
      92        4769 :     CHECK_STATE(HAVE_OBJECT);
      93             : 
      94        4769 :     mName = name;
      95             : 
      96        4769 :     if (mTearOff) {
      97           0 :         mSet = nullptr;
      98           0 :         mInterface = mTearOff->GetInterface();
      99           0 :         mMember = mInterface->FindMember(mName);
     100           0 :         mStaticMemberIsLocal = true;
     101           0 :         if (mMember && !mMember->IsConstant())
     102           0 :             mMethodIndex = mMember->GetIndex();
     103             :     } else {
     104        4769 :         mSet = mWrapper ? mWrapper->GetSet() : nullptr;
     105             : 
     106       23845 :         if (mSet &&
     107       26189 :             mSet->FindMember(mName, &mMember, &mInterface,
     108        4769 :                              mWrapper->HasProto() ?
     109        2344 :                              mWrapper->GetProto()->GetSet() :
     110             :                              nullptr,
     111        4769 :                              &mStaticMemberIsLocal)) {
     112        4635 :             if (mMember && !mMember->IsConstant())
     113        4529 :                 mMethodIndex = mMember->GetIndex();
     114             :         } else {
     115         134 :             mMember = nullptr;
     116         134 :             mInterface = nullptr;
     117         134 :             mStaticMemberIsLocal = false;
     118             :         }
     119             :     }
     120             : 
     121        4769 :     mState = HAVE_NAME;
     122        4769 : }
     123             : 
     124             : void
     125       11153 : XPCCallContext::SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
     126             :                             bool isSetter)
     127             : {
     128       11153 :     CHECK_STATE(HAVE_CONTEXT);
     129             : 
     130             :     // We are going straight to the method info and need not do a lookup
     131             :     // by id.
     132             : 
     133             :     // don't be tricked if method is called with wrong 'this'
     134       11153 :     if (mTearOff && mTearOff->GetInterface() != iface)
     135           0 :         mTearOff = nullptr;
     136             : 
     137       11153 :     mSet = nullptr;
     138       11153 :     mInterface = iface;
     139       11153 :     mMember = member;
     140       11153 :     mMethodIndex = mMember->GetIndex() + (isSetter ? 1 : 0);
     141       11153 :     mName = mMember->GetName();
     142             : 
     143       11153 :     if (mState < HAVE_NAME)
     144           0 :         mState = HAVE_NAME;
     145       11153 : }
     146             : 
     147             : void
     148       12139 : XPCCallContext::SetArgsAndResultPtr(unsigned argc,
     149             :                                     Value* argv,
     150             :                                     Value* rval)
     151             : {
     152       12139 :     CHECK_STATE(HAVE_OBJECT);
     153             : 
     154       12139 :     if (mState < HAVE_NAME) {
     155       11287 :         mSet = nullptr;
     156       11287 :         mInterface = nullptr;
     157       11287 :         mMember = nullptr;
     158       11287 :         mStaticMemberIsLocal = false;
     159             :     }
     160             : 
     161       12139 :     mArgc   = argc;
     162       12139 :     mArgv   = argv;
     163       12139 :     mRetVal = rval;
     164             : 
     165       12139 :     mState = HAVE_ARGS;
     166       12139 : }
     167             : 
     168             : nsresult
     169       11997 : XPCCallContext::CanCallNow()
     170             : {
     171             :     nsresult rv;
     172             : 
     173       11997 :     if (!HasInterfaceAndMember())
     174           0 :         return NS_ERROR_UNEXPECTED;
     175       11997 :     if (mState < HAVE_ARGS)
     176           0 :         return NS_ERROR_UNEXPECTED;
     177             : 
     178       11997 :     if (!mTearOff) {
     179       11997 :         mTearOff = mWrapper->FindTearOff(mInterface, false, &rv);
     180       11997 :         if (!mTearOff || mTearOff->GetInterface() != mInterface) {
     181           0 :             mTearOff = nullptr;
     182           0 :             return NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED;
     183             :         }
     184             :     }
     185             : 
     186             :     // Refresh in case FindTearOff extended the set
     187       11997 :     mSet = mWrapper->GetSet();
     188             : 
     189       11997 :     mState = READY_TO_CALL;
     190       11997 :     return NS_OK;
     191             : }
     192             : 
     193             : void
     194           0 : XPCCallContext::SystemIsBeingShutDown()
     195             : {
     196             :     // XXX This is pretty questionable since the per thread cleanup stuff
     197             :     // can be making this call on one thread for call contexts on another
     198             :     // thread.
     199           0 :     NS_WARNING("Shutting Down XPConnect even through there is a live XPCCallContext");
     200           0 :     mXPCJSContext = nullptr;
     201           0 :     mState = SYSTEM_SHUTDOWN;
     202           0 :     mSet = nullptr;
     203           0 :     mInterface = nullptr;
     204             : 
     205           0 :     if (mPrevCallContext)
     206           0 :         mPrevCallContext->SystemIsBeingShutDown();
     207           0 : }
     208             : 
     209       98258 : XPCCallContext::~XPCCallContext()
     210             : {
     211       49129 :     if (mXPCJSContext) {
     212       98258 :         DebugOnly<XPCCallContext*> old = mXPCJSContext->SetCallContext(mPrevCallContext);
     213       49129 :         MOZ_ASSERT(old == this, "bad pop from per thread data");
     214             :     }
     215       49129 : }
     216             : 
     217             : NS_IMETHODIMP
     218           0 : XPCCallContext::GetCallee(nsISupports * *aCallee)
     219             : {
     220           0 :     nsCOMPtr<nsISupports> rval = mWrapper ? mWrapper->GetIdentityObject() : nullptr;
     221           0 :     rval.forget(aCallee);
     222           0 :     return NS_OK;
     223             : }
     224             : 
     225             : NS_IMETHODIMP
     226           0 : XPCCallContext::GetCalleeMethodIndex(uint16_t* aCalleeMethodIndex)
     227             : {
     228           0 :     *aCalleeMethodIndex = mMethodIndex;
     229           0 :     return NS_OK;
     230             : }
     231             : 
     232             : NS_IMETHODIMP
     233           0 : XPCCallContext::GetCalleeInterface(nsIInterfaceInfo * *aCalleeInterface)
     234             : {
     235           0 :     nsCOMPtr<nsIInterfaceInfo> rval = mInterface->GetInterfaceInfo();
     236           0 :     rval.forget(aCalleeInterface);
     237           0 :     return NS_OK;
     238             : }
     239             : 
     240             : NS_IMETHODIMP
     241           0 : XPCCallContext::GetCalleeClassInfo(nsIClassInfo * *aCalleeClassInfo)
     242             : {
     243           0 :     nsCOMPtr<nsIClassInfo> rval = mWrapper ? mWrapper->GetClassInfo() : nullptr;
     244           0 :     rval.forget(aCalleeClassInfo);
     245           0 :     return NS_OK;
     246             : }
     247             : 
     248             : NS_IMETHODIMP
     249           0 : XPCCallContext::GetJSContext(JSContext * *aJSContext)
     250             : {
     251           0 :     JS_AbortIfWrongThread(mJSContext);
     252           0 :     *aJSContext = mJSContext;
     253           0 :     return NS_OK;
     254             : }
     255             : 
     256             : NS_IMETHODIMP
     257           0 : XPCCallContext::GetArgc(uint32_t* aArgc)
     258             : {
     259           0 :     *aArgc = (uint32_t) mArgc;
     260           0 :     return NS_OK;
     261             : }
     262             : 
     263             : NS_IMETHODIMP
     264           0 : XPCCallContext::GetArgvPtr(Value** aArgvPtr)
     265             : {
     266           0 :     *aArgvPtr = mArgv;
     267           0 :     return NS_OK;
     268             : }
     269             : 
     270             : NS_IMETHODIMP
     271           0 : XPCCallContext::GetPreviousCallContext(nsAXPCNativeCallContext** aResult)
     272             : {
     273           0 :   NS_ENSURE_ARG_POINTER(aResult);
     274           0 :   *aResult = GetPrevCallContext();
     275           0 :   return NS_OK;
     276             : }

Generated by: LCOV version 1.13