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/command_line.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/download/download_permission_request.h"
11 #include "chrome/browser/download/download_request_infobar_delegate.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "components/content_settings/core/browser/host_content_settings_map.h"
18 #include "content/public/browser/navigation_controller.h"
19 #include "content/public/browser/navigation_details.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/frame_navigate_params.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using content::WebContents
;
26 class DownloadRequestLimiterTest
;
28 class FakePermissionBubbleView
: public PermissionBubbleView
{
30 explicit FakePermissionBubbleView(DownloadRequestLimiterTest
*test
)
31 : test_(test
), delegate_(NULL
) {}
33 ~FakePermissionBubbleView() override
{
35 delegate_
->SetView(NULL
);
43 // PermissionBubbleView:
44 void SetDelegate(Delegate
* delegate
) override
{ delegate_
= delegate
; }
46 void Show(const std::vector
<PermissionBubbleRequest
*>& requests
,
47 const std::vector
<bool>& accept_state
) override
;
49 bool CanAcceptRequestUpdate() override
{ return false; }
51 void Hide() override
{}
52 bool IsVisible() override
{ return false; }
55 DownloadRequestLimiterTest
* test_
;
59 class DownloadRequestLimiterTest
: public ChromeRenderViewHostTestHarness
{
67 void SetUp() override
{
68 ChromeRenderViewHostTestHarness::SetUp();
69 InfoBarService::CreateForWebContents(web_contents());
71 PermissionBubbleManager::CreateForWebContents(web_contents());
72 view_
.reset(new FakePermissionBubbleView(this));
73 PermissionBubbleManager::FromWebContents(web_contents())->
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 void TearDown() override
{
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(
130 "GET", // request method
131 base::Bind(&DownloadRequestLimiterTest::ContinueDownload
,
132 base::Unretained(this)));
133 base::RunLoop().RunUntilIdle();
136 void OnUserGesture() {
137 OnUserGestureFor(web_contents());
140 void OnUserGestureFor(WebContents
* web_contents
) {
141 DownloadRequestLimiter::TabDownloadState
* state
=
142 download_request_limiter_
->GetDownloadState(web_contents
, NULL
, false);
144 state
->DidGetUserGesture();
147 void DidNavigateMainFrame() {
149 DownloadRequestLimiter::TabDownloadState
* state
=
150 download_request_limiter_
->GetDownloadState(
151 web_contents(), NULL
, false);
152 content::LoadCommittedDetails details
;
153 content::FrameNavigateParams params
;
154 state
->DidNavigateMainFrame(details
, params
);
157 void ExpectAndResetCounts(
158 int expect_continues
,
162 EXPECT_EQ(expect_continues
, continue_count_
) << "line " << line
;
163 EXPECT_EQ(expect_cancels
, cancel_count_
) << "line " << line
;
164 EXPECT_EQ(expect_asks
, ask_allow_count_
) << "line " << line
;
165 continue_count_
= cancel_count_
= ask_allow_count_
= 0;
169 void ContinueDownload(bool allow
) {
177 void SetHostContentSetting(WebContents
* contents
, ContentSetting setting
) {
178 content_settings_
->SetContentSetting(
179 ContentSettingsPattern::FromURL(contents
->GetURL()),
180 ContentSettingsPattern::Wildcard(),
181 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
,
186 void BubbleManagerDocumentLoadCompleted(bool bubbles_enabled
) {
187 if (!bubbles_enabled
)
189 PermissionBubbleManager::FromWebContents(web_contents())->
190 DocumentOnLoadCompletedInMainFrame();
193 scoped_refptr
<DownloadRequestLimiter
> download_request_limiter_
;
195 // The action that FakeCreate() should take.
196 TestingAction testing_action_
;
198 // Number of times ContinueDownload was invoked.
201 // Number of times CancelDownload was invoked.
204 // Number of times ShouldAllowDownload was invoked.
205 int ask_allow_count_
;
207 scoped_refptr
<HostContentSettingsMap
> content_settings_
;
210 DownloadRequestInfoBarDelegate::FakeCreateCallback fake_create_callback_
;
211 TestingProfile profile_
;
212 scoped_ptr
<FakePermissionBubbleView
> view_
;
215 void FakePermissionBubbleView::Show(
216 const std::vector
<PermissionBubbleRequest
*>& requests
,
217 const std::vector
<bool>& accept_state
) {
219 int action
= test_
->GetAction();
220 if (action
== DownloadRequestLimiterTest::ACCEPT
) {
222 } else if (action
== DownloadRequestLimiterTest::CANCEL
) {
224 } else if (action
== DownloadRequestLimiterTest::WAIT
) {
227 delegate_
->Closing();
231 class DownloadRequestLimiterParamTests
232 : public DownloadRequestLimiterTest
,
233 public ::testing::WithParamInterface
<bool> {
235 DownloadRequestLimiterParamTests() {}
236 ~DownloadRequestLimiterParamTests() override
{}
238 void SetUp() override
{
239 DownloadRequestLimiterTest::SetUp();
240 #if !defined(OS_ANDROID)
242 base::CommandLine::ForCurrentProcess()->AppendSwitch(
243 switches::kEnablePermissionsBubbles
);
244 EXPECT_TRUE(PermissionBubbleManager::Enabled());
246 base::CommandLine::ForCurrentProcess()->AppendSwitch(
247 switches::kDisablePermissionsBubbles
);
252 void BubbleManagerDocumentLoadCompleted() {
253 #if defined(OS_ANDROID)
254 DownloadRequestLimiterTest::BubbleManagerDocumentLoadCompleted(false);
256 DownloadRequestLimiterTest::BubbleManagerDocumentLoadCompleted(GetParam());
260 DISALLOW_COPY_AND_ASSIGN(DownloadRequestLimiterParamTests
);
263 TEST_P(DownloadRequestLimiterParamTests
,
264 DownloadRequestLimiter_Allow
) {
265 BubbleManagerDocumentLoadCompleted();
267 // All tabs should initially start at ALLOW_ONE_DOWNLOAD.
268 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
269 download_request_limiter_
->GetDownloadStatus(web_contents()));
271 // Ask if the tab can do a download. This moves to PROMPT_BEFORE_DOWNLOAD.
273 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
274 download_request_limiter_
->GetDownloadStatus(web_contents()));
275 // We should have been told we can download.
276 ExpectAndResetCounts(1, 0, 0, __LINE__
);
278 // Ask again. This triggers asking the delegate for allow/disallow.
279 testing_action_
= ACCEPT
;
281 // This should ask us if the download is allowed.
282 // We should have been told we can download.
283 ExpectAndResetCounts(1, 0, 1, __LINE__
);
284 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
285 download_request_limiter_
->GetDownloadStatus(web_contents()));
287 // Ask again and make sure continue is invoked.
289 // The state is at allow_all, which means the delegate shouldn't be asked.
290 // We should have been told we can download.
291 ExpectAndResetCounts(1, 0, 0, __LINE__
);
292 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
293 download_request_limiter_
->GetDownloadStatus(web_contents()));
296 TEST_P(DownloadRequestLimiterParamTests
,
297 DownloadRequestLimiter_ResetOnNavigation
) {
298 NavigateAndCommit(GURL("http://foo.com/bar"));
299 BubbleManagerDocumentLoadCompleted();
301 // Do two downloads, allowing the second so that we end up with allow all.
303 ExpectAndResetCounts(1, 0, 0, __LINE__
);
304 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
305 download_request_limiter_
->GetDownloadStatus(web_contents()));
307 testing_action_
= ACCEPT
;
309 ExpectAndResetCounts(1, 0, 1, __LINE__
);
310 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
311 download_request_limiter_
->GetDownloadStatus(web_contents()));
313 // Navigate to a new URL with the same host, which shouldn't reset the allow
315 NavigateAndCommit(GURL("http://foo.com/bar2"));
316 BubbleManagerDocumentLoadCompleted();
318 ExpectAndResetCounts(1, 0, 0, __LINE__
);
319 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
320 download_request_limiter_
->GetDownloadStatus(web_contents()));
322 // Do a user gesture, because we're at allow all, this shouldn't change the
325 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
326 download_request_limiter_
->GetDownloadStatus(web_contents()));
328 // Navigate to a completely different host, which should reset the state.
329 NavigateAndCommit(GURL("http://fooey.com"));
330 BubbleManagerDocumentLoadCompleted();
331 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
332 download_request_limiter_
->GetDownloadStatus(web_contents()));
334 // Do two downloads, allowing the second so that we end up with allow all.
336 ExpectAndResetCounts(1, 0, 0, __LINE__
);
337 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
338 download_request_limiter_
->GetDownloadStatus(web_contents()));
340 testing_action_
= CANCEL
;
342 ExpectAndResetCounts(0, 1, 1, __LINE__
);
343 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
344 download_request_limiter_
->GetDownloadStatus(web_contents()));
346 // Navigate to a new URL with the same host, which shouldn't reset the allow
348 NavigateAndCommit(GURL("http://fooey.com/bar2"));
349 BubbleManagerDocumentLoadCompleted();
351 ExpectAndResetCounts(0, 1, 0, __LINE__
);
352 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
353 download_request_limiter_
->GetDownloadStatus(web_contents()));
356 TEST_P(DownloadRequestLimiterParamTests
,
357 DownloadRequestLimiter_ResetOnUserGesture
) {
358 NavigateAndCommit(GURL("http://foo.com/bar"));
359 BubbleManagerDocumentLoadCompleted();
361 // Do one download, which should change to prompt before download.
363 ExpectAndResetCounts(1, 0, 0, __LINE__
);
364 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
365 download_request_limiter_
->GetDownloadStatus(web_contents()));
367 // Do a user gesture, which should reset back to allow one.
369 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
370 download_request_limiter_
->GetDownloadStatus(web_contents()));
372 // Ask twice, which triggers calling the delegate. Don't allow the download
373 // so that we end up with not allowed.
375 ExpectAndResetCounts(1, 0, 0, __LINE__
);
376 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
377 download_request_limiter_
->GetDownloadStatus(web_contents()));
379 testing_action_
= CANCEL
;
381 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
382 download_request_limiter_
->GetDownloadStatus(web_contents()));
383 ExpectAndResetCounts(0, 1, 1, __LINE__
);
385 // A user gesture now should NOT change the state.
387 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
388 download_request_limiter_
->GetDownloadStatus(web_contents()));
389 // And make sure we really can't download.
391 ExpectAndResetCounts(0, 1, 0, __LINE__
);
392 // And the state shouldn't have changed.
393 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
394 download_request_limiter_
->GetDownloadStatus(web_contents()));
397 TEST_P(DownloadRequestLimiterParamTests
,
398 DownloadRequestLimiter_ResetOnReload
) {
399 NavigateAndCommit(GURL("http://foo.com/bar"));
400 BubbleManagerDocumentLoadCompleted();
401 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
402 download_request_limiter_
->GetDownloadStatus(web_contents()));
404 // If the user refreshes the page without responding to the infobar, pretend
405 // like the refresh is the initial load: they get 1 free download (probably
406 // the same as the actual initial load), then an infobar.
407 testing_action_
= WAIT
;
410 ExpectAndResetCounts(1, 0, 0, __LINE__
);
411 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
412 download_request_limiter_
->GetDownloadStatus(web_contents()));
415 ExpectAndResetCounts(0, 0, 1, __LINE__
);
416 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
417 download_request_limiter_
->GetDownloadStatus(web_contents()));
419 DidNavigateMainFrame();
420 base::RunLoop().RunUntilIdle();
421 ExpectAndResetCounts(0, 1, 0, __LINE__
);
422 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
423 download_request_limiter_
->GetDownloadStatus(web_contents()));
426 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
427 download_request_limiter_
->GetDownloadStatus(web_contents()));
428 ExpectAndResetCounts(1, 0, 0, __LINE__
);
430 testing_action_
= CANCEL
;
432 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
433 download_request_limiter_
->GetDownloadStatus(web_contents()));
434 ExpectAndResetCounts(0, 1, 1, __LINE__
);
436 DidNavigateMainFrame();
437 base::RunLoop().RunUntilIdle();
438 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
439 download_request_limiter_
->GetDownloadStatus(web_contents()));
441 ExpectAndResetCounts(0, 1, 0, __LINE__
);
442 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
443 download_request_limiter_
->GetDownloadStatus(web_contents()));
446 TEST_P(DownloadRequestLimiterParamTests
,
447 DownloadRequestLimiter_RawWebContents
) {
448 scoped_ptr
<WebContents
> web_contents(CreateTestWebContents());
450 // DownloadRequestLimiter won't try to make a permission bubble if there's
451 // no permission bubble manager, so don't put one on the test WebContents.
453 // DownloadRequestLimiter won't try to make an infobar if it doesn't have an
454 // InfoBarService, and we want to test that it will Cancel() instead of
455 // prompting when it doesn't have a InfoBarService, so unset the delegate.
457 ExpectAndResetCounts(0, 0, 0, __LINE__
);
458 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
459 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
460 // You get one freebie.
461 CanDownloadFor(web_contents
.get());
462 ExpectAndResetCounts(1, 0, 0, __LINE__
);
463 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
464 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
465 OnUserGestureFor(web_contents
.get());
466 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
467 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
468 CanDownloadFor(web_contents
.get());
469 ExpectAndResetCounts(1, 0, 0, __LINE__
);
470 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
471 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
472 CanDownloadFor(web_contents
.get());
473 ExpectAndResetCounts(0, 1, 0, __LINE__
);
474 EXPECT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
475 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
476 OnUserGestureFor(web_contents
.get());
477 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
478 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
479 CanDownloadFor(web_contents
.get());
480 ExpectAndResetCounts(1, 0, 0, __LINE__
);
481 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
482 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
485 TEST_P(DownloadRequestLimiterParamTests
,
486 DownloadRequestLimiter_SetHostContentSetting
) {
487 NavigateAndCommit(GURL("http://foo.com/bar"));
488 BubbleManagerDocumentLoadCompleted();
489 SetHostContentSetting(web_contents(), CONTENT_SETTING_ALLOW
);
492 ExpectAndResetCounts(1, 0, 0, __LINE__
);
493 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
494 download_request_limiter_
->GetDownloadStatus(web_contents()));
497 ExpectAndResetCounts(1, 0, 0, __LINE__
);
498 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
499 download_request_limiter_
->GetDownloadStatus(web_contents()));
501 SetHostContentSetting(web_contents(), CONTENT_SETTING_BLOCK
);
504 ExpectAndResetCounts(0, 1, 0, __LINE__
);
505 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
506 download_request_limiter_
->GetDownloadStatus(web_contents()));
509 ExpectAndResetCounts(0, 1, 0, __LINE__
);
510 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
511 download_request_limiter_
->GetDownloadStatus(web_contents()));
514 INSTANTIATE_TEST_CASE_P(DownloadRequestLimiterTestsWithAndWithoutBubbles
,
515 DownloadRequestLimiterParamTests
,
516 ::testing::Values(false, true));