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 #ifndef CHROME_BROWSER_CHROMEOS_CAMERA_MIC_VM_CAMERA_MIC_MANAGER_H_
6 #define CHROME_BROWSER_CHROMEOS_CAMERA_MIC_VM_CAMERA_MIC_MANAGER_H_
7 
8 #include <memory>
9 #include "base/callback_forward.h"
10 #include "base/containers/flat_map.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/observer_list.h"
13 #include "base/observer_list_types.h"
14 #include "base/timer/timer.h"
15 #include "components/keyed_service/core/keyed_service.h"
16 #include "ui/message_center/public/cpp/notification.h"
17 #include "ui/message_center/public/cpp/notification_delegate.h"
18 
19 class Profile;
20 
21 namespace chromeos {
22 
23 // This class manages camera/mic access (and the access notifications) for VMs
24 // (crostini and parallels for now). Like all the VMs, it is only available for
25 // the primary and non-incognito profile. We might need to change this if we
26 // extend this class to support the browser, in which case we will also need to
27 // make the notification ids different for different profiles.
28 class VmCameraMicManager : public KeyedService {
29  public:
30   enum class VmType { kCrostiniVm, kPluginVm };
31 
32   enum class DeviceType {
33     kMic,
34     kCamera,
35   };
36 
37   class Observer : public base::CheckedObserver {
38    public:
OnVmCameraMicActiveChanged(VmCameraMicManager *)39     virtual void OnVmCameraMicActiveChanged(VmCameraMicManager*) {}
40   };
41 
42   // Return nullptr if the profile is non-primary or incognito.
43   static VmCameraMicManager* GetForProfile(Profile* profile);
44 
45   explicit VmCameraMicManager(Profile* profile);
46   ~VmCameraMicManager() override;
47 
48   VmCameraMicManager(const VmCameraMicManager&) = delete;
49   VmCameraMicManager& operator=(const VmCameraMicManager&) = delete;
50 
51   void AddObserver(Observer* observer);
52   void RemoveObserver(Observer* observer);
53 
54   void SetActive(VmType vm, DeviceType device, bool active);
55   bool GetActive(VmType vm, DeviceType device) const;
56   // Return true if any of the VMs is using the device.
57   bool GetDeviceActive(DeviceType device) const;
58 
59  private:
60   using ActiveMap = base::flat_map<std::pair<VmType, DeviceType>, bool>;
61 
62   class VmNotificationObserver : public message_center::NotificationObserver {
63    public:
64     using OpenSettingsFunction = base::RepeatingCallback<void(Profile*)>;
65 
66     VmNotificationObserver(Profile* profile,
67                            OpenSettingsFunction open_settings);
68     ~VmNotificationObserver();
69 
70     base::WeakPtr<NotificationObserver> GetWeakPtr();
71 
72     // message_center::NotificationObserver:
73     void Click(const base::Optional<int>& button_index,
74                const base::Optional<base::string16>& reply) override;
75 
76    private:
77     Profile* const profile_;
78     OpenSettingsFunction open_settings_;
79     base::WeakPtrFactory<VmNotificationObserver> weak_ptr_factory_{this};
80   };
81 
82   void NotifyActiveChanged();
83 
84   void OpenNotification(VmType vm, DeviceType device);
85   void CloseNotification(VmType vm, DeviceType device);
86 
87   Profile* const profile_;
88   VmNotificationObserver crostini_vm_notification_observer_;
89   VmNotificationObserver plugin_vm_notification_observer_;
90   ActiveMap active_map_;
91 
92   base::RetainingOneShotTimer observer_timer_;
93   base::ObserverList<Observer> observers_;
94 };
95 
96 }  // namespace chromeos
97 
98 #endif  // CHROME_BROWSER_CHROMEOS_CAMERA_MIC_VM_CAMERA_MIC_MANAGER_H_
99