Bug 1149987 - Part 1: Make it possible to send an ErrorResult that doesn't encode a JS exception through the IPDL layer; r=bzbarsky
☠☠ backed out by 7fbf03927859 ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 06 Apr 2015 21:36:55 -0400
changeset 269532 e7c41c8653c43605976eb5b1579303590ec35414
parent 269473 256b307c35ce0dd516cc06b74d3bf90173be287e
child 269533 693901a4bcde177154392671ccbae2070697ea36
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1149987
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1149987 - Part 1: Make it possible to send an ErrorResult that doesn't encode a JS exception through the IPDL layer; r=bzbarsky
dom/bindings/BindingUtils.cpp
dom/bindings/ErrorIPCUtils.h
dom/bindings/ErrorResult.h
dom/bindings/moz.build
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -41,16 +41,17 @@
 #include "mozilla/dom/HTMLSharedObjectElement.h"
 #include "mozilla/dom/HTMLEmbedElementBinding.h"
 #include "mozilla/dom/HTMLAppletElementBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ResolveSystemBinding.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "WorkerPrivate.h"
 #include "nsDOMClassInfo.h"
+#include "ipc/ErrorIPCUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 JSErrorFormatString ErrorFormatString[] = {
 #define MSG_DEF(_name, _argc, _exn, _str) \
   { _str, _argc, _exn },
 #include "mozilla/dom/Errors.msg"
@@ -145,16 +146,41 @@ ErrorResult::ThrowErrorWithMessage(va_li
   argCount = std::min<uint16_t>(argCount, 10);
   while (argCount--) {
     message->mArgs.AppendElement(*va_arg(ap, nsString*));
   }
   mMessage = message;
 }
 
 void
+ErrorResult::SerializeMessage(IPC::Message* aMsg) const
+{
+  using namespace IPC;
+  MOZ_ASSERT(mMessage);
+  WriteParam(aMsg, mMessage->mArgs);
+  WriteParam(aMsg, mMessage->mErrorNumber);
+}
+
+bool
+ErrorResult::DeserializeMessage(const IPC::Message* aMsg, void** aIter)
+{
+  using namespace IPC;
+  nsAutoPtr<Message> readMessage(new Message());
+  if (!ReadParam(aMsg, aIter, &readMessage->mArgs) ||
+      !ReadParam(aMsg, aIter, &readMessage->mErrorNumber)) {
+    return false;
+  }
+  if (mMessage) {
+    delete mMessage;
+  }
+  mMessage = readMessage.forget();
+  return true;
+}
+
+void
 ErrorResult::ThrowTypeError(const dom::ErrNum errorNumber, ...)
 {
   va_list ap;
   va_start(ap, errorNumber);
   ThrowErrorWithMessage(ap, errorNumber, NS_ERROR_TYPE_ERR);
   va_end(ap);
 }
 
new file mode 100644
--- /dev/null
+++ b/dom/bindings/ErrorIPCUtils.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* vim: set ts=2 sw=2 et tw=79: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ipc/IPCMessageUtils.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Move.h"
+
+#ifndef IPC_ErrorIPCUtils_h
+#define IPC_ErrorIPCUtils_h
+
+namespace IPC {
+
+template<>
+struct ParamTraits<mozilla::dom::ErrNum> :
+  public ContiguousEnumSerializer<mozilla::dom::ErrNum,
+                                  mozilla::dom::ErrNum(0),
+                                  mozilla::dom::ErrNum(mozilla::dom::Err_Limit)> {};
+
+template<>
+struct ParamTraits<mozilla::ErrorResult>
+{
+  typedef mozilla::ErrorResult paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    // It should be the case that mMightHaveUnreportedJSException can only be
+    // true when we're expecting a JS exception.  We cannot send such messages
+    // over the IPC channel since there is no sane way of transferring the JS
+    // value over to the other side.  Callers should never do that.
+    MOZ_ASSERT_IF(aParam.IsJSException(), aParam.mMightHaveUnreportedJSException);
+    if (aParam.IsJSException()
+#ifdef DEBUG
+        || aParam.mMightHaveUnreportedJSException
+#endif
+        ) {
+      MOZ_CRASH("Cannot encode an ErrorResult representing a Javascript exception");
+    }
+
+    WriteParam(aMsg, aParam.mResult);
+    WriteParam(aMsg, aParam.IsErrorWithMessage());
+    if (aParam.IsErrorWithMessage()) {
+      aParam.SerializeMessage(aMsg);
+    }
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    paramType readValue;
+    if (!ReadParam(aMsg, aIter, &readValue.mResult)) {
+      return false;
+    }
+    bool hasMessage = false;
+    if (!ReadParam(aMsg, aIter, &hasMessage)) {
+      return false;
+    }
+    if (hasMessage && !readValue.DeserializeMessage(aMsg, aIter)) {
+      return false;
+    }
+    *aResult = Move(readValue);
+    return true;
+  }
+};
+
+}
+
+#endif
--- a/dom/bindings/ErrorResult.h
+++ b/dom/bindings/ErrorResult.h
@@ -13,16 +13,21 @@
 
 #include <stdarg.h>
 
 #include "js/Value.h"
 #include "nscore.h"
 #include "nsStringGlue.h"
 #include "mozilla/Assertions.h"
 
+namespace IPC {
+class Message;
+template <typename> struct ParamTraits;
+}
+
 namespace mozilla {
 
 namespace dom {
 
 enum ErrNum {
 #define MSG_DEF(_name, _argc, _exn, _str) \
   _name,
 #include "mozilla/dom/Errors.msg"
@@ -156,16 +161,20 @@ private:
   // ReportErrorWithMessage.
   // mJSException is set (and rooted) by ThrowJSException and unrooted
   // by ReportJSException.
   union {
     Message* mMessage; // valid when IsErrorWithMessage()
     JS::Value mJSException; // valid when IsJSException()
   };
 
+  friend struct IPC::ParamTraits<ErrorResult>;
+  void SerializeMessage(IPC::Message* aMsg) const;
+  bool DeserializeMessage(const IPC::Message* aMsg, void** aIter);
+
 #ifdef DEBUG
   // Used to keep track of codepaths that might throw JS exceptions,
   // for assertion purposes.
   bool mMightHaveUnreportedJSException;
 #endif
 
   // Not to be implemented, to make sure people always pass this by
   // reference, not by value.
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -1,16 +1,20 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['test']
 
+EXPORTS.ipc += [
+    'ErrorIPCUtils.h',
+]
+
 EXPORTS.mozilla += [
     'ErrorResult.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'AtomList.h',
     'BindingDeclarations.h',
     'BindingUtils.h',