chrome.bluetoothSocket: clean-up Listen functions
[chromium-blink-merge.git] / content / renderer / media / media_stream_dispatcher.cc
blob0a2da78e8bd95f12f8453220e36af8661fba0758
1 // Copyright (c) 2012 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.
5 #include "content/renderer/media/media_stream_dispatcher.h"
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "content/common/media/media_stream_messages.h"
10 #include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
11 #include "content/renderer/render_thread_impl.h"
12 #include "content/renderer/render_view_impl.h"
13 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
14 #include "url/gurl.h"
16 namespace content {
18 namespace {
20 bool RemoveStreamDeviceFromArray(const StreamDeviceInfo device_info,
21 StreamDeviceInfoArray* array) {
22 for (StreamDeviceInfoArray::iterator device_it = array->begin();
23 device_it != array->end(); ++device_it) {
24 if (StreamDeviceInfo::IsEqual(*device_it, device_info)) {
25 array->erase(device_it);
26 return true;
29 return false;
32 } // namespace
34 // A request is identified by pair (request_id, handler), or ipc_request.
35 // There could be multiple clients making requests and each has its own
36 // request_id sequence.
37 // The ipc_request is garanteed to be unique when it's created in
38 // MediaStreamDispatcher.
39 struct MediaStreamDispatcher::Request {
40 Request(const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler,
41 int request_id,
42 int ipc_request)
43 : handler(handler),
44 request_id(request_id),
45 ipc_request(ipc_request) {
47 bool IsThisRequest(
48 int request_id1,
49 const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler1) {
50 return (request_id1 == request_id && handler1.get() == handler.get());
52 base::WeakPtr<MediaStreamDispatcherEventHandler> handler;
53 int request_id;
54 int ipc_request;
57 struct MediaStreamDispatcher::Stream {
58 Stream() {}
59 ~Stream() {}
60 base::WeakPtr<MediaStreamDispatcherEventHandler> handler;
61 StreamDeviceInfoArray audio_array;
62 StreamDeviceInfoArray video_array;
65 MediaStreamDispatcher::MediaStreamDispatcher(RenderViewImpl* render_view)
66 : RenderViewObserver(render_view),
67 main_loop_(base::MessageLoopProxy::current()),
68 next_ipc_id_(0) {
71 MediaStreamDispatcher::~MediaStreamDispatcher() {}
73 void MediaStreamDispatcher::GenerateStream(
74 int request_id,
75 const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
76 const StreamOptions& components,
77 const GURL& security_origin) {
78 DCHECK(main_loop_->BelongsToCurrentThread());
79 DVLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")";
81 requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
82 Send(new MediaStreamHostMsg_GenerateStream(
83 routing_id(), next_ipc_id_++, components, security_origin,
84 blink::WebUserGestureIndicator::isProcessingUserGesture()));
87 void MediaStreamDispatcher::CancelGenerateStream(
88 int request_id,
89 const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) {
90 DCHECK(main_loop_->BelongsToCurrentThread());
91 DVLOG(1) << "MediaStreamDispatcher::CancelGenerateStream"
92 << ", {request_id = " << request_id << "}";
94 RequestList::iterator it = requests_.begin();
95 for (; it != requests_.end(); ++it) {
96 if (it->IsThisRequest(request_id, event_handler)) {
97 int ipc_request = it->ipc_request;
98 requests_.erase(it);
99 Send(new MediaStreamHostMsg_CancelGenerateStream(routing_id(),
100 ipc_request));
101 break;
106 void MediaStreamDispatcher::StopStreamDevice(
107 const StreamDeviceInfo& device_info) {
108 DVLOG(1) << "MediaStreamDispatcher::StopStreamDevice"
109 << ", {device_id = " << device_info.device.id << "}";
110 // Remove |device_info| from all streams in |label_stream_map_|.
111 bool device_found = false;
112 LabelStreamMap::iterator stream_it = label_stream_map_.begin();
113 while (stream_it != label_stream_map_.end()) {
114 StreamDeviceInfoArray& audio_array = stream_it->second.audio_array;
115 StreamDeviceInfoArray& video_array = stream_it->second.video_array;
117 if (RemoveStreamDeviceFromArray(device_info, &audio_array) ||
118 RemoveStreamDeviceFromArray(device_info, &video_array)) {
119 device_found = true;
120 if (audio_array.empty() && video_array.empty()) {
121 label_stream_map_.erase(stream_it++);
122 continue;
125 ++stream_it;
127 DCHECK(device_found);
129 Send(new MediaStreamHostMsg_StopStreamDevice(routing_id(),
130 device_info.device.id));
133 void MediaStreamDispatcher::EnumerateDevices(
134 int request_id,
135 const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
136 MediaStreamType type,
137 const GURL& security_origin) {
138 DCHECK(main_loop_->BelongsToCurrentThread());
139 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
140 type == MEDIA_DEVICE_VIDEO_CAPTURE ||
141 type == MEDIA_DEVICE_AUDIO_OUTPUT);
142 DVLOG(1) << "MediaStreamDispatcher::EnumerateDevices("
143 << request_id << ")";
145 for (RequestList::iterator it = requests_.begin(); it != requests_.end();
146 ++it) {
147 DCHECK(!it->IsThisRequest(request_id, event_handler));
150 requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
151 Send(new MediaStreamHostMsg_EnumerateDevices(routing_id(),
152 next_ipc_id_++,
153 type,
154 security_origin));
157 void MediaStreamDispatcher::StopEnumerateDevices(
158 int request_id,
159 const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) {
160 DCHECK(main_loop_->BelongsToCurrentThread());
161 DVLOG(1) << "MediaStreamDispatcher::StopEnumerateDevices("
162 << request_id << ")";
163 for (RequestList::iterator it = requests_.begin(); it != requests_.end();
164 ++it) {
165 if (it->IsThisRequest(request_id, event_handler)) {
166 Send(new MediaStreamHostMsg_CancelEnumerateDevices(routing_id(),
167 it->ipc_request));
168 requests_.erase(it);
169 break;
174 void MediaStreamDispatcher::OpenDevice(
175 int request_id,
176 const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
177 const std::string& device_id,
178 MediaStreamType type,
179 const GURL& security_origin) {
180 DCHECK(main_loop_->BelongsToCurrentThread());
181 DVLOG(1) << "MediaStreamDispatcher::OpenDevice(" << request_id << ")";
183 requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
184 Send(new MediaStreamHostMsg_OpenDevice(routing_id(),
185 next_ipc_id_++,
186 device_id,
187 type,
188 security_origin));
191 void MediaStreamDispatcher::CancelOpenDevice(
192 int request_id,
193 const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) {
194 CancelGenerateStream(request_id, event_handler);
197 void MediaStreamDispatcher::CloseDevice(const std::string& label) {
198 DCHECK(main_loop_->BelongsToCurrentThread());
199 DCHECK(!label.empty());
200 DVLOG(1) << "MediaStreamDispatcher::CloseDevice"
201 << ", {label = " << label << "}";
203 LabelStreamMap::iterator it = label_stream_map_.find(label);
204 if (it == label_stream_map_.end())
205 return;
206 label_stream_map_.erase(it);
208 Send(new MediaStreamHostMsg_CloseDevice(routing_id(), label));
211 bool MediaStreamDispatcher::Send(IPC::Message* message) {
212 if (!RenderThread::Get()) {
213 delete message;
214 return false;
217 return RenderThread::Get()->Send(message);
220 bool MediaStreamDispatcher::OnMessageReceived(const IPC::Message& message) {
221 bool handled = true;
222 IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcher, message)
223 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated,
224 OnStreamGenerated)
225 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
226 OnStreamGenerationFailed)
227 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped,
228 OnDeviceStopped)
229 IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated,
230 OnDevicesEnumerated)
231 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened,
232 OnDeviceOpened)
233 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpenFailed,
234 OnDeviceOpenFailed)
235 IPC_MESSAGE_UNHANDLED(handled = false)
236 IPC_END_MESSAGE_MAP()
237 return handled;
240 void MediaStreamDispatcher::OnStreamGenerated(
241 int request_id,
242 const std::string& label,
243 const StreamDeviceInfoArray& audio_array,
244 const StreamDeviceInfoArray& video_array) {
245 DCHECK(main_loop_->BelongsToCurrentThread());
247 for (RequestList::iterator it = requests_.begin();
248 it != requests_.end(); ++it) {
249 Request& request = *it;
250 if (request.ipc_request == request_id) {
251 Stream new_stream;
252 new_stream.handler = request.handler;
253 new_stream.audio_array = audio_array;
254 new_stream.video_array = video_array;
255 label_stream_map_[label] = new_stream;
256 if (request.handler.get()) {
257 request.handler->OnStreamGenerated(
258 request.request_id, label, audio_array, video_array);
259 DVLOG(1) << "MediaStreamDispatcher::OnStreamGenerated("
260 << request.request_id << ", " << label << ")";
262 requests_.erase(it);
263 break;
268 void MediaStreamDispatcher::OnStreamGenerationFailed(
269 int request_id,
270 content::MediaStreamRequestResult result) {
271 DCHECK(main_loop_->BelongsToCurrentThread());
272 for (RequestList::iterator it = requests_.begin();
273 it != requests_.end(); ++it) {
274 Request& request = *it;
275 if (request.ipc_request == request_id) {
276 if (request.handler.get()) {
277 request.handler->OnStreamGenerationFailed(request.request_id, result);
278 DVLOG(1) << "MediaStreamDispatcher::OnStreamGenerationFailed("
279 << request.request_id << ")\n";
281 requests_.erase(it);
282 break;
287 void MediaStreamDispatcher::OnDeviceStopped(
288 const std::string& label,
289 const StreamDeviceInfo& device_info) {
290 DCHECK(main_loop_->BelongsToCurrentThread());
291 DVLOG(1) << "MediaStreamDispatcher::OnDeviceStopped("
292 << "{label = " << label << "})"
293 << ", {device_id = " << device_info.device.id << "})";
295 LabelStreamMap::iterator it = label_stream_map_.find(label);
296 if (it == label_stream_map_.end()) {
297 // This can happen if a user happen stop a the device from JS at the same
298 // time as the underlying media device is unplugged from the system.
299 return;
301 Stream* stream = &it->second;
302 if (IsAudioInputMediaType(device_info.device.type))
303 RemoveStreamDeviceFromArray(device_info, &stream->audio_array);
304 else
305 RemoveStreamDeviceFromArray(device_info, &stream->video_array);
307 if (stream->handler.get())
308 stream->handler->OnDeviceStopped(label, device_info);
310 if (stream->audio_array.empty() && stream->video_array.empty())
311 label_stream_map_.erase(it);
314 void MediaStreamDispatcher::OnDevicesEnumerated(
315 int request_id,
316 const StreamDeviceInfoArray& device_array) {
317 DCHECK(main_loop_->BelongsToCurrentThread());
318 DCHECK_GE(request_id, 0);
320 for (RequestList::iterator it = requests_.begin(); it != requests_.end();
321 ++it) {
322 if (it->ipc_request == request_id && it->handler.get()) {
323 it->handler->OnDevicesEnumerated(it->request_id, device_array);
324 break;
329 void MediaStreamDispatcher::OnDeviceOpened(
330 int request_id,
331 const std::string& label,
332 const StreamDeviceInfo& device_info) {
333 DCHECK(main_loop_->BelongsToCurrentThread());
334 for (RequestList::iterator it = requests_.begin();
335 it != requests_.end(); ++it) {
336 Request& request = *it;
337 if (request.ipc_request == request_id) {
338 Stream new_stream;
339 new_stream.handler = request.handler;
340 if (IsAudioInputMediaType(device_info.device.type)) {
341 new_stream.audio_array.push_back(device_info);
342 } else if (IsVideoMediaType(device_info.device.type)) {
343 new_stream.video_array.push_back(device_info);
344 } else {
345 NOTREACHED();
347 label_stream_map_[label] = new_stream;
348 if (request.handler.get()) {
349 request.handler->OnDeviceOpened(request.request_id, label, device_info);
350 DVLOG(1) << "MediaStreamDispatcher::OnDeviceOpened("
351 << request.request_id << ", " << label << ")";
353 requests_.erase(it);
354 break;
359 void MediaStreamDispatcher::OnDeviceOpenFailed(int request_id) {
360 DCHECK(main_loop_->BelongsToCurrentThread());
361 for (RequestList::iterator it = requests_.begin();
362 it != requests_.end(); ++it) {
363 Request& request = *it;
364 if (request.ipc_request == request_id) {
365 if (request.handler.get()) {
366 request.handler->OnDeviceOpenFailed(request.request_id);
367 DVLOG(1) << "MediaStreamDispatcher::OnDeviceOpenFailed("
368 << request.request_id << ")\n";
370 requests_.erase(it);
371 break;
376 int MediaStreamDispatcher::audio_session_id(const std::string& label,
377 int index) {
378 LabelStreamMap::iterator it = label_stream_map_.find(label);
379 if (it == label_stream_map_.end() ||
380 it->second.audio_array.size() <= static_cast<size_t>(index)) {
381 return StreamDeviceInfo::kNoId;
383 return it->second.audio_array[index].session_id;
386 bool MediaStreamDispatcher::IsStream(const std::string& label) {
387 return label_stream_map_.find(label) != label_stream_map_.end();
390 int MediaStreamDispatcher::video_session_id(const std::string& label,
391 int index) {
392 LabelStreamMap::iterator it = label_stream_map_.find(label);
393 if (it == label_stream_map_.end() ||
394 it->second.video_array.size() <= static_cast<size_t>(index)) {
395 return StreamDeviceInfo::kNoId;
397 return it->second.video_array[index].session_id;
400 } // namespace content