Bug 1320170 - dom/media should use nsIPrincipal (and PrincipalInfo) instead origin as string, r=rjesup, r=ehsan
authorAndrea Marchesini <amarchesini@mozilla.com>
Sat, 28 Jan 2017 18:29:13 +0100
changeset 331566 e72459157cf91f9332c7e852246333c82032d5c0
parent 331562 7675a6d4b824f29f4cb1fd68c1b7d712e2d6b8bc
child 331567 ab2849f57624c01c344a55b2632dac1c2603ce4c
push id31275
push userphilringnalda@gmail.com
push dateSun, 29 Jan 2017 17:02:37 +0000
treeherdermozilla-central@77af15f468e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrjesup, ehsan
bugs1320170
milestone54.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 1320170 - dom/media should use nsIPrincipal (and PrincipalInfo) instead origin as string, r=rjesup, r=ehsan
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/imagecapture/moz.build
dom/media/systemservices/CamerasChild.cpp
dom/media/systemservices/CamerasChild.h
dom/media/systemservices/CamerasParent.cpp
dom/media/systemservices/CamerasParent.h
dom/media/systemservices/MediaChild.cpp
dom/media/systemservices/MediaChild.h
dom/media/systemservices/MediaParent.cpp
dom/media/systemservices/MediaParent.h
dom/media/systemservices/PCameras.ipdl
dom/media/systemservices/PMedia.ipdl
dom/media/webrtc/MediaEngine.h
dom/media/webrtc/MediaEngineDefault.cpp
dom/media/webrtc/MediaEngineDefault.h
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.h
dom/media/webrtc/MediaEngineTabVideoSource.cpp
dom/media/webrtc/MediaEngineTabVideoSource.h
dom/media/webrtc/MediaEngineWebRTC.h
dom/media/webrtc/MediaEngineWebRTCAudio.cpp
dom/media/webspeech/recognition/SpeechRecognition.cpp
dom/media/webspeech/recognition/SpeechRecognition.h
ipc/glue/BackgroundUtils.cpp
ipc/glue/BackgroundUtils.h
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -870,19 +870,19 @@ VideoDevice::GetSource()
 AudioDevice::Source*
 AudioDevice::GetSource()
 {
   return static_cast<Source*>(&*mSource);
 }
 
 nsresult MediaDevice::Allocate(const dom::MediaTrackConstraints &aConstraints,
                                const MediaEnginePrefs &aPrefs,
-                               const nsACString& aOrigin,
+                               const ipc::PrincipalInfo& aPrincipalInfo,
                                const char** aOutBadConstraint) {
-  return GetSource()->Allocate(aConstraints, aPrefs, mID, aOrigin,
+  return GetSource()->Allocate(aConstraints, aPrefs, mID, aPrincipalInfo,
                                getter_AddRefs(mAllocationHandle),
                                aOutBadConstraint);
 }
 
 nsresult MediaDevice::Restart(const dom::MediaTrackConstraints &aConstraints,
                               const MediaEnginePrefs &aPrefs,
                               const char** aOutBadConstraint) {
   return GetSource()->Restart(mAllocationHandle, aConstraints, aPrefs, mID,
@@ -982,27 +982,27 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(FakeT
 class GetUserMediaStreamRunnable : public Runnable
 {
 public:
   GetUserMediaStreamRunnable(
     nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
     nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
     uint64_t aWindowID,
     GetUserMediaCallbackMediaStreamListener* aListener,
-    const nsCString& aOrigin,
+    const ipc::PrincipalInfo& aPrincipalInfo,
     const MediaStreamConstraints& aConstraints,
     AudioDevice* aAudioDevice,
     VideoDevice* aVideoDevice,
     PeerIdentity* aPeerIdentity)
     : mConstraints(aConstraints)
     , mAudioDevice(aAudioDevice)
     , mVideoDevice(aVideoDevice)
     , mWindowID(aWindowID)
     , mListener(aListener)
-    , mOrigin(aOrigin)
+    , mPrincipalInfo(aPrincipalInfo)
     , mPeerIdentity(aPeerIdentity)
     , mManager(MediaManager::GetInstance())
   {
     mOnSuccess.swap(aOnSuccess);
     mOnFailure.swap(aOnFailure);
   }
 
   ~GetUserMediaStreamRunnable() {}
@@ -1227,33 +1227,34 @@ public:
         new MediaOperationTask(MEDIA_START, mListener, domStream,
                                tracksAvailableCallback,
                                mAudioDevice, mVideoDevice,
                                false, mWindowID, mOnFailure.forget());
     MediaManager::PostTask(mediaOperation.forget());
     // We won't need mOnFailure now.
     mOnFailure = nullptr;
 
-    if (!OriginAttributes::IsPrivateBrowsing(mOrigin)) {
-      // Call GetOriginKey again, this time w/persist = true, to promote
+    if (!IsPincipalInfoPrivate(mPrincipalInfo)) {
+      // Call GetPrincipalKey again, this time w/persist = true, to promote
       // deviceIds to persistent, in case they're not already. Fire'n'forget.
-      RefPtr<Pledge<nsCString>> p = media::GetOriginKey(mOrigin, true);
+      RefPtr<Pledge<nsCString>> p =
+        media::GetPrincipalKey(mPrincipalInfo, true);
     }
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
   MediaStreamConstraints mConstraints;
   RefPtr<AudioDevice> mAudioDevice;
   RefPtr<VideoDevice> mVideoDevice;
   uint64_t mWindowID;
   RefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
-  nsCString mOrigin;
+  ipc::PrincipalInfo mPrincipalInfo;
   RefPtr<PeerIdentity> mPeerIdentity;
   RefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
 // Source getter returning full list
 
 template<class DeviceType>
 static void
@@ -1377,26 +1378,26 @@ class GetUserMediaTask : public Runnable
 {
 public:
   GetUserMediaTask(
     const MediaStreamConstraints& aConstraints,
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aOnSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
     uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
     MediaEnginePrefs &aPrefs,
-    const nsCString& aOrigin,
+    const ipc::PrincipalInfo& aPrincipalInfo,
     bool aIsChrome,
     MediaManager::SourceSet* aSourceSet)
     : mConstraints(aConstraints)
     , mOnSuccess(aOnSuccess)
     , mOnFailure(aOnFailure)
     , mWindowID(aWindowID)
     , mListener(aListener)
     , mPrefs(aPrefs)
-    , mOrigin(aOrigin)
+    , mPrincipalInfo(aPrincipalInfo)
     , mIsChrome(aIsChrome)
     , mDeviceChosen(false)
     , mSourceSet(aSourceSet)
     , mManager(MediaManager::GetInstance())
   {}
 
   ~GetUserMediaTask() {
   }
@@ -1432,30 +1433,32 @@ public:
     // a GetUserMediaStreamRunnable.
 
     nsresult rv;
     const char* errorMsg = nullptr;
     const char* badConstraint = nullptr;
 
     if (mAudioDevice) {
       auto& constraints = GetInvariant(mConstraints.mAudio);
-      rv = mAudioDevice->Allocate(constraints, mPrefs, mOrigin, &badConstraint);
+      rv = mAudioDevice->Allocate(constraints, mPrefs, mPrincipalInfo,
+                                  &badConstraint);
       if (NS_FAILED(rv)) {
         errorMsg = "Failed to allocate audiosource";
         if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
           nsTArray<RefPtr<AudioDevice>> audios;
           audios.AppendElement(mAudioDevice);
           badConstraint = MediaConstraintsHelper::SelectSettings(
               NormalizedConstraints(constraints), audios, mIsChrome);
         }
       }
     }
     if (!errorMsg && mVideoDevice) {
       auto& constraints = GetInvariant(mConstraints.mVideo);
-      rv = mVideoDevice->Allocate(constraints, mPrefs, mOrigin, &badConstraint);
+      rv = mVideoDevice->Allocate(constraints, mPrefs, mPrincipalInfo,
+                                  &badConstraint);
       if (NS_FAILED(rv)) {
         errorMsg = "Failed to allocate videosource";
         if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
           nsTArray<RefPtr<VideoDevice>> videos;
           videos.AppendElement(mVideoDevice);
           badConstraint = MediaConstraintsHelper::SelectSettings(
               NormalizedConstraints(constraints), videos, mIsChrome);
         }
@@ -1478,17 +1481,17 @@ public:
     }
     PeerIdentity* peerIdentity = nullptr;
     if (!mConstraints.mPeerIdentity.IsEmpty()) {
       peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity);
     }
 
     NS_DispatchToMainThread(do_AddRef(
         new GetUserMediaStreamRunnable(mOnSuccess, mOnFailure, mWindowID,
-                                       mListener, mOrigin,
+                                       mListener, mPrincipalInfo,
                                        mConstraints, mAudioDevice, mVideoDevice,
                                        peerIdentity)));
     MOZ_ASSERT(!mOnSuccess);
     MOZ_ASSERT(!mOnFailure);
     return NS_OK;
   }
 
   nsresult
@@ -1560,17 +1563,17 @@ private:
 
   nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
   uint64_t mWindowID;
   RefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
   RefPtr<AudioDevice> mAudioDevice;
   RefPtr<VideoDevice> mVideoDevice;
   MediaEnginePrefs mPrefs;
-  nsCString mOrigin;
+  ipc::PrincipalInfo mPrincipalInfo;
   bool mIsChrome;
 
   bool mDeviceChosen;
 public:
   nsAutoPtr<MediaManager::SourceSet> mSourceSet;
 private:
   RefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
@@ -2075,18 +2078,20 @@ if (privileged) {
   }
 
   nsCOMPtr<nsIPrincipal> principal =
     nsGlobalWindow::Cast(aWindow)->GetPrincipal();
   if (NS_WARN_IF(!principal)) {
     return NS_ERROR_FAILURE;
   }
 
-  nsAutoCString origin;
-  rv = principal->GetOrigin(origin);
+  // This principal needs to be sent to different threads and so via IPC.
+  // For this reason it's better to convert it to PrincipalInfo right now.
+  ipc::PrincipalInfo principalInfo;
+  rv = PrincipalToPrincipalInfo(principal, &principalInfo);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!Preferences::GetBool("media.navigator.video.enabled", true)) {
     c.mVideo.SetAsBoolean() = false;
   }
 
@@ -2281,33 +2286,34 @@ if (privileged) {
 
   bool askPermission =
       (!privileged || Preferences::GetBool("media.navigator.permission.force")) &&
       (!fake || Preferences::GetBool("media.navigator.permission.fake"));
 
   RefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowID, videoType,
                                                    audioType, fake);
   p->Then([this, onSuccess, onFailure, windowID, c, listener, askPermission,
-           prefs, isHTTPS, callID, origin, isChrome](SourceSet*& aDevices) mutable {
+           prefs, isHTTPS, callID, principalInfo,
+           isChrome](SourceSet*& aDevices) mutable {
 
     RefPtr<Refcountable<UniquePtr<SourceSet>>> devices(
          new Refcountable<UniquePtr<SourceSet>>(aDevices)); // grab result
 
     // Ensure that the captured 'this' pointer and our windowID are still good.
     if (!MediaManager::Exists() ||
         !nsGlobalWindow::GetInnerWindowWithId(windowID)) {
       return;
     }
 
     // Apply any constraints. This modifies the passed-in list.
     RefPtr<PledgeChar> p2 = SelectSettings(c, isChrome, devices);
 
     p2->Then([this, onSuccess, onFailure, windowID, c,
-              listener, askPermission, prefs, isHTTPS, callID,
-              origin, isChrome, devices](const char*& badConstraint) mutable {
+              listener, askPermission, prefs, isHTTPS, callID, principalInfo,
+              isChrome, devices](const char*& badConstraint) mutable {
 
       // Ensure that the captured 'this' pointer and our windowID are still good.
       auto* globalWindow = nsGlobalWindow::GetInnerWindowWithId(windowID);
       RefPtr<nsPIDOMWindowInner> window = globalWindow ? globalWindow->AsInner()
                                                        : nullptr;
       if (!MediaManager::Exists() || !window) {
         return;
       }
@@ -2339,17 +2345,17 @@ if (privileged) {
           }
         }
       }
 
       // Pass callbacks and MediaStreamListener along to GetUserMediaTask.
       RefPtr<GetUserMediaTask> task (new GetUserMediaTask(c, onSuccess.forget(),
                                                           onFailure.forget(),
                                                           windowID, listener,
-                                                          prefs, origin,
+                                                          prefs, principalInfo,
                                                           isChrome,
                                                           devices->release()));
       // Store the task w/callbacks.
       mActiveCallbacks.Put(callID, task.forget());
 
       // Add a WindowID cross-reference so OnNavigation can tear things down
       nsTArray<nsString>* array;
       if (!mCallIds.Get(windowID, &array)) {
@@ -2483,27 +2489,34 @@ MediaManager::EnumerateDevicesImpl(uint6
   // 1. Get an origin-key (for either regular or private browsing)
   // 2. Get the raw devices list
   // 3. Anonymize the raw list with the origin-key.
 
   nsCOMPtr<nsIPrincipal> principal =
     nsGlobalWindow::Cast(window)->GetPrincipal();
   MOZ_ASSERT(principal);
 
-  nsAutoCString origin;
-  principal->GetOrigin(origin);
+  ipc::PrincipalInfo principalInfo;
+  nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    RefPtr<PledgeSourceSet> p = new PledgeSourceSet();
+    RefPtr<MediaStreamError> error =
+      new MediaStreamError(window, NS_LITERAL_STRING("NotAllowedError"));
+    p->Reject(error);
+    return p.forget();
+  }
 
   bool persist = IsActivelyCapturingOrHasAPermission(aWindowId);
 
-  // GetOriginKey is an async API that returns a pledge (a promise-like
+  // GetPrincipalKey is an async API that returns a pledge (a promise-like
   // pattern). We use .Then() to pass in a lambda to run back on this same
-  // thread later once GetOriginKey resolves. Needed variables are "captured"
+  // thread later once GetPrincipalKey resolves. Needed variables are "captured"
   // (passed by value) safely into the lambda.
 
-  RefPtr<Pledge<nsCString>> p = media::GetOriginKey(origin, persist);
+  RefPtr<Pledge<nsCString>> p = media::GetPrincipalKey(principalInfo, persist);
   p->Then([id, aWindowId, aVideoType, aAudioType,
            aFake](const nsCString& aOriginKey) mutable {
     MOZ_ASSERT(NS_IsMainThread());
     RefPtr<MediaManager> mgr = MediaManager_GetInstance();
 
     RefPtr<PledgeSourceSet> p = mgr->EnumerateRawDevices(aWindowId, aVideoType,
                                                          aAudioType, aFake);
     p->Then([id, aWindowId, aOriginKey](SourceSet*& aDevices) mutable {
@@ -2547,19 +2560,19 @@ MediaManager::EnumerateDevices(nsPIDOMWi
                                                 MakePrincipalHandle(principal));
 
   // No need for locking because we always do this in the main thread.
   listeners->AppendElement(listener);
 
   bool fake = Preferences::GetBool("media.navigator.streams.fake");
 
   RefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowId,
-                                                     MediaSourceEnum::Camera,
-                                                     MediaSourceEnum::Microphone,
-                                                     fake);
+                                                   MediaSourceEnum::Camera,
+                                                   MediaSourceEnum::Microphone,
+                                                   fake);
   p->Then([onSuccess, windowId, listener](SourceSet*& aDevices) mutable {
     UniquePtr<SourceSet> devices(aDevices); // grab result
     RefPtr<MediaManager> mgr = MediaManager_GetInstance();
     mgr->RemoveFromWindowList(windowId, listener);
     nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*devices);
     onSuccess->OnSuccess(array);
   }, [onFailure, windowId, listener](MediaStreamError*& reason) mutable {
     RefPtr<MediaManager> mgr = MediaManager_GetInstance();
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -45,16 +45,20 @@
 
 namespace mozilla {
 namespace dom {
 struct MediaStreamConstraints;
 struct MediaTrackConstraints;
 struct MediaTrackConstraintSet;
 } // namespace dom
 
+namespace ipc {
+class PrincipalInfo;
+}
+
 class MediaManager;
 class GetUserMediaCallbackMediaStreamListener;
 class GetUserMediaTask;
 
 extern LogModule* GetMediaManagerLog();
 #define MM_LOG(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Debug, msg)
 
 class MediaDevice : public nsIMediaDevice
@@ -68,17 +72,17 @@ public:
   void SetId(const nsAString& aID);
   void SetRawId(const nsAString& aID);
   virtual uint32_t GetBestFitnessDistance(
       const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
       bool aIsChrome);
   virtual Source* GetSource() = 0;
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
-                    const nsACString& aOrigin,
+                    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                     const char** aOutBadConstraint);
   nsresult Restart(const dom::MediaTrackConstraints &aConstraints,
                    const MediaEnginePrefs &aPrefs,
                    const char** aOutBadConstraint);
   nsresult Deallocate();
 protected:
   virtual ~MediaDevice() {}
   explicit MediaDevice(MediaEngineSource* aSource, bool aIsVideo);
@@ -326,15 +330,15 @@ private:
   RefPtr<MediaEngine> mBackend;
 
   static StaticRefPtr<MediaManager> sSingleton;
 
   media::CoatCheck<PledgeSourceSet> mOutstandingPledges;
   media::CoatCheck<PledgeChar> mOutstandingCharPledges;
   media::CoatCheck<PledgeVoid> mOutstandingVoidPledges;
 public:
-  media::CoatCheck<media::Pledge<nsCString>> mGetOriginKeyPledges;
+  media::CoatCheck<media::Pledge<nsCString>> mGetPrincipalKeyPledges;
   RefPtr<media::Parent<media::NonE10s>> mNonE10sParent;
 };
 
 } // namespace mozilla
 
 #endif // MOZILLA_MEDIAMANAGER_H
--- a/dom/media/imagecapture/moz.build
+++ b/dom/media/imagecapture/moz.build
@@ -8,9 +8,11 @@ EXPORTS.mozilla.dom += [
     'ImageCapture.h'
 ]
 
 UNIFIED_SOURCES += [
     'CaptureTask.cpp',
     'ImageCapture.cpp',
 ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -424,24 +424,23 @@ CamerasChild::RecvReplyGetCaptureDevice(
   return IPC_OK();
 }
 
 int
 CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
                                     const char* unique_idUTF8,
                                     const unsigned int unique_idUTF8Length,
                                     int& aStreamId,
-                                    const nsACString& aOrigin)
+                                    const mozilla::ipc::PrincipalInfo& aPrincipalInfo)
 {
   LOG((__PRETTY_FUNCTION__));
   nsCString unique_id(unique_idUTF8);
-  nsCString origin(aOrigin);
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, unique_id, origin]() -> nsresult {
-      if (this->SendAllocateCaptureDevice(aCapEngine, unique_id, origin)) {
+    media::NewRunnableFrom([this, aCapEngine, unique_id, aPrincipalInfo]() -> nsresult {
+      if (this->SendAllocateCaptureDevice(aCapEngine, unique_id, aPrincipalInfo)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   if (dispatcher.Success()) {
     LOG(("Capture Device allocated: %d", mReplyInteger));
     aStreamId = mReplyInteger;
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -24,16 +24,17 @@
 #include "webrtc/modules/video_capture/video_capture_defines.h"
 
 
 
 namespace mozilla {
 
 namespace ipc {
 class BackgroundChildImpl;
+class PrincipalInfo;
 }
 
 namespace camera {
 
 class FrameRelay {
 public:
   virtual int DeliverFrame(uint8_t* buffer,
     const mozilla::camera::VideoFrameProperties& props) = 0;
@@ -189,17 +190,17 @@ public:
   int StartCapture(CaptureEngine aCapEngine,
                    const int capture_id, webrtc::VideoCaptureCapability& capability,
                    FrameRelay* func);
   int StopCapture(CaptureEngine aCapEngine, const int capture_id);
   int AllocateCaptureDevice(CaptureEngine aCapEngine,
                             const char* unique_idUTF8,
                             const unsigned int unique_idUTF8Length,
                             int& capture_id,
-                            const nsACString& aOrigin);
+                            const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
   int GetCaptureCapability(CaptureEngine aCapEngine,
                            const char* unique_idUTF8,
                            const unsigned int capability_number,
                            webrtc::VideoCaptureCapability& capability);
   int GetCaptureDevice(CaptureEngine aCapEngine,
                        unsigned int list_number, char* device_nameUTF8,
                        const unsigned int device_nameUTF8Length,
                        char* unique_idUTF8,
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -631,84 +631,76 @@ CamerasParent::RecvGetCaptureDevice(cons
         });
       self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
-static nsresult
-GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal)
-{
-  nsAutoCString originNoSuffix;
-  mozilla::OriginAttributes attrs;
-  if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
-  principal.forget(aPrincipal);
-  return NS_OK;
-}
-
-// Find out whether the given origin has permission to use the
+// Find out whether the given principal has permission to use the
 // camera. If the permission is not persistent, we'll make it
 // a one-shot by removing the (session) permission.
 static bool
-HasCameraPermission(const nsCString& aOrigin)
+HasCameraPermission(const ipc::PrincipalInfo& aPrincipalInfo)
 {
+  if (aPrincipalInfo.type() == ipc::PrincipalInfo::TNullPrincipalInfo) {
+    return false;
+  }
+
+  if (aPrincipalInfo.type() == ipc::PrincipalInfo::TSystemPrincipalInfo) {
+    return true;
+  }
+
+  MOZ_ASSERT(aPrincipalInfo.type() == ipc::PrincipalInfo::TContentPrincipalInfo);
+
+  nsresult rv;
+  nsCOMPtr<nsIPrincipal> principal =
+    PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
   // Name used with nsIPermissionManager
   static const char* cameraPermission = "MediaManagerVideo";
-  bool allowed = false;
-  nsresult rv;
   nsCOMPtr<nsIPermissionManager> mgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
-  if (NS_SUCCEEDED(rv)) {
-    nsCOMPtr<nsIIOService> ioServ(do_GetIOService());
-    nsCOMPtr<nsIURI> uri;
-    rv = ioServ->NewURI(aOrigin, nullptr, nullptr, getter_AddRefs(uri));
-    if (NS_SUCCEEDED(rv)) {
-      // Permanent permissions are only retrievable via principal, not uri
-      nsCOMPtr<nsIPrincipal> principal;
-      rv = GetPrincipalFromOrigin(aOrigin, getter_AddRefs(principal));
-      if (NS_SUCCEEDED(rv)) {
-        uint32_t video = nsIPermissionManager::UNKNOWN_ACTION;
-        rv = mgr->TestExactPermissionFromPrincipal(principal,
-                                                   cameraPermission,
-                                                   &video);
-        if (NS_SUCCEEDED(rv)) {
-          allowed = (video == nsIPermissionManager::ALLOW_ACTION);
-        }
-        // Session permissions are removed after one use.
-        if (allowed) {
-          mgr->RemoveFromPrincipal(principal, cameraPermission);
-        }
-      }
-    }
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
   }
+
+  uint32_t video = nsIPermissionManager::UNKNOWN_ACTION;
+  rv = mgr->TestExactPermissionFromPrincipal(principal, cameraPermission,
+                                             &video);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  bool allowed = (video == nsIPermissionManager::ALLOW_ACTION);
+
+  // Session permissions are removed after one use.
+  if (allowed) {
+    mgr->RemoveFromPrincipal(principal, cameraPermission);
+  }
+
   return allowed;
 }
 
 mozilla::ipc::IPCResult
 CamerasParent::RecvAllocateCaptureDevice(const CaptureEngine& aCapEngine,
                                          const nsCString& unique_id,
-                                         const nsCString& aOrigin)
+                                         const PrincipalInfo& aPrincipalInfo)
 {
-  LOG(("%s: Verifying permissions for %s", __PRETTY_FUNCTION__, aOrigin.get()));
+  LOG(("%s: Verifying permissions", __PRETTY_FUNCTION__));
   RefPtr<CamerasParent> self(this);
   RefPtr<Runnable> mainthread_runnable =
-    media::NewRunnableFrom([self, aCapEngine, unique_id, aOrigin]() -> nsresult {
+    media::NewRunnableFrom([self, aCapEngine, unique_id, aPrincipalInfo]() -> nsresult {
       // Verify whether the claimed origin has received permission
       // to use the camera, either persistently or this session (one shot).
-      bool allowed = HasCameraPermission(aOrigin);
+      bool allowed = HasCameraPermission(aPrincipalInfo);
       if (!allowed) {
         // Developer preference for turning off permission check.
         if (Preferences::GetBool("media.navigator.permission.disabled", false)
             || Preferences::GetBool("media.navigator.permission.fake")) {
           allowed = true;
           LOG(("No permission but checks are disabled or fake sources active"));
         } else {
           LOG(("No camera permission for this origin"));
--- a/dom/media/systemservices/CamerasParent.h
+++ b/dom/media/systemservices/CamerasParent.h
@@ -23,16 +23,21 @@
 #undef FF
 #include "webrtc/common.h"
 
 #include "CamerasChild.h"
 
 #include "base/thread.h"
 
 namespace mozilla {
+
+namespace ipc {
+class PrincipalInfo;
+}
+
 namespace camera {
 
 class CamerasParent;
 
 class CallbackHelper :
   public webrtc::VideoRenderCallback,
   public webrtc::VideoCaptureDataCallback
 {
@@ -79,18 +84,20 @@ class CamerasParent :  public PCamerasPa
 {
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
 public:
   static already_AddRefed<CamerasParent> Create();
 
   // Messages received form the child. These run on the IPC/PBackground thread.
-  virtual mozilla::ipc::IPCResult RecvAllocateCaptureDevice(const CaptureEngine&, const nsCString&,
-                                                            const nsCString&) override;
+  virtual mozilla::ipc::IPCResult
+  RecvAllocateCaptureDevice(const CaptureEngine& aEngine,
+                            const nsCString& aUnique_idUTF8,
+                            const ipc::PrincipalInfo& aPrincipalInfo) override;
   virtual mozilla::ipc::IPCResult RecvReleaseCaptureDevice(const CaptureEngine&,
                                                            const int&) override;
   virtual mozilla::ipc::IPCResult RecvNumberOfCaptureDevices(const CaptureEngine&) override;
   virtual mozilla::ipc::IPCResult RecvNumberOfCapabilities(const CaptureEngine&,
                                                            const nsCString&) override;
   virtual mozilla::ipc::IPCResult RecvGetCaptureCapability(const CaptureEngine&, const nsCString&,
                                                            const int&) override;
   virtual mozilla::ipc::IPCResult RecvGetCaptureDevice(const CaptureEngine&, const int&) override;
--- a/dom/media/systemservices/MediaChild.cpp
+++ b/dom/media/systemservices/MediaChild.cpp
@@ -15,28 +15,28 @@
 #undef LOG
 mozilla::LazyLogModule gMediaChildLog("MediaChild");
 #define LOG(args) MOZ_LOG(gMediaChildLog, mozilla::LogLevel::Debug, args)
 
 namespace mozilla {
 namespace media {
 
 already_AddRefed<Pledge<nsCString>>
-GetOriginKey(const nsCString& aOrigin, bool aPersist)
+GetPrincipalKey(const ipc::PrincipalInfo& aPrincipalInfo, bool aPersist)
 {
   RefPtr<MediaManager> mgr = MediaManager::GetInstance();
   MOZ_ASSERT(mgr);
 
   RefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
-  uint32_t id = mgr->mGetOriginKeyPledges.Append(*p);
+  uint32_t id = mgr->mGetPrincipalKeyPledges.Append(*p);
 
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
-    mgr->GetNonE10sParent()->RecvGetOriginKey(id, aOrigin, aPersist);
+    mgr->GetNonE10sParent()->RecvGetPrincipalKey(id, aPrincipalInfo, aPersist);
   } else {
-    Child::Get()->SendGetOriginKey(id, aOrigin, aPersist);
+    Child::Get()->SendGetPrincipalKey(id, aPrincipalInfo, aPersist);
   }
   return p.forget();
 }
 
 void
 SanitizeOriginKeys(const uint64_t& aSinceWhen, bool aOnlyPrivateBrowsing)
 {
   LOG(("SanitizeOriginKeys since %llu %s", aSinceWhen,
@@ -79,23 +79,25 @@ Child::~Child()
 }
 
 void Child::ActorDestroy(ActorDestroyReason aWhy)
 {
   mActorDestroyed = true;
 }
 
 mozilla::ipc::IPCResult
-Child::RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey)
+Child::RecvGetPrincipalKeyResponse(const uint32_t& aRequestId,
+                                   const nsCString& aKey)
 {
   RefPtr<MediaManager> mgr = MediaManager::GetInstance();
   if (!mgr) {
     return IPC_FAIL_NO_REASON(this);
   }
-  RefPtr<Pledge<nsCString>> pledge = mgr->mGetOriginKeyPledges.Remove(aRequestId);
+  RefPtr<Pledge<nsCString>> pledge =
+    mgr->mGetPrincipalKeyPledges.Remove(aRequestId);
   if (pledge) {
     pledge->Resolve(aKey);
   }
   return IPC_OK();
 }
 
 PMediaChild*
 AllocPMediaChild()
--- a/dom/media/systemservices/MediaChild.h
+++ b/dom/media/systemservices/MediaChild.h
@@ -8,41 +8,52 @@
 #define mozilla_MediaChild_h
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/media/PMediaChild.h"
 #include "mozilla/media/PMediaParent.h"
 #include "MediaUtils.h"
 
 namespace mozilla {
+
+namespace ipc {
+class PrincipalInfo;
+}
+
 namespace media {
 
 // media::Child implements proxying to the chrome process for some media-related
 // functions, for the moment just:
 //
-// GetOriginKey() - get a cookie-like persisted unique key for a given origin.
+// GetPrincipalKey() - get a cookie-like persisted unique key for a given
+// principalInfo.
+//
 // SanitizeOriginKeys() - reset persisted unique keys.
 
-// GetOriginKey and SanitizeOriginKeys are asynchronous APIs that return pledges
-// (promise-like objects) with the future value. Use pledge.Then(func) to access.
+// GetPrincipalKey and SanitizeOriginKeys are asynchronous APIs that return
+// pledges (promise-like objects) with the future value. Use pledge.Then(func)
+// to access.
 
 already_AddRefed<Pledge<nsCString>>
-GetOriginKey(const nsCString& aOrigin, bool aPersist);
+GetPrincipalKey(const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
+                bool aPersist);
 
 void
 SanitizeOriginKeys(const uint64_t& aSinceWhen, bool aOnlyPrivateBrowsing);
 
 class Child : public PMediaChild
 {
 public:
   static Child* Get();
 
   Child();
 
-  mozilla::ipc::IPCResult RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey) override;
+  mozilla::ipc::IPCResult
+  RecvGetPrincipalKeyResponse(const uint32_t& aRequestId,
+                              const nsCString& aKey) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
   virtual ~Child();
 private:
 
   bool mActorDestroyed;
 };
 
--- a/dom/media/systemservices/MediaParent.cpp
+++ b/dom/media/systemservices/MediaParent.cpp
@@ -57,27 +57,31 @@ class OriginKeyStore : public nsISupport
   };
 
   class OriginKeysTable
   {
   public:
     OriginKeysTable() : mPersistCount(0) {}
 
     nsresult
-    GetOriginKey(const nsACString& aOrigin, nsCString& aResult, bool aPersist = false)
+    GetPrincipalKey(const ipc::PrincipalInfo& aPrincipalInfo, nsCString& aResult,
+                    bool aPersist = false)
     {
+      nsAutoCString principalString;
+      PrincipalInfoToString(aPrincipalInfo, principalString);
+
       OriginKey* key;
-      if (!mKeys.Get(aOrigin, &key)) {
+      if (!mKeys.Get(principalString, &key)) {
         nsCString salt; // Make a new one
         nsresult rv = GenerateRandomName(salt, key->EncodedLength);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         key = new OriginKey(salt);
-        mKeys.Put(aOrigin, key);
+        mKeys.Put(principalString, key);
       }
       if (aPersist && !key->mSecondsStamp) {
         key->mSecondsStamp = PR_Now() / PR_USEC_PER_SEC;
         mPersistCount++;
       }
       aResult = key->mKey;
       return NS_OK;
     }
@@ -95,31 +99,86 @@ class OriginKeyStore : public nsISupport
 
         if (originKey->mSecondsStamp >= since.mSecondsStamp) {
           iter.Remove();
         }
       }
       mPersistCount = 0;
     }
 
+  private:
+    void
+    PrincipalInfoToString(const ipc::PrincipalInfo& aPrincipalInfo,
+                          nsAutoCString aString)
+    {
+      switch (aPrincipalInfo.type()) {
+        case ipc::PrincipalInfo::TSystemPrincipalInfo:
+          aString.Assign("[System Principal]");
+          return;
+
+        case ipc::PrincipalInfo::TNullPrincipalInfo: {
+          const ipc::NullPrincipalInfo& info =
+            aPrincipalInfo.get_NullPrincipalInfo();
+          aString.Assign(info.spec());
+          return;
+        }
+
+        case ipc::PrincipalInfo::TContentPrincipalInfo: {
+          const ipc::ContentPrincipalInfo& info =
+            aPrincipalInfo.get_ContentPrincipalInfo();
+          aString.Assign(info.spec());
+
+          nsAutoCString suffix;
+          info.attrs().CreateSuffix(suffix);
+          suffix.Append(suffix);
+          return;
+        }
+
+        case ipc::PrincipalInfo::TExpandedPrincipalInfo: {
+          const ipc::ExpandedPrincipalInfo& info =
+            aPrincipalInfo.get_ExpandedPrincipalInfo();
+
+          aString.Assign("[Expanded Principal [");
+
+          for (uint32_t i = 0; i < info.whitelist().Length(); i++) {
+            nsAutoCString str;
+            PrincipalInfoToString(info.whitelist()[i], str);
+
+            if (i != 0) {
+              aString.Append(", ");
+            }
+
+            aString.Append(str);
+          }
+
+          aString.Append("]]");
+          return;
+        }
+
+        default:
+          MOZ_CRASH("Unknown PrincipalInfo type!");
+      }
+    }
+
   protected:
     nsClassHashtable<nsCStringHashKey, OriginKey> mKeys;
     size_t mPersistCount;
   };
 
   class OriginKeysLoader : public OriginKeysTable
   {
   public:
     OriginKeysLoader() {}
 
     nsresult
-    GetOriginKey(const nsACString& aOrigin, nsCString& aResult, bool aPersist)
+    GetPrincipalKey(const ipc::PrincipalInfo& aPrincipalInfo,
+                    nsCString& aResult, bool aPersist = false)
     {
       auto before = mPersistCount;
-      OriginKeysTable::GetOriginKey(aOrigin, aResult, aPersist);
+      OriginKeysTable::GetPrincipalKey(aPrincipalInfo, aResult, aPersist);
       if (mPersistCount != before) {
         Save();
       }
       return NS_OK;
     }
 
     already_AddRefed<nsIFile>
     GetFile()
@@ -348,33 +407,33 @@ public:
 
   // Only accessed on StreamTS thread
   OriginKeysLoader mOriginKeys;
   OriginKeysTable mPrivateBrowsingOriginKeys;
 };
 
 NS_IMPL_ISUPPORTS0(OriginKeyStore)
 
-bool NonE10s::SendGetOriginKeyResponse(const uint32_t& aRequestId,
-                                       nsCString aKey) {
+bool NonE10s::SendGetPrincipalKeyResponse(const uint32_t& aRequestId,
+                                          nsCString aKey) {
   MediaManager* mgr = MediaManager::GetIfExists();
   if (!mgr) {
     return false;
   }
-  RefPtr<Pledge<nsCString>> pledge = mgr->mGetOriginKeyPledges.Remove(aRequestId);
+  RefPtr<Pledge<nsCString>> pledge = mgr->mGetPrincipalKeyPledges.Remove(aRequestId);
   if (pledge) {
     pledge->Resolve(aKey);
   }
   return true;
 }
 
 template<class Super> mozilla::ipc::IPCResult
-Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId,
-                                const nsCString& aOrigin,
-                                const bool& aPersist)
+Parent<Super>::RecvGetPrincipalKey(const uint32_t& aRequestId,
+                                   const ipc::PrincipalInfo& aPrincipalInfo,
+                                   const bool& aPersist)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // First, get profile dir.
 
   MOZ_ASSERT(NS_IsMainThread());
   nsCOMPtr<nsIFile> profileDir;
   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
@@ -388,26 +447,26 @@ Parent<Super>::RecvGetOriginKey(const ui
 
   RefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
   uint32_t id = mOutstandingPledges.Append(*p);
 
   nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
   MOZ_ASSERT(sts);
   RefPtr<Parent<Super>> that(this);
 
-  rv = sts->Dispatch(NewRunnableFrom([this, that, id, profileDir, aOrigin,
-                                      aPersist]() -> nsresult {
+  rv = sts->Dispatch(NewRunnableFrom([this, that, id, profileDir,
+                                      aPrincipalInfo, aPersist]() -> nsresult {
     MOZ_ASSERT(!NS_IsMainThread());
     mOriginKeyStore->mOriginKeys.SetProfileDir(profileDir);
 
     nsAutoCString result;
-    if (OriginAttributes::IsPrivateBrowsing(aOrigin)) {
-      mOriginKeyStore->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result);
+    if (IsPincipalInfoPrivate(aPrincipalInfo)) {
+      mOriginKeyStore->mPrivateBrowsingOriginKeys.GetPrincipalKey(aPrincipalInfo, result);
     } else {
-      mOriginKeyStore->mOriginKeys.GetOriginKey(aOrigin, result, aPersist);
+      mOriginKeyStore->mOriginKeys.GetPrincipalKey(aPrincipalInfo, result, aPersist);
     }
 
     // Pass result back to main thread.
     nsresult rv;
     rv = NS_DispatchToMainThread(NewRunnableFrom([this, that, id,
                                                   result]() -> nsresult {
       if (mDestroyed) {
         return NS_OK;
@@ -428,17 +487,17 @@ Parent<Super>::RecvGetOriginKey(const ui
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return IPCResult(this, false);
   }
   p->Then([this, that, aRequestId](const nsCString& aKey) mutable {
     if (mDestroyed) {
       return NS_OK;
     }
-    Unused << this->SendGetOriginKeyResponse(aRequestId, aKey);
+    Unused << this->SendGetPrincipalKeyResponse(aRequestId, aKey);
     return NS_OK;
   });
   return IPC_OK();
 }
 
 template<class Super> mozilla::ipc::IPCResult
 Parent<Super>::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen,
                                       const bool& aOnlyPrivateBrowsing)
--- a/dom/media/systemservices/MediaParent.h
+++ b/dom/media/systemservices/MediaParent.h
@@ -22,41 +22,43 @@ class OriginKeyStore;
 
 class NonE10s
 {
   typedef mozilla::ipc::IProtocol::ActorDestroyReason
       ActorDestroyReason;
 public:
   virtual ~NonE10s() {}
 protected:
-  virtual mozilla::ipc::IPCResult RecvGetOriginKey(const uint32_t& aRequestId,
-                                                   const nsCString& aOrigin,
-                                                   const bool& aPersist) = 0;
+  virtual mozilla::ipc::IPCResult
+  RecvGetPrincipalKey(const uint32_t& aRequestId,
+                      const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
+                      const bool& aPersist) = 0;
   virtual mozilla::ipc::IPCResult RecvSanitizeOriginKeys(const uint64_t& aSinceWhen,
                                                          const bool& aOnlyPrivateBrowsing) = 0;
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) = 0;
 
-  bool SendGetOriginKeyResponse(const uint32_t& aRequestId,
-                                nsCString aKey);
+  bool SendGetPrincipalKeyResponse(const uint32_t& aRequestId,
+                                   nsCString aKey);
 };
 
 // Super = PMediaParent or NonE10s
 
 template<class Super>
 class Parent : public Super
 {
   typedef mozilla::ipc::IProtocol::ActorDestroyReason
       ActorDestroyReason;
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Parent<Super>)
 
-  virtual mozilla::ipc::IPCResult RecvGetOriginKey(const uint32_t& aRequestId,
-                                                   const nsCString& aOrigin,
-                                                   const bool& aPersist) override;
+  virtual mozilla::ipc::IPCResult
+  RecvGetPrincipalKey(const uint32_t& aRequestId,
+                      const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
+                      const bool& aPersist) override;
   virtual mozilla::ipc::IPCResult RecvSanitizeOriginKeys(const uint64_t& aSinceWhen,
                                                          const bool& aOnlyPrivateBrowsing) override;
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   Parent();
 private:
   virtual ~Parent();
 
--- a/dom/media/systemservices/PCameras.ipdl
+++ b/dom/media/systemservices/PCameras.ipdl
@@ -1,15 +1,17 @@
 /* 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 protocol PContent;
 include protocol PBackground;
 
+include PBackgroundSharedTypes;
+
 using mozilla::camera::CaptureEngine from "mozilla/media/CamerasTypes.h";
 
 namespace mozilla {
 namespace camera {
 
 // IPC analog for webrtc::VideoCaptureCapability
 struct VideoCaptureCapability
 {
@@ -70,17 +72,18 @@ child:
 parent:
   async NumberOfCaptureDevices(CaptureEngine engine);
   async NumberOfCapabilities(CaptureEngine engine, nsCString deviceUniqueIdUTF8);
 
   async GetCaptureCapability(CaptureEngine engine, nsCString unique_idUTF8,
                              int capability_number);
   async GetCaptureDevice(CaptureEngine engine, int num);
 
-  async AllocateCaptureDevice(CaptureEngine engine, nsCString unique_idUTF8, nsCString origin);
+  async AllocateCaptureDevice(CaptureEngine engine, nsCString unique_idUTF8,
+                              PrincipalInfo principal);
   async ReleaseCaptureDevice(CaptureEngine engine, int numdev);
   async StartCapture(CaptureEngine engine, int numdev, VideoCaptureCapability capability);
   async StopCapture(CaptureEngine engine, int numdev);
   // transfers frame back
   async ReleaseFrame(Shmem s);
 
   // Ask parent to delete us
   async AllDone();
--- a/dom/media/systemservices/PMedia.ipdl
+++ b/dom/media/systemservices/PMedia.ipdl
@@ -1,52 +1,54 @@
 /* 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 protocol PContent;
 
+include PBackgroundSharedTypes;
+
 namespace mozilla {
 namespace media {
 
 protocol PMedia
 {
   manager PContent;
 
 parent:
   /**
-   * Requests a potentially persistent unique secret key for each origin.
+   * Requests a potentially persistent unique secret key for each principal.
    * Has no expiry, but is cleared by age along with cookies.
    * This is needed by mediaDevices.enumerateDevices() to produce persistent
    * deviceIds that wont work cross-origin.
    *
-   * The origin string must contain the OriginAttributes suffix.
    * If this OriginAttributes dictionary has the privateBrowsing flag set to
    * false, a key for this origin is returned from a primary pool of temporal
    * in-memory keys and persistent keys read from disk. If no key exists, a
    * temporal one is created.
    * If aPersist is true and key is temporal, the key is promoted to persistent.
    * Once persistent, a key cannot become temporal again.
    *
    * If the OriginAttributes dictionary has the privateBrowsing flag set to
    * true, a different key for this origin is returned from a secondary pool
    * that is never persisted to disk, and aPersist is ignored.
    */
-  async GetOriginKey(uint32_t aRequestId, nsCString aOrigin, bool aPersist);
+  async GetPrincipalKey(uint32_t aRequestId, PrincipalInfo aPrincipal,
+                        bool aPersist);
 
   /**
    * Clear per-orgin list of persistent deviceIds stored for enumerateDevices
    * Fire and forget.
    *
    * aSinceTime - milliseconds since 1 January 1970 00:00:00 UTC. 0 = clear all
    *
    * aOnlyPrivateBrowsing - if true then only purge the separate in-memory
    *                        per-origin list used in Private Browsing.
    */
   async SanitizeOriginKeys(uint64_t aSinceWhen, bool aOnlyPrivateBrowsing);
 
 child:
-  async GetOriginKeyResponse(uint32_t aRequestId, nsCString key);
+  async GetPrincipalKeyResponse(uint32_t aRequestId, nsCString key);
   async __delete__();
 };
 
 } // namespace media
 } // namespace mozilla
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -6,16 +6,17 @@
 #define MEDIAENGINE_H_
 
 #include "mozilla/RefPtr.h"
 #include "DOMMediaStream.h"
 #include "MediaStreamGraph.h"
 #include "MediaTrackConstraints.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "mozilla/dom/VideoStreamTrack.h"
+#include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/media/DeviceChangeCallback.h"
 
 namespace mozilla {
 
 namespace dom {
 class Blob;
 } // namespace dom
 
@@ -220,26 +221,27 @@ public:
   class AllocationHandle
   {
   public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AllocationHandle);
   protected:
     ~AllocationHandle() {}
   public:
     AllocationHandle(const dom::MediaTrackConstraints& aConstraints,
-                     const nsACString& aOrigin,
+                     const ipc::PrincipalInfo& aPrincipalInfo,
                      const MediaEnginePrefs& aPrefs,
                      const nsString& aDeviceId)
+
     : mConstraints(aConstraints),
-      mOrigin(aOrigin),
+      mPrincipalInfo(aPrincipalInfo),
       mPrefs(aPrefs),
       mDeviceId(aDeviceId) {}
   public:
     NormalizedConstraints mConstraints;
-    nsCString mOrigin;
+    ipc::PrincipalInfo mPrincipalInfo;
     MediaEnginePrefs mPrefs;
     nsString mDeviceId;
   };
 
   /* Release the device back to the system. */
   virtual nsresult Deallocate(AllocationHandle* aHandle)
   {
     MOZ_ASSERT(aHandle);
@@ -320,24 +322,24 @@ public:
 
   /* It is an error to call Start() before an Allocate(), and Stop() before
    * a Start(). Only Allocate() may be called after a Deallocate(). */
 
   /* This call reserves but does not start the device. */
   virtual nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                             const MediaEnginePrefs &aPrefs,
                             const nsString& aDeviceId,
-                            const nsACString& aOrigin,
+                            const ipc::PrincipalInfo& aPrincipalInfo,
                             AllocationHandle** aOutHandle,
                             const char** aOutBadConstraint)
   {
     AssertIsOnOwningThread();
     MOZ_ASSERT(aOutHandle);
-    RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints, aOrigin,
-                                                           aPrefs, aDeviceId);
+    RefPtr<AllocationHandle> handle =
+      new AllocationHandle(aConstraints, aPrincipalInfo, aPrefs, aDeviceId);
     nsresult rv = ReevaluateAllocation(handle, nullptr, aPrefs, aDeviceId,
                                        aOutBadConstraint);
     if (NS_FAILED(rv)) {
       return rv;
     }
     mRegisteredHandles.AppendElement(handle);
     handle.forget(aOutHandle);
     return NS_OK;
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -83,17 +83,17 @@ MediaEngineDefaultVideoSource::GetBestFi
 #endif
   return distance;
 }
 
 nsresult
 MediaEngineDefaultVideoSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
                                         const MediaEnginePrefs &aPrefs,
                                         const nsString& aDeviceId,
-                                        const nsACString& aOrigin,
+                                        const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                                         AllocationHandle** aOutHandle,
                                         const char** aOutBadConstraint)
 {
   if (mState != kReleased) {
     return NS_ERROR_FAILURE;
   }
 
   FlattenedConstraints c(aConstraints);
@@ -407,17 +407,17 @@ MediaEngineDefaultAudioSource::GetBestFi
 #endif
   return distance;
 }
 
 nsresult
 MediaEngineDefaultAudioSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
                                         const MediaEnginePrefs &aPrefs,
                                         const nsString& aDeviceId,
-                                        const nsACString& aOrigin,
+                                        const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                                         AllocationHandle** aOutHandle,
                                         const char** aOutBadConstraint)
 {
   if (mState != kReleased) {
     return NS_ERROR_FAILURE;
   }
 
   // Mock failure for automated tests.
--- a/dom/media/webrtc/MediaEngineDefault.h
+++ b/dom/media/webrtc/MediaEngineDefault.h
@@ -46,17 +46,17 @@ public:
   MediaEngineDefaultVideoSource();
 
   void GetName(nsAString&) const override;
   void GetUUID(nsACString&) const override;
 
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
                     const nsString& aDeviceId,
-                    const nsACString& aOrigin,
+                    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                     AllocationHandle** aOutHandle,
                     const char** aOutBadConstraint) override;
   nsresult Deallocate(AllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
   nsresult Restart(AllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
@@ -116,17 +116,17 @@ public:
   MediaEngineDefaultAudioSource();
 
   void GetName(nsAString&) const override;
   void GetUUID(nsACString&) const override;
 
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
                     const nsString& aDeviceId,
-                    const nsACString& aOrigin,
+                    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                     AllocationHandle** aOutHandle,
                     const char** aOutBadConstraint) override;
   nsresult Deallocate(AllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
   nsresult Restart(AllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -102,29 +102,29 @@ MediaEngineRemoteVideoSource::Shutdown()
   return;
 }
 
 nsresult
 MediaEngineRemoteVideoSource::Allocate(
     const dom::MediaTrackConstraints& aConstraints,
     const MediaEnginePrefs& aPrefs,
     const nsString& aDeviceId,
-    const nsACString& aOrigin,
+    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
     AllocationHandle** aOutHandle,
     const char** aOutBadConstraint)
 {
   LOG((__PRETTY_FUNCTION__));
   AssertIsOnOwningThread();
 
   if (!mInitDone) {
     LOG(("Init not done"));
     return NS_ERROR_FAILURE;
   }
 
-  nsresult rv = Super::Allocate(aConstraints, aPrefs, aDeviceId, aOrigin,
+  nsresult rv = Super::Allocate(aConstraints, aPrefs, aDeviceId, aPrincipalInfo,
                                 aOutHandle, aOutBadConstraint);
   if (NS_FAILED(rv)) {
     return rv;
   }
   if (mState == kStarted &&
       MOZ_LOG_TEST(GetMediaManagerLog(), mozilla::LogLevel::Debug)) {
     MonitorAutoLock lock(mMonitor);
     if (mSources.IsEmpty()) {
@@ -273,23 +273,22 @@ MediaEngineRemoteVideoSource::UpdateSing
   }
 
   switch (mState) {
     case kReleased:
       MOZ_ASSERT(aHandle);
       if (camera::GetChildAndCall(&camera::CamerasChild::AllocateCaptureDevice,
                                   mCapEngine, GetUUID().get(),
                                   kMaxUniqueIdLength, mCaptureIndex,
-                                  aHandle->mOrigin)) {
+                                  aHandle->mPrincipalInfo)) {
         return NS_ERROR_FAILURE;
       }
       mState = kAllocated;
       SetLastCapability(mCapability);
-      LOG(("Video device %d allocated for %s", mCaptureIndex,
-           aHandle->mOrigin.get()));
+      LOG(("Video device %d allocated", mCaptureIndex));
       break;
 
     case kStarted:
       if (mCapability != mLastCapability) {
         camera::GetChildAndCall(&camera::CamerasChild::StopCapture,
                                 mCapEngine, mCaptureIndex);
         if (camera::GetChildAndCall(&camera::CamerasChild::StartCapture,
                                     mCapEngine, mCaptureIndex, mCapability,
@@ -297,18 +296,17 @@ MediaEngineRemoteVideoSource::UpdateSing
           LOG(("StartCapture failed"));
           return NS_ERROR_FAILURE;
         }
         SetLastCapability(mCapability);
       }
       break;
 
     default:
-      LOG(("Video device %d %s in ignored state %d", mCaptureIndex,
-             (aHandle? aHandle->mOrigin.get() : ""), mState));
+      LOG(("Video device %d in ignored state %d", mCaptureIndex, mState));
       break;
   }
   return NS_OK;
 }
 
 void
 MediaEngineRemoteVideoSource::SetLastCapability(
     const webrtc::CaptureCapability& aCapability)
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -62,17 +62,17 @@ public:
   MediaEngineRemoteVideoSource(int aIndex, mozilla::camera::CaptureEngine aCapEngine,
                                dom::MediaSourceEnum aMediaSource,
                                bool aScary = false,
                                const char* aMonitorName = "RemoteVideo.Monitor");
 
   nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
                     const MediaEnginePrefs& aPrefs,
                     const nsString& aDeviceId,
-                    const nsACString& aOrigin,
+                    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                     AllocationHandle** aOutHandle,
                     const char** aOutBadConstraint) override;
   nsresult Deallocate(AllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
   nsresult Restart(AllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -146,17 +146,17 @@ MediaEngineTabVideoSource::GetUUID(nsACS
 #define DEFAULT_TABSHARE_VIDEO_MAX_WIDTH 4096
 #define DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT 4096
 #define DEFAULT_TABSHARE_VIDEO_FRAMERATE 30
 
 nsresult
 MediaEngineTabVideoSource::Allocate(const dom::MediaTrackConstraints& aConstraints,
                                     const MediaEnginePrefs& aPrefs,
                                     const nsString& aDeviceId,
-                                    const nsACString& aOrigin,
+                                    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                                     AllocationHandle** aOutHandle,
                                     const char** aOutBadConstraint)
 {
   // windowId is not a proper constraint, so just read it.
   // It has no well-defined behavior in advanced, so ignore it there.
 
   mWindowId = aConstraints.mBrowserWindow.WasPassed() ?
               aConstraints.mBrowserWindow.Value() : -1;
--- a/dom/media/webrtc/MediaEngineTabVideoSource.h
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.h
@@ -24,17 +24,17 @@ class MediaEngineTabVideoSource : public
 
     bool GetScary() const override {
       return true;
     }
 
     nsresult Allocate(const dom::MediaTrackConstraints &,
                       const mozilla::MediaEnginePrefs&,
                       const nsString& aDeviceId,
-                      const nsACString& aOrigin,
+                      const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                       AllocationHandle** aOutHandle,
                       const char** aOutBadConstraint) override;
     nsresult Deallocate(AllocationHandle* aHandle) override;
     nsresult Start(mozilla::SourceMediaStream*, mozilla::TrackID, const mozilla::PrincipalHandle&) override;
     void SetDirectListeners(bool aHasDirectListeners) override {};
     void NotifyPull(mozilla::MediaStreamGraph*, mozilla::SourceMediaStream*, mozilla::TrackID, mozilla::StreamTime, const mozilla::PrincipalHandle& aPrincipalHandle) override;
     nsresult Stop(mozilla::SourceMediaStream*, mozilla::TrackID) override;
     nsresult Restart(AllocationHandle* aHandle,
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -73,17 +73,17 @@ public:
     : MediaEngineAudioSource(kReleased)
   {
   }
   void GetName(nsAString& aName) const override;
   void GetUUID(nsACString& aUUID) const override;
   nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
                     const MediaEnginePrefs& aPrefs,
                     const nsString& aDeviceId,
-                    const nsACString& aOrigin,
+                    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
                     AllocationHandle** aOutHandle,
                     const char** aOutBadConstraint) override
   {
     // Nothing to do here, everything is managed in MediaManager.cpp
     *aOutHandle = nullptr;
     return NS_OK;
   }
   nsresult Deallocate(AllocationHandle* aHandle) override
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -324,18 +324,17 @@ MediaEngineWebRTCMicrophoneSource::Updat
           LOG(("Audio device %d reallocated", mCapIndex));
         } else {
           LOG(("Audio device %d allocated shared", mCapIndex));
         }
       }
       break;
 
     default:
-      LOG(("Audio device %d %s in ignored state %d", mCapIndex,
-           (aHandle? aHandle->mOrigin.get() : ""), mState));
+      LOG(("Audio device %d in ignored state %d", mCapIndex, mState));
       break;
   }
 
   if (sChannelsOpen > 0) {
     int error;
 
     error = mVoEProcessing->SetEcStatus(prefs.mAecOn, (webrtc::EcModes)prefs.mAec);
     if (error) {
--- a/dom/media/webspeech/recognition/SpeechRecognition.cpp
+++ b/dom/media/webspeech/recognition/SpeechRecognition.cpp
@@ -15,16 +15,17 @@
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "mozilla/dom/MediaStreamError.h"
 #include "mozilla/MediaManager.h"
 #include "mozilla/Preferences.h"
 #include "MediaPrefs.h"
 #include "mozilla/Services.h"
 
 #include "AudioSegment.h"
+#include "DOMMediaStream.h"
 #include "endpointer.h"
 
 #include "mozilla/dom/SpeechRecognitionEvent.h"
 #include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsIObserverService.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
--- a/dom/media/webspeech/recognition/SpeechRecognition.h
+++ b/dom/media/webspeech/recognition/SpeechRecognition.h
@@ -12,31 +12,32 @@
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsWrapperCache.h"
 #include "nsTArray.h"
 #include "js/TypeDecls.h"
 
 #include "nsIDOMNavigatorUserMedia.h"
 #include "nsITimer.h"
-#include "MediaEngine.h"
 #include "MediaStreamGraph.h"
 #include "AudioSegment.h"
 #include "mozilla/WeakPtr.h"
 
 #include "SpeechGrammarList.h"
 #include "SpeechRecognitionResultList.h"
 #include "SpeechStreamListener.h"
 #include "nsISpeechRecognitionService.h"
 #include "endpointer.h"
 
 #include "mozilla/dom/SpeechRecognitionError.h"
 
 namespace mozilla {
 
+class DOMMediaStream;
+
 namespace dom {
 
 #define SPEECH_RECOGNITION_TEST_EVENT_REQUEST_TOPIC "SpeechRecognitionTest:RequestEvent"
 #define SPEECH_RECOGNITION_TEST_END_TOPIC "SpeechRecognitionTest:End"
 
 class GlobalObject;
 class SpeechEvent;
 
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -220,16 +220,27 @@ PrincipalToPrincipalInfo(nsIPrincipal* a
     return rv;
   }
 
   *aPrincipalInfo = ContentPrincipalInfo(aPrincipal->OriginAttributesRef(),
                                          spec);
   return NS_OK;
 }
 
+bool
+IsPincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo)
+{
+  if (aPrincipalInfo.type() != ipc::PrincipalInfo::TContentPrincipalInfo) {
+    return false;
+  }
+
+  const ContentPrincipalInfo& info = aPrincipalInfo.get_ContentPrincipalInfo();
+  return !!info.attrs().mPrivateBrowsingId;
+}
+
 nsresult
 LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
                        OptionalLoadInfoArgs* aOptionalLoadInfoArgs)
 {
   if (!aLoadInfo) {
     // if there is no loadInfo, then there is nothing to serialize
     *aOptionalLoadInfoArgs = void_t();
     return NS_OK;
--- a/ipc/glue/BackgroundUtils.h
+++ b/ipc/glue/BackgroundUtils.h
@@ -71,16 +71,23 @@ PrincipalInfoToPrincipal(const Principal
  *
  * MUST be called on the main thread only.
  */
 nsresult
 PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
                          PrincipalInfo* aPrincipalInfo);
 
 /**
+ * Return true if this PrincipalInfo is a content principal and it has
+ * a privateBrowsing id in its OriginAttributes
+ */
+bool
+IsPincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo);
+
+/**
  * Convert a LoadInfo to LoadInfoArgs struct.
  */
 nsresult
 LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
                        OptionalLoadInfoArgs* outOptionalLoadInfoArgs);
 
 /**
  * Convert LoadInfoArgs to a LoadInfo.