1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/download/download_request_limiter.h"
8 #include "base/run_loop.h"
9 #include "chrome/browser/content_settings/host_content_settings_map.h"
10 #include "chrome/browser/download/download_request_infobar_delegate.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "content/public/browser/navigation_controller.h"
16 #include "content/public/browser/web_contents.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using content::WebContents;
21 class DownloadRequestLimiterTest;
23 class FakePermissionBubbleView : public PermissionBubbleView {
25 explicit FakePermissionBubbleView(DownloadRequestLimiterTest *test)
26 : test_(test), delegate_(NULL) {}
28 virtual ~FakePermissionBubbleView() {
30 delegate_->SetView(NULL);
38 // PermissionBubbleView:
39 virtual void SetDelegate(Delegate* delegate) OVERRIDE {
44 const std::vector<PermissionBubbleRequest*>& requests,
45 const std::vector<bool>& accept_state,
46 bool customization_mode) OVERRIDE;
48 virtual bool CanAcceptRequestUpdate() OVERRIDE { return false; }
50 virtual void Hide() OVERRIDE {}
53 DownloadRequestLimiterTest* test_;
57 class DownloadRequestLimiterTest : public ChromeRenderViewHostTestHarness {
65 virtual void SetUp() {
66 ChromeRenderViewHostTestHarness::SetUp();
67 InfoBarService::CreateForWebContents(web_contents());
69 PermissionBubbleManager::CreateForWebContents(web_contents());
70 view_.reset(new FakePermissionBubbleView(this));
71 PermissionBubbleManager* manager =
72 PermissionBubbleManager::FromWebContents(web_contents());
73 manager->SetView(view_.get());
74 manager->SetCoalesceIntervalForTesting(0);
76 testing_action_ = ACCEPT;
77 ask_allow_count_ = cancel_count_ = continue_count_ = 0;
78 download_request_limiter_ = new DownloadRequestLimiter();
79 fake_create_callback_ = base::Bind(
80 &DownloadRequestLimiterTest::FakeCreate, base::Unretained(this));
81 DownloadRequestInfoBarDelegate::SetCallbackForTesting(
82 &fake_create_callback_);
83 content_settings_ = new HostContentSettingsMap(profile_.GetPrefs(), false);
84 DownloadRequestLimiter::SetContentSettingsForTesting(
85 content_settings_.get());
89 return testing_action_;
97 InfoBarService* infobar_service,
98 base::WeakPtr<DownloadRequestLimiter::TabDownloadState> host) {
100 switch (testing_action_) {
112 virtual void TearDown() {
113 content_settings_->ShutdownOnUIThread();
114 content_settings_ = NULL;
116 ChromeRenderViewHostTestHarness::TearDown();
119 virtual void UnsetDelegate() {
120 DownloadRequestInfoBarDelegate::SetCallbackForTesting(NULL);
124 CanDownloadFor(web_contents());
127 void CanDownloadFor(WebContents* web_contents) {
128 download_request_limiter_->CanDownloadImpl(
131 "GET", // request method
132 base::Bind(&DownloadRequestLimiterTest::ContinueDownload,
133 base::Unretained(this)));
134 base::RunLoop().RunUntilIdle();
137 void OnUserGesture() {
138 OnUserGestureFor(web_contents());
141 void OnUserGestureFor(WebContents* web_contents) {
142 DownloadRequestLimiter::TabDownloadState* state =
143 download_request_limiter_->GetDownloadState(web_contents, NULL, false);
145 state->DidGetUserGesture();
148 void AboutToNavigateRenderView() {
150 DownloadRequestLimiter::TabDownloadState* state =
151 download_request_limiter_->GetDownloadState(
152 web_contents(), NULL, false);
153 state->AboutToNavigateRenderView(NULL);
156 void ExpectAndResetCounts(
157 int expect_continues,
161 EXPECT_EQ(expect_continues, continue_count_) << "line " << line;
162 EXPECT_EQ(expect_cancels, cancel_count_) << "line " << line;
163 EXPECT_EQ(expect_asks, ask_allow_count_) << "line " << line;
164 continue_count_ = cancel_count_ = ask_allow_count_ = 0;
168 void ContinueDownload(bool allow) {
176 void SetHostContentSetting(WebContents* contents, ContentSetting setting) {
177 content_settings_->SetContentSetting(
178 ContentSettingsPattern::FromURL(contents->GetURL()),
179 ContentSettingsPattern::Wildcard(),
180 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
185 scoped_refptr<DownloadRequestLimiter> download_request_limiter_;
187 // The action that FakeCreate() should take.
188 TestingAction testing_action_;
190 // Number of times ContinueDownload was invoked.
193 // Number of times CancelDownload was invoked.
196 // Number of times ShouldAllowDownload was invoked.
197 int ask_allow_count_;
199 scoped_refptr<HostContentSettingsMap> content_settings_;
202 DownloadRequestInfoBarDelegate::FakeCreateCallback fake_create_callback_;
203 TestingProfile profile_;
204 scoped_ptr<FakePermissionBubbleView> view_;
207 void FakePermissionBubbleView::Show(
208 const std::vector<PermissionBubbleRequest*>& requests,
209 const std::vector<bool>& accept_state,
210 bool customization_mode) {
212 int action = test_->GetAction();
213 if (action == DownloadRequestLimiterTest::ACCEPT) {
215 } else if (action == DownloadRequestLimiterTest::CANCEL) {
217 } else if (action == DownloadRequestLimiterTest::WAIT) {
220 delegate_->Closing();
224 TEST_F(DownloadRequestLimiterTest,
225 DownloadRequestLimiter_Allow) {
226 // All tabs should initially start at ALLOW_ONE_DOWNLOAD.
227 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
228 download_request_limiter_->GetDownloadStatus(web_contents()));
230 // Ask if the tab can do a download. This moves to PROMPT_BEFORE_DOWNLOAD.
232 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
233 download_request_limiter_->GetDownloadStatus(web_contents()));
234 // We should have been told we can download.
235 ExpectAndResetCounts(1, 0, 0, __LINE__);
237 // Ask again. This triggers asking the delegate for allow/disallow.
238 testing_action_ = ACCEPT;
240 // This should ask us if the download is allowed.
241 // We should have been told we can download.
242 ExpectAndResetCounts(1, 0, 1, __LINE__);
243 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
244 download_request_limiter_->GetDownloadStatus(web_contents()));
246 // Ask again and make sure continue is invoked.
248 // The state is at allow_all, which means the delegate shouldn't be asked.
249 // We should have been told we can download.
250 ExpectAndResetCounts(1, 0, 0, __LINE__);
251 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
252 download_request_limiter_->GetDownloadStatus(web_contents()));
255 TEST_F(DownloadRequestLimiterTest,
256 DownloadRequestLimiter_ResetOnNavigation) {
257 NavigateAndCommit(GURL("http://foo.com/bar"));
259 // Do two downloads, allowing the second so that we end up with allow all.
261 ExpectAndResetCounts(1, 0, 0, __LINE__);
262 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
263 download_request_limiter_->GetDownloadStatus(web_contents()));
265 testing_action_ = ACCEPT;
267 ExpectAndResetCounts(1, 0, 1, __LINE__);
268 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
269 download_request_limiter_->GetDownloadStatus(web_contents()));
271 // Navigate to a new URL with the same host, which shouldn't reset the allow
273 NavigateAndCommit(GURL("http://foo.com/bar2"));
275 ExpectAndResetCounts(1, 0, 0, __LINE__);
276 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
277 download_request_limiter_->GetDownloadStatus(web_contents()));
279 // Do a user gesture, because we're at allow all, this shouldn't change the
282 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
283 download_request_limiter_->GetDownloadStatus(web_contents()));
285 // Navigate to a completely different host, which should reset the state.
286 NavigateAndCommit(GURL("http://fooey.com"));
287 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
288 download_request_limiter_->GetDownloadStatus(web_contents()));
290 // Do two downloads, allowing the second so that we end up with allow all.
292 ExpectAndResetCounts(1, 0, 0, __LINE__);
293 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
294 download_request_limiter_->GetDownloadStatus(web_contents()));
296 testing_action_ = CANCEL;
298 ExpectAndResetCounts(0, 1, 1, __LINE__);
299 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
300 download_request_limiter_->GetDownloadStatus(web_contents()));
302 // Navigate to a new URL with the same host, which shouldn't reset the allow
304 NavigateAndCommit(GURL("http://fooey.com/bar2"));
306 ExpectAndResetCounts(0, 1, 0, __LINE__);
307 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
308 download_request_limiter_->GetDownloadStatus(web_contents()));
311 TEST_F(DownloadRequestLimiterTest,
312 DownloadRequestLimiter_ResetOnUserGesture) {
313 NavigateAndCommit(GURL("http://foo.com/bar"));
315 // Do one download, which should change to prompt before download.
317 ExpectAndResetCounts(1, 0, 0, __LINE__);
318 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
319 download_request_limiter_->GetDownloadStatus(web_contents()));
321 // Do a user gesture, which should reset back to allow one.
323 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
324 download_request_limiter_->GetDownloadStatus(web_contents()));
326 // Ask twice, which triggers calling the delegate. Don't allow the download
327 // so that we end up with not allowed.
329 ExpectAndResetCounts(1, 0, 0, __LINE__);
330 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
331 download_request_limiter_->GetDownloadStatus(web_contents()));
333 testing_action_ = CANCEL;
335 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
336 download_request_limiter_->GetDownloadStatus(web_contents()));
337 ExpectAndResetCounts(0, 1, 1, __LINE__);
339 // A user gesture now should NOT change the state.
341 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
342 download_request_limiter_->GetDownloadStatus(web_contents()));
343 // And make sure we really can't download.
345 ExpectAndResetCounts(0, 1, 0, __LINE__);
346 // And the state shouldn't have changed.
347 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
348 download_request_limiter_->GetDownloadStatus(web_contents()));
351 TEST_F(DownloadRequestLimiterTest,
352 DownloadRequestLimiter_ResetOnReload) {
353 NavigateAndCommit(GURL("http://foo.com/bar"));
354 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
355 download_request_limiter_->GetDownloadStatus(web_contents()));
357 // If the user refreshes the page without responding to the infobar, pretend
358 // like the refresh is the initial load: they get 1 free download (probably
359 // the same as the actual initial load), then an infobar.
360 testing_action_ = WAIT;
363 ExpectAndResetCounts(1, 0, 0, __LINE__);
364 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
365 download_request_limiter_->GetDownloadStatus(web_contents()));
368 ExpectAndResetCounts(0, 0, 1, __LINE__);
369 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
370 download_request_limiter_->GetDownloadStatus(web_contents()));
372 AboutToNavigateRenderView();
373 base::RunLoop().RunUntilIdle();
374 ExpectAndResetCounts(0, 1, 0, __LINE__);
375 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
376 download_request_limiter_->GetDownloadStatus(web_contents()));
379 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
380 download_request_limiter_->GetDownloadStatus(web_contents()));
381 ExpectAndResetCounts(1, 0, 0, __LINE__);
383 testing_action_ = CANCEL;
385 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
386 download_request_limiter_->GetDownloadStatus(web_contents()));
387 ExpectAndResetCounts(0, 1, 1, __LINE__);
389 AboutToNavigateRenderView();
390 base::RunLoop().RunUntilIdle();
391 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
392 download_request_limiter_->GetDownloadStatus(web_contents()));
394 ExpectAndResetCounts(0, 1, 0, __LINE__);
395 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
396 download_request_limiter_->GetDownloadStatus(web_contents()));
399 TEST_F(DownloadRequestLimiterTest,
400 DownloadRequestLimiter_RawWebContents) {
401 scoped_ptr<WebContents> web_contents(CreateTestWebContents());
403 // DownloadRequestLimiter won't try to make a permission bubble if there's
404 // no permission bubble manager, so don't put one on the test WebContents.
406 // DownloadRequestLimiter won't try to make an infobar if it doesn't have an
407 // InfoBarService, and we want to test that it will Cancel() instead of
408 // prompting when it doesn't have a InfoBarService, so unset the delegate.
410 ExpectAndResetCounts(0, 0, 0, __LINE__);
411 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
412 download_request_limiter_->GetDownloadStatus(web_contents.get()));
413 // You get one freebie.
414 CanDownloadFor(web_contents.get());
415 ExpectAndResetCounts(1, 0, 0, __LINE__);
416 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
417 download_request_limiter_->GetDownloadStatus(web_contents.get()));
418 OnUserGestureFor(web_contents.get());
419 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
420 download_request_limiter_->GetDownloadStatus(web_contents.get()));
421 CanDownloadFor(web_contents.get());
422 ExpectAndResetCounts(1, 0, 0, __LINE__);
423 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
424 download_request_limiter_->GetDownloadStatus(web_contents.get()));
425 CanDownloadFor(web_contents.get());
426 ExpectAndResetCounts(0, 1, 0, __LINE__);
427 EXPECT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
428 download_request_limiter_->GetDownloadStatus(web_contents.get()));
429 OnUserGestureFor(web_contents.get());
430 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
431 download_request_limiter_->GetDownloadStatus(web_contents.get()));
432 CanDownloadFor(web_contents.get());
433 ExpectAndResetCounts(1, 0, 0, __LINE__);
434 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
435 download_request_limiter_->GetDownloadStatus(web_contents.get()));
438 TEST_F(DownloadRequestLimiterTest,
439 DownloadRequestLimiter_SetHostContentSetting) {
440 NavigateAndCommit(GURL("http://foo.com/bar"));
441 SetHostContentSetting(web_contents(), CONTENT_SETTING_ALLOW);
444 ExpectAndResetCounts(1, 0, 0, __LINE__);
445 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
446 download_request_limiter_->GetDownloadStatus(web_contents()));
449 ExpectAndResetCounts(1, 0, 0, __LINE__);
450 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
451 download_request_limiter_->GetDownloadStatus(web_contents()));
453 SetHostContentSetting(web_contents(), CONTENT_SETTING_BLOCK);
456 ExpectAndResetCounts(0, 1, 0, __LINE__);
457 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
458 download_request_limiter_->GetDownloadStatus(web_contents()));
461 ExpectAndResetCounts(0, 1, 0, __LINE__);
462 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
463 download_request_limiter_->GetDownloadStatus(web_contents()));