Bug 1450658 - Add preference to disable focusing source; r?pehrsons draft
authorDan Minor <dminor@mozilla.com>
Tue, 29 May 2018 16:14:38 -0400
changeset 801739 6edb1d369bdc8e8d47f15ce46488ca7f6cb33ce6
parent 801432 87b9fc6fe5e8122947a995a170d9ec11535909df
push id111720
push userbmo:dminor@mozilla.com
push dateWed, 30 May 2018 17:26:14 +0000
reviewerspehrsons
bugs1450658
milestone62.0a1
Bug 1450658 - Add preference to disable focusing source; r?pehrsons Focusing a source during a test run can cause Firefox to lose focus and subsequent tests to timeout. This adds a preference which defaults to true that allows the source to be focused. It is then set to false for tests that involve screen sharing. MozReview-Commit-ID: CNq2c87y8Ho
browser/base/content/test/webrtc/head.js
dom/media/MediaManager.cpp
dom/media/tests/mochitest/head.js
--- a/browser/base/content/test/webrtc/head.js
+++ b/browser/base/content/test/webrtc/head.js
@@ -1,15 +1,16 @@
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource:///modules/SitePermissions.jsm");
 
 const PREF_PERMISSION_FAKE = "media.navigator.permission.fake";
 const PREF_AUDIO_LOOPBACK = "media.audio_loopback_dev";
 const PREF_VIDEO_LOOPBACK = "media.video_loopback_dev";
 const PREF_FAKE_STREAMS = "media.navigator.streams.fake";
+const PREF_FOCUS_SOURCE = "media.getusermedia.window.focus_source.enabled";
 const CONTENT_SCRIPT_HELPER = getRootDirectory(gTestPath) + "get_user_media_content_script.js";
 
 const STATE_CAPTURE_ENABLED = Ci.nsIMediaManagerService.STATE_CAPTURE_ENABLED;
 const STATE_CAPTURE_DISABLED = Ci.nsIMediaManagerService.STATE_CAPTURE_DISABLED;
 
 function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
   retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30;
   var tries = 0;
@@ -569,17 +570,18 @@ async function runTests(tests, options =
   // Set prefs so that permissions prompts are shown and loopback devices
   // are not used. To test the chrome we want prompts to be shown, and
   // these tests are flakey when using loopback devices (though it would
   // be desirable to make them work with loopback in future).
   let prefs = [
     [PREF_PERMISSION_FAKE, true],
     [PREF_AUDIO_LOOPBACK, ""],
     [PREF_VIDEO_LOOPBACK, ""],
-    [PREF_FAKE_STREAMS, true]
+    [PREF_FAKE_STREAMS, true],
+    [PREF_FOCUS_SOURCE, false]
   ];
   await SpecialPowers.pushPrefEnv({"set": prefs});
 
   for (let testCase of tests) {
     info(testCase.desc);
     await testCase.run(browser);
     await cleanup();
   }
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1631,27 +1631,29 @@ public:
     const nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
     const nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
     uint64_t aWindowID,
     GetUserMediaWindowListener* aWindowListener,
     SourceListener* aSourceListener,
     MediaEnginePrefs& aPrefs,
     const ipc::PrincipalInfo& aPrincipalInfo,
     bool aIsChrome,
-    MediaManager::SourceSet* aSourceSet)
+    MediaManager::SourceSet* aSourceSet,
+    bool aShouldFocusSource)
     : Runnable("GetUserMediaTask")
     , mConstraints(aConstraints)
     , mOnSuccess(aOnSuccess)
     , mOnFailure(aOnFailure)
     , mWindowID(aWindowID)
     , mWindowListener(aWindowListener)
     , mSourceListener(aSourceListener)
     , mPrefs(aPrefs)
     , mPrincipalInfo(aPrincipalInfo)
     , mIsChrome(aIsChrome)
+    , mShouldFocusSource(aShouldFocusSource)
     , mDeviceChosen(false)
     , mSourceSet(aSourceSet)
     , mManager(MediaManager::GetInstance())
   {}
 
   ~GetUserMediaTask() {
   }
 
