Chromium Code Reviews| Index: chrome/browser/ui/website_settings/permission_bubble_manager.cc |
| diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager.cc b/chrome/browser/ui/website_settings/permission_bubble_manager.cc |
| index 9d149df30795ba55d90688c5209ee04acaf9e8b9..9be10274607daab2d443b0acdd6188084d8c19ae 100644 |
| --- a/chrome/browser/ui/website_settings/permission_bubble_manager.cc |
| +++ b/chrome/browser/ui/website_settings/permission_bubble_manager.cc |
| @@ -53,6 +53,17 @@ class CancelledRequest : public PermissionBubbleRequest { |
| GURL origin_; |
| }; |
| +bool IsMessageTextEqual(PermissionBubbleRequest* a, |
| + PermissionBubbleRequest* b) { |
| + if (a == b) |
| + return true; |
| + if (a->GetMessageTextFragment() == b->GetMessageTextFragment() && |
| + a->GetOrigin() == b->GetOrigin()) { |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| } // namespace |
| // PermissionBubbleManager::Observer ------------------------------------------- |
| @@ -83,17 +94,14 @@ PermissionBubbleManager::~PermissionBubbleManager() { |
| if (view_ != NULL) |
| view_->SetDelegate(NULL); |
| - std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
| - for (requests_iter = requests_.begin(); |
| - requests_iter != requests_.end(); |
| - requests_iter++) { |
| - (*requests_iter)->RequestFinished(); |
| - } |
| - for (requests_iter = queued_requests_.begin(); |
| - requests_iter != queued_requests_.end(); |
| - requests_iter++) { |
| - (*requests_iter)->RequestFinished(); |
| - } |
| + for (PermissionBubbleRequest* request : requests_) |
| + request->RequestFinished(); |
| + for (PermissionBubbleRequest* request : queued_requests_) |
| + request->RequestFinished(); |
| + for (PermissionBubbleRequest* request : queued_frame_requests_) |
| + request->RequestFinished(); |
| + for (const auto& entry : duplicate_requests_) |
| + entry.second->RequestFinished(); |
| } |
| void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) { |
| @@ -109,15 +117,18 @@ void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) { |
| .IsSameOriginWith(url::Origin(request->GetOrigin())); |
| // Don't re-add an existing request or one with a duplicate text request. |
| - // TODO(johnme): Instead of dropping duplicate requests, we should queue them |
| - // and eventually run their PermissionGranted/PermissionDenied/Cancelled |
| - // callback (crbug.com/577313). |
| - bool same_object = false; |
| - if (ExistingRequest(request, requests_, &same_object) || |
| - ExistingRequest(request, queued_requests_, &same_object) || |
| - ExistingRequest(request, queued_frame_requests_, &same_object)) { |
| - if (!same_object) |
| - request->RequestFinished(); |
| + PermissionBubbleRequest* existing_request = GetExistingRequest(request); |
| + if (existing_request) { |
| + // |request| is a duplicate. Add it to |duplicate_requests_| unless it's the |
| + // same object as |existing_request| or an existing duplicate. |
| + if (request == existing_request) |
| + return; |
| + auto range = duplicate_requests_.equal_range(existing_request); |
| + for (auto it = range.first; it != range.second; ++it) { |
| + if (request == it->second) |
| + return; |
| + } |
| + duplicate_requests_.insert(std::make_pair(existing_request, request)); |
| return; |
| } |
| @@ -148,18 +159,26 @@ void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) { |
| } |
| void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { |
| - // First look in the queued requests, where we can simply delete the request |
| + // First look in the queued requests, where we can simply finish the request |
| // and go on. |
| std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
| for (requests_iter = queued_requests_.begin(); |
| requests_iter != queued_requests_.end(); |
| requests_iter++) { |
| if (*requests_iter == request) { |
| - (*requests_iter)->RequestFinished(); |
| + RequestFinishedIncludingDuplicates(*requests_iter); |
| queued_requests_.erase(requests_iter); |
| return; |
| } |
| } |
| + for (requests_iter = queued_frame_requests_.begin(); |
| + requests_iter != queued_frame_requests_.end(); requests_iter++) { |
| + if (*requests_iter == request) { |
| + RequestFinishedIncludingDuplicates(*requests_iter); |
| + queued_frame_requests_.erase(requests_iter); |
| + return; |
| + } |
| + } |
| std::vector<bool>::iterator accepts_iter = accept_states_.begin(); |
| for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); |
| @@ -172,7 +191,7 @@ void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { |
| // showing the dialog, or if we are showing it and it can accept the update. |
| bool can_erase = !IsBubbleVisible() || view_->CanAcceptRequestUpdate(); |
| if (can_erase) { |
| - (*requests_iter)->RequestFinished(); |
| + RequestFinishedIncludingDuplicates(*requests_iter); |
| requests_.erase(requests_iter); |
| accept_states_.erase(accepts_iter); |
| @@ -187,11 +206,25 @@ void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { |
| // Cancel the existing request and replace it with a dummy. |
| PermissionBubbleRequest* cancelled_request = |
| new CancelledRequest(*requests_iter); |
| - (*requests_iter)->RequestFinished(); |
| + RequestFinishedIncludingDuplicates(*requests_iter); |
| *requests_iter = cancelled_request; |
| return; |
| } |
| + // Since |request| wasn't found in queued_requests_, queued_frame_requests_ or |
| + // requests_ it must have been marked as a duplicate. We can't search |
| + // duplicate_requests_ by value, so instead use GetExistingRequest to find the |
| + // key (request it was duped against), and iterate through duplicates of that. |
| + PermissionBubbleRequest* existing_request = GetExistingRequest(request); |
| + auto range = duplicate_requests_.equal_range(existing_request); |
| + for (auto it = range.first; it != range.second; ++it) { |
| + if (request == it->second) { |
| + it->second->RequestFinished(); |
| + duplicate_requests_.erase(it); |
| + return; |
| + } |
| + } |
| + |
| NOTREACHED(); // Callers should not cancel requests that are not pending. |
| } |
| @@ -285,10 +318,11 @@ void PermissionBubbleManager::Accept() { |
| for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); |
| requests_iter != requests_.end(); |
| requests_iter++, accepts_iter++) { |
| - if (*accepts_iter) |
| - (*requests_iter)->PermissionGranted(); |
| - else |
| - (*requests_iter)->PermissionDenied(); |
| + if (*accepts_iter) { |
| + PermissionGrantedIncludingDuplicates(*requests_iter); |
| + } else { |
| + PermissionDeniedIncludingDuplicates(*requests_iter); |
| + } |
| } |
| FinalizeBubble(); |
| } |
| @@ -298,7 +332,7 @@ void PermissionBubbleManager::Deny() { |
| for (requests_iter = requests_.begin(); |
| requests_iter != requests_.end(); |
| requests_iter++) { |
| - (*requests_iter)->PermissionDenied(); |
| + PermissionDeniedIncludingDuplicates(*requests_iter); |
| } |
| FinalizeBubble(); |
| } |
| @@ -308,7 +342,7 @@ void PermissionBubbleManager::Closing() { |
| for (requests_iter = requests_.begin(); |
| requests_iter != requests_.end(); |
| requests_iter++) { |
| - (*requests_iter)->Cancelled(); |
| + CancelledIncludingDuplicates(*requests_iter); |
| } |
| FinalizeBubble(); |
| } |
| @@ -372,7 +406,7 @@ void PermissionBubbleManager::FinalizeBubble() { |
| for (requests_iter = requests_.begin(); |
| requests_iter != requests_.end(); |
| requests_iter++) { |
| - (*requests_iter)->RequestFinished(); |
| + RequestFinishedIncludingDuplicates(*requests_iter); |
| } |
| requests_.clear(); |
| accept_states_.clear(); |
| @@ -387,36 +421,29 @@ void PermissionBubbleManager::CancelPendingQueues() { |
| for (requests_iter = queued_requests_.begin(); |
| requests_iter != queued_requests_.end(); |
| requests_iter++) { |
| - (*requests_iter)->RequestFinished(); |
| + RequestFinishedIncludingDuplicates(*requests_iter); |
| } |
| for (requests_iter = queued_frame_requests_.begin(); |
| requests_iter != queued_frame_requests_.end(); |
| requests_iter++) { |
| - (*requests_iter)->RequestFinished(); |
| + RequestFinishedIncludingDuplicates(*requests_iter); |
| } |
| queued_requests_.clear(); |
| queued_frame_requests_.clear(); |
| } |
| -bool PermissionBubbleManager::ExistingRequest( |
| - PermissionBubbleRequest* request, |
| - const std::vector<PermissionBubbleRequest*>& queue, |
| - bool* same_object) { |
| - CHECK(same_object); |
| - *same_object = false; |
| - std::vector<PermissionBubbleRequest*>::const_iterator iter; |
| - for (iter = queue.begin(); iter != queue.end(); iter++) { |
| - if (*iter == request) { |
| - *same_object = true; |
| - return true; |
| - } |
| - if ((*iter)->GetMessageTextFragment() == |
| - request->GetMessageTextFragment() && |
| - (*iter)->GetOrigin() == request->GetOrigin()) { |
| - return true; |
| - } |
| - } |
| - return false; |
| +PermissionBubbleRequest* PermissionBubbleManager::GetExistingRequest( |
| + PermissionBubbleRequest* request) { |
| + for (PermissionBubbleRequest* existing_request : requests_) |
| + if (IsMessageTextEqual(existing_request, request)) |
| + return existing_request; |
| + for (PermissionBubbleRequest* existing_request : queued_requests_) |
| + if (IsMessageTextEqual(existing_request, request)) |
| + return existing_request; |
| + for (PermissionBubbleRequest* existing_request : queued_frame_requests_) |
| + if (IsMessageTextEqual(existing_request, request)) |
| + return existing_request; |
| + return nullptr; |
| } |
| bool PermissionBubbleManager::HasUserGestureRequest( |
| @@ -429,6 +456,45 @@ bool PermissionBubbleManager::HasUserGestureRequest( |
| return false; |
| } |
| +void PermissionBubbleManager::PermissionGrantedIncludingDuplicates( |
| + PermissionBubbleRequest* request) { |
| + DCHECK_EQ(request, GetExistingRequest(request)) |
|
felt
2016/01/28 06:18:14
nit: wondering why this isn't DCHECKing that GetEx
johnme
2016/01/28 15:40:11
I've changed the DCHECK comment to "Only requests
|
| + << "Request must not be a duplicate"; |
| + request->PermissionGranted(); |
| + auto range = duplicate_requests_.equal_range(request); |
| + for (auto it = range.first; it != range.second; ++it) |
| + it->second->PermissionGranted(); |
| +} |
| +void PermissionBubbleManager::PermissionDeniedIncludingDuplicates( |
| + PermissionBubbleRequest* request) { |
| + DCHECK_EQ(request, GetExistingRequest(request)) |
| + << "Request must not be a duplicate"; |
| + request->PermissionDenied(); |
| + auto range = duplicate_requests_.equal_range(request); |
| + for (auto it = range.first; it != range.second; ++it) |
| + it->second->PermissionDenied(); |
| +} |
| +void PermissionBubbleManager::CancelledIncludingDuplicates( |
| + PermissionBubbleRequest* request) { |
| + DCHECK_EQ(request, GetExistingRequest(request)) |
| + << "Request must not be a duplicate"; |
| + request->Cancelled(); |
| + auto range = duplicate_requests_.equal_range(request); |
| + for (auto it = range.first; it != range.second; ++it) |
| + it->second->Cancelled(); |
| +} |
| +void PermissionBubbleManager::RequestFinishedIncludingDuplicates( |
| + PermissionBubbleRequest* request) { |
| + DCHECK_EQ(request, GetExistingRequest(request)) |
| + << "Request must not be a duplicate"; |
| + request->RequestFinished(); |
| + auto range = duplicate_requests_.equal_range(request); |
| + for (auto it = range.first; it != range.second; ++it) |
| + it->second->RequestFinished(); |
| + // Additionally, we can now remove the duplicates. |
| + duplicate_requests_.erase(request); |
| +} |
| + |
| void PermissionBubbleManager::AddObserver(Observer* observer) { |
| observer_list_.AddObserver(observer); |
| } |