chromium/android_webview/browser/permission/media_access_permission_request_unittest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/browser/permission/media_access_permission_request.h"

#include <memory>

#include "android_webview/browser/aw_context_permissions_delegate.h"
#include "android_webview/browser/aw_permission_manager.h"
#include "android_webview/common/aw_features.h"
#include "base/functional/bind.h"
#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"

namespace android_webview {

class TestMediaAccessPermissionRequest : public MediaAccessPermissionRequest {
 public:
  TestMediaAccessPermissionRequest(
      const content::MediaStreamRequest& request,
      content::MediaResponseCallback callback,
      const blink::MediaStreamDevices& audio_devices,
      const blink::MediaStreamDevices& video_devices,
      AwPermissionManager& aw_permission_manager_,
      bool can_cache_file_url_permissions_)
      : MediaAccessPermissionRequest(request,
                                     std::move(callback),
                                     aw_permission_manager_,
                                     can_cache_file_url_permissions_) {
    audio_test_devices_ = audio_devices;
    video_test_devices_ = video_devices;
  }
};

class MockContextPermissionDelegate : public AwContextPermissionsDelegate {
 public:
  MockContextPermissionDelegate() = default;
  PermissionStatus GetGeolocationPermission(
      const GURL& requesting_origin) const override {
    return PermissionStatus::ASK;
  }
};

class MediaAccessPermissionRequestTest : public testing::Test {
 protected:
  void SetUp() override {
    audio_device_id_ = "audio";
    video_device_id_ = "video";
    first_audio_device_id_ = "audio1";
    first_video_device_id_ = "video1";
  }

  std::unique_ptr<TestMediaAccessPermissionRequest> CreateRequest(
      std::string audio_id,
      std::string video_id) {
    blink::MediaStreamDevices audio_devices;
    audio_devices.push_back(blink::MediaStreamDevice(
        blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE,
        first_audio_device_id_, "a2"));
    audio_devices.push_back(blink::MediaStreamDevice(
        blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, audio_device_id_,
        "a1"));

    blink::MediaStreamDevices video_devices;
    video_devices.push_back(blink::MediaStreamDevice(
        blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
        first_video_device_id_, "v2"));
    video_devices.push_back(blink::MediaStreamDevice(
        blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, video_device_id_,
        "v1"));

    GURL origin("https://www.google.com");
    content::MediaStreamRequest request(
        0, 0, 0, url::Origin::Create(origin), false,
        blink::MEDIA_GENERATE_STREAM, {audio_id}, {video_id},
        blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE,
        blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
        false /* disable_local_echo */,
        false /* request_pan_tilt_zoom_permission */,
        false /* captured_surface_control_active */);

    std::unique_ptr<TestMediaAccessPermissionRequest> permission_request;
    permission_request = std::make_unique<TestMediaAccessPermissionRequest>(
        request,
        base::BindOnce(&MediaAccessPermissionRequestTest::Callback,
                       base::Unretained(this)),
        audio_devices, video_devices, aw_permission_manager_, false);
    return permission_request;
  }

  std::string audio_device_id_;
  std::string video_device_id_;
  std::string first_audio_device_id_;
  std::string first_video_device_id_;
  blink::MediaStreamDevices devices_;
  blink::mojom::MediaStreamRequestResult result_;
  MockContextPermissionDelegate mock_permission_delegate_;
  AwPermissionManager aw_permission_manager_{mock_permission_delegate_};
  base::test::ScopedFeatureList feature_list_;

 private:
  void Callback(const blink::mojom::StreamDevicesSet& stream_devices_set,
                blink::mojom::MediaStreamRequestResult result,
                std::unique_ptr<content::MediaStreamUI> ui) {
    devices_ = blink::ToMediaStreamDevicesList(stream_devices_set);
    result_ = result;
  }
};

TEST_F(MediaAccessPermissionRequestTest, TestGrantPermissionRequest) {
  std::unique_ptr<TestMediaAccessPermissionRequest> request =
      CreateRequest(audio_device_id_, video_device_id_);
  request->NotifyRequestResult(true);

  EXPECT_EQ(2u, devices_.size());
  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result_);

  bool audio_exist = false;
  bool video_exist = false;
  for (blink::MediaStreamDevices::iterator i = devices_.begin();
       i != devices_.end(); ++i) {
    if (i->type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE &&
        i->id == audio_device_id_) {
      audio_exist = true;
    } else if (i->type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE &&
               i->id == video_device_id_) {
      video_exist = true;
    }
  }
  EXPECT_TRUE(audio_exist);
  EXPECT_TRUE(video_exist);
}

TEST_F(MediaAccessPermissionRequestTest, TestGrantPermissionRequestWithoutID) {
  std::unique_ptr<TestMediaAccessPermissionRequest> request =
      CreateRequest(std::string(), std::string());
  request->NotifyRequestResult(true);

  EXPECT_EQ(2u, devices_.size());
  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result_);

  bool audio_exist = false;
  bool video_exist = false;
  for (blink::MediaStreamDevices::iterator i = devices_.begin();
       i != devices_.end(); ++i) {
    if (i->type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE &&
        i->id == first_audio_device_id_) {
      audio_exist = true;
    } else if (i->type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE &&
               i->id == first_video_device_id_) {
      video_exist = true;
    }
  }
  EXPECT_TRUE(audio_exist);
  EXPECT_TRUE(video_exist);
}

TEST_F(MediaAccessPermissionRequestTest, TestDenyPermissionRequest) {
  std::unique_ptr<TestMediaAccessPermissionRequest> request =
      CreateRequest(std::string(), std::string());
  request->NotifyRequestResult(false);
  EXPECT_TRUE(devices_.empty());
  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result_);
}

TEST_F(MediaAccessPermissionRequestTest,
       TestGrantedPermissionRequestCachesResult) {
  url::Origin origin = url::Origin::Create(GURL("https://www.google.com"));
  EXPECT_FALSE(
      aw_permission_manager_.ShouldShowEnumerateDevicesAudioLabels(origin));
  EXPECT_FALSE(
      aw_permission_manager_.ShouldShowEnumerateDevicesVideoLabels(origin));
  std::unique_ptr<TestMediaAccessPermissionRequest> request =
      CreateRequest(audio_device_id_, video_device_id_);
  request->NotifyRequestResult(true);
  EXPECT_TRUE(
      aw_permission_manager_.ShouldShowEnumerateDevicesAudioLabels(origin));
  EXPECT_TRUE(
      aw_permission_manager_.ShouldShowEnumerateDevicesVideoLabels(origin));
}

TEST_F(MediaAccessPermissionRequestTest,
       TestGrantedPermissionRequestWithoutCacheFailsEnumerateDevices) {
  feature_list_.InitAndDisableFeature(features::kWebViewEnumerateDevicesCache);
  url::Origin origin = url::Origin::Create(GURL("https://www.google.com"));
  EXPECT_FALSE(
      aw_permission_manager_.ShouldShowEnumerateDevicesAudioLabels(origin));
  EXPECT_FALSE(
      aw_permission_manager_.ShouldShowEnumerateDevicesVideoLabels(origin));
  std::unique_ptr<TestMediaAccessPermissionRequest> request =
      CreateRequest(audio_device_id_, video_device_id_);
  request->NotifyRequestResult(true);
  EXPECT_FALSE(
      aw_permission_manager_.ShouldShowEnumerateDevicesAudioLabels(origin));
  EXPECT_FALSE(
      aw_permission_manager_.ShouldShowEnumerateDevicesVideoLabels(origin));
}
}  // namespace android_webview