Bug 942367 - Part 2: DOMMediaStream support for PeerIdentity. r=bholley, r=roc
☠☠ backed out by c2094871202f ☠ ☠
authorMartin Thomson <martin.thomson@gmail.com>
Thu, 10 Apr 2014 11:51:29 -0700
changeset 179494 7d2138e87ca0d7617333a18137819b5ad6480855
parent 179493 7cc66aee4341db6523eeee2b10f6fa9e58a30ca6
child 179495 1e581e74878de5a0f8d2328a77f686b5d6ce89b2
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersbholley, roc
bugs942367
milestone31.0a1
Bug 942367 - Part 2: DOMMediaStream support for PeerIdentity. r=bholley, r=roc
content/media/DOMMediaStream.h
content/media/webrtc/PeerIdentity.cpp
content/media/webrtc/PeerIdentity.h
content/media/webrtc/moz.build
--- a/content/media/DOMMediaStream.h
+++ b/content/media/DOMMediaStream.h
@@ -6,19 +6,20 @@
 #ifndef NSDOMMEDIASTREAM_H_
 #define NSDOMMEDIASTREAM_H_
 
 #include "nsIDOMMediaStream.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 #include "StreamBuffer.h"
 #include "nsIDOMWindow.h"
+#include "nsIPrincipal.h"
+#include "mozilla/PeerIdentity.h"
 
 class nsXPCClassInfo;
-class nsIPrincipal;
 
 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
 // GetTickCount() and conflicts with NS_DECL_NSIDOMMEDIASTREAM, containing
 // currentTime getter.
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 // X11 has a #define for CurrentTime. Unbelievable :-(.
@@ -91,24 +92,42 @@ public:
   bool IsFinished();
   /**
    * Returns a principal indicating who may access this stream. The stream contents
    * can only be accessed by principals subsuming this principal.
    */
   nsIPrincipal* GetPrincipal() { return mPrincipal; }
 
   /**
+   * These are used in WebRTC.  A peerIdentity constrained MediaStream cannot be sent
+   * across the network to anything other than a peer with the provided identity.
+   * If this is set, then mPrincipal should be an instance of nsNullPrincipal.
+   */
+  PeerIdentity* GetPeerIdentity() const { return mPeerIdentity; }
+  void SetPeerIdentity(PeerIdentity* aPeerIdentity)
+  {
+    mPeerIdentity = aPeerIdentity;
+  }
+
+  /**
    * Indicate that data will be contributed to this stream from origin aPrincipal.
    * If aPrincipal is null, this is ignored. Otherwise, from now on the contents
    * of this stream can only be accessed by principals that subsume aPrincipal.
    * Returns true if the stream's principal changed.
    */
   bool CombineWithPrincipal(nsIPrincipal* aPrincipal);
 
   /**
+   * This is used in WebRTC to move from a protected state (nsNullPrincipal) to
+   * one where the stream is accessible to script.  Don't call this.
+   * CombineWithPrincipal is almost certainly more appropriate.
+   */
+  void SetPrincipal(nsIPrincipal* aPrincipal) { mPrincipal = aPrincipal; }
+
+  /**
    * Called when this stream's MediaStreamGraph has been shut down. Normally
    * MSGs are only shut down when all streams have been removed, so this
    * will only be called during a forced shutdown due to application exit.
    */
   void NotifyMediaStreamGraphShutdown();
   /**
    * Called when the main-thread state of the MediaStream changed.
    */
@@ -195,16 +214,19 @@ protected:
   nsCOMPtr<nsIDOMWindow> mWindow;
 
   // MediaStream is owned by the graph, but we tell it when to die, and it won't
   // die until we let it.
   MediaStream* mStream;
   // Principal identifying who may access the contents of this stream.
   // If null, this stream can be used by anyone because it has no content yet.
   nsCOMPtr<nsIPrincipal> mPrincipal;
+  // this is used in gUM and WebRTC to identify peers that this stream
+  // is allowed to be sent to
+  nsAutoPtr<PeerIdentity> mPeerIdentity;
 
   nsAutoTArray<nsRefPtr<MediaStreamTrack>,2> mTracks;
   nsRefPtr<StreamListener> mListener;
 
   nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable;
 
   // Keep these alive until the stream finishes
   nsTArray<nsCOMPtr<nsISupports> > mConsumersToKeepAlive;
