LCOV - code coverage report
Current view: top level - js/xpconnect/src - XPCThrower.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 30 69 43.5 %
Date: 2017-07-14 16:53:18 Functions: 3 7 42.9 %
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             : /* Code for throwing errors into JavaScript. */
       8             : 
       9             : #include "xpcprivate.h"
      10             : #include "XPCWrapper.h"
      11             : #include "jsprf.h"
      12             : #include "mozilla/dom/BindingUtils.h"
      13             : #include "mozilla/dom/Exceptions.h"
      14             : #include "nsStringGlue.h"
      15             : 
      16             : using namespace mozilla;
      17             : using namespace mozilla::dom;
      18             : 
      19             : bool XPCThrower::sVerbose = true;
      20             : 
      21             : // static
      22             : void
      23           0 : XPCThrower::Throw(nsresult rv, JSContext* cx)
      24             : {
      25             :     const char* format;
      26           0 :     if (JS_IsExceptionPending(cx))
      27           0 :         return;
      28           0 :     if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
      29           0 :         format = "";
      30           0 :     dom::Throw(cx, rv, nsDependentCString(format));
      31             : }
      32             : 
      33             : namespace xpc {
      34             : 
      35             : bool
      36           0 : Throw(JSContext* cx, nsresult rv)
      37             : {
      38           0 :     XPCThrower::Throw(rv, cx);
      39           0 :     return false;
      40             : }
      41             : 
      42             : } // namespace xpc
      43             : 
      44             : /*
      45             :  * If there has already been an exception thrown, see if we're throwing the
      46             :  * same sort of exception, and if we are, don't clobber the old one. ccx
      47             :  * should be the current call context.
      48             :  */
      49             : // static
      50             : bool
      51        1978 : XPCThrower::CheckForPendingException(nsresult result, JSContext* cx)
      52             : {
      53        3956 :     nsCOMPtr<nsIException> e = XPCJSContext::Get()->GetPendingException();
      54        1978 :     if (!e)
      55        1978 :         return false;
      56           0 :     XPCJSContext::Get()->SetPendingException(nullptr);
      57             : 
      58             :     nsresult e_result;
      59           0 :     if (NS_FAILED(e->GetResult(&e_result)) || e_result != result)
      60           0 :         return false;
      61             : 
      62           0 :     ThrowExceptionObject(cx, e);
      63           0 :     return true;
      64             : }
      65             : 
      66             : // static
      67             : void
      68           0 : XPCThrower::Throw(nsresult rv, XPCCallContext& ccx)
      69             : {
      70             :     char* sz;
      71             :     const char* format;
      72             : 
      73           0 :     if (CheckForPendingException(rv, ccx))
      74           0 :         return;
      75             : 
      76           0 :     if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
      77           0 :         format = "";
      78             : 
      79           0 :     sz = (char*) format;
      80           0 :     NS_ENSURE_TRUE_VOID(sz);
      81             : 
      82           0 :     if (sz && sVerbose)
      83           0 :         Verbosify(ccx, &sz, false);
      84             : 
      85           0 :     dom::Throw(ccx, rv, nsDependentCString(sz));
      86             : 
      87           0 :     if (sz && sz != format)
      88           0 :         JS_smprintf_free(sz);
      89             : }
      90             : 
      91             : 
      92             : // static
      93             : void
      94        1978 : XPCThrower::ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx)
      95             : {
      96             :     char* sz;
      97             :     const char* format;
      98             :     const char* name;
      99             : 
     100             :     /*
     101             :     *  If there is a pending exception when the native call returns and
     102             :     *  it has the same error result as returned by the native call, then
     103             :     *  the native call may be passing through an error from a previous JS
     104             :     *  call. So we'll just throw that exception into our JS.  Note that
     105             :     *  we don't need to worry about NS_ERROR_UNCATCHABLE_EXCEPTION,
     106             :     *  because presumably there would be no pending exception for that
     107             :     *  nsresult!
     108             :     */
     109             : 
     110        1978 :     if (CheckForPendingException(result, ccx))
     111           0 :         return;
     112             : 
     113             :     // else...
     114             : 
     115        1978 :     if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format) || !format)
     116           0 :         format = "";
     117             : 
     118        1978 :     if (nsXPCException::NameAndFormatForNSResult(result, &name, nullptr) && name)
     119          75 :         sz = JS_smprintf("%s 0x%x (%s)", format, (unsigned) result, name).release();
     120             :     else
     121        1903 :         sz = JS_smprintf("%s 0x%x", format, (unsigned) result).release();
     122        1978 :     NS_ENSURE_TRUE_VOID(sz);
     123             : 
     124        1978 :     if (sz && sVerbose)
     125        1978 :         Verbosify(ccx, &sz, true);
     126             : 
     127        1978 :     dom::Throw(ccx, result, nsDependentCString(sz));
     128             : 
     129        1978 :     if (sz)
     130        1978 :         JS_smprintf_free(sz);
     131             : }
     132             : 
     133             : // static
     134             : void
     135           0 : XPCThrower::ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx)
     136             : {
     137             :     char* sz;
     138             :     const char* format;
     139             : 
     140           0 :     if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
     141           0 :         format = "";
     142             : 
     143           0 :     sz = JS_smprintf("%s arg %d", format, paramNum).release();
     144           0 :     NS_ENSURE_TRUE_VOID(sz);
     145             : 
     146           0 :     if (sz && sVerbose)
     147           0 :         Verbosify(ccx, &sz, true);
     148             : 
     149           0 :     dom::Throw(ccx, rv, nsDependentCString(sz));
     150             : 
     151           0 :     if (sz)
     152           0 :         JS_smprintf_free(sz);
     153             : }
     154             : 
     155             : 
     156             : // static
     157             : void
     158        1978 : XPCThrower::Verbosify(XPCCallContext& ccx,
     159             :                       char** psz, bool own)
     160             : {
     161        1978 :     char* sz = nullptr;
     162             : 
     163        1978 :     if (ccx.HasInterfaceAndMember()) {
     164        1978 :         XPCNativeInterface* iface = ccx.GetInterface();
     165        1978 :         jsid id = ccx.GetMember()->GetName();
     166        3956 :         JSAutoByteString bytes;
     167        1978 :         const char* name = JSID_IS_VOID(id) ? "Unknown" : bytes.encodeLatin1(ccx, JSID_TO_STRING(id));
     168        1978 :         if (!name) {
     169           0 :             name = "";
     170             :         }
     171        1978 :         sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), name).release();
     172             :     }
     173             : 
     174        1978 :     if (sz) {
     175        1978 :         if (own)
     176        1978 :             JS_smprintf_free(*psz);
     177        1978 :         *psz = sz;
     178             :     }
     179        1978 : }

Generated by: LCOV version 1.13