LCOV - app.info - js/xpconnect/src/XPCException.cpp

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-04-21 | 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           45477 : nsXPCException::NameAndFormatForNSResult(nsresult rv,
          73                 :                                          const char** name,
          74                 :                                          const char** format)
          75                 : {
          76                 :
          77         1934865 :     for (ResultMap* p = map; p->name; p++) {
          78         1934581 :         if (rv == p->rv) {
          79           45193 :             if (name) *name = p->name;
          80           45193 :             if (format) *format = p->format;
          81           45193 :             return true;
          82                 :         }
          83                 :     }
          84             284 :     return false;
          85                 : }
          86                 :
          87                 : // static
          88                 : void*
          89          921725 : nsXPCException::IterateNSResults(nsresult* rv,
          90                 :                                  const char** name,
          91                 :                                  const char** format,
          92                 :                                  void** iterp)
          93                 : {
          94          921725 :     ResultMap* p = (ResultMap*) *iterp;
          95          921725 :     if (!p)
          96            5725 :         p = map;
          97                 :     else
          98          916000 :         p++;
          99          921725 :     if (!p->name)
         100            5725 :         p = nsnull;
         101                 :     else {
         102          916000 :         if (rv)
         103          916000 :             *rv = p->rv;
         104          916000 :         if (name)
         105          916000 :             *name = p->name;
         106          916000 :         if (format)
         107               0 :             *format = p->format;
         108                 :     }
         109          921725 :     *iterp = p;
         110          921725 :     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          226256 : NS_INTERFACE_MAP_BEGIN(nsXPCException)
         125          226256 :   NS_INTERFACE_MAP_ENTRY(nsIException)
         126          155656 :   NS_INTERFACE_MAP_ENTRY(nsIXPCException)
         127          139936 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
         128          120993 :   NS_IMPL_QUERY_CLASSINFO(nsXPCException)
         129          102050 : NS_INTERFACE_MAP_END_THREADSAFE
         130                 :
         131          157966 : NS_IMPL_THREADSAFE_ADDREF(nsXPCException)
         132          157966 : NS_IMPL_THREADSAFE_RELEASE(nsXPCException)
         133                 :
         134            4234 : NS_IMPL_CI_INTERFACE_GETTER1(nsXPCException, nsIXPCException)
         135                 :
         136           26521 : 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           26521 :       mInitialized(false)
         146                 : {
         147           26521 :     MOZ_COUNT_CTOR(nsXPCException);
         148           26521 : }
         149                 :
         150           79563 : nsXPCException::~nsXPCException()
         151                 : {
         152           26521 :     MOZ_COUNT_DTOR(nsXPCException);
         153           26521 :     Reset();
         154          106084 : }
         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            6249 : nsXPCException::StowJSVal(JSContext* cx, jsval v)
         170                 : {
         171            6249 :     if (mThrownJSVal.Hold(cx)) {
         172            6249 :         mThrownJSVal = v;
         173            6249 :         return NS_OK;
         174                 :     }
         175               0 :     return NS_ERROR_FAILURE;
         176                 : }
         177                 :
         178                 : void
         179           52033 : nsXPCException::Reset()
         180                 : {
         181           52033 :     if (mMessage) {
         182           25512 :         nsMemory::Free(mMessage);
         183           25512 :         mMessage = nsnull;
         184                 :     }
         185           52033 :     if (mName) {
         186               0 :         nsMemory::Free(mName);
         187               0 :         mName = nsnull;
         188                 :     }
         189           52033 :     if (mFilename) {
         190           21117 :         nsMemory::Free(mFilename);
         191           21117 :         mFilename = nsnull;
         192                 :     }
         193           52033 :     mLineNumber = (PRUint32)-1;
         194           52033 :     NS_IF_RELEASE(mLocation);
         195           52033 :     NS_IF_RELEASE(mData);
         196           52033 :     NS_IF_RELEASE(mInner);
         197           52033 : }
         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           13209 : nsXPCException::GetResult(nsresult *aResult)
         211                 : {
         212           13209 :     if (!aResult)
         213               0 :         return NS_ERROR_NULL_POINTER;
         214           13209 :     if (!mInitialized)
         215               0 :         return NS_ERROR_NOT_INITIALIZED;
         216           13209 :     *aResult = mResult;
         217           13209 :     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             120 : nsXPCException::GetLocation(nsIStackFrame * *aLocation)
         266                 : {
         267             120 :     if (!aLocation)
         268               0 :         return NS_ERROR_NULL_POINTER;
         269             120 :     if (!mInitialized)
         270               0 :         return NS_ERROR_NOT_INITIALIZED;
         271             120 :     *aLocation = mLocation;
         272             120 :     NS_IF_ADDREF(mLocation);
         273             120 :     return NS_OK;
         274                 : }
         275                 :
         276                 : /* readonly attribute nsISupports data; */
         277                 : NS_IMETHODIMP
         278              95 : nsXPCException::GetData(nsISupports * *aData)
         279                 : {
         280              95 :     if (!aData)
         281               0 :         return NS_ERROR_NULL_POINTER;
         282              95 :     if (!mInitialized)
         283               0 :         return NS_ERROR_NOT_INITIALIZED;
         284              95 :     *aData = mData;
         285              95 :     NS_IF_ADDREF(mData);
         286              95 :     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           25512 : nsXPCException::Initialize(const char *aMessage, nsresult aResult, const char *aName, nsIStackFrame *aLocation, nsISupports *aData, nsIException *aInner)
         305                 : {
         306           25512 :     if (mInitialized)
         307               0 :         return NS_ERROR_ALREADY_INITIALIZED;
         308                 :
         309           25512 :     Reset();
         310                 :
         311           25512 :     if (aMessage) {
         312           51024 :         if (!(mMessage = (char*) nsMemory::Clone(aMessage,
         313           51024 :                                                  sizeof(char)*(strlen(aMessage)+1))))
         314               0 :             return NS_ERROR_OUT_OF_MEMORY;
         315                 :     }
         316                 :
         317           25512 :     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           25512 :     mResult = aResult;
         324                 :
         325           25512 :     if (aLocation) {
         326           21136 :         mLocation = aLocation;
         327           21136 :         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           21136 :         if (NS_FAILED(rc = aLocation->GetFilename(&mFilename)))
         332               0 :             return rc;
         333           21136 :         if (NS_FAILED(rc = aLocation->GetLineNumber(&mLineNumber)))
         334               0 :             return rc;
         335                 :     } else {
         336                 :         nsresult rv;
         337            4376 :         nsXPConnect* xpc = nsXPConnect::GetXPConnect();
         338            4376 :         if (!xpc)
         339               0 :             return NS_ERROR_FAILURE;
         340            4376 :         rv = xpc->GetCurrentJSStack(&mLocation);
         341            4376 :         if (NS_FAILED(rv))
         342               0 :             return rv;
         343                 :     }
         344                 :
         345           25512 :     if (aData) {
         346             270 :         mData = aData;
         347             270 :         NS_ADDREF(mData);
         348                 :     }
         349           25512 :     if (aInner) {
         350               0 :         mInner = aInner;
         351               0 :         NS_ADDREF(mInner);
         352                 :     }
         353                 :
         354           25512 :     mInitialized = true;
         355           25512 :     return NS_OK;
         356                 : }
         357                 :
         358                 : /* string toString (); */
         359                 : NS_IMETHODIMP
         360            1341 : nsXPCException::ToString(char **_retval)
         361                 : {
         362            1341 :     if (!_retval)
         363               0 :         return NS_ERROR_NULL_POINTER;
         364            1341 :     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            1341 :     char* indicatedLocation = nsnull;
         373                 :
         374            1341 :     if (mLocation) {
         375                 :         // we need to free this if it does not fail
         376            1191 :         nsresult rv = mLocation->ToString(&indicatedLocation);
         377            1191 :         if (NS_FAILED(rv))
         378               0 :             return rv;
         379                 :     }
         380                 :
         381            1341 :     const char* msg = mMessage ? mMessage : nsnull;
         382                 :     const char* location = indicatedLocation ?
         383            1341 :                                 indicatedLocation : defaultLocation;
         384            1341 :     const char* resultName = mName;
         385            2682 :     if (!resultName && !NameAndFormatForNSResult(mResult, &resultName,
         386            1341 :                                                  (!msg) ? &msg : nsnull)) {
         387               0 :         if (!msg)
         388               0 :             msg = defaultMsg;
         389               0 :         resultName = "<unknown>";
         390                 :     }
         391            1341 :     const char* data = mData ? "yes" : "no";
         392                 :
         393            1341 :     char* temp = JS_smprintf(format, msg, mResult, resultName, location, data);
         394            1341 :     if (indicatedLocation)
         395            1191 :         nsMemory::Free(indicatedLocation);
         396                 :
         397            1341 :     char* final = nsnull;
         398            1341 :     if (temp) {
         399            1341 :         final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1));
         400            1341 :         JS_smprintf_free(temp);
         401                 :     }
         402                 :
         403            1341 :     *_retval = final;
         404            1341 :     return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
         405                 : }
         406                 :
         407                 : JSBool nsXPCException::sEverMadeOneFromFactory = false;
         408                 :
         409                 : // static
         410                 : nsresult
         411           25512 : 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           25512 :     if (!sEverMadeOneFromFactory) {
         425                 :         nsCOMPtr<nsIXPCException> e =
         426            2018 :             do_CreateInstance(XPC_EXCEPTION_CONTRACTID);
         427            1009 :         sEverMadeOneFromFactory = true;
         428                 :     }
         429                 :
         430                 :     nsresult rv;
         431           25512 :     nsXPCException* e = new nsXPCException();
         432           25512 :     if (e) {
         433           25512 :         NS_ADDREF(e);
         434                 :
         435                 :         nsIStackFrame* location;
         436           25512 :         if (aLocation) {
         437              10 :             location = aLocation;
         438              10 :             NS_ADDREF(location);
         439                 :         } else {
         440           25502 :             nsXPConnect* xpc = nsXPConnect::GetXPConnect();
         441           25502 :             if (!xpc) {
         442               0 :                 NS_RELEASE(e);
         443               0 :                 return NS_ERROR_FAILURE;
         444                 :             }
         445           25502 :             rv = xpc->GetCurrentJSStack(&location);
         446           25502 :             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           25512 :         if (location)
         458               0 :             while (1) {
         459                 :                 PRUint32 language;
         460                 :                 PRInt32 lineNumber;
         461           21155 :                 if (NS_FAILED(location->GetLanguage(&language)) ||
         462                 :                     language == nsIProgrammingLanguage::JAVASCRIPT ||
         463              19 :                     NS_FAILED(location->GetLineNumber(&lineNumber)) ||
         464                 :                     lineNumber) {
         465           21117 :                     break;
         466                 :                 }
         467              38 :                 nsCOMPtr<nsIStackFrame> caller;
         468              19 :                 if (NS_FAILED(location->GetCaller(getter_AddRefs(caller))) || !caller)
         469                 :                     break;
         470               0 :                 NS_RELEASE(location);
         471              19 :                 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           25512 :         rv = e->Initialize(aMessage, aResult, nsnull, location, aData, nsnull);
         476           25512 :         NS_IF_RELEASE(location);
         477           25512 :         if (NS_FAILED(rv))
         478               0 :             NS_RELEASE(e);
         479                 :     }
         480                 :
         481           25512 :     if (!e)
         482               0 :         return NS_ERROR_FAILURE;
         483                 :
         484           25512 :     *exceptn = static_cast<nsIXPCException*>(e);
         485           25512 :     return NS_OK;
         486                 : }

Generated by: LCOV version 1.7