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());
75 testing_action_
= ACCEPT
;
76 ask_allow_count_
= cancel_count_
= continue_count_
= 0;
77 download_request_limiter_
= new DownloadRequestLimiter();
78 fake_create_callback_
= base::Bind(
79 &DownloadRequestLimiterTest::FakeCreate
, base::Unretained(this));
80 DownloadRequestInfoBarDelegate::SetCallbackForTesting(
81 &fake_create_callback_
);
82 content_settings_
= new HostContentSettingsMap(profile_
.GetPrefs(), false);
83 DownloadRequestLimiter::SetContentSettingsForTesting(
84 content_settings_
.get());
88 return testing_action_
;
96 InfoBarService
* infobar_service
,
97 base::WeakPtr
<DownloadRequestLimiter::TabDownloadState
> host
) {
99 switch (testing_action_
) {
111 virtual void TearDown() {
112 content_settings_
->ShutdownOnUIThread();
113 content_settings_
= NULL
;
115 ChromeRenderViewHostTestHarness::TearDown();
118 virtual void UnsetDelegate() {
119 DownloadRequestInfoBarDelegate::SetCallbackForTesting(NULL
);
123 CanDownloadFor(web_contents());
126 void CanDownloadFor(WebContents
* web_contents
) {
127 download_request_limiter_
->CanDownloadImpl(
129 "GET", // request method
130 base::Bind(&DownloadRequestLimiterTest::ContinueDownload
,
131 base::Unretained(this)));
132 base::RunLoop().RunUntilIdle();
135 void OnUserGesture() {
136 OnUserGestureFor(web_contents());
139 void OnUserGestureFor(WebContents
* web_contents
) {
140 DownloadRequestLimiter::TabDownloadState
* state
=
141 download_request_limiter_
->GetDownloadState(web_contents
, NULL
, false);
143 state
->DidGetUserGesture();
146 void AboutToNavigateRenderView() {
148 DownloadRequestLimiter::TabDownloadState
* state
=
149 download_request_limiter_
->GetDownloadState(
150 web_contents(), NULL
, false);
151 state
->AboutToNavigateRenderView(NULL
);
154 void ExpectAndResetCounts(
155 int expect_continues
,
159 EXPECT_EQ(expect_continues
, continue_count_
) << "line " << line
;
160 EXPECT_EQ(expect_cancels
, cancel_count_
) << "line " << line
;
161 EXPECT_EQ(expect_asks
, ask_allow_count_
) << "line " << line
;
162 continue_count_
= cancel_count_
= ask_allow_count_
= 0;
166 void ContinueDownload(bool allow
) {
174 void SetHostContentSetting(WebContents
* contents
, ContentSetting setting
) {
175 content_settings_
->SetContentSetting(
176 ContentSettingsPattern::FromURL(contents
->GetURL()),
177 ContentSettingsPattern::Wildcard(),
178 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
,
183 scoped_refptr
<DownloadRequestLimiter
> download_request_limiter_
;
185 // The action that FakeCreate() should take.
186 TestingAction testing_action_
;
188 // Number of times ContinueDownload was invoked.
191 // Number of times CancelDownload was invoked.
194 // Number of times ShouldAllowDownload was invoked.
195 int ask_allow_count_
;
197 scoped_refptr
<HostContentSettingsMap
> content_settings_
;
200 DownloadRequestInfoBarDelegate::FakeCreateCallback fake_create_callback_
;
201 TestingProfile profile_
;
202 scoped_ptr
<FakePermissionBubbleView
> view_
;
205 void FakePermissionBubbleView::Show(
206 const std::vector
<PermissionBubbleRequest
*>& requests
,
207 const std::vector
<bool>& accept_state
,
208 bool customization_mode
) {
210 int action
= test_
->GetAction();
211 if (action
== DownloadRequestLimiterTest::ACCEPT
) {
213 } else if (action
== DownloadRequestLimiterTest::CANCEL
) {
215 } else if (action
== DownloadRequestLimiterTest::WAIT
) {
218 delegate_
->Closing();
222 TEST_F(DownloadRequestLimiterTest
,
223 DownloadRequestLimiter_Allow
) {
224 // All tabs should initially start at ALLOW_ONE_DOWNLOAD.
225 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
226 download_request_limiter_
->GetDownloadStatus(web_contents()));
228 // Ask if the tab can do a download. This moves to PROMPT_BEFORE_DOWNLOAD.
230 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
231 download_request_limiter_
->GetDownloadStatus(web_contents()));
232 // We should have been told we can download.
233 ExpectAndResetCounts(1, 0, 0, __LINE__
);
235 // Ask again. This triggers asking the delegate for allow/disallow.
236 testing_action_
= ACCEPT
;
238 // This should ask us if the download is allowed.
239 // We should have been told we can download.
240 ExpectAndResetCounts(1, 0, 1, __LINE__
);
241 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
242 download_request_limiter_
->GetDownloadStatus(web_contents()));
244 // Ask again and make sure continue is invoked.
246 // The state is at allow_all, which means the delegate shouldn't be asked.
247 // We should have been told we can download.
248 ExpectAndResetCounts(1, 0, 0, __LINE__
);
249 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
250 download_request_limiter_
->GetDownloadStatus(web_contents()));
253 TEST_F(DownloadRequestLimiterTest
,
254 DownloadRequestLimiter_ResetOnNavigation
) {
255 NavigateAndCommit(GURL("http://foo.com/bar"));
257 // Do two downloads, allowing the second so that we end up with allow all.
259 ExpectAndResetCounts(1, 0, 0, __LINE__
);
260 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
261 download_request_limiter_
->GetDownloadStatus(web_contents()));
263 testing_action_
= ACCEPT
;
265 ExpectAndResetCounts(1, 0, 1, __LINE__
);
266 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
267 download_request_limiter_
->GetDownloadStatus(web_contents()));
269 // Navigate to a new URL with the same host, which shouldn't reset the allow
271 NavigateAndCommit(GURL("http://foo.com/bar2"));
273 ExpectAndResetCounts(1, 0, 0, __LINE__
);
274 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
275 download_request_limiter_
->GetDownloadStatus(web_contents()));
277 // Do a user gesture, because we're at allow all, this shouldn't change the
280 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
,
281 download_request_limiter_
->GetDownloadStatus(web_contents()));
283 // Navigate to a completely different host, which should reset the state.
284 NavigateAndCommit(GURL("http://fooey.com"));
285 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
286 download_request_limiter_
->GetDownloadStatus(web_contents()));
288 // Do two downloads, allowing the second so that we end up with allow all.
290 ExpectAndResetCounts(1, 0, 0, __LINE__
);
291 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
292 download_request_limiter_
->GetDownloadStatus(web_contents()));
294 testing_action_
= CANCEL
;
296 ExpectAndResetCounts(0, 1, 1, __LINE__
);
297 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
298 download_request_limiter_
->GetDownloadStatus(web_contents()));
300 // Navigate to a new URL with the same host, which shouldn't reset the allow
302 NavigateAndCommit(GURL("http://fooey.com/bar2"));
304 ExpectAndResetCounts(0, 1, 0, __LINE__
);
305 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
306 download_request_limiter_
->GetDownloadStatus(web_contents()));
309 TEST_F(DownloadRequestLimiterTest
,
310 DownloadRequestLimiter_ResetOnUserGesture
) {
311 NavigateAndCommit(GURL("http://foo.com/bar"));
313 // Do one download, which should change to prompt before download.
315 ExpectAndResetCounts(1, 0, 0, __LINE__
);
316 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
317 download_request_limiter_
->GetDownloadStatus(web_contents()));
319 // Do a user gesture, which should reset back to allow one.
321 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
322 download_request_limiter_
->GetDownloadStatus(web_contents()));
324 // Ask twice, which triggers calling the delegate. Don't allow the download
325 // so that we end up with not allowed.
327 ExpectAndResetCounts(1, 0, 0, __LINE__
);
328 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
329 download_request_limiter_
->GetDownloadStatus(web_contents()));
331 testing_action_
= CANCEL
;
333 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
334 download_request_limiter_
->GetDownloadStatus(web_contents()));
335 ExpectAndResetCounts(0, 1, 1, __LINE__
);
337 // A user gesture now should NOT change the state.
339 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
340 download_request_limiter_
->GetDownloadStatus(web_contents()));
341 // And make sure we really can't download.
343 ExpectAndResetCounts(0, 1, 0, __LINE__
);
344 // And the state shouldn't have changed.
345 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
346 download_request_limiter_
->GetDownloadStatus(web_contents()));
349 TEST_F(DownloadRequestLimiterTest
,
350 DownloadRequestLimiter_ResetOnReload
) {
351 NavigateAndCommit(GURL("http://foo.com/bar"));
352 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
353 download_request_limiter_
->GetDownloadStatus(web_contents()));
355 // If the user refreshes the page without responding to the infobar, pretend
356 // like the refresh is the initial load: they get 1 free download (probably
357 // the same as the actual initial load), then an infobar.
358 testing_action_
= WAIT
;
361 ExpectAndResetCounts(1, 0, 0, __LINE__
);
362 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
363 download_request_limiter_
->GetDownloadStatus(web_contents()));
366 ExpectAndResetCounts(0, 0, 1, __LINE__
);
367 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
368 download_request_limiter_
->GetDownloadStatus(web_contents()));
370 AboutToNavigateRenderView();
371 base::RunLoop().RunUntilIdle();
372 ExpectAndResetCounts(0, 1, 0, __LINE__
);
373 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
374 download_request_limiter_
->GetDownloadStatus(web_contents()));
377 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
378 download_request_limiter_
->GetDownloadStatus(web_contents()));
379 ExpectAndResetCounts(1, 0, 0, __LINE__
);
381 testing_action_
= CANCEL
;
383 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
384 download_request_limiter_
->GetDownloadStatus(web_contents()));
385 ExpectAndResetCounts(0, 1, 1, __LINE__
);
387 AboutToNavigateRenderView();
388 base::RunLoop().RunUntilIdle();
389 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
390 download_request_limiter_
->GetDownloadStatus(web_contents()));
392 ExpectAndResetCounts(0, 1, 0, __LINE__
);
393 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
394 download_request_limiter_
->GetDownloadStatus(web_contents()));
397 TEST_F(DownloadRequestLimiterTest
,
398 DownloadRequestLimiter_RawWebContents
) {
399 scoped_ptr
<WebContents
> web_contents(CreateTestWebContents());
401 // DownloadRequestLimiter won't try to make a permission bubble if there's
402 // no permission bubble manager, so don't put one on the test WebContents.
404 // DownloadRequestLimiter won't try to make an infobar if it doesn't have an
405 // InfoBarService, and we want to test that it will Cancel() instead of
406 // prompting when it doesn't have a InfoBarService, so unset the delegate.
408 ExpectAndResetCounts(0, 0, 0, __LINE__
);
409 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
410 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
411 // You get one freebie.
412 CanDownloadFor(web_contents
.get());
413 ExpectAndResetCounts(1, 0, 0, __LINE__
);
414 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
415 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
416 OnUserGestureFor(web_contents
.get());
417 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
418 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
419 CanDownloadFor(web_contents
.get());
420 ExpectAndResetCounts(1, 0, 0, __LINE__
);
421 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
422 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
423 CanDownloadFor(web_contents
.get());
424 ExpectAndResetCounts(0, 1, 0, __LINE__
);
425 EXPECT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED
,
426 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
427 OnUserGestureFor(web_contents
.get());
428 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD
,
429 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
430 CanDownloadFor(web_contents
.get());
431 ExpectAndResetCounts(1, 0, 0, __LINE__
);
432 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
433 download_request_limiter_
->GetDownloadStatus(web_contents
.get()));
436 TEST_F(DownloadRequestLimiterTest
,
437 DownloadRequestLimiter_SetHostContentSetting
) {
438 NavigateAndCommit(GURL("http://foo.com/bar"));
439 SetHostContentSetting(web_contents(), CONTENT_SETTING_ALLOW
);
442 ExpectAndResetCounts(1, 0, 0, __LINE__
);
443 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
444 download_request_limiter_
->GetDownloadStatus(web_contents()));
447 ExpectAndResetCounts(1, 0, 0, __LINE__
);
448 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
449 download_request_limiter_
->GetDownloadStatus(web_contents()));
451 SetHostContentSetting(web_contents(), CONTENT_SETTING_BLOCK
);
454 ExpectAndResetCounts(0, 1, 0, __LINE__
);
455 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
456 download_request_limiter_
->GetDownloadStatus(web_contents()));
459 ExpectAndResetCounts(0, 1, 0, __LINE__
);
460 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD
,
461 download_request_limiter_
->GetDownloadStatus(web_contents()));