permission_bubble_manager.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionBubbleManager);
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This is how many ms to wait to see if there's another permission request
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// we should coalesce.
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kPermissionsCoalesceIntervalMs = 400;
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PermissionBubbleManager::Enabled() {
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return CommandLine::ForCurrentProcess()->HasSwitch(
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      switches::kEnablePermissionsBubbles);
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PermissionBubbleManager::PermissionBubbleManager(
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    content::WebContents* web_contents)
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  : content::WebContentsObserver(web_contents),
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bubble_showing_(false),
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    view_(NULL),
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    customization_mode_(false) {
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  timer_.reset(new base::Timer(FROM_HERE,
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(kPermissionsCoalesceIntervalMs),
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&PermissionBubbleManager::ShowBubble, base::Unretained(this)),
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      false));
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PermissionBubbleManager::~PermissionBubbleManager() {
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (view_ != NULL)
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    view_->SetDelegate(NULL);
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<PermissionBubbleRequest*>::iterator requests_iter;
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (requests_iter = requests_.begin();
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       requests_iter != requests_.end();
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       requests_iter++) {
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    (*requests_iter)->RequestFinished();
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (requests_iter = queued_requests_.begin();
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       requests_iter != queued_requests_.end();
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       requests_iter++) {
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    (*requests_iter)->RequestFinished();
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) {
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Don't re-add an existing request or one with a duplicate text request.
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<PermissionBubbleRequest*>::iterator requests_iter;
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (requests_iter = requests_.begin();
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter != requests_.end();
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter++) {
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (*requests_iter == request)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(gbillock): worry about the requesting host name as well.
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if ((*requests_iter)->GetMessageTextFragment() ==
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        request->GetMessageTextFragment()) {
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      request->RequestFinished();
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (requests_iter = queued_requests_.begin();
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       requests_iter != queued_requests_.end();
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       requests_iter++) {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (*requests_iter == request)
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if ((*requests_iter)->GetMessageTextFragment() ==
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        request->GetMessageTextFragment()) {
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      request->RequestFinished();
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (bubble_showing_) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    queued_requests_.push_back(request);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  requests_.push_back(request);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(gbillock): do we need to make default state a request property?
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  accept_states_.push_back(true);
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Start the timer when there is both a view and a request.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (view_ && !timer_->IsRunning())
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    timer_->Reset();
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) {
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(gbillock): implement
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NOTREACHED();
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::SetView(PermissionBubbleView* view) {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (view == view_)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (view_ != NULL) {
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view_->SetDelegate(NULL);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view_->Hide();
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bubble_showing_ = false;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view_ = view;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (view_)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view_->SetDelegate(this);
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Even if there are requests queued up, add a short delay before the bubble
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // appears.
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!requests_.empty() && !timer_->IsRunning())
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    timer_->Reset();
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view_->Hide();
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::DidFinishLoad(
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 frame_id,
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const GURL& validated_url,
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_main_frame,
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderViewHost* render_view_host) {
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Allows extra time for additional requests to coalesce.
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (timer_->IsRunning())
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    timer_->Reset();
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::WebContentsDestroyed(
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::WebContents* web_contents) {
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // If the web contents has been destroyed, do not attempt to notify
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // the requests of any changes - simply close the bubble.
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FinalizeBubble();
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The WebContents is going away; be aggressively paranoid and delete
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ourselves lest other parts of the system attempt to add permission bubbles
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // or use us otherwise during the destruction.
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents->RemoveUserData(UserDataKey());
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // That was the equivalent of "delete this". This object is now destroyed;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // returning from this function is the only safe thing to do.
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::ToggleAccept(int request_index, bool new_value) {
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(request_index < static_cast<int>(accept_states_.size()));
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  accept_states_[request_index] = new_value;
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::SetCustomizationMode() {
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  customization_mode_ = true;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (view_)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view_->Show(requests_, accept_states_, customization_mode_);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::Accept() {
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<PermissionBubbleRequest*>::iterator requests_iter;
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<bool>::iterator accepts_iter = accept_states_.begin();
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin();
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter != requests_.end();
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter++, accepts_iter++) {
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (*accepts_iter)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (*requests_iter)->PermissionGranted();
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (*requests_iter)->PermissionDenied();
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FinalizeBubble();
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::Deny() {
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<PermissionBubbleRequest*>::iterator requests_iter;
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (requests_iter = requests_.begin();
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter != requests_.end();
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter++) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    (*requests_iter)->PermissionDenied();
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FinalizeBubble();
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::Closing() {
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<PermissionBubbleRequest*>::iterator requests_iter;
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (requests_iter = requests_.begin();
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter != requests_.end();
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter++) {
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    (*requests_iter)->Cancelled();
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FinalizeBubble();
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::ShowBubble() {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (view_ && !bubble_showing_ && requests_.size()) {
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Note: this should appear above Show() for testing, since in that
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // case we may do in-line calling of finalization.
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bubble_showing_ = true;
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    view_->Show(requests_, accept_states_, customization_mode_);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::FinalizeBubble() {
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (view_)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view_->Hide();
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bubble_showing_ = false;
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<PermissionBubbleRequest*>::iterator requests_iter;
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (requests_iter = requests_.begin();
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter != requests_.end();
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       requests_iter++) {
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    (*requests_iter)->RequestFinished();
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  requests_.clear();
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  accept_states_.clear();
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (queued_requests_.size()) {
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    requests_ = queued_requests_;
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    accept_states_.resize(requests_.size(), true);
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    queued_requests_.clear();
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(leng):  Explore other options of showing the next bubble.  The
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // advantage of this is that it uses the same code path as the first bubble.
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    timer_->Reset();
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::SetCoalesceIntervalForTesting(int interval_ms) {
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  timer_.reset(new base::Timer(FROM_HERE,
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(interval_ms),
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&PermissionBubbleManager::ShowBubble, base::Unretained(this)),
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      false));
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
235