@@ -1714,19 +1716,22 @@ public:
           badConstraint = MediaConstraintsHelper::SelectSettings(
               NormalizedConstraints(constraints), devices, mIsChrome);
         }
         if (mAudioDevice) {
           mAudioDevice->Deallocate();
         }
       } else {
         if (!mIsChrome) {
-          rv = mVideoDevice->FocusOnSelectedSource();
-          if (NS_FAILED(rv)) {
-            LOG(("FocusOnSelectedSource failed"));
+          if (mShouldFocusSource) {
+            rv = mVideoDevice->FocusOnSelectedSource();
+
+            if (NS_FAILED(rv)) {
+              LOG(("FocusOnSelectedSource failed"));
+            }
           }
         }
       }
     }
     if (errorMsg) {
       LOG(("%s %" PRIu32, errorMsg, static_cast<uint32_t>(rv)));
       if (badConstraint) {
         Fail(MediaMgrError::Name::OverconstrainedError,
@@ -1828,16 +1833,17 @@ private:
   uint64_t mWindowID;
   RefPtr<GetUserMediaWindowListener> mWindowListener;
   RefPtr<SourceListener> mSourceListener;
   RefPtr<MediaDevice> mAudioDevice;
   RefPtr<MediaDevice> mVideoDevice;
   MediaEnginePrefs mPrefs;
   ipc::PrincipalInfo mPrincipalInfo;
   bool mIsChrome;
+  bool mShouldFocusSource;
 
   bool mDeviceChosen;
 public:
   nsAutoPtr<MediaManager::SourceSet> mSourceSet;
 private:
   RefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
@@ -2884,27 +2890,31 @@ MediaManager::GetUserMedia(nsPIDOMWindow
         for (auto& device : **devices) {
           nsresult rv = devicesCopy->AppendElement(device);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return;
           }
         }
       }
 
+      bool focusSource;
+      focusSource = mozilla::Preferences::GetBool("media.getusermedia.window.focus_source.enabled", true);
+
       // Pass callbacks and listeners along to GetUserMediaTask.
       RefPtr<GetUserMediaTask> task (new GetUserMediaTask(c,
                                                           onSuccess,
                                                           onFailure,
                                                           windowID,
                                                           windowListener,
                                                           sourceListener,
                                                           prefs,
                                                           principalInfo,
                                                           isChrome,
-                                                          devices->release()));
+                                                          devices->release(),
+                                                          focusSource));
       // Store the task w/callbacks.
       self->mActiveCallbacks.Put(callID, task.forget());
 
       // Add a WindowID cross-reference so OnNavigation can tear things down
       nsTArray<nsString>* array;
       if (!self->mCallIds.Get(windowID, &array)) {
         array = new nsTArray<nsString>();
         self->mCallIds.Put(windowID, array);
--- a/dom/media/tests/mochitest/head.js
+++ b/dom/media/tests/mochitest/head.js
@@ -413,18 +413,19 @@ function setupEnvironment() {
       ['media.peerconnection.ice.stun_client_maximum_transmits', 14],
       ['media.peerconnection.ice.trickle_grace_period', 30000],
       ['media.peerconnection.remoteTrackId.enabled', true],
       ['media.peerconnection.rtpsourcesapi.enabled', true],
       ['media.navigator.permission.disabled', true],
       // If either fake audio or video is desired we enable fake streams.
       // If loopback devices are set they will be chosen instead of fakes in gecko.
       ['media.navigator.streams.fake', WANT_FAKE_AUDIO || WANT_FAKE_VIDEO],
+      ['media.getusermedia.audiocapture.enabled', true],
       ['media.getusermedia.screensharing.enabled', true],
-      ['media.getusermedia.audiocapture.enabled', true],
+      ['media.getusermedia.window.focus_source.enabled', false],
       ['media.recorder.audio_node.enabled', true],
       ['media.webaudio.audiocontextoptions-samplerate.enabled', true]
     ]
   };
 
   if (!WANT_FAKE_AUDIO) {
     defaultMochitestPrefs.set.push(
       ["media.volume_scale", "1"],