Upload upstream chromium 69.0.3497
[platform/framework/web/chromium-efl.git] / content / browser / renderer_host / media / render_frame_audio_input_stream_factory.cc
1 // Copyright 2018 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 "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/trace_event/trace_event.h"
11 #include "content/browser/browser_main_loop.h"
12 #include "content/browser/media/capture/desktop_capture_device_uma_types.h"
13 #include "content/browser/media/forwarding_audio_stream_factory.h"
14 #include "content/browser/media/media_devices_permission_checker.h"
15 #include "content/browser/renderer_host/media/media_stream_manager.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/media_device_id.h"
18 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "content/public/browser/web_contents_media_capture_id.h"
21 #include "content/public/common/media_stream_request.h"
22 #include "media/audio/audio_device_description.h"
23 #include "media/audio/audio_input_device.h"
24 #include "media/base/audio_parameters.h"
25
26 namespace content {
27
28 namespace {
29
30 void LookUpDeviceAndRespondIfFound(
31     scoped_refptr<AudioInputDeviceManager> audio_input_device_manager,
32     int32_t session_id,
33     base::OnceCallback<void(const MediaStreamDevice&)> response) {
34   DCHECK_CURRENTLY_ON(BrowserThread::IO);
35   const MediaStreamDevice* device =
36       audio_input_device_manager->GetOpenedDeviceById(session_id);
37   if (device) {
38     // Copies device.
39     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
40                             base::BindOnce(std::move(response), *device));
41   }
42 }
43
44 void EnumerateOutputDevices(MediaStreamManager* media_stream_manager,
45                             MediaDevicesManager::EnumerationCallback cb) {
46   DCHECK_CURRENTLY_ON(BrowserThread::IO);
47   MediaDevicesManager::BoolDeviceTypes device_types;
48   device_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
49   media_stream_manager->media_devices_manager()->EnumerateDevices(
50       device_types, std::move(cb));
51 }
52
53 void TranslateDeviceId(const std::string& device_id,
54                        const MediaDeviceSaltAndOrigin& salt_and_origin,
55                        base::RepeatingCallback<void(const std::string&)> cb,
56                        const MediaDeviceEnumeration& device_array) {
57   DCHECK_CURRENTLY_ON(BrowserThread::IO);
58   for (const auto& device_info : device_array[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
59     if (MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
60             salt_and_origin.device_id_salt, salt_and_origin.origin, device_id,
61             device_info.device_id)) {
62       BrowserThread::PostTask(
63           BrowserThread::UI, FROM_HERE,
64           base::BindOnce(std::move(cb), device_info.device_id));
65       break;
66     }
67   }
68   // If we're unable to translate the device id, |cb| will not be run.
69 }
70
71 }  // namespace
72
73 RenderFrameAudioInputStreamFactory::RenderFrameAudioInputStreamFactory(
74     mojom::RendererAudioInputStreamFactoryRequest request,
75     scoped_refptr<AudioInputDeviceManager> audio_input_device_manager,
76     RenderFrameHost* render_frame_host)
77     : binding_(this, std::move(request)),
78       audio_input_device_manager_(std::move(audio_input_device_manager)),
79       render_frame_host_(render_frame_host),
80       weak_ptr_factory_(this) {
81   DCHECK_CURRENTLY_ON(BrowserThread::UI);
82 }
83
84 RenderFrameAudioInputStreamFactory::~RenderFrameAudioInputStreamFactory() {
85   DCHECK_CURRENTLY_ON(BrowserThread::UI);
86 }
87
88 void RenderFrameAudioInputStreamFactory::CreateStream(
89     mojom::RendererAudioInputStreamFactoryClientPtr client,
90     int32_t session_id,
91     const media::AudioParameters& audio_params,
92     bool automatic_gain_control,
93     uint32_t shared_memory_count) {
94   DCHECK_CURRENTLY_ON(BrowserThread::UI);
95   TRACE_EVENT_INSTANT1("audio",
96                        "RenderFrameAudioInputStreamFactory::CreateStream",
97                        TRACE_EVENT_SCOPE_THREAD, "session id", session_id);
98
99   BrowserThread::PostTask(
100       BrowserThread::IO, FROM_HERE,
101       base::BindOnce(
102           &LookUpDeviceAndRespondIfFound, audio_input_device_manager_,
103           session_id,
104           base::BindOnce(&RenderFrameAudioInputStreamFactory::
105                              CreateStreamAfterLookingUpDevice,
106                          weak_ptr_factory_.GetWeakPtr(), std::move(client),
107                          audio_params, automatic_gain_control,
108                          shared_memory_count)));
109 }
110
111 void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
112     mojom::RendererAudioInputStreamFactoryClientPtr client,
113     const media::AudioParameters& audio_params,
114     bool automatic_gain_control,
115     uint32_t shared_memory_count,
116     const MediaStreamDevice& device) {
117   TRACE_EVENT1(
118       "audio",
119       "RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice",
120       "device id", device.id);
121   DCHECK_CURRENTLY_ON(BrowserThread::UI);
122   ForwardingAudioStreamFactory* factory =
123       ForwardingAudioStreamFactory::ForFrame(render_frame_host_);
124   if (!factory)
125     return;
126
127   WebContentsMediaCaptureId capture_id;
128   if (WebContentsMediaCaptureId::Parse(device.id, &capture_id)) {
129     // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker
130     // window, we do not mute the source audio.
131     // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
132     // the source audio.
133     // TODO(qiangchen): Analyze audio constraints to make a duplicating or
134     // diverting decision. It would give web developer more flexibility.
135
136     RenderFrameHost* source_host = RenderFrameHost::FromID(
137         capture_id.render_process_id, capture_id.main_render_frame_id);
138     if (!source_host) {
139       // The source of the capture has already been destroyed, so fail early.
140       return;
141     }
142
143     factory->CreateLoopbackStream(
144         render_frame_host_, source_host, audio_params, shared_memory_count,
145         capture_id.disable_local_echo, std::move(client));
146
147     if (device.type == MEDIA_DESKTOP_AUDIO_CAPTURE)
148       IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
149   } else {
150     factory->CreateInputStream(render_frame_host_, device.id, audio_params,
151                                shared_memory_count, automatic_gain_control,
152                                std::move(client));
153
154     // Only count for captures from desktop media picker dialog and system loop
155     // back audio.
156     if (device.type == MEDIA_DESKTOP_AUDIO_CAPTURE &&
157         (media::AudioDeviceDescription::IsLoopbackDevice(device.id))) {
158       IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
159     }
160   }
161 }
162
163 void RenderFrameAudioInputStreamFactory::AssociateInputAndOutputForAec(
164     const base::UnguessableToken& input_stream_id,
165     const std::string& output_device_id) {
166   DCHECK_CURRENTLY_ON(BrowserThread::UI);
167   if (!IsValidDeviceId(output_device_id))
168     return;
169
170   ForwardingAudioStreamFactory* factory =
171       ForwardingAudioStreamFactory::ForFrame(render_frame_host_);
172   if (!factory)
173     return;
174
175   const int process_id = render_frame_host_->GetProcess()->GetID();
176   const int frame_id = render_frame_host_->GetRoutingID();
177   auto salt_and_origin = GetMediaDeviceSaltAndOrigin(process_id, frame_id);
178
179   // Check permissions for everything but the default device
180   if (!media::AudioDeviceDescription::IsDefaultDevice(output_device_id) &&
181       !MediaDevicesPermissionChecker().CheckPermissionOnUIThread(
182           MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, process_id, frame_id)) {
183     return;
184   }
185
186   if (media::AudioDeviceDescription::IsDefaultDevice(output_device_id) ||
187       media::AudioDeviceDescription::IsCommunicationsDevice(output_device_id)) {
188     factory->AssociateInputAndOutputForAec(input_stream_id, output_device_id);
189   } else {
190     auto* media_stream_manager =
191         BrowserMainLoop::GetInstance()->media_stream_manager();
192     BrowserThread::PostTask(
193         BrowserThread::IO, FROM_HERE,
194         base::BindOnce(
195             EnumerateOutputDevices, media_stream_manager,
196             base::BindRepeating(
197                 &TranslateDeviceId, output_device_id, salt_and_origin,
198                 base::BindRepeating(&RenderFrameAudioInputStreamFactory::
199                                         AssociateTranslatedOutputDeviceForAec,
200                                     weak_ptr_factory_.GetWeakPtr(),
201                                     input_stream_id))));
202   }
203 }
204
205 void RenderFrameAudioInputStreamFactory::AssociateTranslatedOutputDeviceForAec(
206     const base::UnguessableToken& input_stream_id,
207     const std::string& raw_output_device_id) {
208   DCHECK_CURRENTLY_ON(BrowserThread::UI);
209   ForwardingAudioStreamFactory* factory =
210       ForwardingAudioStreamFactory::ForFrame(render_frame_host_);
211   if (factory)
212     factory->AssociateInputAndOutputForAec(input_stream_id,
213                                            raw_output_device_id);
214 }
215
216 }  // namespace content