new file mode 100644
--- /dev/null
+++ b/content/media/webrtc/PeerIdentity.cpp
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * 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 "PeerIdentity.h"
+
+#include "nsCOMPtr.h"
+#include "nsIIDNService.h"
+#include "nsNetCID.h"
+
+namespace mozilla {
+
+bool
+PeerIdentity::Equals(const PeerIdentity& aOther) const
+{
+  return Equals(aOther.mPeerIdentity);
+}
+
+bool
+PeerIdentity::Equals(const nsAString& aOtherString) const
+{
+  nsString user;
+  GetUser(mPeerIdentity, user);
+  nsString otherUser;
+  GetUser(aOtherString, otherUser);
+  if (user != otherUser) {
+    return false;
+  }
+
+  nsString host;
+  GetHost(mPeerIdentity, host);
+  nsString otherHost;
+  GetHost(aOtherString, otherHost);
+
+  nsresult rv;
+  nsCOMPtr<nsIIDNService> idnService
+    = do_GetService(NS_IDNSERVICE_CONTRACTID, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return host == otherHost;
+  }
+
+  nsCString normHost;
+  GetNormalizedHost(idnService, host, normHost);
+  nsCString normOtherHost;
+  GetNormalizedHost(idnService, otherHost, normOtherHost);
+  return normHost == normOtherHost;
+}
+
+/* static */ void
+PeerIdentity::GetUser(const nsAString& aPeerIdentity, nsAString& aUser)
+{
+  int32_t at = aPeerIdentity.FindChar('@');
+  if (at >= 0) {
+    aUser = Substring(aPeerIdentity, 0, at);
+  } else {
+    aUser.Truncate();
+  }
+}
+
+/* static */ void
+PeerIdentity::GetHost(const nsAString& aPeerIdentity, nsAString& aHost)
+{
+  int32_t at = aPeerIdentity.FindChar('@');
+  if (at >= 0) {
+    aHost = Substring(aPeerIdentity, at + 1);
+  } else {
+    aHost = aPeerIdentity;
+  }
+}
+
+/* static */ void
+PeerIdentity::GetNormalizedHost(const nsCOMPtr<nsIIDNService>& aIdnService,
+                                const nsAString& aHost,
+                                nsACString& aNormalizedHost)
+{
+  nsCString chost = NS_ConvertUTF16toUTF8(aHost);
+  nsresult rv = aIdnService->ConvertUTF8toACE(chost, aNormalizedHost);
+  NS_WARN_IF(NS_FAILED(rv));
+}
+
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/content/media/webrtc/PeerIdentity.h
@@ -0,0 +1,79 @@
+ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+  * vim: sw=2 ts=2 sts=2 expandtab
+  * 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/. */
+
+#ifndef PeerIdentity_h
+#define PeerIdentity_h
+
+#ifdef MOZILLA_INTERNAL_API
+#include "nsString.h"
+#else
+#include "nsStringAPI.h"
+#endif
+
+template <class T> class nsCOMPtr;
+class nsIIDNService;
+
+namespace mozilla {
+
+/**
+ * This class implements the identifier used in WebRTC identity.  Peers are
+ * identified using a string in the form [<user>@]<domain>, for instance,
+ * "user@example.com'. The (optional) user portion is a site-controlled string
+ * containing any character other than '@'.  The domain portion is a valid IDN
+ * domain name and is compared accordingly.
+ *
+ * See: http://tools.ietf.org/html/draft-ietf-rtcweb-security-arch-09#section-5.6.5.3.3.1
+ */
+class PeerIdentity MOZ_FINAL
+{
+public:
+  PeerIdentity(const nsAString& aPeerIdentity)
+    : mPeerIdentity(aPeerIdentity) {}
+  ~PeerIdentity() {}
+
+  bool Equals(const PeerIdentity& aOther) const;
+  bool Equals(const nsAString& aOtherString) const;
+  const nsString& ToString() const { return mPeerIdentity; }
+
+private:
+  static void GetUser(const nsAString& aPeerIdentity, nsAString& aUser);
+  static void GetHost(const nsAString& aPeerIdentity, nsAString& aHost);
+
+  static void GetNormalizedHost(const nsCOMPtr<nsIIDNService>& aIdnService,
+                                const nsAString& aHost,
+                                nsACString& aNormalizedHost);
+
+  nsString mPeerIdentity;
+};
+
+inline bool
+operator==(const PeerIdentity& aOne, const PeerIdentity& aTwo)
+{
+  return aOne.Equals(aTwo);
+}
+
+inline bool
+operator==(const PeerIdentity& aOne, const nsAString& aString)
+{
+  return aOne.Equals(aString);
+}
+
+inline bool
+operator!=(const PeerIdentity& aOne, const PeerIdentity& aTwo)
+{
+  return !aOne.Equals(aTwo);
+}
+
+inline bool
+operator!=(const PeerIdentity& aOne, const nsAString& aString)
+{
+  return !aOne.Equals(aString);
+}
+
+
+} /* namespace mozilla */
+
+#endif /* PeerIdentity_h */
--- a/content/media/webrtc/moz.build
+++ b/content/media/webrtc/moz.build
@@ -42,15 +42,20 @@ if CONFIG['MOZ_WEBRTC']:
     ]
 
 XPIDL_SOURCES += [
     'nsITabSource.idl'
 ]
 
 UNIFIED_SOURCES += [
     'MediaEngineDefault.cpp',
+    'PeerIdentity.cpp',
+]
+
+EXPORTS.mozilla += [
+    'PeerIdentity.h',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 if CONFIG['OS_ARCH'] == 'WINNT':
     DEFINES['NOMINMAX'] = True