OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" | 5 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "chrome/browser/ui/website_settings/permission_bubble_request.h" | 8 #include "chrome/browser/ui/website_settings/permission_bubble_request.h" |
9 #include "chrome/common/chrome_switches.h" | 9 #include "chrome/common/chrome_switches.h" |
| 10 #include "content/public/browser/browser_thread.h" |
10 | 11 |
11 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionBubbleManager); | 12 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionBubbleManager); |
12 | 13 |
13 namespace { | |
14 | |
15 // This is how many ms to wait to see if there's another permission request | |
16 // we should coalesce. | |
17 const int kPermissionsCoalesceIntervalMs = 400; | |
18 | |
19 } | |
20 | |
21 // static | 14 // static |
22 bool PermissionBubbleManager::Enabled() { | 15 bool PermissionBubbleManager::Enabled() { |
23 return CommandLine::ForCurrentProcess()->HasSwitch( | 16 return CommandLine::ForCurrentProcess()->HasSwitch( |
24 switches::kEnablePermissionsBubbles); | 17 switches::kEnablePermissionsBubbles); |
25 } | 18 } |
26 | 19 |
27 PermissionBubbleManager::PermissionBubbleManager( | 20 PermissionBubbleManager::PermissionBubbleManager( |
28 content::WebContents* web_contents) | 21 content::WebContents* web_contents) |
29 : content::WebContentsObserver(web_contents), | 22 : content::WebContentsObserver(web_contents), |
30 bubble_showing_(false), | 23 bubble_showing_(false), |
31 view_(NULL), | 24 view_(NULL), |
32 customization_mode_(false) { | 25 request_url_has_loaded_(false), |
33 timer_.reset(new base::Timer(FROM_HERE, | 26 customization_mode_(false), |
34 base::TimeDelta::FromMilliseconds(kPermissionsCoalesceIntervalMs), | 27 weak_factory_(this) {} |
35 base::Bind(&PermissionBubbleManager::ShowBubble, base::Unretained(this)), | |
36 false)); | |
37 } | |
38 | 28 |
39 PermissionBubbleManager::~PermissionBubbleManager() { | 29 PermissionBubbleManager::~PermissionBubbleManager() { |
40 if (view_ != NULL) | 30 if (view_ != NULL) |
41 view_->SetDelegate(NULL); | 31 view_->SetDelegate(NULL); |
42 | 32 |
43 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 33 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
44 for (requests_iter = requests_.begin(); | 34 for (requests_iter = requests_.begin(); |
45 requests_iter != requests_.end(); | 35 requests_iter != requests_.end(); |
46 requests_iter++) { | 36 requests_iter++) { |
47 (*requests_iter)->RequestFinished(); | 37 (*requests_iter)->RequestFinished(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 | 80 |
91 if (bubble_showing_) { | 81 if (bubble_showing_) { |
92 queued_requests_.push_back(request); | 82 queued_requests_.push_back(request); |
93 return; | 83 return; |
94 } | 84 } |
95 | 85 |
96 requests_.push_back(request); | 86 requests_.push_back(request); |
97 // TODO(gbillock): do we need to make default state a request property? | 87 // TODO(gbillock): do we need to make default state a request property? |
98 accept_states_.push_back(true); | 88 accept_states_.push_back(true); |
99 | 89 |
100 // Start the timer when there is both a view and a request. | 90 if (request->HasUserGesture()) |
101 if (view_ && !timer_->IsRunning()) | 91 ShowBubble(); |
102 timer_->Reset(); | |
103 } | 92 } |
104 | 93 |
105 void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { | 94 void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { |
106 // TODO(gbillock): implement | 95 // TODO(gbillock): implement |
107 NOTREACHED(); | 96 NOTREACHED(); |
108 } | 97 } |
109 | 98 |
110 void PermissionBubbleManager::SetView(PermissionBubbleView* view) { | 99 void PermissionBubbleManager::SetView(PermissionBubbleView* view) { |
111 if (view == view_) | 100 if (view == view_) |
112 return; | 101 return; |
113 | 102 |
114 if (view_ != NULL) { | 103 if (view_ != NULL) { |
115 view_->SetDelegate(NULL); | 104 view_->SetDelegate(NULL); |
116 view_->Hide(); | 105 view_->Hide(); |
117 bubble_showing_ = false; | 106 bubble_showing_ = false; |
118 } | 107 } |
119 | 108 |
120 view_ = view; | 109 view_ = view; |
121 if (view_) | 110 if (view_) |
122 view_->SetDelegate(this); | 111 view_->SetDelegate(this); |
123 else | 112 else |
124 return; | 113 return; |
125 | 114 |
126 // Even if there are requests queued up, add a short delay before the bubble | 115 ShowBubble(); |
127 // appears. | |
128 if (!requests_.empty() && !timer_->IsRunning()) | |
129 timer_->Reset(); | |
130 else | |
131 view_->Hide(); | |
132 } | 116 } |
133 | 117 |
134 void PermissionBubbleManager::DidFinishLoad( | 118 void PermissionBubbleManager::DocumentOnLoadCompletedInMainFrame( |
135 int64 frame_id, | 119 int32 page_id) { |
136 const GURL& validated_url, | 120 request_url_has_loaded_ = true; |
137 bool is_main_frame, | 121 // This is scheduled because while all calls to the browser have been |
138 content::RenderViewHost* render_view_host) { | 122 // issued at DOMContentLoaded, they may be bouncing around in scheduled |
139 // Allows extra time for additional requests to coalesce. | 123 // callbacks finding the UI thread still. This makes sure we allow those |
140 if (timer_->IsRunning()) | 124 // scheduled calls to AddRequest to complete before we show the page-load |
141 timer_->Reset(); | 125 // permissions bubble. |
| 126 // TODO(gbillock): make this bind safe with a weak ptr. |
| 127 content::BrowserThread::PostTask( |
| 128 content::BrowserThread::UI, FROM_HERE, |
| 129 base::Bind(&PermissionBubbleManager::ShowBubble, |
| 130 weak_factory_.GetWeakPtr())); |
142 } | 131 } |
143 | 132 |
144 void PermissionBubbleManager::NavigationEntryCommitted( | 133 void PermissionBubbleManager::NavigationEntryCommitted( |
145 const content::LoadCommittedDetails& details) { | 134 const content::LoadCommittedDetails& details) { |
146 if (!request_url_.is_empty() && | 135 if (!request_url_.is_empty() && |
147 request_url_ != web_contents()->GetLastCommittedURL()) { | 136 request_url_ != web_contents()->GetLastCommittedURL()) { |
148 // Kill off existing bubble and cancel any pending requests. | 137 // Kill off existing bubble and cancel any pending requests. |
149 CancelPendingQueue(); | 138 CancelPendingQueue(); |
150 FinalizeBubble(); | 139 FinalizeBubble(); |
151 } | 140 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 194 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
206 for (requests_iter = requests_.begin(); | 195 for (requests_iter = requests_.begin(); |
207 requests_iter != requests_.end(); | 196 requests_iter != requests_.end(); |
208 requests_iter++) { | 197 requests_iter++) { |
209 (*requests_iter)->Cancelled(); | 198 (*requests_iter)->Cancelled(); |
210 } | 199 } |
211 FinalizeBubble(); | 200 FinalizeBubble(); |
212 } | 201 } |
213 | 202 |
214 void PermissionBubbleManager::ShowBubble() { | 203 void PermissionBubbleManager::ShowBubble() { |
215 if (view_ && !bubble_showing_ && requests_.size()) { | 204 if (view_ && !bubble_showing_ && request_url_has_loaded_ && |
| 205 requests_.size()) { |
216 // Note: this should appear above Show() for testing, since in that | 206 // Note: this should appear above Show() for testing, since in that |
217 // case we may do in-line calling of finalization. | 207 // case we may do in-line calling of finalization. |
218 bubble_showing_ = true; | 208 bubble_showing_ = true; |
219 view_->Show(requests_, accept_states_, customization_mode_); | 209 view_->Show(requests_, accept_states_, customization_mode_); |
220 } | 210 } |
221 } | 211 } |
222 | 212 |
223 void PermissionBubbleManager::FinalizeBubble() { | 213 void PermissionBubbleManager::FinalizeBubble() { |
224 if (view_) | 214 if (view_) |
225 view_->Hide(); | 215 view_->Hide(); |
226 bubble_showing_ = false; | 216 bubble_showing_ = false; |
227 | 217 |
228 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 218 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
229 for (requests_iter = requests_.begin(); | 219 for (requests_iter = requests_.begin(); |
230 requests_iter != requests_.end(); | 220 requests_iter != requests_.end(); |
231 requests_iter++) { | 221 requests_iter++) { |
232 (*requests_iter)->RequestFinished(); | 222 (*requests_iter)->RequestFinished(); |
233 } | 223 } |
234 requests_.clear(); | 224 requests_.clear(); |
235 accept_states_.clear(); | 225 accept_states_.clear(); |
236 if (queued_requests_.size()) { | 226 if (queued_requests_.size()) { |
237 requests_ = queued_requests_; | 227 requests_ = queued_requests_; |
238 accept_states_.resize(requests_.size(), true); | 228 accept_states_.resize(requests_.size(), true); |
239 queued_requests_.clear(); | 229 queued_requests_.clear(); |
240 // TODO(leng): Explore other options of showing the next bubble. The | 230 ShowBubble(); |
241 // advantage of this is that it uses the same code path as the first bubble. | |
242 timer_->Reset(); | |
243 } else { | 231 } else { |
244 request_url_ = GURL(); | 232 request_url_ = GURL(); |
245 } | 233 } |
246 } | 234 } |
247 | 235 |
248 void PermissionBubbleManager::CancelPendingQueue() { | 236 void PermissionBubbleManager::CancelPendingQueue() { |
249 std::vector<PermissionBubbleRequest*>::iterator requests_iter; | 237 std::vector<PermissionBubbleRequest*>::iterator requests_iter; |
250 for (requests_iter = queued_requests_.begin(); | 238 for (requests_iter = queued_requests_.begin(); |
251 requests_iter != queued_requests_.end(); | 239 requests_iter != queued_requests_.end(); |
252 requests_iter++) { | 240 requests_iter++) { |
253 (*requests_iter)->RequestFinished(); | 241 (*requests_iter)->RequestFinished(); |
254 } | 242 } |
255 } | 243 } |
256 | |
257 void PermissionBubbleManager::SetCoalesceIntervalForTesting(int interval_ms) { | |
258 timer_.reset(new base::Timer(FROM_HERE, | |
259 base::TimeDelta::FromMilliseconds(interval_ms), | |
260 base::Bind(&PermissionBubbleManager::ShowBubble, base::Unretained(this)), | |
261 false)); | |
262 } | |
OLD | NEW |