| 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 cb3df39d6b39ba73206ca70d492a2a430354a009..990d124df440414409cc28736b54a2edc59db926 100644
|
| --- a/chrome/browser/ui/website_settings/permission_bubble_manager.cc
|
| +++ b/chrome/browser/ui/website_settings/permission_bubble_manager.cc
|
| @@ -10,6 +10,14 @@
|
|
|
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionBubbleManager);
|
|
|
| +namespace {
|
| +
|
| +// This is how many ms to wait to see if there's another permission request
|
| +// we should coalesce.
|
| +const int kPermissionsCoalesceIntervalMs = 400;
|
| +
|
| +}
|
| +
|
| // static
|
| bool PermissionBubbleManager::Enabled() {
|
| return CommandLine::ForCurrentProcess()->HasSwitch(
|
| @@ -18,24 +26,32 @@ bool PermissionBubbleManager::Enabled() {
|
|
|
| void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) {
|
| // Don't re-add an existing request.
|
| - std::vector<PermissionBubbleRequest*>::iterator di;
|
| - for (di = requests_.begin(); di != requests_.end(); di++) {
|
| - if (*di == request)
|
| + std::vector<PermissionBubbleRequest*>::iterator requests_iter;
|
| + for (requests_iter = requests_.begin();
|
| + requests_iter != requests_.end();
|
| + requests_iter++) {
|
| + if (*requests_iter == request)
|
| return;
|
| }
|
|
|
| + if (bubble_showing_) {
|
| + for (requests_iter = queued_requests_.begin();
|
| + requests_iter != queued_requests_.end();
|
| + requests_iter++) {
|
| + if (*requests_iter == request)
|
| + return;
|
| + }
|
| + queued_requests_.push_back(request);
|
| + return;
|
| + }
|
| +
|
| requests_.push_back(request);
|
| // TODO(gbillock): do we need to make default state a request property?
|
| - accept_state_.push_back(true);
|
| + accept_states_.push_back(true);
|
|
|
| - // TODO(gbillock): need significantly more complex logic here to deal
|
| - // with various states of the manager.
|
| -
|
| - if (view_ && !bubble_showing_) {
|
| - view_->SetDelegate(this);
|
| - view_->Show(requests_, accept_state_, customization_mode_);
|
| - bubble_showing_ = true;
|
| - }
|
| + // Start the timer when there is both a view and a request.
|
| + if (view_ && !timer_->IsRunning())
|
| + timer_->Reset();
|
| }
|
|
|
| void PermissionBubbleManager::SetView(PermissionBubbleView* view) {
|
| @@ -45,6 +61,7 @@ void PermissionBubbleManager::SetView(PermissionBubbleView* view) {
|
| if (view_ != NULL) {
|
| view_->SetDelegate(NULL);
|
| view_->Hide();
|
| + bubble_showing_ = false;
|
| }
|
|
|
| view_ = view;
|
| @@ -53,11 +70,10 @@ void PermissionBubbleManager::SetView(PermissionBubbleView* view) {
|
| else
|
| return;
|
|
|
| - if (!requests_.empty())
|
| - bubble_showing_ = true;
|
| -
|
| - if (bubble_showing_)
|
| - view_->Show(requests_, accept_state_, customization_mode_);
|
| + // Even if there are requests queued up, add a short delay before the bubble
|
| + // appears.
|
| + if (!requests_.empty() && !timer_->IsRunning())
|
| + timer_->Reset();
|
| else
|
| view_->Hide();
|
| }
|
| @@ -68,10 +84,24 @@ PermissionBubbleManager::PermissionBubbleManager(
|
| bubble_showing_(false),
|
| view_(NULL),
|
| customization_mode_(false) {
|
| + timer_.reset(new base::Timer(FROM_HERE,
|
| + base::TimeDelta::FromMilliseconds(kPermissionsCoalesceIntervalMs),
|
| + base::Bind(&PermissionBubbleManager::ShowBubble, base::Unretained(this)),
|
| + false));
|
| }
|
|
|
| PermissionBubbleManager::~PermissionBubbleManager() {}
|
|
|
| +void PermissionBubbleManager::DidFinishLoad(
|
| + int64 frame_id,
|
| + const GURL& validated_url,
|
| + bool is_main_frame,
|
| + content::RenderViewHost* render_view_host) {
|
| + // Allows extra time for additional requests to coalesce.
|
| + if (timer_->IsRunning())
|
| + timer_->Reset();
|
| +}
|
| +
|
| void PermissionBubbleManager::WebContentsDestroyed(
|
| content::WebContents* web_contents) {
|
| // Synthetic cancel event if the user closes the WebContents.
|
| @@ -86,53 +116,86 @@ void PermissionBubbleManager::WebContentsDestroyed(
|
| }
|
|
|
| void PermissionBubbleManager::ToggleAccept(int request_index, bool new_value) {
|
| - DCHECK(request_index < static_cast<int>(accept_state_.size()));
|
| - accept_state_[request_index] = new_value;
|
| + DCHECK(request_index < static_cast<int>(accept_states_.size()));
|
| + accept_states_[request_index] = new_value;
|
| }
|
|
|
| void PermissionBubbleManager::SetCustomizationMode() {
|
| customization_mode_ = true;
|
| if (view_)
|
| - view_->Show(requests_, accept_state_, customization_mode_);
|
| + view_->Show(requests_, accept_states_, customization_mode_);
|
| }
|
|
|
| void PermissionBubbleManager::Accept() {
|
| - std::vector<PermissionBubbleRequest*>::iterator di;
|
| - std::vector<bool>::iterator ai;
|
| - for (di = requests_.begin(), ai = accept_state_.begin();
|
| - di != requests_.end(); di++, ai++) {
|
| - if (*ai)
|
| - (*di)->PermissionGranted();
|
| + std::vector<PermissionBubbleRequest*>::iterator requests_iter;
|
| + std::vector<bool>::iterator accepts_iter = accept_states_.begin();
|
| + 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
|
| - (*di)->PermissionDenied();
|
| + (*requests_iter)->PermissionDenied();
|
| }
|
| FinalizeBubble();
|
| }
|
|
|
| void PermissionBubbleManager::Deny() {
|
| - std::vector<PermissionBubbleRequest*>::iterator di;
|
| - for (di = requests_.begin(); di != requests_.end(); di++)
|
| - (*di)->PermissionDenied();
|
| + std::vector<PermissionBubbleRequest*>::iterator requests_iter;
|
| + for (requests_iter = requests_.begin();
|
| + requests_iter != requests_.end();
|
| + requests_iter++) {
|
| + (*requests_iter)->PermissionDenied();
|
| + }
|
| FinalizeBubble();
|
| }
|
|
|
| void PermissionBubbleManager::Closing() {
|
| - std::vector<PermissionBubbleRequest*>::iterator di;
|
| - for (di = requests_.begin(); di != requests_.end(); di++)
|
| - (*di)->Cancelled();
|
| + std::vector<PermissionBubbleRequest*>::iterator requests_iter;
|
| + for (requests_iter = requests_.begin();
|
| + requests_iter != requests_.end();
|
| + requests_iter++) {
|
| + (*requests_iter)->Cancelled();
|
| + }
|
| FinalizeBubble();
|
| }
|
|
|
| +void PermissionBubbleManager::ShowBubble() {
|
| + if (view_ && !bubble_showing_ && requests_.size()) {
|
| + view_->SetDelegate(this);
|
| + view_->Show(requests_, accept_states_, customization_mode_);
|
| + bubble_showing_ = true;
|
| + }
|
| +}
|
| +
|
| void PermissionBubbleManager::FinalizeBubble() {
|
| if (view_) {
|
| view_->SetDelegate(NULL);
|
| view_->Hide();
|
| }
|
|
|
| - std::vector<PermissionBubbleRequest*>::iterator di;
|
| - for (di = requests_.begin(); di != requests_.end(); di++)
|
| - (*di)->RequestFinished();
|
| + std::vector<PermissionBubbleRequest*>::iterator requests_iter;
|
| + for (requests_iter = requests_.begin();
|
| + requests_iter != requests_.end();
|
| + requests_iter++) {
|
| + (*requests_iter)->RequestFinished();
|
| + }
|
| requests_.clear();
|
| - accept_state_.clear();
|
| + accept_states_.clear();
|
| + bubble_showing_ = false;
|
| + if (queued_requests_.size()) {
|
| + requests_ = queued_requests_;
|
| + accept_states_.resize(requests_.size(), true);
|
| + queued_requests_.clear();
|
| + // TODO(leng): Explore other options of showing the next bubble. The
|
| + // advantage of this is that it uses the same code path as the first bubble.
|
| + timer_->Reset();
|
| + }
|
| }
|
|
|
| +void PermissionBubbleManager::SetCoalesceIntervalForTesting(int interval_ms) {
|
| + timer_.reset(new base::Timer(FROM_HERE,
|
| + base::TimeDelta::FromMilliseconds(interval_ms),
|
| + base::Bind(&PermissionBubbleManager::ShowBubble, base::Unretained(this)),
|
| + false));
|
| +}
|
|
|