1 // Copyright 2016 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/ui/webui/settings/settings_media_devices_selection_handler.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/macros.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/prefs/pref_service.h"
17
18 #if BUILDFLAG(ENABLE_EXTENSIONS)
19 #include "extensions/strings/grit/extensions_strings.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #endif
22
23 namespace {
24
25 const char kAudio[] = "mic";
26 const char kVideo[] = "camera";
27
28 } // namespace
29
30 namespace settings {
31
MediaDevicesSelectionHandler(Profile * profile)32 MediaDevicesSelectionHandler::MediaDevicesSelectionHandler(Profile* profile)
33 : profile_(profile), observer_(this) {
34 }
35
~MediaDevicesSelectionHandler()36 MediaDevicesSelectionHandler::~MediaDevicesSelectionHandler() {
37 }
38
OnJavascriptAllowed()39 void MediaDevicesSelectionHandler::OnJavascriptAllowed() {
40 // Register to the device observer list to get up-to-date device lists.
41 observer_.Add(MediaCaptureDevicesDispatcher::GetInstance());
42 }
43
OnJavascriptDisallowed()44 void MediaDevicesSelectionHandler::OnJavascriptDisallowed() {
45 observer_.RemoveAll();
46 }
47
RegisterMessages()48 void MediaDevicesSelectionHandler::RegisterMessages() {
49 web_ui()->RegisterMessageCallback(
50 "getDefaultCaptureDevices",
51 base::BindRepeating(
52 &MediaDevicesSelectionHandler::GetDefaultCaptureDevices,
53 base::Unretained(this)));
54 web_ui()->RegisterMessageCallback(
55 "setDefaultCaptureDevice",
56 base::BindRepeating(
57 &MediaDevicesSelectionHandler::SetDefaultCaptureDevice,
58 base::Unretained(this)));
59 }
60
OnUpdateAudioDevices(const blink::MediaStreamDevices & devices)61 void MediaDevicesSelectionHandler::OnUpdateAudioDevices(
62 const blink::MediaStreamDevices& devices) {
63 UpdateDevicesMenu(AUDIO, devices);
64 }
65
OnUpdateVideoDevices(const blink::MediaStreamDevices & devices)66 void MediaDevicesSelectionHandler::OnUpdateVideoDevices(
67 const blink::MediaStreamDevices& devices) {
68 UpdateDevicesMenu(VIDEO, devices);
69 }
70
GetDefaultCaptureDevices(const base::ListValue * args)71 void MediaDevicesSelectionHandler::GetDefaultCaptureDevices(
72 const base::ListValue* args) {
73 DCHECK_EQ(1U, args->GetSize());
74 std::string type;
75 if (!args->GetString(0, &type)) {
76 NOTREACHED();
77 return;
78 }
79 DCHECK(!type.empty());
80
81 if (type == kAudio)
82 UpdateDevicesMenuForType(AUDIO);
83 else if (type == kVideo)
84 UpdateDevicesMenuForType(VIDEO);
85 }
86
SetDefaultCaptureDevice(const base::ListValue * args)87 void MediaDevicesSelectionHandler::SetDefaultCaptureDevice(
88 const base::ListValue* args) {
89 DCHECK_EQ(2U, args->GetSize());
90 std::string type, device;
91 if (!(args->GetString(0, &type) && args->GetString(1, &device))) {
92 NOTREACHED();
93 return;
94 }
95
96 DCHECK(!type.empty());
97 DCHECK(!device.empty());
98
99 PrefService* prefs = profile_->GetPrefs();
100 if (type == kAudio)
101 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
102 else if (type == kVideo)
103 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
104 else
105 NOTREACHED();
106 }
107
UpdateDevicesMenu(DeviceType type,const blink::MediaStreamDevices & devices)108 void MediaDevicesSelectionHandler::UpdateDevicesMenu(
109 DeviceType type,
110 const blink::MediaStreamDevices& devices) {
111 AllowJavascript();
112
113 // Get the default device unique id from prefs.
114 PrefService* prefs = profile_->GetPrefs();
115 std::string default_device;
116 std::string device_type;
117 switch (type) {
118 case AUDIO:
119 default_device = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
120 device_type = kAudio;
121 break;
122 case VIDEO:
123 default_device = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
124 device_type = kVideo;
125 break;
126 }
127
128 // Build the list of devices to send to JS.
129 std::string default_id;
130 base::ListValue device_list;
131 for (size_t i = 0; i < devices.size(); ++i) {
132 std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue());
133 entry->SetString("name", GetDeviceDisplayName(devices[i]));
134 entry->SetString("id", devices[i].id);
135 device_list.Append(std::move(entry));
136 if (devices[i].id == default_device)
137 default_id = default_device;
138 }
139
140 // Use the first device as the default device if the preferred default device
141 // does not exist in the OS.
142 if (!devices.empty() && default_id.empty())
143 default_id = devices[0].id;
144
145 base::Value default_value(default_id);
146 base::Value type_value(device_type);
147 FireWebUIListener("updateDevicesMenu", type_value, device_list,
148 default_value);
149 }
150
GetDeviceDisplayName(const blink::MediaStreamDevice & device) const151 std::string MediaDevicesSelectionHandler::GetDeviceDisplayName(
152 const blink::MediaStreamDevice& device) const {
153 std::string facing_info;
154
155 #if BUILDFLAG(ENABLE_EXTENSIONS)
156 switch (device.video_facing) {
157 case media::VideoFacingMode::MEDIA_VIDEO_FACING_USER:
158 facing_info = l10n_util::GetStringUTF8(IDS_CAMERA_FACING_USER);
159 break;
160 case media::VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT:
161 facing_info = l10n_util::GetStringUTF8(IDS_CAMERA_FACING_ENVIRONMENT);
162 break;
163 case media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE:
164 break;
165 case media::VideoFacingMode::NUM_MEDIA_VIDEO_FACING_MODES:
166 NOTREACHED();
167 break;
168 }
169 #endif
170
171 if (facing_info.empty())
172 return device.name;
173 return device.name + " " + facing_info;
174 }
175
UpdateDevicesMenuForType(DeviceType type)176 void MediaDevicesSelectionHandler::UpdateDevicesMenuForType(DeviceType type) {
177 blink::MediaStreamDevices devices;
178 switch (type) {
179 case AUDIO:
180 devices = MediaCaptureDevicesDispatcher::GetInstance()->
181 GetAudioCaptureDevices();
182 break;
183 case VIDEO:
184 devices = MediaCaptureDevicesDispatcher::GetInstance()->
185 GetVideoCaptureDevices();
186 break;
187 }
188
189 UpdateDevicesMenu(type, devices);
190 }
191
192 } // namespace settings
193