LCOV - code coverage report
Current view: directory - js/xpconnect/src - XPCException.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 222 161 72.5 %
Date: 2012-06-02 Functions: 25 21 84.0 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code, released
      17                 :  * March 31, 1998.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 1999
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   John Bandhauer <jband@netscape.com> (original author)
      26                 :  *   Mark Hammond <MarkH@ActiveState.com>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /* An implementaion of nsIException. */
      43                 : 
      44                 : #include "xpcprivate.h"
      45                 : #include "nsNetError.h"
      46                 : #include "mozStorage.h"
      47                 : #include "nsPluginError.h"
      48                 : #include "nsIUnicodeDecoder.h"
      49                 : 
      50                 : /***************************************************************************/
      51                 : /* Quick and dirty mapping of well known result codes to strings. We only
      52                 : *  call this when building an exception object, so iterating the short array
      53                 : *  is not too bad.
      54                 : *
      55                 : *  It sure would be nice to have exceptions declared in idl and available
      56                 : *  in some more global way at runtime.
      57                 : */
      58                 : 
      59                 : static struct ResultMap
      60                 : {nsresult rv; const char* name; const char* format;} map[] = {
      61                 : #define XPC_MSG_DEF(val, format) \
      62                 :     {(val), #val, format},
      63                 : #include "xpc.msg"
      64                 : #undef XPC_MSG_DEF
      65                 :     {0,0,0}   // sentinel to mark end of array
      66                 : };
      67                 : 
      68                 : #define RESULT_COUNT ((sizeof(map) / sizeof(map[0]))-1)
      69                 : 
      70                 : // static
      71                 : JSBool
      72           84154 : nsXPCException::NameAndFormatForNSResult(nsresult rv,
      73                 :                                          const char** name,
      74                 :                                          const char** format)
      75                 : {
      76                 : 
      77         3222952 :     for (ResultMap* p = map; p->name; p++) {
      78         3222668 :         if (rv == p->rv) {
      79           83870 :             if (name) *name = p->name;
      80           83870 :             if (format) *format = p->format;
      81           83870 :             return true;
      82                 :         }
      83                 :     }
      84             284 :     return false;
      85                 : }
      86                 : 
      87                 : // static
      88                 : void*
      89          927843 : nsXPCException::IterateNSResults(nsresult* rv,
      90                 :                                  const char** name,
      91                 :                                  const char** format,
      92                 :                                  void** iterp)
      93                 : {
      94          927843 :     ResultMap* p = (ResultMap*) *iterp;
      95          927843 :     if (!p)
      96            5763 :         p = map;
      97                 :     else
      98          922080 :         p++;
      99          927843 :     if (!p->name)
     100            5763 :         p = nsnull;
     101                 :     else {
     102          922080 :         if (rv)
     103          922080 :             *rv = p->rv;
     104          922080 :         if (name)
     105          922080 :             *name = p->name;
     106          922080 :         if (format)
     107               0 :             *format = p->format;
     108                 :     }
     109          927843 :     *iterp = p;
     110          927843 :     return p;
     111                 : }
     112                 : 
     113                 : // static
     114                 : PRUint32
     115               0 : nsXPCException::GetNSResultCount()
     116                 : {
     117               0 :     return RESULT_COUNT;
     118                 : }
     119                 : 
     120                 : /***************************************************************************/
     121                 : 
     122                 : NS_IMPL_CLASSINFO(nsXPCException, NULL, nsIClassInfo::DOM_OBJECT,
     123                 :                   NS_XPCEXCEPTION_CID)
     124          419390 : NS_INTERFACE_MAP_BEGIN(nsXPCException)
     125          419390 :   NS_INTERFACE_MAP_ENTRY(nsIException)
     126          290735 :   NS_INTERFACE_MAP_ENTRY(nsIXPCException)
     127          274894 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
     128          236670 :   NS_IMPL_QUERY_CLASSINFO(nsXPCException)
     129          198446 : NS_INTERFACE_MAP_END_THREADSAFE
     130                 : 
     131          274197 : NS_IMPL_THREADSAFE_ADDREF(nsXPCException)
     132          274197 : NS_IMPL_THREADSAFE_RELEASE(nsXPCException)
     133                 : 
     134            4216 : NS_IMPL_CI_INTERFACE_GETTER1(nsXPCException, nsIXPCException)
     135                 : 
     136           45911 : nsXPCException::nsXPCException()
     137                 :     : mMessage(nsnull),
     138                 :       mResult(0),
     139                 :       mName(nsnull),
     140                 :       mLocation(nsnull),
     141                 :       mData(nsnull),
     142                 :       mFilename(nsnull),
     143                 :       mLineNumber(0),
     144                 :       mInner(nsnull),
     145           45911 :       mInitialized(false)
     146                 : {
     147           45911 :     MOZ_COUNT_CTOR(nsXPCException);
     148           45911 : }
     149                 : 
     150          137733 : nsXPCException::~nsXPCException()
     151                 : {
     152           45911 :     MOZ_COUNT_DTOR(nsXPCException);
     153           45911 :     Reset();
     154          183644 : }
     155                 : 
     156                 : /* [noscript] xpcexJSVal stealJSVal (); */
     157                 : NS_IMETHODIMP
     158               0 : nsXPCException::StealJSVal(jsval *vp NS_OUTPARAM)
     159                 : {
     160               0 :     if (mThrownJSVal.IsHeld()) {
     161               0 :         *vp = mThrownJSVal.Release();
     162               0 :         return NS_OK;
     163                 :     }
     164               0 :     return NS_ERROR_FAILURE;
     165                 : }
     166                 : 
     167                 : /* [noscript] void stowJSVal (in xpcexJSContextPtr cx, in xpcexJSVal val); */
     168                 : NS_IMETHODIMP
     169            6371 : nsXPCException::StowJSVal(JSContext* cx, jsval v)
     170                 : {
     171            6371 :     if (mThrownJSVal.Hold(cx)) {
     172            6371 :         mThrownJSVal = v;
     173            6371 :         return NS_OK;
     174                 :     }
     175               0 :     return NS_ERROR_FAILURE;
     176                 : }
     177                 : 
     178                 : void
     179           90809 : nsXPCException::Reset()
     180                 : {
     181           90809 :     if (mMessage) {
     182           44898 :         nsMemory::Free(mMessage);
     183           44898 :         mMessage = nsnull;
     184                 :     }
     185           90809 :     if (mName) {
     186               0 :         nsMemory::Free(mName);
     187               0 :         mName = nsnull;
     188                 :     }
     189           90809 :     if (mFilename) {
     190           40398 :         nsMemory::Free(mFilename);
     191           40398 :         mFilename = nsnull;
     192                 :     }
     193           90809 :     mLineNumber = (PRUint32)-1;
     194           90809 :     NS_IF_RELEASE(mLocation);
     195           90809 :     NS_IF_RELEASE(mData);
     196           90809 :     NS_IF_RELEASE(mInner);
     197           90809 : }
     198                 : 
     199                 : /* readonly attribute string message; */
     200                 : NS_IMETHODIMP
     201              81 : nsXPCException::GetMessageMoz(char * *aMessage)
     202                 : {
     203              81 :     if (!mInitialized)
     204               0 :         return NS_ERROR_NOT_INITIALIZED;
     205              81 :     XPC_STRING_GETTER_BODY(aMessage, mMessage);
     206                 : }
     207                 : 
     208                 : /* readonly attribute nsresult result; */
     209                 : NS_IMETHODIMP
     210           13299 : nsXPCException::GetResult(nsresult *aResult)
     211                 : {
     212           13299 :     if (!aResult)
     213               0 :         return NS_ERROR_NULL_POINTER;
     214           13299 :     if (!mInitialized)
     215               0 :         return NS_ERROR_NOT_INITIALIZED;
     216           13299 :     *aResult = mResult;
     217           13299 :     return NS_OK;
     218                 : }
     219                 : 
     220                 : /* readonly attribute string name; */
     221                 : NS_IMETHODIMP
     222             332 : nsXPCException::GetName(char * *aName)
     223                 : {
     224             332 :     if (!mInitialized)
     225               0 :         return NS_ERROR_NOT_INITIALIZED;
     226                 : 
     227             332 :     const char* name = mName;
     228             332 :     if (!name)
     229             332 :         NameAndFormatForNSResult(mResult, &name, nsnull);
     230                 : 
     231             332 :     XPC_STRING_GETTER_BODY(aName, name);
     232                 : }
     233                 : 
     234                 : /* readonly attribute string filename; */
     235              24 : NS_IMETHODIMP nsXPCException::GetFilename(char * *aFilename)
     236                 : {
     237              24 :     if (!mInitialized)
     238               0 :         return NS_ERROR_NOT_INITIALIZED;
     239              24 :     XPC_STRING_GETTER_BODY(aFilename, mFilename);
     240                 : }
     241                 : 
     242                 : /* readonly attribute PRUint32 lineNumber; */
     243              24 : NS_IMETHODIMP nsXPCException::GetLineNumber(PRUint32 *aLineNumber)
     244                 : {
     245              24 :     if (!aLineNumber)
     246               0 :         return NS_ERROR_NULL_POINTER;
     247              24 :     if (!mInitialized)
     248               0 :         return NS_ERROR_NOT_INITIALIZED;
     249              24 :     *aLineNumber = mLineNumber;
     250              24 :     return NS_OK;
     251                 : }
     252                 : 
     253                 : /* readonly attribute PRUint32 columnNumber; */
     254               0 : NS_IMETHODIMP nsXPCException::GetColumnNumber(PRUint32 *aColumnNumber)
     255                 : {
     256               0 :     NS_ENSURE_ARG_POINTER(aColumnNumber);
     257               0 :     if (!mInitialized)
     258               0 :         return NS_ERROR_NOT_INITIALIZED;
     259               0 :     *aColumnNumber = 0;
     260               0 :     return NS_OK;
     261                 : }
     262                 : 
     263                 : /* readonly attribute nsIStackFrame location; */
     264                 : NS_IMETHODIMP
     265             116 : nsXPCException::GetLocation(nsIStackFrame * *aLocation)
     266                 : {
     267             116 :     if (!aLocation)
     268               0 :         return NS_ERROR_NULL_POINTER;
     269             116 :     if (!mInitialized)
     270               0 :         return NS_ERROR_NOT_INITIALIZED;
     271             116 :     *aLocation = mLocation;
     272             116 :     NS_IF_ADDREF(mLocation);
     273             116 :     return NS_OK;
     274                 : }
     275                 : 
     276                 : /* readonly attribute nsISupports data; */
     277                 : NS_IMETHODIMP
     278              91 : nsXPCException::GetData(nsISupports * *aData)
     279                 : {
     280              91 :     if (!aData)
     281               0 :         return NS_ERROR_NULL_POINTER;
     282              91 :     if (!mInitialized)
     283               0 :         return NS_ERROR_NOT_INITIALIZED;
     284              91 :     *aData = mData;
     285              91 :     NS_IF_ADDREF(mData);
     286              91 :     return NS_OK;
     287                 : }
     288                 : 
     289                 : /* readonly attribute nsIException inner; */
     290                 : NS_IMETHODIMP
     291               0 : nsXPCException::GetInner(nsIException* *aException)
     292                 : {
     293               0 :     if (!aException)
     294               0 :         return NS_ERROR_NULL_POINTER;
     295               0 :     if (!mInitialized)
     296               0 :         return NS_ERROR_NOT_INITIALIZED;
     297               0 :     *aException = mInner;
     298               0 :     NS_IF_ADDREF(mInner);
     299               0 :     return NS_OK;
     300                 : }
     301                 : 
     302                 : /* void initialize (in string aMessage, in nsresult aResult, in string aName, in nsIStackFrame aLocation, in nsISupports aData, in nsIException aInner); */
     303                 : NS_IMETHODIMP
     304           44898 : nsXPCException::Initialize(const char *aMessage, nsresult aResult, const char *aName, nsIStackFrame *aLocation, nsISupports *aData, nsIException *aInner)
     305                 : {
     306           44898 :     if (mInitialized)
     307               0 :         return NS_ERROR_ALREADY_INITIALIZED;
     308                 : 
     309           44898 :     Reset();
     310                 : 
     311           44898 :     if (aMessage) {
     312           89796 :         if (!(mMessage = (char*) nsMemory::Clone(aMessage,
     313           89796 :                                                  sizeof(char)*(strlen(aMessage)+1))))
     314               0 :             return NS_ERROR_OUT_OF_MEMORY;
     315                 :     }
     316                 : 
     317           44898 :     if (aName) {
     318               0 :         if (!(mName = (char*) nsMemory::Clone(aName,
     319               0 :                                               sizeof(char)*(strlen(aName)+1))))
     320               0 :             return NS_ERROR_OUT_OF_MEMORY;
     321                 :     }
     322                 : 
     323           44898 :     mResult = aResult;
     324                 : 
     325           44898 :     if (aLocation) {
     326           40415 :         mLocation = aLocation;
     327           40415 :         NS_ADDREF(mLocation);
     328                 :         // For now, fill in our location details from our stack frame.
     329                 :         // Later we may allow other locations?
     330                 :         nsresult rc;
     331           40415 :         if (NS_FAILED(rc = aLocation->GetFilename(&mFilename)))
     332               0 :             return rc;
     333           40415 :         if (NS_FAILED(rc = aLocation->GetLineNumber(&mLineNumber)))
     334               0 :             return rc;
     335                 :     } else {
     336                 :         nsresult rv;
     337            4483 :         nsXPConnect* xpc = nsXPConnect::GetXPConnect();
     338            4483 :         if (!xpc)
     339               0 :             return NS_ERROR_FAILURE;
     340            4483 :         rv = xpc->GetCurrentJSStack(&mLocation);
     341            4483 :         if (NS_FAILED(rv))
     342               0 :             return rv;
     343                 :     }
     344                 : 
     345           44898 :     if (aData) {
     346             257 :         mData = aData;
     347             257 :         NS_ADDREF(mData);
     348                 :     }
     349           44898 :     if (aInner) {
     350               0 :         mInner = aInner;
     351               0 :         NS_ADDREF(mInner);
     352                 :     }
     353                 : 
     354           44898 :     mInitialized = true;
     355           44898 :     return NS_OK;
     356                 : }
     357                 : 
     358                 : /* string toString (); */
     359                 : NS_IMETHODIMP
     360            1339 : nsXPCException::ToString(char **_retval)
     361                 : {
     362            1339 :     if (!_retval)
     363               0 :         return NS_ERROR_NULL_POINTER;
     364            1339 :     if (!mInitialized)
     365               0 :         return NS_ERROR_NOT_INITIALIZED;
     366                 : 
     367                 :     static const char defaultMsg[] = "<no message>";
     368                 :     static const char defaultLocation[] = "<unknown>";
     369                 :     static const char format[] =
     370                 :  "[Exception... \"%s\"  nsresult: \"0x%x (%s)\"  location: \"%s\"  data: %s]";
     371                 : 
     372            1339 :     char* indicatedLocation = nsnull;
     373                 : 
     374            1339 :     if (mLocation) {
     375                 :         // we need to free this if it does not fail
     376            1195 :         nsresult rv = mLocation->ToString(&indicatedLocation);
     377            1195 :         if (NS_FAILED(rv))
     378               0 :             return rv;
     379                 :     }
     380                 : 
     381            1339 :     const char* msg = mMessage ? mMessage : nsnull;
     382                 :     const char* location = indicatedLocation ?
     383            1339 :                                 indicatedLocation : defaultLocation;
     384            1339 :     const char* resultName = mName;
     385            2678 :     if (!resultName && !NameAndFormatForNSResult(mResult, &resultName,
     386            1339 :                                                  (!msg) ? &msg : nsnull)) {
     387               0 :         if (!msg)
     388               0 :             msg = defaultMsg;
     389               0 :         resultName = "<unknown>";
     390                 :     }
     391            1339 :     const char* data = mData ? "yes" : "no";
     392                 : 
     393            1339 :     char* temp = JS_smprintf(format, msg, mResult, resultName, location, data);
     394            1339 :     if (indicatedLocation)
     395            1195 :         nsMemory::Free(indicatedLocation);
     396                 : 
     397            1339 :     char* final = nsnull;
     398            1339 :     if (temp) {
     399            1339 :         final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1));
     400            1339 :         JS_smprintf_free(temp);
     401                 :     }
     402                 : 
     403            1339 :     *_retval = final;
     404            1339 :     return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     405                 : }
     406                 : 
     407                 : JSBool nsXPCException::sEverMadeOneFromFactory = false;
     408                 : 
     409                 : // static
     410                 : nsresult
     411           44898 : nsXPCException::NewException(const char *aMessage,
     412                 :                              nsresult aResult,
     413                 :                              nsIStackFrame *aLocation,
     414                 :                              nsISupports *aData,
     415                 :                              nsIException** exceptn)
     416                 : {
     417                 :     // A little hack... The nsIGenericModule nsIClassInfo scheme relies on there
     418                 :     // having been at least one instance made via the factory. Otherwise, the
     419                 :     // shared factory/classinsance object never gets created and our QI getter
     420                 :     // for our instance's pointer to our nsIClassInfo will always return null.
     421                 :     // This is bad because it means that wrapped exceptions will never have a
     422                 :     // shared prototype. So... We force one to be created via the factory
     423                 :     // *once* and then go about our business.
     424           44898 :     if (!sEverMadeOneFromFactory) {
     425                 :         nsCOMPtr<nsIXPCException> e =
     426            2026 :             do_CreateInstance(XPC_EXCEPTION_CONTRACTID);
     427            1013 :         sEverMadeOneFromFactory = true;
     428                 :     }
     429                 : 
     430                 :     nsresult rv;
     431           44898 :     nsXPCException* e = new nsXPCException();
     432           44898 :     if (e) {
     433           44898 :         NS_ADDREF(e);
     434                 : 
     435                 :         nsIStackFrame* location;
     436           44898 :         if (aLocation) {
     437              10 :             location = aLocation;
     438              10 :             NS_ADDREF(location);
     439                 :         } else {
     440           44888 :             nsXPConnect* xpc = nsXPConnect::GetXPConnect();
     441           44888 :             if (!xpc) {
     442               0 :                 NS_RELEASE(e);
     443               0 :                 return NS_ERROR_FAILURE;
     444                 :             }
     445           44888 :             rv = xpc->GetCurrentJSStack(&location);
     446           44888 :             if (NS_FAILED(rv)) {
     447               0 :                 NS_RELEASE(e);
     448               0 :                 return NS_ERROR_FAILURE;
     449                 :             }
     450                 :             // it is legal for there to be no active JS stack, if C++ code
     451                 :             // is operating on a JS-implemented interface pointer without
     452                 :             // having been called in turn by JS.  This happens in the JS
     453                 :             // component loader, and will become more common as additional
     454                 :             // components are implemented in JS.
     455                 :         }
     456                 :         // We want to trim off any leading native 'dataless' frames
     457           44898 :         if (location)
     458               0 :             while (1) {
     459                 :                 PRUint32 language;
     460                 :                 PRInt32 lineNumber;
     461           40432 :                 if (NS_FAILED(location->GetLanguage(&language)) ||
     462                 :                     language == nsIProgrammingLanguage::JAVASCRIPT ||
     463              17 :                     NS_FAILED(location->GetLineNumber(&lineNumber)) ||
     464                 :                     lineNumber) {
     465           40398 :                     break;
     466                 :                 }
     467              34 :                 nsCOMPtr<nsIStackFrame> caller;
     468              17 :                 if (NS_FAILED(location->GetCaller(getter_AddRefs(caller))) || !caller)
     469                 :                     break;
     470               0 :                 NS_RELEASE(location);
     471              17 :                 caller->QueryInterface(NS_GET_IID(nsIStackFrame), (void **)&location);
     472                 :             }
     473                 :         // at this point we have non-null location with one extra addref,
     474                 :         // or no location at all
     475           44898 :         rv = e->Initialize(aMessage, aResult, nsnull, location, aData, nsnull);
     476           44898 :         NS_IF_RELEASE(location);
     477           44898 :         if (NS_FAILED(rv))
     478               0 :             NS_RELEASE(e);
     479                 :     }
     480                 : 
     481           44898 :     if (!e)
     482               0 :         return NS_ERROR_FAILURE;
     483                 : 
     484           44898 :     *exceptn = static_cast<nsIXPCException*>(e);
     485           44898 :     return NS_OK;
     486                 : }

Generated by: LCOV version 1.7