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_device_settings.h" | 5 #include "content/browser/renderer_host/media/media_stream_device_settings.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" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 int render_pid, | 92 int render_pid, |
93 int render_vid, | 93 int render_vid, |
94 const GURL& origin, | 94 const GURL& origin, |
95 const StreamOptions& request_options) | 95 const StreamOptions& request_options) |
96 : MediaStreamRequest(render_pid, render_vid, origin), | 96 : MediaStreamRequest(render_pid, render_vid, origin), |
97 options(request_options), | 97 options(request_options), |
98 posted_task(false) {} | 98 posted_task(false) {} |
99 | 99 |
100 ~MediaStreamDeviceSettingsRequest() {} | 100 ~MediaStreamDeviceSettingsRequest() {} |
101 | 101 |
102 bool IsReadyForView() { | |
103 if (options.audio && | |
104 !devices_full.count(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE)) | |
mflodman_chromium_OOO
2012/08/09 09:57:05
Since it is counting, I would prefer '== 0' rather
no longer working on chromium
2012/08/09 15:54:54
Hope this is fine.
| |
105 return false; | |
106 | |
107 if (options.video && | |
108 !devices_full.count(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE)) | |
109 return false; | |
110 | |
111 // We have got all the requested devices, it is ready if it has not | |
112 // been posted for UI. | |
113 return !posted_task; | |
114 } | |
115 | |
102 // Request options. | 116 // Request options. |
103 StreamOptions options; | 117 StreamOptions options; |
perkj_chrome
2012/08/09 07:31:14
options_
no longer working on chromium
2012/08/09 15:54:54
Done.
| |
104 // Map containing available devices for the requested capture types. | 118 // Map containing available devices for the requested capture types. |
119 // Note, never call devices_full[stream_type] before making sure the entry | |
perkj_chrome
2012/08/09 07:31:14
nit- this comment seems irrelevant in this class
no longer working on chromium
2012/08/09 15:54:54
It is relevant. One of the bug we are fixing is in
| |
120 // has been created. | |
105 DeviceMap devices_full; | 121 DeviceMap devices_full; |
perkj_chrome
2012/08/09 07:31:14
device_full_
no longer working on chromium
2012/08/09 15:54:54
Done.
| |
106 // Whether or not a task was posted to make the call to | 122 // Whether or not a task was posted to make the call to |
107 // RequestMediaAccessPermission, to make sure that we never post twice to it. | 123 // RequestMediaAccessPermission, to make sure that we never post twice to it. |
108 bool posted_task; | 124 bool posted_task; |
perkj_chrome
2012/08/09 07:31:14
posted_task_
no longer working on chromium
2012/08/09 15:54:54
Done.
| |
109 }; | 125 }; |
110 | 126 |
111 namespace { | 127 namespace { |
112 | 128 |
113 // Sends the request to the appropriate WebContents. | 129 // Sends the request to the appropriate WebContents. |
114 void DoDeviceRequest( | 130 void DoDeviceRequest( |
115 const MediaStreamDeviceSettingsRequest& request, | 131 const MediaStreamDeviceSettingsRequest& request, |
116 const content::MediaResponseCallback& callback) { | 132 const content::MediaResponseCallback& callback) { |
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
118 | 134 |
(...skipping 22 matching lines...) Expand all Loading... | |
141 } | 157 } |
142 | 158 |
143 MediaStreamDeviceSettings::~MediaStreamDeviceSettings() { | 159 MediaStreamDeviceSettings::~MediaStreamDeviceSettings() { |
144 STLDeleteValues(&requests_); | 160 STLDeleteValues(&requests_); |
145 } | 161 } |
146 | 162 |
147 void MediaStreamDeviceSettings::RequestCaptureDeviceUsage( | 163 void MediaStreamDeviceSettings::RequestCaptureDeviceUsage( |
148 const std::string& label, int render_process_id, int render_view_id, | 164 const std::string& label, int render_process_id, int render_view_id, |
149 const StreamOptions& request_options, const GURL& security_origin) { | 165 const StreamOptions& request_options, const GURL& security_origin) { |
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
151 | |
152 if (requests_.find(label) != requests_.end()) { | 167 if (requests_.find(label) != requests_.end()) { |
mflodman_chromium_OOO
2012/08/09 09:57:05
This should never happen, can switch to a DCHECK i
no longer working on chromium
2012/08/09 15:54:54
Good point. Done
| |
153 // Request with this id already exists. | 168 // Request with this id already exists. |
154 requester_->SettingsError(label); | 169 requester_->SettingsError(label); |
155 return; | 170 return; |
156 } | 171 } |
157 | 172 |
158 // Create a new request. | 173 // Create a new request. |
159 requests_.insert(std::make_pair(label, new MediaStreamDeviceSettingsRequest( | 174 requests_.insert(std::make_pair(label, new MediaStreamDeviceSettingsRequest( |
160 render_process_id, render_view_id, security_origin, request_options))); | 175 render_process_id, render_view_id, security_origin, request_options))); |
161 } | 176 } |
162 | 177 |
163 void MediaStreamDeviceSettings::RemovePendingCaptureRequest( | 178 void MediaStreamDeviceSettings::RemovePendingCaptureRequest( |
164 const std::string& label) { | 179 const std::string& label) { |
165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
166 | |
167 SettingsRequests::iterator request_it = requests_.find(label); | 181 SettingsRequests::iterator request_it = requests_.find(label); |
168 if (request_it != requests_.end()) { | 182 if (request_it != requests_.end()) { |
169 // Proceed the next pending request for the same page. | |
170 MediaStreamDeviceSettingsRequest* request = request_it->second; | 183 MediaStreamDeviceSettingsRequest* request = request_it->second; |
171 std::string new_label = FindReadyRequestForView(request->render_view_id, | 184 int render_view_id = request->render_view_id; |
172 request->render_process_id); | 185 int render_process_id = request->render_process_id; |
173 if (!new_label.empty()) { | |
174 PostRequestToUi(new_label); | |
175 } | |
176 | |
177 // TODO(xians): Post a cancel request on UI thread to dismiss the infobar | 186 // TODO(xians): Post a cancel request on UI thread to dismiss the infobar |
perkj_chrome
2012/08/09 07:31:14
Is this todo rellevant still? Sounds important.
no longer working on chromium
2012/08/09 15:54:54
No, they are not relevant to the issues we are fix
| |
178 // if request has been sent to the UI. | 187 // if request has been sent to the UI. |
179 // Remove the request from the queue. | 188 // Remove the request from the queue. |
180 requests_.erase(request_it); | 189 requests_.erase(request_it); |
181 delete request; | 190 delete request; |
191 | |
192 // Proceed the next pending request for the same page. | |
193 std::string new_label = FindReadyRequestForView(render_view_id, | |
mflodman_chromium_OOO
2012/08/09 09:57:05
This should only be done if the removed request ha
no longer working on chromium
2012/08/09 15:54:54
Done.
| |
194 render_process_id); | |
195 if (!new_label.empty()) { | |
196 PostRequestToUi(new_label); | |
197 } | |
182 } | 198 } |
183 } | 199 } |
184 | 200 |
185 void MediaStreamDeviceSettings::AvailableDevices( | 201 void MediaStreamDeviceSettings::AvailableDevices( |
186 const std::string& label, | 202 const std::string& label, |
187 MediaStreamType stream_type, | 203 MediaStreamType stream_type, |
188 const StreamDeviceInfoArray& devices) { | 204 const StreamDeviceInfoArray& devices) { |
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
190 | 206 |
191 SettingsRequests::iterator request_it = requests_.find(label); | 207 SettingsRequests::iterator request_it = requests_.find(label); |
192 DCHECK(request_it != requests_.end()); | 208 DCHECK(request_it != requests_.end()); |
193 | |
194 // Add the answer for the request. | 209 // Add the answer for the request. |
195 MediaStreamDeviceSettingsRequest* request = request_it->second; | 210 MediaStreamDeviceSettingsRequest* request = request_it->second; |
196 DCHECK_EQ(request->devices_full.count(stream_type), static_cast<size_t>(0)) << | 211 DCHECK_EQ(request->devices_full.count(stream_type), static_cast<size_t>(0)) << |
197 "This request already has a list of devices for this stream type."; | 212 "This request already has a list of devices for this stream type."; |
198 request->devices_full[stream_type] = devices; | 213 request->devices_full[stream_type] = devices; |
199 | 214 |
200 // Check if we're done. | 215 if (request->IsReadyForView()) { |
201 size_t num_media_requests = 0; | |
202 if (request->options.audio) { | |
203 num_media_requests++; | |
204 } | |
205 if (request->options.video) { | |
206 num_media_requests++; | |
207 } | |
208 | |
209 if (request->devices_full.size() == num_media_requests) { | |
210 // We have all answers needed. | 216 // We have all answers needed. |
211 if (!use_fake_ui_) { | 217 if (!use_fake_ui_) { |
212 // Abort if the task was already posted: wait for it to PostResponse. | 218 // Abort if the task was already posted: wait for it to PostResponse. |
213 if (request->posted_task) { | 219 if (request->posted_task) { |
214 return; | 220 return; |
215 } | 221 } |
216 // Since the UI can only handle one request at the time, verify there | 222 // Since the UI can only handle one request at the time, verify there |
217 // is no unanswered request posted for this view. If there is, this | 223 // is no unanswered request posted for this view. If there is, this |
218 // new request will be handled once we get a response for the first one. | 224 // new request will be handled once we get a response for the first one. |
219 if (IsUiBusy(request->render_view_id, request->render_process_id)) { | 225 if (IsUiBusy(request->render_view_id, request->render_process_id)) { |
220 return; | 226 return; |
221 } | 227 } |
222 PostRequestToUi(label); | 228 PostRequestToUi(label); |
223 } else { | 229 } else { |
224 // Used to fake UI, which is needed for server based testing. | 230 // Used to fake UI, which is needed for server based testing. |
perkj_chrome
2012/08/09 07:31:14
Can this whole else case be moved to a new functio
mflodman_chromium_OOO
2012/08/09 09:57:05
+1, this would be nice to hide.
no longer working on chromium
2012/08/09 15:54:54
Done.
| |
225 // Choose first non-opened device for each media type. | 231 // Choose first non-opened device for each media type. |
226 StreamDeviceInfoArray devices_to_use; | 232 StreamDeviceInfoArray devices_to_use; |
227 for (DeviceMap::iterator it = request->devices_full.begin(); | 233 for (DeviceMap::iterator it = request->devices_full.begin(); |
228 it != request->devices_full.end(); ++it) { | 234 it != request->devices_full.end(); ++it) { |
229 for (StreamDeviceInfoArray::iterator device_it = it->second.begin(); | 235 StreamDeviceInfoArray::iterator device_it = it->second.begin(); |
230 device_it != it->second.end(); ++device_it) { | 236 for (; device_it != it->second.end(); ++device_it) { |
231 if (!device_it->in_use) { | 237 if (!device_it->in_use) { |
232 devices_to_use.push_back(*device_it); | 238 devices_to_use.push_back(*device_it); |
233 break; | 239 break; |
234 } | 240 } |
235 } | 241 } |
236 } | |
237 | 242 |
238 if (!request->devices_full[ | |
239 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE].empty() && | |
240 num_media_requests != devices_to_use.size()) { | |
241 // Not all requested device types were opened. This happens if all | 243 // Not all requested device types were opened. This happens if all |
242 // video capture devices are already opened, |in_use| isn't set for | 244 // video capture devices are already opened, |in_use| isn't set for |
perkj_chrome
2012/08/09 07:31:14
Is this comment valid? Can't you open the same dev
mflodman_chromium_OOO
2012/08/09 09:57:05
This was to be able to open several devices before
no longer working on chromium
2012/08/09 15:54:54
No idea if the comment is valid or not. If will be
| |
243 // audio devices. Allow the first video capture device in the list to be | 245 // audio devices. Allow the first video capture device in the list to be |
244 // opened for this user too. | 246 // opened for this user too. |
245 StreamDeviceInfoArray device_array = | 247 if (it->second.begin() != it->second.end() && |
perkj_chrome
2012/08/09 07:31:14
How about using a temp variable above instead of i
no longer working on chromium
2012/08/09 15:54:54
How about it->second.size() != 0 && device_it == i
| |
246 request->devices_full[ | 248 device_it == it->second.end()) { |
247 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE]; | 249 devices_to_use.push_back(*it->second.begin()); |
248 devices_to_use.push_back(*(device_array.begin())); | 250 } |
249 } | 251 } |
250 | 252 |
251 // Post result and delete request. | 253 // Post result and delete request. |
252 requester_->DevicesAccepted(label, devices_to_use); | 254 requester_->DevicesAccepted(label, devices_to_use); |
253 requests_.erase(request_it); | 255 requests_.erase(request_it); |
254 delete request; | 256 delete request; |
255 } | 257 } |
256 } | 258 } |
257 } | 259 } |
258 | 260 |
259 void MediaStreamDeviceSettings::PostResponse( | 261 void MediaStreamDeviceSettings::PostResponse( |
260 const std::string& label, | 262 const std::string& label, |
261 const content::MediaStreamDevices& devices) { | 263 const content::MediaStreamDevices& devices) { |
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
263 | |
264 SettingsRequests::iterator req = requests_.find(label); | 265 SettingsRequests::iterator req = requests_.find(label); |
265 // Return if the request has been removed. | 266 // Return if the request has been removed. |
266 if (req == requests_.end()) | 267 if (req == requests_.end()) |
267 return; | 268 return; |
268 | 269 |
269 DCHECK(requester_); | 270 DCHECK(requester_); |
270 MediaStreamDeviceSettingsRequest* request = req->second; | 271 MediaStreamDeviceSettingsRequest* request = req->second; |
271 requests_.erase(req); | 272 requests_.erase(req); |
272 | 273 |
273 // Look for queued requests for the same view. If there is a pending request, | 274 // Look for queued requests for the same view. If there is a pending request, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 } | 316 } |
316 | 317 |
317 std::string MediaStreamDeviceSettings::FindReadyRequestForView( | 318 std::string MediaStreamDeviceSettings::FindReadyRequestForView( |
318 int render_view_id, int render_process_id) { | 319 int render_view_id, int render_process_id) { |
319 for (SettingsRequests::iterator it = requests_.begin(); it != requests_.end(); | 320 for (SettingsRequests::iterator it = requests_.begin(); it != requests_.end(); |
320 ++it) { | 321 ++it) { |
321 if (it->second->render_process_id == render_process_id && | 322 if (it->second->render_process_id == render_process_id && |
322 it->second->render_view_id == render_view_id) { | 323 it->second->render_view_id == render_view_id) { |
323 // This request belongs to the given render view. | 324 // This request belongs to the given render view. |
324 MediaStreamDeviceSettingsRequest* request = it->second; | 325 MediaStreamDeviceSettingsRequest* request = it->second; |
325 if (request->options.audio && | 326 if (request->IsReadyForView()) |
326 request->devices_full[ | 327 return it->first; |
327 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE].empty()) { | |
328 // Audio requested, but no devices enumerated yet. Continue to next | |
329 // request. | |
330 continue; | |
331 } | |
332 if (request->options.video && | |
333 request->devices_full[ | |
334 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE].empty()) { | |
335 // Video requested, but no devices enumerated yet. Continue to next | |
336 // request. | |
337 continue; | |
338 } | |
339 // This request belongs to the same view as the treated request and is | |
340 // ready to be requested. Return its label. | |
341 return it->first; | |
342 } | 328 } |
343 } | 329 } |
344 return std::string(); | 330 return std::string(); |
345 } | 331 } |
346 | 332 |
347 void MediaStreamDeviceSettings::PostRequestToUi(const std::string& label) { | 333 void MediaStreamDeviceSettings::PostRequestToUi(const std::string& label) { |
348 MediaStreamDeviceSettingsRequest* request = requests_[label]; | 334 MediaStreamDeviceSettingsRequest* request = requests_[label]; |
349 DCHECK(request != NULL); | 335 DCHECK(request != NULL); |
350 | 336 |
351 request->posted_task = true; | 337 request->posted_task = true; |
(...skipping 14 matching lines...) Expand all Loading... | |
366 content::MediaResponseCallback callback = | 352 content::MediaResponseCallback callback = |
367 base::Bind(&ResponseCallbackHelper::PostResponse, | 353 base::Bind(&ResponseCallbackHelper::PostResponse, |
368 helper.get(), label); | 354 helper.get(), label); |
369 | 355 |
370 BrowserThread::PostTask( | 356 BrowserThread::PostTask( |
371 BrowserThread::UI, FROM_HERE, | 357 BrowserThread::UI, FROM_HERE, |
372 base::Bind(&DoDeviceRequest, *request, callback)); | 358 base::Bind(&DoDeviceRequest, *request, callback)); |
373 } | 359 } |
374 | 360 |
375 } // namespace media_stream | 361 } // namespace media_stream |
OLD | NEW |