Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / download / download_request_limiter_unittest.cc
blob7b963a5b032e5993c816b6ad56224126f4af764f
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"
7 #include "base/bind.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/ui/website_settings/permission_bubble_manager.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "components/content_settings/core/browser/host_content_settings_map.h"
16 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/navigation_details.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/frame_navigate_params.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 #if defined(OS_ANDROID)
23 #include "chrome/browser/download/download_request_infobar_delegate.h"
24 #include "chrome/browser/infobars/infobar_service.h"
25 #endif
27 using content::WebContents;
29 class DownloadRequestLimiterTest;
31 class FakePermissionBubbleView : public PermissionBubbleView {
32 public:
33 class Factory : public base::RefCounted<FakePermissionBubbleView::Factory> {
34 public:
35 explicit Factory(DownloadRequestLimiterTest* test) : test_(test) {}
37 scoped_ptr<PermissionBubbleView> Create(Browser* browser) {
38 return make_scoped_ptr(new FakePermissionBubbleView(test_));
41 private:
42 friend class base::RefCounted<FakePermissionBubbleView::Factory>;
44 ~Factory() {}
45 DownloadRequestLimiterTest* test_;
48 explicit FakePermissionBubbleView(DownloadRequestLimiterTest *test)
49 : test_(test), delegate_(NULL) {}
51 ~FakePermissionBubbleView() override {
54 void Close() {
55 if (delegate_)
56 delegate_->Closing();
59 // PermissionBubbleView:
60 void SetDelegate(Delegate* delegate) override { delegate_ = delegate; }
62 void Show(const std::vector<PermissionBubbleRequest*>& requests,
63 const std::vector<bool>& accept_state) override;
65 bool CanAcceptRequestUpdate() override { return false; }
67 void Hide() override {}
68 bool IsVisible() override { return false; }
69 void UpdateAnchorPosition() override{};
70 gfx::NativeWindow GetNativeWindow() override { return nullptr; }
72 private:
73 DownloadRequestLimiterTest* test_;
74 Delegate* delegate_;
77 class DownloadRequestLimiterTest : public ChromeRenderViewHostTestHarness {
78 public:
79 enum TestingAction {
80 ACCEPT,
81 CANCEL,
82 WAIT
85 void SetUp() override {
86 ChromeRenderViewHostTestHarness::SetUp();
87 profile_.reset(new TestingProfile());
89 if (PermissionBubbleManager::Enabled()) {
90 PermissionBubbleManager::CreateForWebContents(web_contents());
91 scoped_refptr<FakePermissionBubbleView::Factory> factory =
92 new FakePermissionBubbleView::Factory(this);
93 PermissionBubbleManager::FromWebContents(web_contents())->view_factory_ =
94 base::Bind(&FakePermissionBubbleView::Factory::Create, factory);
95 PermissionBubbleManager::FromWebContents(web_contents())
96 ->DisplayPendingRequests();
99 testing_action_ = ACCEPT;
100 ask_allow_count_ = cancel_count_ = continue_count_ = 0;
101 download_request_limiter_ = new DownloadRequestLimiter();
103 #if defined(OS_ANDROID)
104 InfoBarService::CreateForWebContents(web_contents());
105 fake_create_callback_ = base::Bind(
106 &DownloadRequestLimiterTest::FakeCreate, base::Unretained(this));
107 DownloadRequestInfoBarDelegate::SetCallbackForTesting(
108 &fake_create_callback_);
109 #endif
111 content_settings_ = new HostContentSettingsMap(profile_->GetPrefs(), false);
112 DownloadRequestLimiter::SetContentSettingsForTesting(
113 content_settings_.get());
116 int GetAction() {
117 return testing_action_;
120 void AskAllow() {
121 ask_allow_count_++;
124 void TearDown() override {
125 content_settings_->ShutdownOnUIThread();
126 content_settings_ = NULL;
127 #if defined(OS_ANDROID)
128 UnsetDelegate();
129 #endif
130 ChromeRenderViewHostTestHarness::TearDown();
133 #if defined(OS_ANDROID)
134 void FakeCreate(
135 InfoBarService* infobar_service,
136 base::WeakPtr<DownloadRequestLimiter::TabDownloadState> host) {
137 AskAllow();
138 switch (testing_action_) {
139 case ACCEPT:
140 host->Accept();
141 break;
142 case CANCEL:
143 host->Cancel();
144 break;
145 case WAIT:
146 break;
150 virtual void UnsetDelegate() {
151 DownloadRequestInfoBarDelegate::SetCallbackForTesting(NULL);
153 #endif
155 void CanDownload() {
156 CanDownloadFor(web_contents());
159 void CanDownloadFor(WebContents* web_contents) {
160 download_request_limiter_->CanDownloadImpl(
161 web_contents,
162 "GET", // request method
163 base::Bind(&DownloadRequestLimiterTest::ContinueDownload,
164 base::Unretained(this)));
165 base::RunLoop().RunUntilIdle();
168 void OnUserGesture() {
169 OnUserGestureFor(web_contents());
172 void OnUserGestureFor(WebContents* web_contents) {
173 DownloadRequestLimiter::TabDownloadState* state =
174 download_request_limiter_->GetDownloadState(web_contents, NULL, false);
175 if (state)
176 state->DidGetUserGesture();
179 void ExpectAndResetCounts(
180 int expect_continues,
181 int expect_cancels,
182 int expect_asks,
183 int line) {
184 EXPECT_EQ(expect_continues, continue_count_) << "line " << line;
185 EXPECT_EQ(expect_cancels, cancel_count_) << "line " << line;
186 EXPECT_EQ(expect_asks, ask_allow_count_) << "line " << line;
187 continue_count_ = cancel_count_ = ask_allow_count_ = 0;
190 protected:
191 void ContinueDownload(bool allow) {
192 if (allow) {
193 continue_count_++;
194 } else {
195 cancel_count_++;
199 void SetHostContentSetting(WebContents* contents, ContentSetting setting) {
200 content_settings_->SetContentSetting(
201 ContentSettingsPattern::FromURL(contents->GetURL()),
202 ContentSettingsPattern::Wildcard(),
203 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
204 std::string(),
205 setting);
208 void BubbleManagerDocumentLoadCompleted() {
209 #if !defined(OS_ANDROID)
210 PermissionBubbleManager::FromWebContents(web_contents())->
211 DocumentOnLoadCompletedInMainFrame();
212 #endif
215 scoped_refptr<DownloadRequestLimiter> download_request_limiter_;
217 // The action that FakeCreate() should take.
218 TestingAction testing_action_;
220 // Number of times ContinueDownload was invoked.
221 int continue_count_;
223 // Number of times CancelDownload was invoked.
224 int cancel_count_;
226 // Number of times ShouldAllowDownload was invoked.
227 int ask_allow_count_;
229 scoped_refptr<HostContentSettingsMap> content_settings_;
231 private:
232 #if defined(OS_ANDROID)
233 DownloadRequestInfoBarDelegate::FakeCreateCallback fake_create_callback_;
234 #endif
236 scoped_ptr<TestingProfile> profile_;
239 void FakePermissionBubbleView::Show(
240 const std::vector<PermissionBubbleRequest*>& requests,
241 const std::vector<bool>& accept_state) {
242 test_->AskAllow();
243 int action = test_->GetAction();
244 if (action == DownloadRequestLimiterTest::ACCEPT) {
245 delegate_->Accept();
246 } else if (action == DownloadRequestLimiterTest::CANCEL) {
247 delegate_->Deny();
248 } else if (action == DownloadRequestLimiterTest::WAIT) {
249 // do nothing.
250 } else {
251 delegate_->Closing();
255 TEST_F(DownloadRequestLimiterTest, DownloadRequestLimiter_Allow) {
256 BubbleManagerDocumentLoadCompleted();
258 // All tabs should initially start at ALLOW_ONE_DOWNLOAD.
259 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
260 download_request_limiter_->GetDownloadStatus(web_contents()));
262 // Ask if the tab can do a download. This moves to PROMPT_BEFORE_DOWNLOAD.
263 CanDownload();
264 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
265 download_request_limiter_->GetDownloadStatus(web_contents()));
266 // We should have been told we can download.
267 ExpectAndResetCounts(1, 0, 0, __LINE__);
269 // Ask again. This triggers asking the delegate for allow/disallow.
270 testing_action_ = ACCEPT;
271 CanDownload();
272 // This should ask us if the download is allowed.
273 // We should have been told we can download.
274 ExpectAndResetCounts(1, 0, 1, __LINE__);
275 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
276 download_request_limiter_->GetDownloadStatus(web_contents()));
278 // Ask again and make sure continue is invoked.
279 CanDownload();
280 // The state is at allow_all, which means the delegate shouldn't be asked.
281 // We should have been told we can download.
282 ExpectAndResetCounts(1, 0, 0, __LINE__);
283 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
284 download_request_limiter_->GetDownloadStatus(web_contents()));
287 TEST_F(DownloadRequestLimiterTest, DownloadRequestLimiter_ResetOnNavigation) {
288 NavigateAndCommit(GURL("http://foo.com/bar"));
289 BubbleManagerDocumentLoadCompleted();
291 // Do two downloads, allowing the second so that we end up with allow all.
292 CanDownload();
293 ExpectAndResetCounts(1, 0, 0, __LINE__);
294 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
295 download_request_limiter_->GetDownloadStatus(web_contents()));
297 testing_action_ = ACCEPT;
298 CanDownload();
299 ExpectAndResetCounts(1, 0, 1, __LINE__);
300 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
301 download_request_limiter_->GetDownloadStatus(web_contents()));
303 // Navigate to a new URL with the same host, which shouldn't reset the allow
304 // all state.
305 NavigateAndCommit(GURL("http://foo.com/bar2"));
306 BubbleManagerDocumentLoadCompleted();
307 CanDownload();
308 ExpectAndResetCounts(1, 0, 0, __LINE__);
309 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
310 download_request_limiter_->GetDownloadStatus(web_contents()));
312 // Do a user gesture, because we're at allow all, this shouldn't change the
313 // state.
314 OnUserGesture();
315 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
316 download_request_limiter_->GetDownloadStatus(web_contents()));
318 // Navigate to a completely different host, which should reset the state.
319 NavigateAndCommit(GURL("http://fooey.com"));
320 BubbleManagerDocumentLoadCompleted();
321 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
322 download_request_limiter_->GetDownloadStatus(web_contents()));
324 // Do two downloads, allowing the second so that we end up with allow all.
325 CanDownload();
326 ExpectAndResetCounts(1, 0, 0, __LINE__);
327 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
328 download_request_limiter_->GetDownloadStatus(web_contents()));
330 testing_action_ = CANCEL;
331 CanDownload();
332 ExpectAndResetCounts(0, 1, 1, __LINE__);
333 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
334 download_request_limiter_->GetDownloadStatus(web_contents()));
336 // Navigate to a new URL with the same host, which shouldn't reset the allow
337 // all state.
338 NavigateAndCommit(GURL("http://fooey.com/bar2"));
339 BubbleManagerDocumentLoadCompleted();
340 CanDownload();
341 ExpectAndResetCounts(0, 1, 0, __LINE__);
342 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
343 download_request_limiter_->GetDownloadStatus(web_contents()));
346 TEST_F(DownloadRequestLimiterTest, DownloadRequestLimiter_ResetOnUserGesture) {
347 NavigateAndCommit(GURL("http://foo.com/bar"));
348 BubbleManagerDocumentLoadCompleted();
350 // Do one download, which should change to prompt before download.
351 CanDownload();
352 ExpectAndResetCounts(1, 0, 0, __LINE__);
353 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
354 download_request_limiter_->GetDownloadStatus(web_contents()));
356 // Do a user gesture, which should reset back to allow one.
357 OnUserGesture();
358 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
359 download_request_limiter_->GetDownloadStatus(web_contents()));
361 // Ask twice, which triggers calling the delegate. Don't allow the download
362 // so that we end up with not allowed.
363 CanDownload();
364 ExpectAndResetCounts(1, 0, 0, __LINE__);
365 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
366 download_request_limiter_->GetDownloadStatus(web_contents()));
368 testing_action_ = CANCEL;
369 CanDownload();
370 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
371 download_request_limiter_->GetDownloadStatus(web_contents()));
372 ExpectAndResetCounts(0, 1, 1, __LINE__);
374 // A user gesture now should NOT change the state.
375 OnUserGesture();
376 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
377 download_request_limiter_->GetDownloadStatus(web_contents()));
378 // And make sure we really can't download.
379 CanDownload();
380 ExpectAndResetCounts(0, 1, 0, __LINE__);
381 // And the state shouldn't have changed.
382 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
383 download_request_limiter_->GetDownloadStatus(web_contents()));
386 TEST_F(DownloadRequestLimiterTest, DownloadRequestLimiter_ResetOnReload) {
387 NavigateAndCommit(GURL("http://foo.com/bar"));
388 BubbleManagerDocumentLoadCompleted();
389 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
390 download_request_limiter_->GetDownloadStatus(web_contents()));
392 // If the user refreshes the page without responding to the infobar, pretend
393 // like the refresh is the initial load: they get 1 free download (probably
394 // the same as the actual initial load), then an infobar.
395 testing_action_ = WAIT;
397 CanDownload();
398 ExpectAndResetCounts(1, 0, 0, __LINE__);
399 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
400 download_request_limiter_->GetDownloadStatus(web_contents()));
402 CanDownload();
403 ExpectAndResetCounts(0, 0, 1, __LINE__);
404 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
405 download_request_limiter_->GetDownloadStatus(web_contents()));
407 Reload();
408 BubbleManagerDocumentLoadCompleted();
409 base::RunLoop().RunUntilIdle();
410 ExpectAndResetCounts(0, 1, 0, __LINE__);
411 ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
412 download_request_limiter_->GetDownloadStatus(web_contents()));
414 CanDownload();
415 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
416 download_request_limiter_->GetDownloadStatus(web_contents()));
417 ExpectAndResetCounts(1, 0, 0, __LINE__);
419 testing_action_ = CANCEL;
420 CanDownload();
421 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
422 download_request_limiter_->GetDownloadStatus(web_contents()));
423 ExpectAndResetCounts(0, 1, 1, __LINE__);
425 Reload();
426 BubbleManagerDocumentLoadCompleted();
427 base::RunLoop().RunUntilIdle();
428 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
429 download_request_limiter_->GetDownloadStatus(web_contents()));
430 CanDownload();
431 ExpectAndResetCounts(0, 1, 0, __LINE__);
432 ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
433 download_request_limiter_->GetDownloadStatus(web_contents()));
436 #if defined(OS_ANDROID)
437 TEST_F(DownloadRequestLimiterTest, DownloadRequestLimiter_RawWebContents) {
438 scoped_ptr<WebContents> web_contents(CreateTestWebContents());
440 // DownloadRequestLimiter won't try to make a permission bubble if there's
441 // no permission bubble manager, so don't put one on the test WebContents.
443 // DownloadRequestLimiter won't try to make an infobar if it doesn't have an
444 // InfoBarService, and we want to test that it will Cancel() instead of
445 // prompting when it doesn't have a InfoBarService, so unset the delegate.
446 UnsetDelegate();
447 ExpectAndResetCounts(0, 0, 0, __LINE__);
448 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
449 download_request_limiter_->GetDownloadStatus(web_contents.get()));
450 // You get one freebie.
451 CanDownloadFor(web_contents.get());
452 ExpectAndResetCounts(1, 0, 0, __LINE__);
453 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
454 download_request_limiter_->GetDownloadStatus(web_contents.get()));
455 OnUserGestureFor(web_contents.get());
456 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
457 download_request_limiter_->GetDownloadStatus(web_contents.get()));
458 CanDownloadFor(web_contents.get());
459 ExpectAndResetCounts(1, 0, 0, __LINE__);
460 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
461 download_request_limiter_->GetDownloadStatus(web_contents.get()));
462 CanDownloadFor(web_contents.get());
463 ExpectAndResetCounts(0, 1, 0, __LINE__);
464 EXPECT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
465 download_request_limiter_->GetDownloadStatus(web_contents.get()));
466 OnUserGestureFor(web_contents.get());
467 EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
468 download_request_limiter_->GetDownloadStatus(web_contents.get()));
469 CanDownloadFor(web_contents.get());
470 ExpectAndResetCounts(1, 0, 0, __LINE__);
471 EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
472 download_request_limiter_->GetDownloadStatus(web_contents.get()));
474 #endif
476 TEST_F(DownloadRequestLimiterTest,
477 DownloadRequestLimiter_SetHostContentSetting) {
478 NavigateAndCommit(GURL("http://foo.com/bar"));
479 BubbleManagerDocumentLoadCompleted();
480 SetHostContentSetting(web_contents(), CONTENT_SETTING_ALLOW);
482 CanDownload();
483 ExpectAndResetCounts(1, 0, 0, __LINE__);
484 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
485 download_request_limiter_->GetDownloadStatus(web_contents()));
487 CanDownload();
488 ExpectAndResetCounts(1, 0, 0, __LINE__);
489 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
490 download_request_limiter_->GetDownloadStatus(web_contents()));
492 SetHostContentSetting(web_contents(), CONTENT_SETTING_BLOCK);
494 CanDownload();
495 ExpectAndResetCounts(0, 1, 0, __LINE__);
496 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
497 download_request_limiter_->GetDownloadStatus(web_contents()));
499 CanDownload();
500 ExpectAndResetCounts(0, 1, 0, __LINE__);
501 ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
502 download_request_limiter_->GetDownloadStatus(web_contents()));