OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/media/media_stream_ui_controller.h" | 5 #include "content/browser/renderer_host/media/media_stream_ui_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
13 #include "content/browser/renderer_host/media/media_stream_settings_requester.h" | 13 #include "content/browser/renderer_host/media/media_stream_settings_requester.h" |
14 #include "content/browser/renderer_host/render_view_host_delegate.h" | 14 #include "content/browser/renderer_host/render_view_host_delegate.h" |
15 #include "content/browser/renderer_host/render_view_host_impl.h" | 15 #include "content/browser/renderer_host/render_view_host_impl.h" |
16 #include "content/common/media/media_stream_options.h" | 16 #include "content/common/media/media_stream_options.h" |
17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/content_browser_client.h" | 18 #include "content/public/browser/content_browser_client.h" |
19 #include "content/public/browser/media_observer.h" | 19 #include "content/public/browser/media_observer.h" |
20 #include "content/public/common/media_stream_request.h" | 20 #include "content/public/common/media_stream_request.h" |
21 #include "googleurl/src/gurl.h" | 21 #include "googleurl/src/gurl.h" |
22 | 22 |
23 using content::BrowserThread; | 23 namespace content { |
24 using content::MediaStreamDevice; | |
25 using content::MediaStreamRequest; | |
26 | |
27 namespace { | 24 namespace { |
28 | 25 |
29 // Helper class to handle the callbacks to a MediaStreamUIController instance. | 26 // Helper class to handle the callbacks to a MediaStreamUIController instance. |
30 // This class will make sure that the call to PostResponse is executed on the IO | 27 // This class will make sure that the call to PostResponse is executed on the IO |
31 // thread (and that the instance of MediaStreamUIController still exists). | 28 // thread (and that the instance of MediaStreamUIController still exists). |
32 // This allows us to pass a simple base::Callback object to any class that needs | 29 // This allows us to pass a simple base::Callback object to any class that needs |
33 // to post a response to the MediaStreamUIController object. This logic cannot | 30 // to post a response to the MediaStreamUIController object. This logic cannot |
34 // be implemented inside MediaStreamUIController::PostResponse since that | 31 // be implemented inside MediaStreamUIController::PostResponse since that |
35 // would imply that the WeakPtr<MediaStreamUIController> pointer has been | 32 // would imply that the WeakPtr<MediaStreamUIController> pointer has been |
36 // dereferenced already (which would cause an error in the ThreadChecker before | 33 // dereferenced already (which would cause an error in the ThreadChecker before |
37 // we even get there). | 34 // we even get there). |
38 class ResponseCallbackHelper | 35 class ResponseCallbackHelper |
39 : public base::RefCountedThreadSafe<ResponseCallbackHelper> { | 36 : public base::RefCountedThreadSafe<ResponseCallbackHelper> { |
40 public: | 37 public: |
41 explicit ResponseCallbackHelper( | 38 explicit ResponseCallbackHelper( |
42 base::WeakPtr<content::MediaStreamUIController> controller) | 39 base::WeakPtr<MediaStreamUIController> controller) |
43 : controller_(controller) { | 40 : controller_(controller) { |
44 } | 41 } |
45 | 42 |
46 void PostResponse(const std::string& label, | 43 void PostResponse(const std::string& label, |
47 const content::MediaStreamDevices& devices) { | 44 const MediaStreamDevices& devices) { |
48 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 45 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
49 BrowserThread::PostTask( | 46 BrowserThread::PostTask( |
50 BrowserThread::IO, FROM_HERE, | 47 BrowserThread::IO, FROM_HERE, |
51 base::Bind(&content::MediaStreamUIController::PostResponse, | 48 base::Bind(&MediaStreamUIController::PostResponse, |
52 controller_, label, devices)); | 49 controller_, label, devices)); |
53 return; | 50 return; |
54 } else if (controller_) { | 51 } else if (controller_) { |
55 controller_->PostResponse(label, devices); | 52 controller_->PostResponse(label, devices); |
56 } | 53 } |
57 } | 54 } |
58 | 55 |
59 private: | 56 private: |
60 friend class base::RefCountedThreadSafe<ResponseCallbackHelper>; | 57 friend class base::RefCountedThreadSafe<ResponseCallbackHelper>; |
61 ~ResponseCallbackHelper() {} | 58 ~ResponseCallbackHelper() {} |
62 | 59 |
63 base::WeakPtr<content::MediaStreamUIController> controller_; | 60 base::WeakPtr<MediaStreamUIController> controller_; |
64 | 61 |
65 DISALLOW_COPY_AND_ASSIGN(ResponseCallbackHelper); | 62 DISALLOW_COPY_AND_ASSIGN(ResponseCallbackHelper); |
66 }; | 63 }; |
67 | 64 |
68 } // namespace | 65 } // namespace |
69 | 66 |
70 namespace content { | |
71 | |
72 // UI request contains all data needed to keep track of requests between the | 67 // UI request contains all data needed to keep track of requests between the |
73 // different calls. | 68 // different calls. |
74 class MediaStreamRequestForUI : public content::MediaStreamRequest { | 69 class MediaStreamRequestForUI : public MediaStreamRequest { |
75 public: | 70 public: |
76 MediaStreamRequestForUI( | 71 MediaStreamRequestForUI( |
77 int render_pid, | 72 int render_pid, |
tfarina
2012/10/29 17:41:34
nit: it does fits into the previous line now.
jam
2012/10/29 18:14:45
i'm not sure what you mean? the 4 won't fit in the
tfarina
2012/10/29 18:19:33
I mean this:
MediaStreamRequestForUI(int render_p
jam
2012/10/29 18:25:03
Done.
| |
78 int render_vid, | 73 int render_vid, |
79 const GURL& origin, | 74 const GURL& origin, |
80 const media_stream::StreamOptions& options) | 75 const StreamOptions& options) |
81 : MediaStreamRequest(render_pid, render_vid, origin), | 76 : MediaStreamRequest(render_pid, render_vid, origin), |
82 wait_for_audio(IsAudioMediaType(options.audio_type)), | 77 wait_for_audio(IsAudioMediaType(options.audio_type)), |
83 wait_for_video(IsVideoMediaType(options.video_type)), | 78 wait_for_video(IsVideoMediaType(options.video_type)), |
84 posted_task(false) { | 79 posted_task(false) { |
85 DCHECK(wait_for_audio || wait_for_video); | 80 DCHECK(wait_for_audio || wait_for_video); |
86 } | 81 } |
87 | 82 |
88 ~MediaStreamRequestForUI() {} | 83 ~MediaStreamRequestForUI() {} |
89 | 84 |
90 bool IsRequestReadyForView() const { | 85 bool IsRequestReadyForView() const { |
(...skipping 15 matching lines...) Expand all Loading... | |
106 }; | 101 }; |
107 | 102 |
108 namespace { | 103 namespace { |
109 | 104 |
110 // Sends the request to the appropriate WebContents. | 105 // Sends the request to the appropriate WebContents. |
111 void ProceedMediaAccessPermission(const MediaStreamRequestForUI& request, | 106 void ProceedMediaAccessPermission(const MediaStreamRequestForUI& request, |
112 const MediaResponseCallback& callback) { | 107 const MediaResponseCallback& callback) { |
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
114 | 109 |
115 // Send the permission request to the web contents. | 110 // Send the permission request to the web contents. |
116 content::RenderViewHostImpl* host = | 111 RenderViewHostImpl* host = RenderViewHostImpl::FromID( |
117 content::RenderViewHostImpl::FromID(request.render_process_id, | 112 request.render_process_id, request.render_view_id); |
118 request.render_view_id); | |
119 | 113 |
120 // Tab may have gone away. | 114 // Tab may have gone away. |
121 if (!host || !host->GetDelegate()) { | 115 if (!host || !host->GetDelegate()) { |
122 callback.Run(content::MediaStreamDevices()); | 116 callback.Run(MediaStreamDevices()); |
123 return; | 117 return; |
124 } | 118 } |
125 | 119 |
126 host->GetDelegate()->RequestMediaAccessPermission(&request, callback); | 120 host->GetDelegate()->RequestMediaAccessPermission(&request, callback); |
127 } | 121 } |
128 | 122 |
129 } // namespace | 123 } // namespace |
130 | 124 |
131 MediaStreamUIController::MediaStreamUIController( | 125 MediaStreamUIController::MediaStreamUIController( |
132 media_stream::SettingsRequester* requester) | 126 SettingsRequester* requester) |
tfarina
2012/10/29 17:41:34
fits above.
jam
2012/10/29 18:14:45
Done.
| |
133 : requester_(requester), | 127 : requester_(requester), |
134 use_fake_ui_(false), | 128 use_fake_ui_(false), |
135 weak_ptr_factory_(this) { | 129 weak_ptr_factory_(this) { |
136 DCHECK(requester_); | 130 DCHECK(requester_); |
137 } | 131 } |
138 | 132 |
139 MediaStreamUIController::~MediaStreamUIController() { | 133 MediaStreamUIController::~MediaStreamUIController() { |
140 DCHECK(requests_.empty()); | 134 DCHECK(requests_.empty()); |
141 } | 135 } |
142 | 136 |
143 void MediaStreamUIController::MakeUIRequest( | 137 void MediaStreamUIController::MakeUIRequest( |
144 const std::string& label, int render_process_id, int render_view_id, | 138 const std::string& label, int render_process_id, int render_view_id, |
145 const media_stream::StreamOptions& request_options, | 139 const StreamOptions& request_options, |
146 const GURL& security_origin) { | 140 const GURL& security_origin) { |
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
148 | 142 |
149 // Create a new request. | 143 // Create a new request. |
150 if (!requests_.insert( | 144 if (!requests_.insert( |
151 std::make_pair(label, new MediaStreamRequestForUI( | 145 std::make_pair(label, new MediaStreamRequestForUI( |
152 render_process_id, render_view_id, security_origin, | 146 render_process_id, render_view_id, security_origin, |
153 request_options))).second) { | 147 request_options))).second) { |
154 NOTREACHED(); | 148 NOTREACHED(); |
155 } | 149 } |
(...skipping 20 matching lines...) Expand all Loading... | |
176 | 170 |
177 // Process the next pending request to replace the old infobar on the same | 171 // Process the next pending request to replace the old infobar on the same |
178 // page. | 172 // page. |
179 ProcessNextRequestForView(render_process_id, render_view_id); | 173 ProcessNextRequestForView(render_process_id, render_view_id); |
180 } | 174 } |
181 } | 175 } |
182 | 176 |
183 void MediaStreamUIController::AddAvailableDevicesToRequest( | 177 void MediaStreamUIController::AddAvailableDevicesToRequest( |
184 const std::string& label, | 178 const std::string& label, |
185 MediaStreamDeviceType stream_type, | 179 MediaStreamDeviceType stream_type, |
186 const media_stream::StreamDeviceInfoArray& devices) { | 180 const StreamDeviceInfoArray& devices) { |
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
188 | 182 |
189 UIRequests::const_iterator request_iter = requests_.find(label); | 183 UIRequests::const_iterator request_iter = requests_.find(label); |
190 if (request_iter == requests_.end()) { | 184 if (request_iter == requests_.end()) { |
191 NOTREACHED(); | 185 NOTREACHED(); |
192 return; | 186 return; |
193 } | 187 } |
194 | 188 |
195 // Add the available devices to the request. | 189 // Add the available devices to the request. |
196 MediaStreamRequestForUI* request = request_iter->second; | 190 MediaStreamRequestForUI* request = request_iter->second; |
197 | 191 |
198 // Create the simplified list of devices. | 192 // Create the simplified list of devices. |
199 content::MediaStreamDevices& requested_devices = | 193 MediaStreamDevices& requested_devices = request->devices[stream_type]; |
200 request->devices[stream_type]; | |
201 DCHECK(requested_devices.empty()); | 194 DCHECK(requested_devices.empty()); |
202 for (media_stream::StreamDeviceInfoArray::const_iterator it = devices.begin(); | 195 for (StreamDeviceInfoArray::const_iterator it = devices.begin(); |
203 it != devices.end(); | 196 it != devices.end(); |
204 ++it) { | 197 ++it) { |
205 requested_devices.push_back(MediaStreamDevice(stream_type, | 198 requested_devices.push_back(MediaStreamDevice(stream_type, |
206 it->device_id, | 199 it->device_id, |
207 it->name)); | 200 it->name)); |
208 } | 201 } |
209 | 202 |
210 if (IsAudioMediaType(stream_type)) { | 203 if (IsAudioMediaType(stream_type)) { |
211 DCHECK(request->wait_for_audio); | 204 DCHECK(request->wait_for_audio); |
212 request->wait_for_audio = false; | 205 request->wait_for_audio = false; |
(...skipping 14 matching lines...) Expand all Loading... | |
227 // request to the view if the UI is handling any other request. | 220 // request to the view if the UI is handling any other request. |
228 if (IsUIBusy(request->render_process_id, request->render_view_id)) | 221 if (IsUIBusy(request->render_process_id, request->render_view_id)) |
229 return; | 222 return; |
230 | 223 |
231 PostRequestToUI(label); | 224 PostRequestToUI(label); |
232 } | 225 } |
233 } | 226 } |
234 | 227 |
235 void MediaStreamUIController::PostResponse( | 228 void MediaStreamUIController::PostResponse( |
236 const std::string& label, | 229 const std::string& label, |
237 const content::MediaStreamDevices& devices) { | 230 const MediaStreamDevices& devices) { |
238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
239 UIRequests::iterator request_iter = requests_.find(label); | 232 UIRequests::iterator request_iter = requests_.find(label); |
240 // Return if the request has been removed. | 233 // Return if the request has been removed. |
241 if (request_iter == requests_.end()) | 234 if (request_iter == requests_.end()) |
242 return; | 235 return; |
243 | 236 |
244 DCHECK(requester_); | 237 DCHECK(requester_); |
245 scoped_ptr<MediaStreamRequestForUI> request(request_iter->second); | 238 scoped_ptr<MediaStreamRequestForUI> request(request_iter->second); |
246 requests_.erase(request_iter); | 239 requests_.erase(request_iter); |
247 | 240 |
248 // Look for queued requests for the same view. If there is a pending request, | 241 // Look for queued requests for the same view. If there is a pending request, |
249 // post it for user approval. | 242 // post it for user approval. |
250 ProcessNextRequestForView(request->render_process_id, | 243 ProcessNextRequestForView(request->render_process_id, |
251 request->render_view_id); | 244 request->render_view_id); |
252 | 245 |
253 if (devices.size() > 0) { | 246 if (devices.size() > 0) { |
254 // Build a list of "full" device objects for the accepted devices. | 247 // Build a list of "full" device objects for the accepted devices. |
255 media_stream::StreamDeviceInfoArray device_list; | 248 StreamDeviceInfoArray device_list; |
256 // TODO(xians): figure out if it is all right to hard code in_use to false, | 249 // TODO(xians): figure out if it is all right to hard code in_use to false, |
257 // though DevicesAccepted seems to do so. | 250 // though DevicesAccepted seems to do so. |
258 for (MediaStreamDevices::const_iterator dev = devices.begin(); | 251 for (MediaStreamDevices::const_iterator dev = devices.begin(); |
259 dev != devices.end(); ++dev) { | 252 dev != devices.end(); ++dev) { |
260 device_list.push_back(media_stream::StreamDeviceInfo( | 253 device_list.push_back(StreamDeviceInfo( |
261 dev->type, dev->name, dev->device_id, false)); | 254 dev->type, dev->name, dev->device_id, false)); |
262 } | 255 } |
263 | 256 |
264 requester_->DevicesAccepted(label, device_list); | 257 requester_->DevicesAccepted(label, device_list); |
265 } else { | 258 } else { |
266 requester_->SettingsError(label); | 259 requester_->SettingsError(label); |
267 } | 260 } |
268 } | 261 } |
269 | 262 |
270 void MediaStreamUIController::NotifyUIIndicatorDevicesOpened( | 263 void MediaStreamUIController::NotifyUIIndicatorDevicesOpened( |
271 int render_process_id, | 264 int render_process_id, |
272 int render_view_id, | 265 int render_view_id, |
273 const content::MediaStreamDevices& devices) { | 266 const MediaStreamDevices& devices) { |
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
275 DCHECK(!devices.empty()); | 268 DCHECK(!devices.empty()); |
276 content::MediaObserver* media_observer = | 269 MediaObserver* media_observer = |
277 content::GetContentClient()->browser()->GetMediaObserver(); | 270 GetContentClient()->browser()->GetMediaObserver(); |
278 if (media_observer == NULL) | 271 if (media_observer == NULL) |
279 return; | 272 return; |
280 | 273 |
281 media_observer->OnCaptureDevicesOpened(render_process_id, | 274 media_observer->OnCaptureDevicesOpened(render_process_id, |
282 render_view_id, | 275 render_view_id, |
283 devices); | 276 devices); |
284 } | 277 } |
285 | 278 |
286 void MediaStreamUIController::NotifyUIIndicatorDevicesClosed( | 279 void MediaStreamUIController::NotifyUIIndicatorDevicesClosed( |
287 int render_process_id, | 280 int render_process_id, |
288 int render_view_id, | 281 int render_view_id, |
289 const content::MediaStreamDevices& devices) { | 282 const MediaStreamDevices& devices) { |
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
291 DCHECK(!devices.empty()); | 284 DCHECK(!devices.empty()); |
292 content::MediaObserver* media_observer = | 285 MediaObserver* media_observer = |
293 content::GetContentClient()->browser()->GetMediaObserver(); | 286 GetContentClient()->browser()->GetMediaObserver(); |
294 if (media_observer == NULL) | 287 if (media_observer == NULL) |
295 return; | 288 return; |
296 | 289 |
297 media_observer->OnCaptureDevicesClosed(render_process_id, | 290 media_observer->OnCaptureDevicesClosed(render_process_id, |
298 render_view_id, | 291 render_view_id, |
299 devices); | 292 devices); |
300 } | 293 } |
301 | 294 |
302 void MediaStreamUIController::UseFakeUI() { | 295 void MediaStreamUIController::UseFakeUI() { |
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 NOTREACHED(); | 341 NOTREACHED(); |
349 return; | 342 return; |
350 } | 343 } |
351 MediaStreamRequestForUI* request = request_iter->second; | 344 MediaStreamRequestForUI* request = request_iter->second; |
352 DCHECK(request != NULL); | 345 DCHECK(request != NULL); |
353 | 346 |
354 request->posted_task = true; | 347 request->posted_task = true; |
355 | 348 |
356 scoped_refptr<ResponseCallbackHelper> helper = | 349 scoped_refptr<ResponseCallbackHelper> helper = |
357 new ResponseCallbackHelper(weak_ptr_factory_.GetWeakPtr()); | 350 new ResponseCallbackHelper(weak_ptr_factory_.GetWeakPtr()); |
358 content::MediaResponseCallback callback = | 351 MediaResponseCallback callback = |
359 base::Bind(&ResponseCallbackHelper::PostResponse, | 352 base::Bind(&ResponseCallbackHelper::PostResponse, |
360 helper.get(), label); | 353 helper.get(), label); |
361 | 354 |
362 BrowserThread::PostTask( | 355 BrowserThread::PostTask( |
363 BrowserThread::UI, FROM_HERE, | 356 BrowserThread::UI, FROM_HERE, |
364 base::Bind(&ProceedMediaAccessPermission, *request, callback)); | 357 base::Bind(&ProceedMediaAccessPermission, *request, callback)); |
365 } | 358 } |
366 | 359 |
367 void MediaStreamUIController::PostRequestToFakeUI(const std::string& label) { | 360 void MediaStreamUIController::PostRequestToFakeUI(const std::string& label) { |
368 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
(...skipping 10 matching lines...) Expand all Loading... | |
379 devices_to_use.push_back(it->second.front()); | 372 devices_to_use.push_back(it->second.front()); |
380 } | 373 } |
381 } | 374 } |
382 | 375 |
383 BrowserThread::PostTask( | 376 BrowserThread::PostTask( |
384 BrowserThread::IO, FROM_HERE, | 377 BrowserThread::IO, FROM_HERE, |
385 base::Bind(&MediaStreamUIController::PostResponse, | 378 base::Bind(&MediaStreamUIController::PostResponse, |
386 weak_ptr_factory_.GetWeakPtr(), label, devices_to_use)); | 379 weak_ptr_factory_.GetWeakPtr(), label, devices_to_use)); |
387 } | 380 } |
388 | 381 |
389 } // namespace media_stream | 382 } // namespace content |
OLD | NEW |