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