1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
// 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.
#ifndef CHROME_BROWSER_UI_ASH_MEDIA_CLIENT_MEDIA_CLIENT_IMPL_H_
#define CHROME_BROWSER_UI_ASH_MEDIA_CLIENT_MEDIA_CLIENT_IMPL_H_
#include "ash/public/cpp/media_client.h"
#include "ash/public/cpp/media_controller.h"
#include "ash/system/privacy_hub/privacy_hub_notification.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "chrome/browser/ash/camera_mic/vm_camera_mic_manager.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
#include "media/capture/video/chromeos/mojom/cros_camera_service.mojom.h"
#include "services/video_capture/public/mojom/video_source_provider.mojom.h"
#include "ui/base/accelerators/media_keys_listener.h"
using GetSourceInfosResult =
video_capture::mojom::VideoSourceProvider::GetSourceInfosResult;
class MediaClientImpl : public ash::MediaClient,
public ash::VmCameraMicManager::Observer,
public BrowserListObserver,
public MediaCaptureDevicesDispatcher::Observer,
public media::CameraPrivacySwitchObserver,
public media::CameraActiveClientObserver {
public:
MediaClientImpl();
MediaClientImpl(const MediaClientImpl&) = delete;
MediaClientImpl& operator=(const MediaClientImpl&) = delete;
~MediaClientImpl() override;
// Initializes and set as client for ash.
void Init();
// Tests can provide a mock mojo interface for the ash controller.
void InitForTesting(ash::MediaController* controller);
// Returns a pointer to the singleton MediaClient, or nullptr if none exists.
static MediaClientImpl* Get();
// ash::MediaClient:
void HandleMediaNextTrack() override;
void HandleMediaPlayPause() override;
void HandleMediaPlay() override;
void HandleMediaPause() override;
void HandleMediaStop() override;
void HandleMediaPrevTrack() override;
void HandleMediaSeekBackward() override;
void HandleMediaSeekForward() override;
void RequestCaptureState() override;
void SuspendMediaSessions() override;
// MediaCaptureDevicesDispatcher::Observer:
void OnRequestUpdate(int render_process_id,
int render_frame_id,
blink::mojom::MediaStreamType stream_type,
const content::MediaRequestState state) override;
// BrowserListObserver:
void OnBrowserSetLastActive(Browser* browser) override;
// ash::VmCameraMicManager::Observer
void OnVmCameraMicActiveChanged(ash::VmCameraMicManager* manager) override;
// media::CameraPrivacySwitchObserver:
void OnCameraHWPrivacySwitchStateChanged(
const std::string& device_id,
cros::mojom::CameraPrivacySwitchState state) override;
void OnCameraSWPrivacySwitchStateChanged(
cros::mojom::CameraPrivacySwitchState state) override;
// media::CameraActiveClientObserver:
void OnActiveClientChange(
cros::mojom::CameraClientType type,
bool is_active,
const base::flat_set<std::string>& device_ids) override;
// Enables/disables custom media key handling when |context| is the active
// browser. Media keys will be forwarded to |delegate|.
void EnableCustomMediaKeyHandler(content::BrowserContext* context,
ui::MediaKeysListener::Delegate* delegate);
void DisableCustomMediaKeyHandler(content::BrowserContext* context,
ui::MediaKeysListener::Delegate* delegate);
private:
friend class MediaClientAppUsingCameraTest;
using GetSourceCallback = base::OnceCallback<void(
GetSourceInfosResult,
const std::vector<media::VideoCaptureDeviceInfo>&)>;
// Passes a given callback to the GetSourcesInfos() method of the video source
// provider
void ProcessSourceInfos(GetSourceCallback callback);
// Sets |is_forcing_media_client_key_handling_| to true if
// |GetCurrentMediaKeyDelegate| returns a delegate. This will also mirror the
// value of |is_forcing_media_client_key_handling_| to Ash.
void UpdateForceMediaClientKeyHandling();
// Gets the current media key delegate that we should forward media keys to.
// This will be the delegate that is associated with the current active
// browser. If there is no delegate registered or there is no active browser
// then this will return |nullptr|.
ui::MediaKeysListener::Delegate* GetCurrentMediaKeyDelegate() const;
// Returns the media capture state for the current user at
// |user_index|. (Note that this isn't stable, see implementation comment on
// RequestCaptureState()).
ash::MediaCaptureState GetMediaCaptureStateByIndex(int user_index);
// Handles the media key action for the key with |code|. If there is a
// |GetCurrentMediaKeyDelegate| then the action will be forwarded to the
// delegate. Otherwise, we will forward the action to the extensions API.
void HandleMediaAction(ui::KeyboardCode code);
// Shows a notification informing the user that an app is trying to use the
// camera while the camera hardware privacy switch is turned on. If
// `resurface` is false the notification text will be updated but the
// notification won't be brought to the users attention again.
void ShowCameraOffNotification(const std::string& device_id,
const std::string& device_name,
bool resurface = true);
// Removes the camera notification for device with id `device_id` and returns
// iterator to the next device id in `devices_having_visible_notification_`.
base::flat_set<std::string>::iterator RemoveCameraOffNotificationForDevice(
const std::string& device_id);
void OnGetSourceInfosByCameraHWPrivacySwitchStateChanged(
const std::string& device_id,
cros::mojom::CameraPrivacySwitchState state,
GetSourceInfosResult,
const std::vector<media::VideoCaptureDeviceInfo>& devices);
void OnGetSourceInfosByActiveClientChanged(
const base::flat_set<std::string>& active_device_ids,
GetSourceInfosResult,
const std::vector<media::VideoCaptureDeviceInfo>& devices);
// Returns true if the device (camera) with id `device_id` is being actively
// used by a client.
bool IsDeviceActive(const std::string& device_id);
void OnGetSourceInfosByCameraSWPrivacySwitchStateChanged(
GetSourceInfosResult,
const std::vector<media::VideoCaptureDeviceInfo>& devices);
void OnGetCameraSWPrivacySwitchState(
cros::mojom::CameraPrivacySwitchState state);
raw_ptr<ash::MediaController> media_controller_ = nullptr;
base::flat_map<content::BrowserContext*,
raw_ptr<ui::MediaKeysListener::Delegate, CtnExperimental>>
media_key_delegates_;
// If true then ash will always forward media keys to |this| instead of trying
// to handle them first.
bool is_forcing_media_client_key_handling_ = false;
raw_ptr<content::BrowserContext, DanglingUntriaged> active_context_ = nullptr;
ash::MediaCaptureState vm_media_capture_state_ =
ash::MediaCaptureState::kNone;
// The most recent observed camera privacy switch state.
base::flat_map<std::string, cros::mojom::CameraPrivacySwitchState>
device_id_to_camera_privacy_switch_state_;
int active_camera_client_count_ = 0;
// Most recent time the notification that the camera privacy switch is on was
// shown.
base::TimeTicks camera_switch_notification_shown_timestamp_;
mojo::Remote<video_capture::mojom::VideoSourceProvider>
video_source_provider_remote_;
// Points each CameraClientType to a set which contains the id of the devices
// the CameraClientType is currently using.
base::flat_map<cros::mojom::CameraClientType, base::flat_set<std::string>>
devices_used_by_client_;
// Set of IDs of the camera devices having a visible notification in the
// message center.
base::flat_set<std::string> devices_having_visible_notification_;
// Stores the state of the camera software privacy switch state locally.
cros::mojom::CameraPrivacySwitchState camera_sw_privacy_switch_state_ =
cros::mojom::CameraPrivacySwitchState::UNKNOWN;
ash::PrivacyHubNotification notification_;
// Can be used to disable/enable the display of HW switch toasts.
bool hw_switch_toasts_disabled_ = false;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<MediaClientImpl> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_UI_ASH_MEDIA_CLIENT_MEDIA_CLIENT_IMPL_H_
|