dom/bindings/ErrorResult.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
     2 /* vim: set ts=2 sw=2 et tw=79: */
     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 file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /**
     8  * A struct for tracking exceptions that need to be thrown to JS.
     9  */
    11 #ifndef mozilla_ErrorResult_h
    12 #define mozilla_ErrorResult_h
    14 #include <stdarg.h>
    16 #include "js/Value.h"
    17 #include "nscore.h"
    18 #include "nsStringGlue.h"
    19 #include "mozilla/Assertions.h"
    21 namespace mozilla {
    23 namespace dom {
    25 enum ErrNum {
    26 #define MSG_DEF(_name, _argc, _str) \
    27   _name,
    28 #include "mozilla/dom/Errors.msg"
    29 #undef MSG_DEF
    30   Err_Limit
    31 };
    33 bool
    34 ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...);
    36 } // namespace dom
    38 class ErrorResult {
    39 public:
    40   ErrorResult() {
    41     mResult = NS_OK;
    43 #ifdef DEBUG
    44     // ErrorResult is extremely performance-sensitive code, where literally
    45     // every machine instruction matters. Initialize mMessage only to suppress
    46     // a debug-only warning from gcc 4.6.
    47     mMessage = nullptr;
    48     mMightHaveUnreportedJSException = false;
    49 #endif
    50   }
    52 #ifdef DEBUG
    53   ~ErrorResult() {
    54     MOZ_ASSERT_IF(IsTypeError(), !mMessage);
    55     MOZ_ASSERT(!mMightHaveUnreportedJSException);
    56   }
    57 #endif
    59   void Throw(nsresult rv) {
    60     MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
    61     MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
    62     MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
    63     MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
    64     MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
    65     MOZ_ASSERT(rv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
    66     MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
    67     mResult = rv;
    68   }
    70   void ThrowTypeError(const dom::ErrNum errorNumber, ...);
    71   void ReportTypeError(JSContext* cx);
    72   void ClearMessage();
    73   bool IsTypeError() const { return ErrorCode() == NS_ERROR_TYPE_ERR; }
    75   // Facilities for throwing a preexisting JS exception value via this
    76   // ErrorResult.  The contract is that any code which might end up calling
    77   // ThrowJSException() must call MightThrowJSException() even if no exception
    78   // is being thrown.  Code that would call ReportJSException* or
    79   // StealJSException as needed must first call WouldReportJSException even if
    80   // this ErrorResult has not failed.
    81   //
    82   // The exn argument to ThrowJSException can be in any compartment.  It does
    83   // not have to be in the compartment of cx.  If someone later uses it, they
    84   // will wrap it into whatever compartment they're working in, as needed.
    85   void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
    86   void ReportJSException(JSContext* cx);
    87   // Used to implement throwing exceptions from the JS implementation of
    88   // bindings to callers of the binding.
    89   void ReportJSExceptionFromJSImplementation(JSContext* aCx);
    90   bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
    92   void ThrowNotEnoughArgsError() { mResult = NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
    93   void ReportNotEnoughArgsError(JSContext* cx,
    94                                 const char* ifaceName,
    95                                 const char* memberName);
    96   bool IsNotEnoughArgsError() const { return ErrorCode() == NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
    98   // StealJSException steals the JS Exception from the object. This method must
    99   // be called only if IsJSException() returns true. This method also resets the
   100   // ErrorCode() to NS_OK.
   101   void StealJSException(JSContext* cx, JS::MutableHandle<JS::Value> value);
   103   void MOZ_ALWAYS_INLINE MightThrowJSException()
   104   {
   105 #ifdef DEBUG
   106     mMightHaveUnreportedJSException = true;
   107 #endif
   108   }
   109   void MOZ_ALWAYS_INLINE WouldReportJSException()
   110   {
   111 #ifdef DEBUG
   112     mMightHaveUnreportedJSException = false;
   113 #endif
   114   }
   116   // In the future, we can add overloads of Throw that take more
   117   // interesting things, like strings or DOM exception types or
   118   // something if desired.
   120   // Backwards-compat to make conversion simpler.  We don't call
   121   // Throw() here because people can easily pass success codes to
   122   // this.
   123   void operator=(nsresult rv) {
   124     MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
   125     MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
   126     MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
   127     MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
   128     MOZ_ASSERT(rv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
   129     MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
   130     mResult = rv;
   131   }
   133   bool Failed() const {
   134     return NS_FAILED(mResult);
   135   }
   137   nsresult ErrorCode() const {
   138     return mResult;
   139   }
   141 private:
   142   nsresult mResult;
   143   struct Message;
   144   // mMessage is set by ThrowTypeError and cleared (and deallocatd) by
   145   // ReportTypeError.
   146   // mJSException is set (and rooted) by ThrowJSException and unrooted
   147   // by ReportJSException.
   148   union {
   149     Message* mMessage; // valid when IsTypeError()
   150     JS::Value mJSException; // valid when IsJSException()
   151   };
   153 #ifdef DEBUG
   154   // Used to keep track of codepaths that might throw JS exceptions,
   155   // for assertion purposes.
   156   bool mMightHaveUnreportedJSException;
   157 #endif
   159   // Not to be implemented, to make sure people always pass this by
   160   // reference, not by value.
   161   ErrorResult(const ErrorResult&) MOZ_DELETE;
   162 };
   164 /******************************************************************************
   165  ** Macros for checking results
   166  ******************************************************************************/
   168 #define ENSURE_SUCCESS(res, ret)                                          \
   169   do {                                                                    \
   170     if (res.Failed()) {                                                   \
   171       nsCString msg;                                                      \
   172       msg.AppendPrintf("ENSURE_SUCCESS(%s, %s) failed with "              \
   173                        "result 0x%X", #res, #ret, res.ErrorCode());       \
   174       NS_WARNING(msg.get());                                              \
   175       return ret;                                                         \
   176     }                                                                     \
   177   } while(0)
   179 #define ENSURE_SUCCESS_VOID(res)                                          \
   180   do {                                                                    \
   181     if (res.Failed()) {                                                   \
   182       nsCString msg;                                                      \
   183       msg.AppendPrintf("ENSURE_SUCCESS_VOID(%s) failed with "             \
   184                        "result 0x%X", #res, res.ErrorCode());             \
   185       NS_WARNING(msg.get());                                              \
   186       return;                                                             \
   187     }                                                                     \
   188   } while(0)
   190 } // namespace mozilla
   192 #endif /* mozilla_ErrorResult_h */

mercurial