Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: content/browser/renderer_host/media/media_stream_device_settings.cc

Issue 10829190: Resolve the problems where we can leak the system tray UI (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed more relevant problems, ready for review now. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698