Bug 1450762 - Don't prompt for device permissions on Android in MediaDevices.enumerateDevices() r=achronop
authorJames Willcox <snorp@snorp.net>
Wed, 02 Jan 2019 16:44:35 +0000
changeset 509388 b0471cb7631f638fddf2776a50eeb641ac04e5f1
parent 509387 4904e5bf5df7cc1f2f676272266d13e71c317ca5
child 509389 7ce57fba4ad06615ddfa701b3e9b224f83b2b7a3
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersachronop
bugs1450762
milestone66.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 1450762 - Don't prompt for device permissions on Android in MediaDevices.enumerateDevices() r=achronop Differential Revision: https://phabricator.services.mozilla.com/D14575
dom/media/MediaManager.cpp
dom/media/MediaManager.h
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1767,17 +1767,17 @@ class GetUserMediaRunnableWrapper : publ
  * EnumerateRawDevices - Enumerate a list of audio & video devices that
  * satisfy passed-in constraints. List contains raw id's.
  */
 
 RefPtr<MediaManager::MgrPromise> MediaManager::EnumerateRawDevices(
     uint64_t aWindowId, MediaSourceEnum aVideoInputType,
     MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
     DeviceEnumerationType aVideoInputEnumType,
-    DeviceEnumerationType aAudioInputEnumType,
+    DeviceEnumerationType aAudioInputEnumType, bool aForceNoPermRequest,
     const RefPtr<MediaDeviceSetRefCnt>& aOutDevices) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aVideoInputType != MediaSourceEnum::Other ||
              aAudioInputType != MediaSourceEnum::Other ||
              aAudioOutputType != MediaSinkEnum::Other);
   // Since the enums can take one of several values, the following asserts rely
   // on short circuting behavior. E.g. aVideoInputEnumType != Fake will be true
   // if the requested device is not fake and thus the assert will pass. However,
@@ -1874,17 +1874,17 @@ RefPtr<MediaManager::MgrPromise> MediaMa
       realBackend->EnumerateDevices(aWindowId, MediaSourceEnum::Other,
                                     MediaSinkEnum::Speaker, &outputs);
       aOutDevices->AppendElements(outputs);
     }
 
     holder->Resolve(false, __func__);
   });
 
-  if (realDeviceRequested &&
+  if (realDeviceRequested && aForceNoPermRequest &&
       Preferences::GetBool("media.navigator.permission.device", false)) {
     // Need to ask permission to retrieve list of all devices;
     // notify frontend observer and wait for callback notification to post task.
     const char16_t* const type =
         (aVideoInputType != MediaSourceEnum::Camera)
             ? u"audio"
             : (aAudioInputType != MediaSourceEnum::Microphone) ? u"video"
                                                                : u"all";
@@ -2193,17 +2193,17 @@ void MediaManager::OnDeviceChange() {
         // On some Windows machine, if we call EnumerateRawDevices immediately
         // after receiving devicechange event, sometimes we would get outdated
         // devices list.
         PR_Sleep(PR_MillisecondsToInterval(100));
         auto devices = MakeRefPtr<MediaDeviceSetRefCnt>();
         self->EnumerateRawDevices(
                 0, MediaSourceEnum::Camera, MediaSourceEnum::Microphone,
                 MediaSinkEnum::Speaker, DeviceEnumerationType::Normal,
-                DeviceEnumerationType::Normal, devices)
+                DeviceEnumerationType::Normal, false, devices)
             ->Then(GetCurrentThreadSerialEventTarget(), __func__,
                    [self, devices](bool) {
                      if (!MediaManager::GetIfExists()) {
                        return;
                      }
 
                      nsTArray<nsString> deviceIDs;
 
@@ -2736,17 +2736,17 @@ RefPtr<MediaManager::StreamPromise> Medi
       static_cast<uint8_t>(videoEnumerationType),
       static_cast<uint8_t>(audioEnumerationType),
       askPermission ? "true" : "false");
 
   RefPtr<MediaManager> self = this;
   auto devices = MakeRefPtr<MediaDeviceSetRefCnt>();
   return EnumerateDevicesImpl(windowID, videoType, audioType,
                               MediaSinkEnum::Other, videoEnumerationType,
-                              audioEnumerationType, devices)
+                              audioEnumerationType, true, devices)
       ->Then(
           GetCurrentThreadSerialEventTarget(), __func__,
           [self, windowID, c, windowListener, isChrome, devices](bool) {
             LOG("GetUserMedia: post enumeration promise success callback "
                 "starting");
             // Ensure that our windowID is still good.
             auto* globalWindow =
                 nsGlobalWindowInner::GetInnerWindowWithId(windowID);
@@ -3054,17 +3054,17 @@ already_AddRefed<nsIWritableVariant> Med
   }
   return var.forget();
 }
 
 RefPtr<MediaManager::MgrPromise> MediaManager::EnumerateDevicesImpl(
     uint64_t aWindowId, MediaSourceEnum aVideoInputType,
     MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
     DeviceEnumerationType aVideoInputEnumType,
-    DeviceEnumerationType aAudioInputEnumType,
+    DeviceEnumerationType aAudioInputEnumType, bool aForceNoPermRequest,
     const RefPtr<MediaDeviceSetRefCnt>& aOutDevices) {
   MOZ_ASSERT(NS_IsMainThread());
 
   LOG("%s: aWindowId=%" PRIu64 ", aVideoInputType=%" PRIu8
       ", aAudioInputType=%" PRIu8 ", aVideoInputEnumType=%" PRIu8
       ", aAudioInputEnumType=%" PRIu8,
       __func__, aWindowId, static_cast<uint8_t>(aVideoInputType),
       static_cast<uint8_t>(aAudioInputType),
@@ -3096,30 +3096,31 @@ RefPtr<MediaManager::MgrPromise> MediaMa
   // pass in a lambda to run back on this same thread later once
   // GetPrincipalKey resolves. Needed variables are "captured"
   // (passed by value) safely into the lambda.
   auto originKey = MakeRefPtr<Refcountable<nsCString>>();
   return media::GetPrincipalKey(principalInfo, persist)
       ->Then(
           GetMainThreadSerialEventTarget(), __func__,
           [aWindowId, aVideoInputType, aAudioInputType, aAudioOutputType,
-           aVideoInputEnumType, aAudioInputEnumType, aOutDevices,
-           originKey](const nsCString& aOriginKey) {
+           aVideoInputEnumType, aAudioInputEnumType, aForceNoPermRequest,
+           aOutDevices, originKey](const nsCString& aOriginKey) {
             MOZ_ASSERT(NS_IsMainThread());
             originKey->Assign(aOriginKey);
             MediaManager* mgr = MediaManager::GetIfExists();
             MOZ_ASSERT(mgr);
             if (!mgr->IsWindowStillActive(aWindowId)) {
               return MgrPromise::CreateAndReject(
                   MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
                   __func__);
             }
             return mgr->EnumerateRawDevices(
                 aWindowId, aVideoInputType, aAudioInputType, aAudioOutputType,
-                aVideoInputEnumType, aAudioInputEnumType, aOutDevices);
+                aVideoInputEnumType, aAudioInputEnumType, aForceNoPermRequest,
+                aOutDevices);
           },
           [](nsresult rs) {
             NS_WARNING(
                 "EnumerateDevicesImpl failed to get Principal Key. Enumeration "
                 "will not continue.");
             return MgrPromise::CreateAndReject(
                 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
                 __func__);
@@ -3227,17 +3228,17 @@ RefPtr<MediaManager::DevicesPromise> Med
 
   MediaSinkEnum audioOutputType = MediaSinkEnum::Other;
   if (Preferences::GetBool("media.setsinkid.enabled")) {
     audioOutputType = MediaSinkEnum::Speaker;
   }
   auto devices = MakeRefPtr<MediaDeviceSetRefCnt>();
   return EnumerateDevicesImpl(windowId, MediaSourceEnum::Camera,
                               MediaSourceEnum::Microphone, audioOutputType,
-                              videoEnumerationType, audioEnumerationType,
+                              videoEnumerationType, audioEnumerationType, false,
                               devices)
       ->Then(GetCurrentThreadSerialEventTarget(), __func__,
              [windowListener, sourceListener, devices](bool) {
                DebugOnly<bool> rv = windowListener->Remove(sourceListener);
                MOZ_ASSERT(rv);
                return DevicesPromise::CreateAndResolve(devices, __func__);
              },
              [windowListener, sourceListener](RefPtr<MediaMgrError>&& aError) {
@@ -3276,17 +3277,17 @@ RefPtr<SinkInfoPromise> MediaManager::Ge
   auto sourceListener = MakeRefPtr<SourceListener>();
   windowListener->Register(sourceListener);
 
   bool isSecure = aWindow->IsSecureContext();
   auto devices = MakeRefPtr<MediaDeviceSetRefCnt>();
   return EnumerateDevicesImpl(aWindow->WindowID(), MediaSourceEnum::Other,
                               MediaSourceEnum::Other, MediaSinkEnum::Speaker,
                               DeviceEnumerationType::Normal,
-                              DeviceEnumerationType::Normal, devices)
+                              DeviceEnumerationType::Normal, true, devices)
       ->Then(GetCurrentThreadSerialEventTarget(), __func__,
              [aDeviceId, isSecure, devices](bool) {
                for (RefPtr<MediaDevice>& device : *devices) {
                  if (aDeviceId.IsEmpty() && device->mSinkInfo->Preferred()) {
                    return SinkInfoPromise::CreateAndResolve(device->mSinkInfo,
                                                             __func__);
                  }
                  if (device->mID.Equals(aDeviceId)) {
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -286,24 +286,24 @@ class MediaManager final : public nsIMed
     Loopback /* Enumeration should return loopback device(s) (possibly in
              addition to normal devices) */
   };
 
   RefPtr<MgrPromise> EnumerateRawDevices(
       uint64_t aWindowId, dom::MediaSourceEnum aVideoInputType,
       dom::MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
       DeviceEnumerationType aVideoInputEnumType,
-      DeviceEnumerationType aAudioInputEnumType,
+      DeviceEnumerationType aAudioInputEnumType, bool aForceNoPermRequest,
       const RefPtr<MediaDeviceSetRefCnt>& aOutDevices);
 
   RefPtr<MgrPromise> EnumerateDevicesImpl(
       uint64_t aWindowId, dom::MediaSourceEnum aVideoInputType,
       dom::MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
       DeviceEnumerationType aVideoInputEnumType,
-      DeviceEnumerationType aAudioInputEnumType,
+      DeviceEnumerationType aAudioInputEnumType, bool aForceNoPermRequest,
       const RefPtr<MediaDeviceSetRefCnt>& aOutDevices);
 
   RefPtr<BadConstraintsPromise> SelectSettings(
       const dom::MediaStreamConstraints& aConstraints, bool aIsChrome,
       const RefPtr<MediaDeviceSetRefCnt>& aSources);
 
   void GetPref(nsIPrefBranch* aBranch, const char* aPref, const char* aData,
                int32_t* aVal);
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt
@@ -45,29 +45,16 @@ class PermissionDelegateTest : BaseSessi
 
         // Media test is relatively resource-intensive. Clean up resources from previous tests
         // first to improve the stability of this test.
         sessionRule.forceGarbageCollection()
 
         mainSession.loadTestPath(HELLO_HTML_PATH)
         mainSession.waitForPageStop()
 
-
-        mainSession.delegateDuringNextWait(object : Callbacks.PermissionDelegate {
-            @AssertCalled(count = 1)
-            override fun onAndroidPermissionsRequest(
-                    session: GeckoSession, permissions: Array<out String>?,
-                    callback: GeckoSession.PermissionDelegate.Callback) {
-                assertThat("Permissions list should be correct",
-                           listOf(*permissions!!), hasItems(Manifest.permission.CAMERA,
-                                                            Manifest.permission.RECORD_AUDIO))
-                callback.grant()
-            }
-        })
-
         val devices = mainSession.waitForJS(
                 "window.navigator.mediaDevices.enumerateDevices()")
 
         assertThat("Device list should contain camera device",
                    devices.asJSList<Any>(), hasItem(hasEntry("kind", "videoinput")))
         assertThat("Device list should contain microphone device",
                    devices.asJSList<Any>(), hasItem(hasEntry("kind", "audioinput")))