OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/ui/website_settings/permission_bubble_manager.h" | 5 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/metrics/user_metrics_action.h" | 8 #include "base/metrics/user_metrics_action.h" |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 #include "chrome/browser/ui/website_settings/permission_bubble_request.h" | 10 #include "chrome/browser/ui/website_settings/permission_bubble_request.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 view_(nullptr), | 76 view_(nullptr), |
77 main_frame_has_fully_loaded_(false), | 77 main_frame_has_fully_loaded_(false), |
78 auto_response_for_test_(NONE), | 78 auto_response_for_test_(NONE), |
79 weak_factory_(this) { | 79 weak_factory_(this) { |
80 } | 80 } |
81 | 81 |
82 PermissionBubbleManager::~PermissionBubbleManager() { | 82 PermissionBubbleManager::~PermissionBubbleManager() { |
83 if (view_ != NULL) | 83 if (view_ != NULL) |
84 view_->SetDelegate(NULL); | 84 view_->SetDelegate(NULL); |
85 | 85 |
86 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 86 for (PermissionBubbleRequest* request : requests_) |
87 for (requests_iter = requests_.begin(); | 87 request->RequestFinished(); |
88 requests_iter != requests_.end(); | 88 for (PermissionBubbleRequest* request : queued_requests_) |
89 requests_iter++) { | 89 request->RequestFinished(); |
90 (*requests_iter)->RequestFinished(); | 90 for (PermissionBubbleRequest* request : queued_frame_requests_) |
johnme
2016/01/20 19:29:04
n.b. queued_frame_requests_ was missing here befor
| |
91 } | 91 request->RequestFinished(); |
92 for (requests_iter = queued_requests_.begin(); | 92 for (const auto& entry : duplicate_requests_) |
93 requests_iter != queued_requests_.end(); | 93 entry.second->RequestFinished(); |
94 requests_iter++) { | |
95 (*requests_iter)->RequestFinished(); | |
96 } | |
97 } | 94 } |
98 | 95 |
99 void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) { | 96 void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) { |
100 content::RecordAction(base::UserMetricsAction("PermissionBubbleRequest")); | 97 content::RecordAction(base::UserMetricsAction("PermissionBubbleRequest")); |
101 // TODO(gbillock): is there a race between an early request on a | 98 // TODO(gbillock): is there a race between an early request on a |
102 // newly-navigated page and the to-be-cleaned-up requests on the previous | 99 // newly-navigated page and the to-be-cleaned-up requests on the previous |
103 // page? We should maybe listen to DidStartNavigationToPendingEntry (and | 100 // page? We should maybe listen to DidStartNavigationToPendingEntry (and |
104 // any other renderer-side nav initiations?). Double-check this for | 101 // any other renderer-side nav initiations?). Double-check this for |
105 // correct behavior on interstitials -- we probably want to basically queue | 102 // correct behavior on interstitials -- we probably want to basically queue |
106 // any request for which GetVisibleURL != GetLastCommittedURL. | 103 // any request for which GetVisibleURL != GetLastCommittedURL. |
107 request_url_ = web_contents()->GetLastCommittedURL(); | 104 request_url_ = web_contents()->GetLastCommittedURL(); |
108 bool is_main_frame = | 105 bool is_main_frame = |
109 url::Origin(request_url_) | 106 url::Origin(request_url_) |
110 .IsSameOriginWith(url::Origin(request->GetRequestingHostname())); | 107 .IsSameOriginWith(url::Origin(request->GetRequestingHostname())); |
111 | 108 |
112 // Don't re-add an existing request or one with a duplicate text request. | 109 // Don't re-add an existing request or one with a duplicate text request. |
113 // TODO(johnme): Instead of dropping duplicate requests, we should queue them | 110 PermissionBubbleRequest* existing_request = GetExistingRequest(request); |
114 // and eventually run their PermissionGranted/PermissionDenied/Cancelled | 111 if (existing_request) { |
115 // callback (crbug.com/577313). | 112 // |request| is a duplicate. Add it to |duplicate_requests_| unless it's the |
116 bool same_object = false; | 113 // same object as |existing_request| or an existing duplicate. |
117 if (ExistingRequest(request, requests_, &same_object) || | 114 if (request == existing_request) |
118 ExistingRequest(request, queued_requests_, &same_object) || | 115 return; |
119 ExistingRequest(request, queued_frame_requests_, &same_object)) { | 116 auto range = duplicate_requests_.equal_range(existing_request); |
120 if (!same_object) | 117 for (auto it = range.first; it != range.second; ++it) { |
121 request->RequestFinished(); | 118 if (request == it->second) |
119 return; | |
120 } | |
121 duplicate_requests_.insert(std::make_pair(existing_request, request)); | |
122 return; | 122 return; |
123 } | 123 } |
124 | 124 |
125 if (IsBubbleVisible()) { | 125 if (IsBubbleVisible()) { |
126 if (is_main_frame) { | 126 if (is_main_frame) { |
127 content::RecordAction( | 127 content::RecordAction( |
128 base::UserMetricsAction("PermissionBubbleRequestQueued")); | 128 base::UserMetricsAction("PermissionBubbleRequestQueued")); |
129 queued_requests_.push_back(request); | 129 queued_requests_.push_back(request); |
130 } else { | 130 } else { |
131 content::RecordAction( | 131 content::RecordAction( |
(...skipping 10 matching lines...) Expand all Loading... | |
142 } else { | 142 } else { |
143 content::RecordAction( | 143 content::RecordAction( |
144 base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); | 144 base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); |
145 queued_frame_requests_.push_back(request); | 145 queued_frame_requests_.push_back(request); |
146 } | 146 } |
147 | 147 |
148 ScheduleShowBubble(); | 148 ScheduleShowBubble(); |
149 } | 149 } |
150 | 150 |
151 void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { | 151 void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { |
152 // First look in the queued requests, where we can simply delete the request | 152 // First look in the queued requests, where we can simply finish the request |
153 // and go on. | 153 // and go on. |
154 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 154 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
155 for (requests_iter = queued_requests_.begin(); | 155 for (requests_iter = queued_requests_.begin(); |
156 requests_iter != queued_requests_.end(); | 156 requests_iter != queued_requests_.end(); |
157 requests_iter++) { | 157 requests_iter++) { |
158 if (*requests_iter == request) { | 158 if (*requests_iter == request) { |
159 (*requests_iter)->RequestFinished(); | 159 RequestFinishedIncludingDuplicates(*requests_iter); |
160 queued_requests_.erase(requests_iter); | 160 queued_requests_.erase(requests_iter); |
161 return; | 161 return; |
162 } | 162 } |
163 } | 163 } |
164 for (requests_iter = queued_frame_requests_.begin(); | |
johnme
2016/01/20 19:29:04
n.b. queued_frame_requests_ was missing here befor
| |
165 requests_iter != queued_frame_requests_.end(); requests_iter++) { | |
166 if (*requests_iter == request) { | |
167 RequestFinishedIncludingDuplicates(*requests_iter); | |
168 queued_frame_requests_.erase(requests_iter); | |
169 return; | |
170 } | |
171 } | |
164 | 172 |
165 std::vector<bool>::iterator accepts_iter = accept_states_.begin(); | 173 std::vector<bool>::iterator accepts_iter = accept_states_.begin(); |
166 for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); | 174 for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); |
167 requests_iter != requests_.end(); | 175 requests_iter != requests_.end(); |
168 requests_iter++, accepts_iter++) { | 176 requests_iter++, accepts_iter++) { |
169 if (*requests_iter != request) | 177 if (*requests_iter != request) |
170 continue; | 178 continue; |
171 | 179 |
172 // We can simply erase the current entry in the request table if we aren't | 180 // We can simply erase the current entry in the request table if we aren't |
173 // showing the dialog, or if we are showing it and it can accept the update. | 181 // showing the dialog, or if we are showing it and it can accept the update. |
174 bool can_erase = !IsBubbleVisible() || view_->CanAcceptRequestUpdate(); | 182 bool can_erase = !IsBubbleVisible() || view_->CanAcceptRequestUpdate(); |
175 if (can_erase) { | 183 if (can_erase) { |
176 (*requests_iter)->RequestFinished(); | 184 RequestFinishedIncludingDuplicates(*requests_iter); |
177 requests_.erase(requests_iter); | 185 requests_.erase(requests_iter); |
178 accept_states_.erase(accepts_iter); | 186 accept_states_.erase(accepts_iter); |
179 | 187 |
180 if (IsBubbleVisible()) { | 188 if (IsBubbleVisible()) { |
181 view_->Hide(); | 189 view_->Hide(); |
182 // Will redraw the bubble if it is being shown. | 190 // Will redraw the bubble if it is being shown. |
183 TriggerShowBubble(); | 191 TriggerShowBubble(); |
184 } | 192 } |
185 return; | 193 return; |
186 } | 194 } |
187 | 195 |
188 // Cancel the existing request and replace it with a dummy. | 196 // Cancel the existing request and replace it with a dummy. |
189 PermissionBubbleRequest* cancelled_request = | 197 PermissionBubbleRequest* cancelled_request = |
190 new CancelledRequest(*requests_iter); | 198 new CancelledRequest(*requests_iter); |
191 (*requests_iter)->RequestFinished(); | 199 RequestFinishedIncludingDuplicates(*requests_iter); |
192 *requests_iter = cancelled_request; | 200 *requests_iter = cancelled_request; |
193 return; | 201 return; |
194 } | 202 } |
195 | 203 |
204 // Finally look through the duplicate requests, which can simply be finished. | |
205 PermissionBubbleRequest* existing_request = GetExistingRequest(request); | |
206 auto range = duplicate_requests_.equal_range(existing_request); | |
207 for (auto it = range.first; it != range.second; ++it) { | |
208 if (request == it->second) { | |
209 it->second->RequestFinished(); | |
210 duplicate_requests_.erase(it); | |
211 return; | |
212 } | |
213 } | |
214 | |
196 NOTREACHED(); // Callers should not cancel requests that are not pending. | 215 NOTREACHED(); // Callers should not cancel requests that are not pending. |
197 } | 216 } |
198 | 217 |
199 void PermissionBubbleManager::HideBubble() { | 218 void PermissionBubbleManager::HideBubble() { |
200 // Disengage from the existing view if there is one. | 219 // Disengage from the existing view if there is one. |
201 if (!view_) | 220 if (!view_) |
202 return; | 221 return; |
203 | 222 |
204 view_->SetDelegate(nullptr); | 223 view_->SetDelegate(nullptr); |
205 view_->Hide(); | 224 view_->Hide(); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 DCHECK(request_index < static_cast<int>(accept_states_.size())); | 298 DCHECK(request_index < static_cast<int>(accept_states_.size())); |
280 accept_states_[request_index] = new_value; | 299 accept_states_[request_index] = new_value; |
281 } | 300 } |
282 | 301 |
283 void PermissionBubbleManager::Accept() { | 302 void PermissionBubbleManager::Accept() { |
284 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 303 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
285 std::vector<bool>::iterator accepts_iter = accept_states_.begin(); | 304 std::vector<bool>::iterator accepts_iter = accept_states_.begin(); |
286 for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); | 305 for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); |
287 requests_iter != requests_.end(); | 306 requests_iter != requests_.end(); |
288 requests_iter++, accepts_iter++) { | 307 requests_iter++, accepts_iter++) { |
289 if (*accepts_iter) | 308 if (*accepts_iter) { |
290 (*requests_iter)->PermissionGranted(); | 309 PermissionGrantedIncludingDuplicates(*requests_iter); |
291 else | 310 } else { |
292 (*requests_iter)->PermissionDenied(); | 311 PermissionDeniedIncludingDuplicates(*requests_iter); |
312 } | |
293 } | 313 } |
294 FinalizeBubble(); | 314 FinalizeBubble(); |
295 } | 315 } |
296 | 316 |
297 void PermissionBubbleManager::Deny() { | 317 void PermissionBubbleManager::Deny() { |
298 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 318 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
299 for (requests_iter = requests_.begin(); | 319 for (requests_iter = requests_.begin(); |
300 requests_iter != requests_.end(); | 320 requests_iter != requests_.end(); |
301 requests_iter++) { | 321 requests_iter++) { |
302 (*requests_iter)->PermissionDenied(); | 322 PermissionDeniedIncludingDuplicates(*requests_iter); |
303 } | 323 } |
304 FinalizeBubble(); | 324 FinalizeBubble(); |
305 } | 325 } |
306 | 326 |
307 void PermissionBubbleManager::Closing() { | 327 void PermissionBubbleManager::Closing() { |
308 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 328 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
309 for (requests_iter = requests_.begin(); | 329 for (requests_iter = requests_.begin(); |
310 requests_iter != requests_.end(); | 330 requests_iter != requests_.end(); |
311 requests_iter++) { | 331 requests_iter++) { |
312 (*requests_iter)->Cancelled(); | 332 CancelledIncludingDuplicates(*requests_iter); |
313 } | 333 } |
314 FinalizeBubble(); | 334 FinalizeBubble(); |
315 } | 335 } |
316 | 336 |
317 void PermissionBubbleManager::ScheduleShowBubble() { | 337 void PermissionBubbleManager::ScheduleShowBubble() { |
318 // ::ScheduleShowBubble() will be called again when the main frame will be | 338 // ::ScheduleShowBubble() will be called again when the main frame will be |
319 // loaded. | 339 // loaded. |
320 if (!main_frame_has_fully_loaded_) | 340 if (!main_frame_has_fully_loaded_) |
321 return; | 341 return; |
322 | 342 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
366 } | 386 } |
367 | 387 |
368 void PermissionBubbleManager::FinalizeBubble() { | 388 void PermissionBubbleManager::FinalizeBubble() { |
369 if (view_) | 389 if (view_) |
370 view_->Hide(); | 390 view_->Hide(); |
371 | 391 |
372 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 392 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
373 for (requests_iter = requests_.begin(); | 393 for (requests_iter = requests_.begin(); |
374 requests_iter != requests_.end(); | 394 requests_iter != requests_.end(); |
375 requests_iter++) { | 395 requests_iter++) { |
376 (*requests_iter)->RequestFinished(); | 396 RequestFinishedIncludingDuplicates(*requests_iter); |
377 } | 397 } |
378 requests_.clear(); | 398 requests_.clear(); |
379 accept_states_.clear(); | 399 accept_states_.clear(); |
380 if (queued_requests_.size() || queued_frame_requests_.size()) | 400 if (queued_requests_.size() || queued_frame_requests_.size()) |
381 TriggerShowBubble(); | 401 TriggerShowBubble(); |
382 else | 402 else |
383 request_url_ = GURL(); | 403 request_url_ = GURL(); |
384 } | 404 } |
385 | 405 |
386 void PermissionBubbleManager::CancelPendingQueues() { | 406 void PermissionBubbleManager::CancelPendingQueues() { |
387 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 407 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
388 for (requests_iter = queued_requests_.begin(); | 408 for (requests_iter = queued_requests_.begin(); |
389 requests_iter != queued_requests_.end(); | 409 requests_iter != queued_requests_.end(); |
390 requests_iter++) { | 410 requests_iter++) { |
391 (*requests_iter)->RequestFinished(); | 411 RequestFinishedIncludingDuplicates(*requests_iter); |
392 } | 412 } |
393 for (requests_iter = queued_frame_requests_.begin(); | 413 for (requests_iter = queued_frame_requests_.begin(); |
394 requests_iter != queued_frame_requests_.end(); | 414 requests_iter != queued_frame_requests_.end(); |
395 requests_iter++) { | 415 requests_iter++) { |
396 (*requests_iter)->RequestFinished(); | 416 RequestFinishedIncludingDuplicates(*requests_iter); |
397 } | 417 } |
398 queued_requests_.clear(); | 418 queued_requests_.clear(); |
399 queued_frame_requests_.clear(); | 419 queued_frame_requests_.clear(); |
400 } | 420 } |
401 | 421 |
402 bool PermissionBubbleManager::ExistingRequest( | 422 bool MessageTextIsEqual(PermissionBubbleRequest* a, |
403 PermissionBubbleRequest* request, | 423 PermissionBubbleRequest* b) { |
404 const std::vector<PermissionBubbleRequest*>& queue, | 424 if (a == b) |
405 bool* same_object) { | 425 return true; |
406 CHECK(same_object); | 426 if (a->GetMessageTextFragment() == b->GetMessageTextFragment() && |
407 *same_object = false; | 427 a->GetRequestingHostname() == b->GetRequestingHostname()) { |
408 std::vector<PermissionBubbleRequest*>::const_iterator iter; | 428 return true; |
409 for (iter = queue.begin(); iter != queue.end(); iter++) { | |
410 if (*iter == request) { | |
411 *same_object = true; | |
412 return true; | |
413 } | |
414 if ((*iter)->GetMessageTextFragment() == | |
415 request->GetMessageTextFragment() && | |
416 (*iter)->GetRequestingHostname() == request->GetRequestingHostname()) { | |
417 return true; | |
418 } | |
419 } | 429 } |
420 return false; | 430 return false; |
421 } | 431 } |
422 | 432 |
433 PermissionBubbleRequest* PermissionBubbleManager::GetExistingRequest( | |
434 PermissionBubbleRequest* request) { | |
435 for (PermissionBubbleRequest* existing_request : requests_) | |
436 if (MessageTextIsEqual(existing_request, request)) | |
437 return existing_request; | |
438 for (PermissionBubbleRequest* existing_request : queued_requests_) | |
439 if (MessageTextIsEqual(existing_request, request)) | |
440 return existing_request; | |
441 for (PermissionBubbleRequest* existing_request : queued_frame_requests_) | |
442 if (MessageTextIsEqual(existing_request, request)) | |
443 return existing_request; | |
444 return nullptr; | |
445 } | |
446 | |
423 bool PermissionBubbleManager::HasUserGestureRequest( | 447 bool PermissionBubbleManager::HasUserGestureRequest( |
424 const std::vector<PermissionBubbleRequest*>& queue) { | 448 const std::vector<PermissionBubbleRequest*>& queue) { |
425 std::vector<PermissionBubbleRequest*>::const_iterator iter; | 449 std::vector<PermissionBubbleRequest*>::const_iterator iter; |
426 for (iter = queue.begin(); iter != queue.end(); iter++) { | 450 for (iter = queue.begin(); iter != queue.end(); iter++) { |
427 if ((*iter)->HasUserGesture()) | 451 if ((*iter)->HasUserGesture()) |
428 return true; | 452 return true; |
429 } | 453 } |
430 return false; | 454 return false; |
431 } | 455 } |
432 | 456 |
457 void PermissionBubbleManager::PermissionGrantedIncludingDuplicates( | |
458 PermissionBubbleRequest* request) { | |
459 DCHECK_EQ(request, GetExistingRequest(request)) | |
460 << "Request must not be a duplicate"; | |
461 request->PermissionGranted(); | |
462 auto range = duplicate_requests_.equal_range(request); | |
463 for (auto it = range.first; it != range.second; ++it) | |
464 it->second->PermissionGranted(); | |
465 } | |
466 void PermissionBubbleManager::PermissionDeniedIncludingDuplicates( | |
467 PermissionBubbleRequest* request) { | |
468 DCHECK_EQ(request, GetExistingRequest(request)) | |
469 << "Request must not be a duplicate"; | |
470 request->PermissionDenied(); | |
471 auto range = duplicate_requests_.equal_range(request); | |
472 for (auto it = range.first; it != range.second; ++it) | |
473 it->second->PermissionDenied(); | |
474 } | |
475 void PermissionBubbleManager::CancelledIncludingDuplicates( | |
476 PermissionBubbleRequest* request) { | |
477 DCHECK_EQ(request, GetExistingRequest(request)) | |
478 << "Request must not be a duplicate"; | |
479 request->Cancelled(); | |
480 auto range = duplicate_requests_.equal_range(request); | |
481 for (auto it = range.first; it != range.second; ++it) | |
482 it->second->Cancelled(); | |
483 } | |
484 void PermissionBubbleManager::RequestFinishedIncludingDuplicates( | |
485 PermissionBubbleRequest* request) { | |
486 DCHECK_EQ(request, GetExistingRequest(request)) | |
487 << "Request must not be a duplicate"; | |
488 request->RequestFinished(); | |
489 auto range = duplicate_requests_.equal_range(request); | |
490 for (auto it = range.first; it != range.second; ++it) | |
491 it->second->RequestFinished(); | |
492 // Additionally, we can now remove the duplicates. | |
493 duplicate_requests_.erase(request); | |
494 } | |
495 | |
433 void PermissionBubbleManager::AddObserver(Observer* observer) { | 496 void PermissionBubbleManager::AddObserver(Observer* observer) { |
434 observer_list_.AddObserver(observer); | 497 observer_list_.AddObserver(observer); |
435 } | 498 } |
436 | 499 |
437 void PermissionBubbleManager::RemoveObserver(Observer* observer) { | 500 void PermissionBubbleManager::RemoveObserver(Observer* observer) { |
438 observer_list_.RemoveObserver(observer); | 501 observer_list_.RemoveObserver(observer); |
439 } | 502 } |
440 | 503 |
441 void PermissionBubbleManager::NotifyBubbleAdded() { | 504 void PermissionBubbleManager::NotifyBubbleAdded() { |
442 FOR_EACH_OBSERVER(Observer, observer_list_, OnBubbleAdded()); | 505 FOR_EACH_OBSERVER(Observer, observer_list_, OnBubbleAdded()); |
443 } | 506 } |
444 | 507 |
445 void PermissionBubbleManager::DoAutoResponseForTesting() { | 508 void PermissionBubbleManager::DoAutoResponseForTesting() { |
446 switch (auto_response_for_test_) { | 509 switch (auto_response_for_test_) { |
447 case ACCEPT_ALL: | 510 case ACCEPT_ALL: |
448 Accept(); | 511 Accept(); |
449 break; | 512 break; |
450 case DENY_ALL: | 513 case DENY_ALL: |
451 Deny(); | 514 Deny(); |
452 break; | 515 break; |
453 case DISMISS: | 516 case DISMISS: |
454 Closing(); | 517 Closing(); |
455 break; | 518 break; |
456 case NONE: | 519 case NONE: |
457 NOTREACHED(); | 520 NOTREACHED(); |
458 } | 521 } |
459 } | 522 } |
OLD | NEW |