blob: 47bb914536ecbae6f8ecebba2d091189e597e881 [file] [log] [blame] [edit]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "chrome/browser/download/download_request_limiter.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/tab_contents/test_tab_contents.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread;
using content::WebContents;
class DownloadRequestLimiterTest : public TabContentsTestHarness {
public:
DownloadRequestLimiterTest()
: ui_thread_(BrowserThread::UI, &message_loop_),
file_user_blocking_thread_(
BrowserThread::FILE_USER_BLOCKING, &message_loop_),
io_thread_(BrowserThread::IO, &message_loop_) {
}
virtual void SetUp() {
TabContentsTestHarness::SetUp();
allow_download_ = true;
ask_allow_count_ = cancel_count_ = continue_count_ = 0;
download_request_limiter_ = new DownloadRequestLimiter();
test_delegate_.reset(new DownloadRequestLimiterTestDelegate(this));
DownloadRequestLimiter::SetTestingDelegate(test_delegate_.get());
}
virtual void TearDown() {
UnsetDelegate();
TabContentsTestHarness::TearDown();
}
virtual void UnsetDelegate() {
DownloadRequestLimiter::SetTestingDelegate(NULL);
}
void CanDownload() {
CanDownloadFor(web_contents());
}
void CanDownloadFor(WebContents* web_contents) {
download_request_limiter_->CanDownloadImpl(
web_contents,
-1, // request id
"GET", // request method
base::Bind(&DownloadRequestLimiterTest::ContinueDownload,
base::Unretained(this)));
message_loop_.RunAllPending();
}
void OnUserGesture() {
OnUserGestureFor(web_contents());
}
void OnUserGestureFor(WebContents* web_contents) {
DownloadRequestLimiter::TabDownloadState* state =
download_request_limiter_->GetDownloadState(web_contents, NULL, false);
if (state)
state->DidGetUserGesture();
}
bool ShouldAllowDownload() {
ask_allow_count_++;
return allow_download_;
}
protected:
void ContinueDownload(bool allow) {
if (allow) {
continue_count_++;
} else {
cancel_count_++;
}
}
class DownloadRequestLimiterTestDelegate
: public DownloadRequestLimiter::TestingDelegate {
public:
explicit DownloadRequestLimiterTestDelegate(
DownloadRequestLimiterTest* test)
: test_(test) { }
virtual bool ShouldAllowDownload() {
return test_->ShouldAllowDownload();
}
private:
DownloadRequestLimiterTest* test_;
};
scoped_ptr<DownloadRequestLimiterTestDelegate> test_delegate_;
scoped_refptr<DownloadRequestLimiter> download_request_limiter_;
// Number of times ContinueDownload was invoked.
int continue_count_;
// Number of times CancelDownload was invoked.
int cancel_count_;
// Whether the download should be allowed.
bool allow_download_;
// Number of times ShouldAllowDownload was invoked.
int ask_allow_count_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_user_blocking_thread_;
content::TestBrowserThread io_thread_;
};
TEST_F(DownloadRequestLimiterTest,
DownloadRequestLimiter_Allow) {
// All tabs should initially start at ALLOW_ONE_DOWNLOAD.
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(contents()));
// Ask if the tab can do a download. This moves to PROMPT_BEFORE_DOWNLOAD.
CanDownload();
ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(contents()));
// We should have been told we can download.
ASSERT_EQ(1, continue_count_);
ASSERT_EQ(0, cancel_count_);
ASSERT_EQ(0, ask_allow_count_);
continue_count_ = 0;
// Ask again. This triggers asking the delegate for allow/disallow.
allow_download_ = true;
CanDownload();
// This should ask us if the download is allowed.
ASSERT_EQ(1, ask_allow_count_);
ask_allow_count_ = 0;
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
download_request_limiter_->GetDownloadStatus(contents()));
// We should have been told we can download.
ASSERT_EQ(1, continue_count_);
ASSERT_EQ(0, cancel_count_);
continue_count_ = 0;
// Ask again and make sure continue is invoked.
CanDownload();
// The state is at allow_all, which means the delegate shouldn't be asked.
ASSERT_EQ(0, ask_allow_count_);
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
download_request_limiter_->GetDownloadStatus(contents()));
// We should have been told we can download.
ASSERT_EQ(1, continue_count_);
ASSERT_EQ(0, cancel_count_);
continue_count_ = 0;
}
TEST_F(DownloadRequestLimiterTest,
DownloadRequestLimiter_ResetOnNavigation) {
NavigateAndCommit(GURL("http://foo.com/bar"));
// Do two downloads, allowing the second so that we end up with allow all.
CanDownload();
allow_download_ = true;
CanDownload();
ask_allow_count_ = continue_count_ = cancel_count_ = 0;
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
download_request_limiter_->GetDownloadStatus(contents()));
// Navigate to a new URL with the same host, which shouldn't reset the allow
// all state.
NavigateAndCommit(GURL("http://foo.com/bar2"));
CanDownload();
ASSERT_EQ(1, continue_count_);
ASSERT_EQ(0, cancel_count_);
ASSERT_EQ(0, ask_allow_count_);
ask_allow_count_ = continue_count_ = cancel_count_ = 0;
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
download_request_limiter_->GetDownloadStatus(contents()));
// Do a user gesture, because we're at allow all, this shouldn't change the
// state.
OnUserGesture();
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS,
download_request_limiter_->GetDownloadStatus(contents()));
// Navigate to a completely different host, which should reset the state.
NavigateAndCommit(GURL("http://fooey.com"));
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(contents()));
}
TEST_F(DownloadRequestLimiterTest,
DownloadRequestLimiter_ResetOnUserGesture) {
NavigateAndCommit(GURL("http://foo.com/bar"));
// Do one download, which should change to prompt before download.
CanDownload();
ask_allow_count_ = continue_count_ = cancel_count_ = 0;
ASSERT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(contents()));
// Do a user gesture, which should reset back to allow one.
OnUserGesture();
ASSERT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(contents()));
// Ask twice, which triggers calling the delegate. Don't allow the download
// so that we end up with not allowed.
allow_download_ = false;
CanDownload();
CanDownload();
ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
download_request_limiter_->GetDownloadStatus(contents()));
// A user gesture now should NOT change the state.
OnUserGesture();
ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
download_request_limiter_->GetDownloadStatus(contents()));
// And make sure we really can't download.
ask_allow_count_ = continue_count_ = cancel_count_ = 0;
CanDownload();
ASSERT_EQ(0, ask_allow_count_);
ASSERT_EQ(0, continue_count_);
ASSERT_EQ(1, cancel_count_);
// And the state shouldn't have changed.
ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
download_request_limiter_->GetDownloadStatus(contents()));
}
TEST_F(DownloadRequestLimiterTest,
DownloadRequestLimiter_RawWebContents) {
// By-pass TabContentsTestHarness and use
// RenderViewHostTestHarness::CreateTestWebContents() directly so that there
// will be no TabContents for web_contents.
scoped_ptr<WebContents> web_contents(CreateTestWebContents());
TabContents* tab_contents = TabContents::FromWebContents(web_contents.get());
ASSERT_TRUE(tab_contents == NULL);
// DownloadRequestLimiter won't try to make an infobar if it doesn't have a
// TabContents, and we want to test that it will Cancel() instead of prompting
// when it doesn't have a TabContents, so unset the delegate.
UnsetDelegate();
EXPECT_EQ(0, continue_count_);
EXPECT_EQ(0, cancel_count_);
EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(web_contents.get()));
// You get one freebie.
CanDownloadFor(web_contents.get());
EXPECT_EQ(1, continue_count_);
EXPECT_EQ(0, cancel_count_);
EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(web_contents.get()));
OnUserGestureFor(web_contents.get());
EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(web_contents.get()));
CanDownloadFor(web_contents.get());
EXPECT_EQ(2, continue_count_);
EXPECT_EQ(0, cancel_count_);
EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(web_contents.get()));
CanDownloadFor(web_contents.get());
EXPECT_EQ(2, continue_count_);
EXPECT_EQ(1, cancel_count_);
EXPECT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
download_request_limiter_->GetDownloadStatus(web_contents.get()));
OnUserGestureFor(web_contents.get());
EXPECT_EQ(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(web_contents.get()));
CanDownloadFor(web_contents.get());
EXPECT_EQ(3, continue_count_);
EXPECT_EQ(1, cancel_count_);
EXPECT_EQ(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD,
download_request_limiter_->GetDownloadStatus(web_contents.get()));
}