1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.h"
6 
7 #include <algorithm>
8 #include <memory>
9 
10 #include "ash/public/cpp/vm_camera_mic_constants.h"
11 #include "base/bind.h"
12 #include "base/test/scoped_feature_list.h"
13 #include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_factory.h"
14 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
15 #include "chrome/browser/notifications/notification_display_service.h"
16 #include "chrome/browser/notifications/notification_display_service_factory.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "chromeos/constants/chromeos_features.h"
19 #include "components/user_manager/scoped_user_manager.h"
20 #include "components/user_manager/user.h"
21 #include "content/public/test/browser_task_environment.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 
25 namespace {
26 using testing::UnorderedElementsAre;
27 using VmType = chromeos::VmCameraMicManager::VmType;
28 using DeviceType = chromeos::VmCameraMicManager::DeviceType;
29 
30 class FakeNotificationDisplayService : public NotificationDisplayService {
31  public:
32   FakeNotificationDisplayService() = default;
33   ~FakeNotificationDisplayService() override = default;
34 
Display(NotificationHandler::Type notification_type,const message_center::Notification & notification,std::unique_ptr<NotificationCommon::Metadata> metadata)35   void Display(
36       NotificationHandler::Type notification_type,
37       const message_center::Notification& notification,
38       std::unique_ptr<NotificationCommon::Metadata> metadata) override {
39     notification_id_to_notifier_id_[notification.id()] =
40         notification.notifier_id().id;
41   }
42 
Close(NotificationHandler::Type notification_type,const std::string & notification_id)43   void Close(NotificationHandler::Type notification_type,
44              const std::string& notification_id) override {
45     size_t count = notification_id_to_notifier_id_.erase(notification_id);
46     CHECK(count == 1);
47   }
48 
GetDisplayed(DisplayedNotificationsCallback callback)49   void GetDisplayed(DisplayedNotificationsCallback callback) override {}
AddObserver(Observer * observer)50   void AddObserver(Observer* observer) override {}
RemoveObserver(Observer * observer)51   void RemoveObserver(Observer* observer) override {}
52 
CountNotifier(const std::string & notifier)53   size_t CountNotifier(const std::string& notifier) {
54     return std::count_if(
55         notification_id_to_notifier_id_.begin(),
56         notification_id_to_notifier_id_.end(),
57         [&notifier](auto& pair) { return pair.second == notifier; });
58   }
59 
60  private:
61   std::map<std::string, std::string> notification_id_to_notifier_id_;
62 };
63 
64 }  // namespace
65 
66 namespace chromeos {
67 
68 class VmCameraMicManagerTest : public testing::Test {
69  public:
VmCameraMicManagerTest()70   VmCameraMicManagerTest() {
71     // Make the profile the primary one.
72     auto mock_user_manager =
73         std::make_unique<testing::NiceMock<chromeos::MockUserManager>>();
74     mock_user_manager->AddUser(AccountId::FromUserEmailGaiaId(
75         testing_profile_.GetProfileUserName(), "id"));
76     scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
77         std::move(mock_user_manager));
78     scoped_feature_list_.InitAndEnableFeature(
79         features::kVmCameraMicIndicatorsAndNotifications);
80 
81     // Inject a fake notification display service.
82     fake_display_service_ = static_cast<FakeNotificationDisplayService*>(
83         NotificationDisplayServiceFactory::GetInstance()
84             ->SetTestingFactoryAndUse(
85                 &testing_profile_,
86                 base::BindRepeating([](content::BrowserContext* context)
87                                         -> std::unique_ptr<KeyedService> {
88                   return std::make_unique<FakeNotificationDisplayService>();
89                 })));
90 
91     vm_camera_mic_manager_ =
92         VmCameraMicManagerFactory::GetForProfile(&testing_profile_);
93   }
94 
95  protected:
96   content::BrowserTaskEnvironment task_environment_;
97   TestingProfile testing_profile_;
98   std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
99   base::test::ScopedFeatureList scoped_feature_list_;
100 
101   FakeNotificationDisplayService* fake_display_service_;
102   VmCameraMicManager* vm_camera_mic_manager_;
103 
104   DISALLOW_COPY_AND_ASSIGN(VmCameraMicManagerTest);
105 };
106 
TEST_F(VmCameraMicManagerTest,GetActive)107 TEST_F(VmCameraMicManagerTest, GetActive) {
108   EXPECT_FALSE(vm_camera_mic_manager_->GetActive(VmType::kCrostiniVm,
109                                                  DeviceType::kCamera));
110   EXPECT_FALSE(vm_camera_mic_manager_->GetActive(VmType::kPluginVm,
111                                                  DeviceType::kCamera));
112 
113   vm_camera_mic_manager_->SetActive(VmType::kCrostiniVm, DeviceType::kCamera,
114                                     true);
115   EXPECT_TRUE(vm_camera_mic_manager_->GetActive(VmType::kCrostiniVm,
116                                                 DeviceType::kCamera));
117   EXPECT_FALSE(vm_camera_mic_manager_->GetActive(VmType::kPluginVm,
118                                                  DeviceType::kCamera));
119 
120   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kCamera,
121                                     true);
122   EXPECT_TRUE(vm_camera_mic_manager_->GetActive(VmType::kCrostiniVm,
123                                                 DeviceType::kCamera));
124   EXPECT_TRUE(vm_camera_mic_manager_->GetActive(VmType::kPluginVm,
125                                                 DeviceType::kCamera));
126 
127   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kCamera,
128                                     false);
129   EXPECT_TRUE(vm_camera_mic_manager_->GetActive(VmType::kCrostiniVm,
130                                                 DeviceType::kCamera));
131   EXPECT_FALSE(vm_camera_mic_manager_->GetActive(VmType::kPluginVm,
132                                                  DeviceType::kCamera));
133 }
134 
TEST_F(VmCameraMicManagerTest,GetDeviceActive)135 TEST_F(VmCameraMicManagerTest, GetDeviceActive) {
136   EXPECT_FALSE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kCamera));
137   EXPECT_FALSE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kMic));
138 
139   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kCamera,
140                                     true);
141   EXPECT_TRUE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kCamera));
142   EXPECT_FALSE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kMic));
143 
144   vm_camera_mic_manager_->SetActive(VmType::kCrostiniVm, DeviceType::kCamera,
145                                     true);
146   EXPECT_TRUE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kCamera));
147   EXPECT_FALSE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kMic));
148 
149   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kCamera,
150                                     false);
151   EXPECT_TRUE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kCamera));
152   EXPECT_FALSE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kMic));
153 
154   vm_camera_mic_manager_->SetActive(VmType::kCrostiniVm, DeviceType::kCamera,
155                                     false);
156   EXPECT_FALSE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kCamera));
157   EXPECT_FALSE(vm_camera_mic_manager_->GetDeviceActive(DeviceType::kMic));
158 }
159 
TEST_F(VmCameraMicManagerTest,SetActiveTriggerNotifications)160 TEST_F(VmCameraMicManagerTest, SetActiveTriggerNotifications) {
161   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 0);
162   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 0);
163 
164   vm_camera_mic_manager_->SetActive(VmType::kCrostiniVm, DeviceType::kCamera,
165                                     true);
166   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 1);
167   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 0);
168 
169   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kCamera,
170                                     true);
171   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 2);
172   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 0);
173 
174   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kMic, true);
175   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 2);
176   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 1);
177 
178   // No new notification for already active (VmType, DeviceType) combination.
179   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kMic, true);
180   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 2);
181   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 1);
182 
183   vm_camera_mic_manager_->SetActive(VmType::kCrostiniVm, DeviceType::kCamera,
184                                     false);
185   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 1);
186   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 1);
187 
188   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kMic, false);
189   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 1);
190   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 0);
191 
192   // Ignore already inactive (VmType, DeviceType) combination.
193   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kMic, false);
194   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 1);
195   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 0);
196 
197   vm_camera_mic_manager_->SetActive(VmType::kPluginVm, DeviceType::kCamera,
198                                     false);
199   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmCameraNotifierId), 0);
200   EXPECT_EQ(fake_display_service_->CountNotifier(ash::kVmMicNotifierId), 0);
201 }
202 
203 }  // namespace chromeos
204