Bug 1382251: Part 5 - Add IpdlTuple for type-safely marshaling tuples r=jld
☠☠ backed out by 398fb8533bcb ☠ ☠
authorDavid Parks <dparks@mozilla.com>
Mon, 06 Nov 2017 10:17:15 -0800
changeset 399852 37cad137215fa5ef9febbeb9401ff35269a769ab
parent 399851 0d82d0b69c9e62cc4923e361b1ac468674d6b7cb
child 399853 95701ac611fa0e4a18d76d55bb39c0a79e6b0dde
push id33279
push useraciure@mozilla.com
push dateThu, 18 Jan 2018 21:53:37 +0000
treeherdermozilla-central@cffb3cd9dbb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjld
bugs1382251
milestone59.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 1382251: Part 5 - Add IpdlTuple for type-safely marshaling tuples r=jld IpdlTuple is an array of Variants that is accessed by type and that reports an error if there is a type error. This is used for safe and easy communication of IPDL objects, validated at run time since IPC data is untrusted.
dom/plugins/ipc/IpdlTuple.h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/ipc/IpdlTuple.h
@@ -0,0 +1,184 @@
+#ifndef dom_plugins_ipc_ipdltuple_h
+#define dom_plugins_ipc_ipdltuple_h
+
+#include "mozilla/plugins/FunctionBrokerIPCUtils.h"
+#include "mozilla/Variant.h"
+
+namespace mozilla {
+namespace plugins {
+
+/**
+ * IpdlTuple is used by automatic function brokering to pass parameter
+ * lists for brokered functions.  It supports a limited set of types
+ * (see IpdlTuple::IpdlTupleElement).
+ */
+class IpdlTuple
+{
+public:
+  uint32_t NumElements() const { return mTupleElements.Length(); }
+
+  template<typename EltType>
+  EltType* Element(uint32_t index)
+  {
+    if ((index >= mTupleElements.Length()) ||
+        !mTupleElements[index].GetVariant().is<EltType>()) {
+      return nullptr;
+    }
+    return &mTupleElements[index].GetVariant().as<EltType>();
+  }
+
+  template<typename EltType>
+  const EltType* Element(uint32_t index) const
+  {
+    return const_cast<IpdlTuple*>(this)->Element<EltType>(index);
+  }
+
+  template <typename EltType>
+  void AddElement(const EltType& aElt)
+  {
+    IpdlTupleElement* newEntry = mTupleElements.AppendElement();
+    newEntry->Set(aElt);
+  }
+
+private:
+  struct InvalidType {};
+
+  // Like Variant but with a default constructor.
+  template <typename ... Types>
+  struct MaybeVariant
+  {
+  public:
+    MaybeVariant() : mValue(InvalidType()) {}
+    MaybeVariant(MaybeVariant&& o) : mValue(Move(o.mValue)) {}
+
+    template <typename Param> void Set(const Param& aParam)
+    {
+      mValue = mozilla::AsVariant(aParam);
+    }
+
+    typedef mozilla::Variant<InvalidType, Types...> MaybeVariantType;
+    MaybeVariantType& GetVariant() { return mValue; }
+    const MaybeVariantType& GetVariant() const { return mValue; }
+
+  private:
+    MaybeVariantType mValue;
+  };
+
+#if defined(XP_WIN)
+  typedef MaybeVariant<int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,
+                       int64_t,uint64_t,nsCString,bool,OpenFileNameIPC,
+                       OpenFileNameRetIPC,NativeWindowHandle,
+                       IPCSchannelCred,IPCInternetBuffers,StringArray,
+                       IPCPrintDlg> IpdlTupleElement;
+#else
+  typedef MaybeVariant<int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,
+                       int64_t,uint64_t,nsCString,bool> IpdlTupleElement;
+#endif // defined(XP_WIN)
+
+  friend struct IPC::ParamTraits<IpdlTuple>;
+  friend struct IPC::ParamTraits<IpdlTuple::IpdlTupleElement>;
+  friend struct IPC::ParamTraits<IpdlTuple::InvalidType>;
+
+  nsTArray<IpdlTupleElement> mTupleElements;
+};
+
+template <> template<>
+inline void IpdlTuple::IpdlTupleElement::Set<nsDependentCSubstring>(const nsDependentCSubstring& aParam)
+{
+  mValue = MaybeVariantType(mozilla::VariantType<nsCString>(), aParam);
+}
+
+} // namespace plugins
+} // namespace mozilla
+
+namespace IPC {
+
+using namespace mozilla::plugins;
+
+template <>
+struct ParamTraits<IpdlTuple>
+{
+  typedef IpdlTuple paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mTupleElements);
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter,
+                   paramType* aParam)
+  {
+    return ReadParam(aMsg, aIter, &aParam->mTupleElements);
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    LogParam(aParam.mTupleElements, aLog);
+  }
+};
+
+template<>
+struct ParamTraits<IpdlTuple::IpdlTupleElement>
+{
+  typedef IpdlTuple::IpdlTupleElement paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    MOZ_RELEASE_ASSERT(!aParam.GetVariant().is<IpdlTuple::InvalidType>());
+    WriteParam(aMsg, aParam.GetVariant());
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter,
+                   paramType* aParam)
+  {
+    bool ret = ReadParam(aMsg, aIter, &aParam->GetVariant());
+    MOZ_RELEASE_ASSERT(!aParam->GetVariant().is<IpdlTuple::InvalidType>());
+    return ret;
+  }
+
+  struct LogMatcher
+  {
+    explicit LogMatcher(std::wstring* aLog) : mLog(aLog) {}
+
+    template <typename EntryType>
+    void match(const EntryType& aParam)
+    {
+      LogParam(aParam, mLog);
+    }
+
+  private:
+    std::wstring* mLog;
+  };
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aParam.GetVariant().match(LogMatcher(aLog));
+  }
+};
+
+template<>
+struct ParamTraits<IpdlTuple::InvalidType>
+{
+  typedef IpdlTuple::InvalidType paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    MOZ_ASSERT_UNREACHABLE("Attempt to serialize an invalid tuple element");
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter,
+                   paramType* aParam)
+  {
+    MOZ_ASSERT_UNREACHABLE("Attempt to deserialize an invalid tuple element");
+    return false;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aLog->append(L"<Invalid Tuple Entry>");
+  }
+};
+
+} // namespace IPC
+
+#endif /* dom_plugins_ipc_ipdltuple_h */