Bug 1213517 - Consider competing required constraints with OverconstrainedError. r=padenot
authorJan-Ivar Bruaroey <jib@mozilla.com>
Tue, 14 Jun 2016 14:42:46 -0400
changeset 330481 de8a576b136dc69a29a0250f7d7f377cc1e47f9d
parent 330480 dbf1866063ce9f13a17b9c152b86994e3fbc7836
child 330482 7be03e7ea90984952284b9ee58b6d4b522a2d885
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1213517
milestone50.0a1
Bug 1213517 - Consider competing required constraints with OverconstrainedError. r=padenot MozReview-Commit-ID: EHIY1hpaEQn
dom/media/MediaManager.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1388,18 +1388,20 @@ public:
     , mSourceSet(aSourceSet)
     , mManager(MediaManager::GetInstance())
   {}
 
   ~GetUserMediaTask() {
   }
 
   void
-  Fail(const nsAString& aName, const nsAString& aMessage = EmptyString()) {
-    RefPtr<MediaMgrError> error = new MediaMgrError(aName, aMessage);
+  Fail(const nsAString& aName,
+       const nsAString& aMessage = EmptyString(),
+       const nsAString& aConstraint = EmptyString()) {
+    RefPtr<MediaMgrError> error = new MediaMgrError(aName, aMessage, aConstraint);
     RefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>> runnable =
       new ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>(mOnSuccess,
                                                                    mOnFailure,
                                                                    *error,
                                                                    mWindowID);
     // These should be empty now
     MOZ_ASSERT(!mOnSuccess);
     MOZ_ASSERT(!mOnFailure);
@@ -1416,40 +1418,65 @@ public:
     MOZ_ASSERT(mOnSuccess);
     MOZ_ASSERT(mOnFailure);
     MOZ_ASSERT(mDeviceChosen);
 
     // Allocate a video or audio device and return a MediaStream via
     // a GetUserMediaStreamRunnable.
 
     nsresult rv;
+    const char* errorMsg = nullptr;
+    const char* badConstraint = nullptr;
 
     if (mAudioDevice) {
-      rv = mAudioDevice->Allocate(GetInvariant(mConstraints.mAudio),
-                                  mPrefs, mOrigin);
+      auto& constraints = GetInvariant(mConstraints.mAudio);
+      rv = mAudioDevice->Allocate(constraints, mPrefs, mOrigin);
       if (NS_FAILED(rv)) {
-        LOG(("Failed to allocate audiosource %d",rv));
-        Fail(NS_LITERAL_STRING("NotReadableError"),
-             NS_LITERAL_STRING("Failed to allocate audiosource"));
-        return NS_OK;
+        errorMsg = "Failed to allocate audiosource";
+        if (rv == NS_ERROR_NOT_AVAILABLE) {
+          nsTArray<RefPtr<AudioDevice>> audios;
+          audios.AppendElement(mAudioDevice);
+          badConstraint = MediaConstraintsHelper::SelectSettings(constraints,
+                                                                 audios);
+        }
       }
     }
-    if (mVideoDevice) {
-      rv = mVideoDevice->Allocate(GetInvariant(mConstraints.mVideo),
-                                  mPrefs, mOrigin);
+    if (!errorMsg && mVideoDevice) {
+      auto& constraints = GetInvariant(mConstraints.mVideo);
+      rv = mVideoDevice->Allocate(constraints, mPrefs, mOrigin);
       if (NS_FAILED(rv)) {
-        LOG(("Failed to allocate videosource %d\n",rv));
+        errorMsg = "Failed to allocate videosource";
+        if (rv == NS_ERROR_NOT_AVAILABLE) {
+          nsTArray<RefPtr<VideoDevice>> videos;
+          videos.AppendElement(mVideoDevice);
+          badConstraint = MediaConstraintsHelper::SelectSettings(constraints,
+                                                                 videos);
+        }
         if (mAudioDevice) {
           mAudioDevice->Deallocate();
         }
-        Fail(NS_LITERAL_STRING("NotReadableError"),
-             NS_LITERAL_STRING("Failed to allocate videosource"));
-        return NS_OK;
       }
     }
+    if (errorMsg) {
+      LOG(("%s %d", errorMsg, rv));
+      switch (rv) {
+        case NS_ERROR_NOT_AVAILABLE: {
+          MOZ_ASSERT(badConstraint);
+          Fail(NS_LITERAL_STRING("OverconstrainedError"),
+               NS_LITERAL_STRING(""),
+               NS_ConvertUTF8toUTF16(badConstraint));
+          break;
+        }
+        default:
+          Fail(NS_LITERAL_STRING("NotReadableError"),
+               NS_ConvertUTF8toUTF16(errorMsg));
+          break;
+      }
+      return NS_OK;
+    }
     PeerIdentity* peerIdentity = nullptr;
     if (!mConstraints.mPeerIdentity.IsEmpty()) {
       peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity);
     }
 
     NS_DispatchToMainThread(do_AddRef(
         new GetUserMediaStreamRunnable(mOnSuccess, mOnFailure, mWindowID,
                                        mListener, mOrigin, mConstraints,
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -117,21 +117,21 @@ MediaEngineRemoteVideoSource::Allocate(
   for (auto& registered : mRegisteredHandles) {
     allConstraints.AppendElement(&registered->mConstraints);
   }
   RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints);
   allConstraints.AppendElement(&handle->mConstraints);
 
   NormalizedConstraints netConstraints(allConstraints);
   if (netConstraints.mOverconstrained) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (!ChooseCapability(netConstraints, aPrefs, aDeviceId)) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (mState == kReleased) {
     if (mozilla::camera::GetChildAndCall(
       &mozilla::camera::CamerasChild::AllocateCaptureDevice,
       mCapEngine, GetUUID().get(), kMaxUniqueIdLength, mCaptureIndex, aOrigin)) {
       return NS_ERROR_FAILURE;
     }