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

Unified Diff: chrome/browser/ui/website_settings/permission_bubble_manager.cc

Issue 1610753002: Fixes Permission Bubbles never responding to duplicate requests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix tests and RequestFinishedIncludingDuplicates DCHECK Created 4 years, 11 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 side-by-side diff with in-line comments
Download patch
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);
}

Powered by Google App Engine
This is Rietveld 408576698