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 [¬ifier](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