Bug 1403348: Part 3 - Support plain XPC Exceptions in ExtractErrorValues. r=baku
authorKris Maglione <maglione.k@gmail.com>
Thu, 09 Nov 2017 12:32:15 -0800
changeset 695890 8daf75d35c4843b10c40652abce7fd0ff8514114
parent 695889 4f8dcbc80a0c33e129463d4d351ada407165bf2d
child 695891 186ee641ae417ac0217a0a656a8a4ce5c936fad0
push id88577
push usermozilla@noorenberghe.ca
push dateThu, 09 Nov 2017 23:43:51 +0000
reviewersbaku
bugs1403348
milestone58.0a1
Bug 1403348: Part 3 - Support plain XPC Exceptions in ExtractErrorValues. r=baku MozReview-Commit-ID: LrnE82vHjK
dom/base/nsContentUtils.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -66,16 +66,17 @@
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/Likely.h"
 #include "mozilla/ManualNAC.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/ResultExtensions.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/TextEvents.h"
 #include "nsArrayUtils.h"
 #include "nsAString.h"
 #include "nsAttrName.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsBindingManager.h"
@@ -10907,30 +10908,65 @@ nsContentUtils::IsOverridingWindowName(c
 {
   return !aName.IsEmpty() &&
     !aName.LowerCaseEqualsLiteral("_blank") &&
     !aName.LowerCaseEqualsLiteral("_top") &&
     !aName.LowerCaseEqualsLiteral("_parent") &&
     !aName.LowerCaseEqualsLiteral("_self");
 }
 
+// Unfortunately, we can't unwrap an IDL object using only a concrete type.
+// We need to calculate type data based on the IDL typename. Which means
+// wrapping our templated function in a macro.
+#define EXTRACT_EXN_VALUES(T, ...)                                \
+  ExtractExceptionValues<mozilla::dom::prototypes::id::T,         \
+                         T##Binding::NativeType, T>(__VA_ARGS__).isOk()
+
+template <prototypes::ID PrototypeID, class NativeType, typename T>
+static Result<Ok, nsresult>
+ExtractExceptionValues(JSContext* aCx,
+                       JS::HandleObject aObj,
+                       nsACString& aSourceSpecOut,
+                       uint32_t* aLineOut,
+                       uint32_t* aColumnOut,
+                       nsString& aMessageOut)
+{
+  RefPtr<T> exn;
+  MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn)));
+
+  nsAutoString filename;
+  exn->GetFilename(aCx, filename);
+  if (!filename.IsEmpty()) {
+    CopyUTF16toUTF8(filename, aSourceSpecOut);
+    *aLineOut = exn->LineNumber(aCx);
+    *aColumnOut = exn->ColumnNumber();
+  }
+
+  exn->GetName(aMessageOut);
+  aMessageOut.AppendLiteral(": ");
+
+  nsAutoString message;
+  exn->GetMessageMoz(message);
+  aMessageOut.Append(message);
+  return Ok();
+}
+
 /* static */ void
 nsContentUtils::ExtractErrorValues(JSContext* aCx,
                                    JS::Handle<JS::Value> aValue,
                                    nsACString& aSourceSpecOut,
                                    uint32_t* aLineOut,
                                    uint32_t* aColumnOut,
                                    nsString& aMessageOut)
 {
   MOZ_ASSERT(aLineOut);
   MOZ_ASSERT(aColumnOut);
 
   if (aValue.isObject()) {
     JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
-    RefPtr<dom::DOMException> domException;
 
     // Try to process as an Error object.  Use the file/line/column values
     // from the Error as they will be more specific to the root cause of
     // the problem.
     JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr;
     if (err) {
       // Use xpc to extract the error message only.  We don't actually send
       // this report anywhere.
@@ -10944,48 +10980,43 @@ nsContentUtils::ExtractErrorValues(JSCon
         CopyUTF16toUTF8(report->mFileName, aSourceSpecOut);
         *aLineOut = report->mLineNumber;
         *aColumnOut = report->mColumn;
       }
       aMessageOut.Assign(report->mErrorMsg);
     }
 
     // Next, try to unwrap the rejection value as a DOMException.
-    else if(NS_SUCCEEDED(UNWRAP_OBJECT(DOMException, obj, domException))) {
-
-      nsAutoString filename;
-      domException->GetFilename(aCx, filename);
-      if (!filename.IsEmpty()) {
-        CopyUTF16toUTF8(filename, aSourceSpecOut);
-        *aLineOut = domException->LineNumber(aCx);
-        *aColumnOut = domException->ColumnNumber();
-      }
-
-      domException->GetName(aMessageOut);
-      aMessageOut.AppendLiteral(": ");
-
-      nsAutoString message;
-      domException->GetMessageMoz(message);
-      aMessageOut.Append(message);
+    else if (EXTRACT_EXN_VALUES(DOMException, aCx, obj, aSourceSpecOut,
+                                aLineOut, aColumnOut, aMessageOut)) {
+      return;
+    }
+
+    // Next, try to unwrap the rejection value as an XPC Exception.
+    else if (EXTRACT_EXN_VALUES(Exception, aCx, obj, aSourceSpecOut,
+                                aLineOut, aColumnOut, aMessageOut)) {
+      return;
     }
   }
 
   // If we could not unwrap a specific error type, then perform default safe
   // string conversions on primitives.  Objects will result in "[Object]"
   // unfortunately.
   if (aMessageOut.IsEmpty()) {
     nsAutoJSString jsString;
     if (jsString.init(aCx, aValue)) {
       aMessageOut = jsString;
     } else {
       JS_ClearPendingException(aCx);
     }
   }
 }
 
+#undef EXTRACT_EXN_VALUES
+
 /* static */ bool
 nsContentUtils::DevToolsEnabled(JSContext* aCx)
 {
   if (NS_IsMainThread()) {
     return sDevToolsEnabled;
   }
 
   workers::WorkerPrivate* workerPrivate = workers::GetWorkerPrivateFromContext(aCx);