| 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..d08238301fddd1c018e006c8809208e00c6a04db 100644
|
| --- a/chrome/browser/ui/website_settings/permission_bubble_manager.cc
|
| +++ b/chrome/browser/ui/website_settings/permission_bubble_manager.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
|
|
|
| +#include <algorithm>
|
| +
|
| #include "base/command_line.h"
|
| #include "base/metrics/user_metrics_action.h"
|
| #include "build/build_config.h"
|
| @@ -53,6 +55,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 +96,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 +119,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 +161,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 +193,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 +208,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 +320,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 +334,7 @@ void PermissionBubbleManager::Deny() {
|
| for (requests_iter = requests_.begin();
|
| requests_iter != requests_.end();
|
| requests_iter++) {
|
| - (*requests_iter)->PermissionDenied();
|
| + PermissionDeniedIncludingDuplicates(*requests_iter);
|
| }
|
| FinalizeBubble();
|
| }
|
| @@ -308,7 +344,7 @@ void PermissionBubbleManager::Closing() {
|
| for (requests_iter = requests_.begin();
|
| requests_iter != requests_.end();
|
| requests_iter++) {
|
| - (*requests_iter)->Cancelled();
|
| + CancelledIncludingDuplicates(*requests_iter);
|
| }
|
| FinalizeBubble();
|
| }
|
| @@ -372,7 +408,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 +423,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 +458,52 @@ bool PermissionBubbleManager::HasUserGestureRequest(
|
| return false;
|
| }
|
|
|
| +void PermissionBubbleManager::PermissionGrantedIncludingDuplicates(
|
| + PermissionBubbleRequest* request) {
|
| + DCHECK_EQ(request, GetExistingRequest(request))
|
| + << "Only requests in [queued_[frame_]]requests_ can have duplicates";
|
| + 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))
|
| + << "Only requests in [queued_[frame_]]requests_ can have duplicates";
|
| + 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))
|
| + << "Only requests in [queued_[frame_]]requests_ can have duplicates";
|
| + 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) {
|
| + // We can't call GetExistingRequest here, because other entries in requests_,
|
| + // queued_requests_ or queued_frame_requests_ might already have been deleted.
|
| + DCHECK_EQ(1, std::count(requests_.begin(), requests_.end(), request) +
|
| + std::count(queued_requests_.begin(), queued_requests_.end(),
|
| + request) +
|
| + std::count(queued_frame_requests_.begin(),
|
| + queued_frame_requests_.end(), request))
|
| + << "Only requests in [queued_[frame_]]requests_ can have duplicates";
|
| + request->RequestFinished();
|
| + // Beyond this point, |request| has probably been deleted.
|
| + 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);
|
| }
|
|
|