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 {}
51 virtual bool IsVisible() OVERRIDE { return false; }
54 DownloadRequestLimiterTest* test_;
58 class DownloadRequestLimiterTest : public ChromeRenderViewHostTestHarness {
66 virtual void SetUp() {
67 ChromeRenderViewHostTestHarness::SetUp();
68 InfoBarService::CreateForWebContents(web_contents());
70 PermissionBubbleManager::CreateForWebContents(web_contents());
71 view_.reset(new FakePermissionBubbleView(this));
72 PermissionBubbleManager* manager =
73 PermissionBubbleManager::FromWebContents(web_contents());
74 manager->SetView(view_.get());
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(
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 AboutToNavigateRenderView() {
149 DownloadRequestLimiter::TabDownloadState* state =
150 download_request_limiter_->GetDownloadState(
151 web_contents(), NULL, false);
152 state->AboutToNavigateRenderView(NULL);
155 void ExpectAndResetCounts(
156 int expect_continues,
160 EXPECT_EQ(expect_continues, continue_count_) << "line " << line;
161 EXPECT_EQ(expect_cancels, cancel_count_) << "line " << line;
162 EXPECT_EQ(expect_asks, ask_allow_count_) << "line " << line;
163 continue_count_ = cancel_count_ = ask_allow_count_ = 0;
167 void ContinueDownload(bool allow) {
175 void SetHostContentSetting(WebContents* contents, ContentSetting setting) {
176 content_settings_->SetContentSetting(
177 ContentSettingsPattern::FromURL(contents->GetURL()),
178 ContentSettingsPattern::Wildcard(),
179 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
184 scoped_refptr<DownloadRequestLimiter> download_request_limiter_;
186 // The action that FakeCreate() should take.
187 TestingAction testing_action_;
189 // Number of times ContinueDownload was invoked.
192 // Number of times CancelDownload was invoked.
195 // Number of times ShouldAllowDownload was invoked.
196 int ask_allow_count_;
198 scoped_refptr<HostContentSettingsMap> content_settings_;
201 DownloadRequestInfoBarDelegate::FakeCreateCallback fake_create_callback_;
202 TestingProfile profile_;
203 scoped_ptr<FakePermissionBubbleView> view_;
206 void FakePermissionBubbleView::Show(
207 const std::vector<PermissionBubbleRequest*>& requests,
208 const std::vector<bool>& accept_state,
209 bool customization_mode) {
211 int action = test_->GetAction();
212 if (action == DownloadRequestLimiterTest::ACCEPT) {
214 } else if (action == DownloadRequestLimiterTest::CANCEL) {
216 } else if (action == DownloadRequestLimiterTest::WAIT) {
219 delegate_->Closing();
223 TEST_F(DownloadRequestLimiterTest,
224 DownloadRequestLimiter_Allow) {
225 // All tabs should initially start at ALLOW_ONE_DOWNLOAD.
226 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
227 download_request_limiter_->GetDownloadStatus(web_contents()));
229 // Ask if the tab can do a download. This moves to PROMPT_BEFORE_DOWNLOAD.
231 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
232 download_request_limiter_->GetDownloadStatus(web_contents()));
233 // We should have been told we can download.
234 ExpectAndResetCounts(1, 0, 0, __LINE__);
236 // Ask again. This triggers asking the delegate for allow/disallow.
237 testing_action_ = ACCEPT;
239 // This should ask us if the download is allowed.
240 // We should have been told we can download.
241 ExpectAndResetCounts(1, 0, 1, __LINE__);
242 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
243 download_request_limiter_->GetDownloadStatus(web_contents()));
245 // Ask again and make sure continue is invoked.
247 // The state is at allow_all, which means the delegate shouldn't be asked.
248 // We should have been told we can download.
249 ExpectAndResetCounts(1, 0, 0, __LINE__);
250 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
251 download_request_limiter_->GetDownloadStatus(web_contents()));
254 TEST_F(DownloadRequestLimiterTest,
255 DownloadRequestLimiter_ResetOnNavigation) {
256 NavigateAndCommit(GURL("http://foo.com/bar"));
258 // Do two downloads, allowing the second so that we end up with allow all.
260 ExpectAndResetCounts(1, 0, 0, __LINE__);
261 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
262 download_request_limiter_->GetDownloadStatus(web_contents()));
264 testing_action_ = ACCEPT;
266 ExpectAndResetCounts(1, 0, 1, __LINE__);
267 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
268 download_request_limiter_->GetDownloadStatus(web_contents()));
270 // Navigate to a new URL with the same host, which shouldn't reset the allow
272 NavigateAndCommit(GURL("http://foo.com/bar2"));
274 ExpectAndResetCounts(1, 0, 0, __LINE__);
275 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
276 download_request_limiter_->GetDownloadStatus(web_contents()));
278 // Do a user gesture, because we're at allow all, this shouldn't change the
281 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
282 download_request_limiter_->GetDownloadStatus(web_contents()));
284 // Navigate to a completely different host, which should reset the state.
285 NavigateAndCommit(GURL("http://fooey.com"));
286 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
287 download_request_limiter_->GetDownloadStatus(web_contents()));
289 // Do two downloads, allowing the second so that we end up with allow all.
291 ExpectAndResetCounts(1, 0, 0, __LINE__);
292 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
293 download_request_limiter_->GetDownloadStatus(web_contents()));
295 testing_action_ = CANCEL;
297 ExpectAndResetCounts(0, 1, 1, __LINE__);
298 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
299 download_request_limiter_->GetDownloadStatus(web_contents()));
301 // Navigate to a new URL with the same host, which shouldn't reset the allow
303 NavigateAndCommit(GURL("http://fooey.com/bar2"));
305 ExpectAndResetCounts(0, 1, 0, __LINE__);
306 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
307 download_request_limiter_->GetDownloadStatus(web_contents()));
310 TEST_F(DownloadRequestLimiterTest,
311 DownloadRequestLimiter_ResetOnUserGesture) {
312 NavigateAndCommit(GURL("http://foo.com/bar"));
314 // Do one download, which should change to prompt before download.
316 ExpectAndResetCounts(1, 0, 0, __LINE__);
317 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
318 download_request_limiter_->GetDownloadStatus(web_contents()));
320 // Do a user gesture, which should reset back to allow one.
322 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
323 download_request_limiter_->GetDownloadStatus(web_contents()));
325 // Ask twice, which triggers calling the delegate. Don't allow the download
326 // so that we end up with not allowed.
328 ExpectAndResetCounts(1, 0, 0, __LINE__);
329 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
330 download_request_limiter_->GetDownloadStatus(web_contents()));
332 testing_action_ = CANCEL;
334 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
335 download_request_limiter_->GetDownloadStatus(web_contents()));
336 ExpectAndResetCounts(0, 1, 1, __LINE__);
338 // A user gesture now should NOT change the state.
340 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
341 download_request_limiter_->GetDownloadStatus(web_contents()));
342 // And make sure we really can't download.
344 ExpectAndResetCounts(0, 1, 0, __LINE__);
345 // And the state shouldn't have changed.
346 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
347 download_request_limiter_->GetDownloadStatus(web_contents()));
350 TEST_F(DownloadRequestLimiterTest,
351 DownloadRequestLimiter_ResetOnReload) {
352 NavigateAndCommit(GURL("http://foo.com/bar"));
353 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
354 download_request_limiter_->GetDownloadStatus(web_contents()));
356 // If the user refreshes the page without responding to the infobar, pretend
357 // like the refresh is the initial load: they get 1 free download (probably
358 // the same as the actual initial load), then an infobar.
359 testing_action_ = WAIT;
362 ExpectAndResetCounts(1, 0, 0, __LINE__);
363 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
364 download_request_limiter_->GetDownloadStatus(web_contents()));
367 ExpectAndResetCounts(0, 0, 1, __LINE__);
368 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
369 download_request_limiter_->GetDownloadStatus(web_contents()));
371 AboutToNavigateRenderView();
372 base::RunLoop().RunUntilIdle();
373 ExpectAndResetCounts(0, 1, 0, __LINE__);
374 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
375 download_request_limiter_->GetDownloadStatus(web_contents()));
378 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
379 download_request_limiter_->GetDownloadStatus(web_contents()));
380 ExpectAndResetCounts(1, 0, 0, __LINE__);
382 testing_action_ = CANCEL;
384 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
385 download_request_limiter_->GetDownloadStatus(web_contents()));
386 ExpectAndResetCounts(0, 1, 1, __LINE__);
388 AboutToNavigateRenderView();
389 base::RunLoop().RunUntilIdle();
390 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
391 download_request_limiter_->GetDownloadStatus(web_contents()));
393 ExpectAndResetCounts(0, 1, 0, __LINE__);
394 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
395 download_request_limiter_->GetDownloadStatus(web_contents()));
398 TEST_F(DownloadRequestLimiterTest,
399 DownloadRequestLimiter_RawWebContents) {
400 scoped_ptr<WebContents> web_contents(CreateTestWebContents());
402 // DownloadRequestLimiter won't try to make a permission bubble if there's
403 // no permission bubble manager, so don't put one on the test WebContents.
405 // DownloadRequestLimiter won't try to make an infobar if it doesn't have an
406 // InfoBarService, and we want to test that it will Cancel() instead of
407 // prompting when it doesn't have a InfoBarService, so unset the delegate.
409 ExpectAndResetCounts(0, 0, 0, __LINE__);
410 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
411 download_request_limiter_->GetDownloadStatus(web_contents.get()));
412 // You get one freebie.
413 CanDownloadFor(web_contents.get());
414 ExpectAndResetCounts(1, 0, 0, __LINE__);
415 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
416 download_request_limiter_->GetDownloadStatus(web_contents.get()));
417 OnUserGestureFor(web_contents.get());
418 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
419 download_request_limiter_->GetDownloadStatus(web_contents.get()));
420 CanDownloadFor(web_contents.get());
421 ExpectAndResetCounts(1, 0, 0, __LINE__);
422 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
423 download_request_limiter_->GetDownloadStatus(web_contents.get()));
424 CanDownloadFor(web_contents.get());
425 ExpectAndResetCounts(0, 1, 0, __LINE__);
426 EXPECT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
427 download_request_limiter_->GetDownloadStatus(web_contents.get()));
428 OnUserGestureFor(web_contents.get());
429 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
430 download_request_limiter_->GetDownloadStatus(web_contents.get()));
431 CanDownloadFor(web_contents.get());
432 ExpectAndResetCounts(1, 0, 0, __LINE__);
433 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
434 download_request_limiter_->GetDownloadStatus(web_contents.get()));
437 TEST_F(DownloadRequestLimiterTest,
438 DownloadRequestLimiter_SetHostContentSetting) {
439 NavigateAndCommit(GURL("http://foo.com/bar"));
440 SetHostContentSetting(web_contents(), CONTENT_SETTING_ALLOW);
443 ExpectAndResetCounts(1, 0, 0, __LINE__);
444 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
445 download_request_limiter_->GetDownloadStatus(web_contents()));
448 ExpectAndResetCounts(1, 0, 0, __LINE__);
449 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
450 download_request_limiter_->GetDownloadStatus(web_contents()));
452 SetHostContentSetting(web_contents(), CONTENT_SETTING_BLOCK);
455 ExpectAndResetCounts(0, 1, 0, __LINE__);
456 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
457 download_request_limiter_->GetDownloadStatus(web_contents()));
460 ExpectAndResetCounts(0, 1, 0, __LINE__);
461 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
462 download_request_limiter_->GetDownloadStatus(web_contents()));