Commit b296c9a2 authored by Jason Lin's avatar Jason Lin Committed by Chromium LUCI CQ

Convert VmCameraMicManager from a KeyedService to a singleton

MediaClientImpl needs to register itself as an observer of
VmCameraMicManager. Depending on whether the user has customized a flag
or not, MediaClientImpl is either constructed before or after
`UserSessionInitializer::OnUserSessionStarted(/*is_primary_user*/=true)`
is run. The reason seems to be that 1) MediaClientImpl is constructed in
a task queue; 2) Customizing a flag causes the browser to be restarted
after the user signs in, which changes the execution characteristics.

My last attempt (CL 2586286) to fix the registration does not work if
the user has customized flags. So, this CL makes VmCameraMicManager
a singleton which is always available so that MediaClientImpl can always
reliably do the registration in its ctor.

Bug: b/167491603
Change-Id: I2b73b59216851f0b8b2533120317e54c98382b45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2589061
Commit-Queue: Jason Lin <lxj@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarJoel Hockey <joelhockey@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836941}
parent 0f0879fd
...@@ -916,8 +916,6 @@ source_set("chromeos") { ...@@ -916,8 +916,6 @@ source_set("chromeos") {
"camera_detector.h", "camera_detector.h",
"camera_mic/vm_camera_mic_manager.cc", "camera_mic/vm_camera_mic_manager.cc",
"camera_mic/vm_camera_mic_manager.h", "camera_mic/vm_camera_mic_manager.h",
"camera_mic/vm_camera_mic_manager_factory.cc",
"camera_mic/vm_camera_mic_manager_factory.h",
"camera_presence_notifier.cc", "camera_presence_notifier.cc",
"camera_presence_notifier.h", "camera_presence_notifier.h",
"cert_provisioning/cert_provisioning_common.cc", "cert_provisioning/cert_provisioning_common.cc",
......
...@@ -10,12 +10,12 @@ ...@@ -10,12 +10,12 @@
#include "ash/public/cpp/vm_camera_mic_constants.h" #include "ash/public/cpp/vm_camera_mic_constants.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/no_destructor.h"
#include "base/notreached.h" #include "base/notreached.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/system/sys_info.h" #include "base/system/sys_info.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_factory.h"
#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service.h"
...@@ -64,26 +64,26 @@ constexpr VmCameraMicManager::NotificationType ...@@ -64,26 +64,26 @@ constexpr VmCameraMicManager::NotificationType
constexpr VmCameraMicManager::NotificationType constexpr VmCameraMicManager::NotificationType
VmCameraMicManager::kCameraWithMicNotification; VmCameraMicManager::kCameraWithMicNotification;
VmCameraMicManager* VmCameraMicManager::GetForProfile(Profile* profile) { VmCameraMicManager* VmCameraMicManager::Get() {
return VmCameraMicManagerFactory::GetForProfile(profile); static base::NoDestructor<VmCameraMicManager> manager;
return manager.get();
} }
VmCameraMicManager::VmCameraMicManager(Profile* profile) VmCameraMicManager::VmCameraMicManager()
: profile_(profile), : observer_timer_(
crostini_vm_notification_observer_(
profile,
base::BindRepeating(OpenCrostiniSettings)),
plugin_vm_notification_observer_(
profile,
base::BindRepeating(OpenPluginVmSettings)),
observer_timer_(
FROM_HERE, FROM_HERE,
kObserverTimerDelay, kObserverTimerDelay,
base::BindRepeating(&VmCameraMicManager::NotifyActiveChanged, base::BindRepeating(&VmCameraMicManager::NotifyActiveChanged,
// Unretained because the timer cannot // Unretained because the timer cannot
// live longer than the manager. // live longer than the manager.
base::Unretained(this))) { base::Unretained(this))) {}
DCHECK(ProfileHelper::IsPrimaryProfile(profile));
void VmCameraMicManager::OnPrimaryUserSessionStarted(Profile* primary_profile) {
primary_profile_ = primary_profile;
crostini_vm_notification_observer_.Initialize(
primary_profile_, base::BindRepeating(OpenCrostiniSettings));
plugin_vm_notification_observer_.Initialize(
primary_profile_, base::BindRepeating(OpenPluginVmSettings));
for (VmType vm : {VmType::kCrostiniVm, VmType::kPluginVm}) { for (VmType vm : {VmType::kCrostiniVm, VmType::kPluginVm}) {
notification_map_[vm] = {}; notification_map_[vm] = {};
...@@ -95,10 +95,13 @@ VmCameraMicManager::VmCameraMicManager(Profile* profile) ...@@ -95,10 +95,13 @@ VmCameraMicManager::VmCameraMicManager(Profile* profile)
media::ShouldUseCrosCameraService()) { media::ShouldUseCrosCameraService()) {
// OnActiveClientChange() will be called automatically after the // OnActiveClientChange() will be called automatically after the
// subscription, so there is no need to get the current status here. // subscription, so there is no need to get the current status here.
camera_observation_.Observe(media::CameraHalDispatcherImpl::GetInstance()); media::CameraHalDispatcherImpl::GetInstance()->AddActiveClientObserver(
this);
} }
} }
// The class is supposed to be used as a singleton with `base::NoDestructor`, so
// we do not do clean up (e.g. deregister as observers) here.
VmCameraMicManager::~VmCameraMicManager() = default; VmCameraMicManager::~VmCameraMicManager() = default;
void VmCameraMicManager::SetActive(VmType vm, DeviceType device, bool active) { void VmCameraMicManager::SetActive(VmType vm, DeviceType device, bool active) {
...@@ -164,9 +167,8 @@ void VmCameraMicManager::OnActiveClientChange( ...@@ -164,9 +167,8 @@ void VmCameraMicManager::OnActiveClientChange(
type == cros::mojom::CameraClientType::PLUGINVM) { type == cros::mojom::CameraClientType::PLUGINVM) {
content::GetUIThreadTaskRunner({})->PostTask( content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&VmCameraMicManager::SetActive, base::BindOnce(&VmCameraMicManager::SetActive, base::Unretained(this),
weak_ptr_factory_.GetWeakPtr(), VmType::kPluginVm, VmType::kPluginVm, DeviceType::kCamera, is_active));
DeviceType::kCamera, is_active));
} }
} }
...@@ -264,9 +266,9 @@ void VmCameraMicManager::OpenNotification(VmType vm, NotificationType type) { ...@@ -264,9 +266,9 @@ void VmCameraMicManager::OpenNotification(VmType vm, NotificationType type) {
base::MakeRefCounted<message_center::ThunkNotificationDelegate>( base::MakeRefCounted<message_center::ThunkNotificationDelegate>(
std::move(notification_observer_))); std::move(notification_observer_)));
NotificationDisplayService::GetForProfile(profile_)->Display( NotificationDisplayService::GetForProfile(primary_profile_)
NotificationHandler::Type::TRANSIENT, notification, ->Display(NotificationHandler::Type::TRANSIENT, notification,
/*metadata=*/nullptr); /*metadata=*/nullptr);
} }
void VmCameraMicManager::CloseNotification(VmType vm, NotificationType type) { void VmCameraMicManager::CloseNotification(VmType vm, NotificationType type) {
...@@ -275,17 +277,21 @@ void VmCameraMicManager::CloseNotification(VmType vm, NotificationType type) { ...@@ -275,17 +277,21 @@ void VmCameraMicManager::CloseNotification(VmType vm, NotificationType type) {
features::kVmCameraMicIndicatorsAndNotifications)) { features::kVmCameraMicIndicatorsAndNotifications)) {
return; return;
} }
NotificationDisplayService::GetForProfile(profile_)->Close( NotificationDisplayService::GetForProfile(primary_profile_)
NotificationHandler::Type::TRANSIENT, GetNotificationId(vm, type)); ->Close(NotificationHandler::Type::TRANSIENT,
GetNotificationId(vm, type));
} }
VmCameraMicManager::VmNotificationObserver::VmNotificationObserver( VmCameraMicManager::VmNotificationObserver::VmNotificationObserver() = default;
Profile* profile,
OpenSettingsFunction open_settings)
: profile_{profile}, open_settings_{open_settings} {}
VmCameraMicManager::VmNotificationObserver::~VmNotificationObserver() = default; VmCameraMicManager::VmNotificationObserver::~VmNotificationObserver() = default;
void VmCameraMicManager::VmNotificationObserver::Initialize(
Profile* profile,
OpenSettingsFunction open_settings) {
profile_ = profile;
open_settings_ = std::move(open_settings);
}
base::WeakPtr<message_center::NotificationObserver> base::WeakPtr<message_center::NotificationObserver>
VmCameraMicManager::VmNotificationObserver::GetWeakPtr() { VmCameraMicManager::VmNotificationObserver::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr(); return weak_ptr_factory_.GetWeakPtr();
......
...@@ -25,12 +25,12 @@ class Profile; ...@@ -25,12 +25,12 @@ class Profile;
namespace chromeos { namespace chromeos {
// This class manages camera/mic access (and the access notifications) for VMs // This class manages camera/mic access (and the access notifications) for VMs
// (crostini and parallels for now). Like all the VMs, it is only available for // (crostini and parallels for now). All of the notifications are sent to the
// the primary and non-incognito profile. We might need to change this if we // primary profile since all VMs support only the primary profile. We might need
// extend this class to support the browser, in which case we will also need to // to change this if we extend this class to support the browser, in which case
// make the notification ids different for different profiles. // we will also need to make the notification ids different for different
class VmCameraMicManager : public KeyedService, // profiles.
public media::CameraActiveClientObserver { class VmCameraMicManager : public media::CameraActiveClientObserver {
public: public:
enum class VmType { kCrostiniVm, kPluginVm }; enum class VmType { kCrostiniVm, kPluginVm };
...@@ -45,12 +45,13 @@ class VmCameraMicManager : public KeyedService, ...@@ -45,12 +45,13 @@ class VmCameraMicManager : public KeyedService,
virtual void OnVmCameraMicActiveChanged(VmCameraMicManager*) {} virtual void OnVmCameraMicActiveChanged(VmCameraMicManager*) {}
}; };
// Return nullptr if the profile is non-primary or incognito. static VmCameraMicManager* Get();
static VmCameraMicManager* GetForProfile(Profile* profile);
explicit VmCameraMicManager(Profile* profile); VmCameraMicManager();
~VmCameraMicManager() override; ~VmCameraMicManager() override;
void OnPrimaryUserSessionStarted(Profile* primary_profile);
VmCameraMicManager(const VmCameraMicManager&) = delete; VmCameraMicManager(const VmCameraMicManager&) = delete;
VmCameraMicManager& operator=(const VmCameraMicManager&) = delete; VmCameraMicManager& operator=(const VmCameraMicManager&) = delete;
...@@ -88,10 +89,11 @@ class VmCameraMicManager : public KeyedService, ...@@ -88,10 +89,11 @@ class VmCameraMicManager : public KeyedService,
public: public:
using OpenSettingsFunction = base::RepeatingCallback<void(Profile*)>; using OpenSettingsFunction = base::RepeatingCallback<void(Profile*)>;
VmNotificationObserver(Profile* profile, VmNotificationObserver();
OpenSettingsFunction open_settings);
~VmNotificationObserver(); ~VmNotificationObserver();
void Initialize(Profile* profile, OpenSettingsFunction open_settings);
base::WeakPtr<NotificationObserver> GetWeakPtr(); base::WeakPtr<NotificationObserver> GetWeakPtr();
// message_center::NotificationObserver: // message_center::NotificationObserver:
...@@ -99,7 +101,7 @@ class VmCameraMicManager : public KeyedService, ...@@ -99,7 +101,7 @@ class VmCameraMicManager : public KeyedService,
const base::Optional<base::string16>& reply) override; const base::Optional<base::string16>& reply) override;
private: private:
Profile* const profile_; Profile* profile_ = nullptr;
OpenSettingsFunction open_settings_; OpenSettingsFunction open_settings_;
base::WeakPtrFactory<VmNotificationObserver> weak_ptr_factory_{this}; base::WeakPtrFactory<VmNotificationObserver> weak_ptr_factory_{this};
}; };
...@@ -116,22 +118,13 @@ class VmCameraMicManager : public KeyedService, ...@@ -116,22 +118,13 @@ class VmCameraMicManager : public KeyedService,
void OpenNotification(VmType vm, NotificationType type); void OpenNotification(VmType vm, NotificationType type);
void CloseNotification(VmType vm, NotificationType type); void CloseNotification(VmType vm, NotificationType type);
Profile* const profile_; Profile* primary_profile_ = nullptr;
VmNotificationObserver crostini_vm_notification_observer_; VmNotificationObserver crostini_vm_notification_observer_;
VmNotificationObserver plugin_vm_notification_observer_; VmNotificationObserver plugin_vm_notification_observer_;
NotificationMap notification_map_; NotificationMap notification_map_;
base::RetainingOneShotTimer observer_timer_; base::RetainingOneShotTimer observer_timer_;
base::ObserverList<Observer> observers_; base::ObserverList<Observer> observers_;
base::ScopedObservation<
media::CameraHalDispatcherImpl,
media::CameraActiveClientObserver,
&media::CameraHalDispatcherImpl::AddActiveClientObserver,
&media::CameraHalDispatcherImpl::RemoveActiveClientObserver>
camera_observation_{this};
base::WeakPtrFactory<VmCameraMicManager> weak_ptr_factory_{this};
}; };
} // namespace chromeos } // namespace chromeos
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_factory.h"
#include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
namespace chromeos {
VmCameraMicManager* VmCameraMicManagerFactory::GetForProfile(Profile* profile) {
return static_cast<VmCameraMicManager*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
VmCameraMicManagerFactory* VmCameraMicManagerFactory::GetInstance() {
static base::NoDestructor<VmCameraMicManagerFactory> factory;
return factory.get();
}
VmCameraMicManagerFactory::VmCameraMicManagerFactory()
: BrowserContextKeyedServiceFactory(
"VmCameraMicManager",
BrowserContextDependencyManager::GetInstance()) {}
VmCameraMicManagerFactory::~VmCameraMicManagerFactory() = default;
// BrowserContextKeyedServiceFactory:
KeyedService* VmCameraMicManagerFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
Profile* profile = Profile::FromBrowserContext(context);
if (ProfileHelper::IsPrimaryProfile(profile))
return new VmCameraMicManager(profile);
return nullptr;
}
} // namespace chromeos
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_CAMERA_MIC_VM_CAMERA_MIC_MANAGER_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_CAMERA_MIC_VM_CAMERA_MIC_MANAGER_FACTORY_H_
#include "base/no_destructor.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
class Profile;
namespace chromeos {
class VmCameraMicManager;
class VmCameraMicManagerFactory : public BrowserContextKeyedServiceFactory {
public:
static VmCameraMicManager* GetForProfile(Profile* profile);
static VmCameraMicManagerFactory* GetInstance();
private:
friend class base::NoDestructor<VmCameraMicManagerFactory>;
VmCameraMicManagerFactory();
~VmCameraMicManagerFactory() override;
// BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CAMERA_MIC_VM_CAMERA_MIC_MANAGER_FACTORY_H_
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_factory.h"
#include "chrome/browser/chromeos/login/users/mock_user_manager.h" #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/notifications/notification_display_service_factory.h"
...@@ -124,8 +123,8 @@ class VmCameraMicManagerTest : public testing::Test { ...@@ -124,8 +123,8 @@ class VmCameraMicManagerTest : public testing::Test {
return std::make_unique<FakeNotificationDisplayService>(); return std::make_unique<FakeNotificationDisplayService>();
}))); })));
vm_camera_mic_manager_ = vm_camera_mic_manager_ = std::make_unique<VmCameraMicManager>();
VmCameraMicManagerFactory::GetForProfile(&testing_profile_); vm_camera_mic_manager_->OnPrimaryUserSessionStarted(&testing_profile_);
} }
void SetActive(const ActiveMap& active_map) { void SetActive(const ActiveMap& active_map) {
...@@ -145,7 +144,7 @@ class VmCameraMicManagerTest : public testing::Test { ...@@ -145,7 +144,7 @@ class VmCameraMicManagerTest : public testing::Test {
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
FakeNotificationDisplayService* fake_display_service_; FakeNotificationDisplayService* fake_display_service_;
VmCameraMicManager* vm_camera_mic_manager_; std::unique_ptr<VmCameraMicManager> vm_camera_mic_manager_;
DISALLOW_COPY_AND_ASSIGN(VmCameraMicManagerTest); DISALLOW_COPY_AND_ASSIGN(VmCameraMicManagerTest);
}; };
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part_chromeos.h" #include "chrome/browser/browser_process_platform_part_chromeos.h"
#include "chrome/browser/chromeos/arc/session/arc_service_launcher.h" #include "chrome/browser/chromeos/arc/session/arc_service_launcher.h"
#include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_factory.h" #include "chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.h"
#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h" #include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h" #include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.h" #include "chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.h"
...@@ -213,11 +213,7 @@ void UserSessionInitializer::OnUserSessionStarted(bool is_primary_user) { ...@@ -213,11 +213,7 @@ void UserSessionInitializer::OnUserSessionStarted(bool is_primary_user) {
if (plugin_vm_manager) if (plugin_vm_manager)
plugin_vm_manager->OnPrimaryUserSessionStarted(); plugin_vm_manager->OnPrimaryUserSessionStarted();
VmCameraMicManagerFactory::GetForProfile(primary_profile_); VmCameraMicManager::Get()->OnPrimaryUserSessionStarted(primary_profile_);
auto* media_client_impl = MediaClientImpl::Get();
if (media_client_impl)
media_client_impl->OnPrimaryUserSessionStarted(primary_profile_);
} }
} }
......
...@@ -141,6 +141,8 @@ MediaClientImpl::MediaClientImpl() { ...@@ -141,6 +141,8 @@ MediaClientImpl::MediaClientImpl() {
MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this); MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
BrowserList::AddObserver(this); BrowserList::AddObserver(this);
chromeos::VmCameraMicManager::Get()->AddObserver(this);
DCHECK(!g_media_client); DCHECK(!g_media_client);
g_media_client = this; g_media_client = this;
} }
...@@ -154,10 +156,7 @@ MediaClientImpl::~MediaClientImpl() { ...@@ -154,10 +156,7 @@ MediaClientImpl::~MediaClientImpl() {
MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this); MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
BrowserList::RemoveObserver(this); BrowserList::RemoveObserver(this);
auto* vm_camera_mic_manager = chromeos::VmCameraMicManager::GetForProfile( chromeos::VmCameraMicManager::Get()->RemoveObserver(this);
ProfileManager::GetPrimaryUserProfile());
if (vm_camera_mic_manager)
vm_camera_mic_manager->RemoveObserver(this);
} }
// static // static
...@@ -179,18 +178,6 @@ void MediaClientImpl::InitForTesting(ash::MediaController* controller) { ...@@ -179,18 +178,6 @@ void MediaClientImpl::InitForTesting(ash::MediaController* controller) {
media_controller_->SetClient(this); media_controller_->SetClient(this);
} }
void MediaClientImpl::OnPrimaryUserSessionStarted(Profile* primary_profile) {
// Skip when not on real device (i.e. tests and emulator on dev box). The
// reason is that some tests cause this function to be run more than once,
// which results in a crash.
if (base::SysInfo::IsRunningOnChromeOS()) {
auto* vm_camera_mic_manager =
chromeos::VmCameraMicManager::GetForProfile(primary_profile);
if (vm_camera_mic_manager)
vm_camera_mic_manager->AddObserver(this);
}
}
void MediaClientImpl::HandleMediaNextTrack() { void MediaClientImpl::HandleMediaNextTrack() {
HandleMediaAction(ui::VKEY_MEDIA_NEXT_TRACK); HandleMediaAction(ui::VKEY_MEDIA_NEXT_TRACK);
} }
......
...@@ -29,8 +29,6 @@ class MediaClientImpl : public ash::MediaClient, ...@@ -29,8 +29,6 @@ class MediaClientImpl : public ash::MediaClient,
// Tests can provide a mock mojo interface for the ash controller. // Tests can provide a mock mojo interface for the ash controller.
void InitForTesting(ash::MediaController* controller); void InitForTesting(ash::MediaController* controller);
void OnPrimaryUserSessionStarted(Profile* primary_prifle);
// Returns a pointer to the singleton MediaClient, or nullptr if none exists. // Returns a pointer to the singleton MediaClient, or nullptr if none exists.
static MediaClientImpl* Get(); static MediaClientImpl* Get();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment