This source file includes following definitions.
- request_count_
- requested_authorities
- request_count
- GetClientCerts
- total_bytes_downloaded_
- set_defer_request_on_will_start
- start_url
- response
- received_response_completed
- status
- total_bytes_downloaded
- Resume
- OnUploadProgress
- OnRequestRedirected
- OnResponseStarted
- OnWillStart
- OnBeforeNetworkStart
- OnWillRead
- OnReadCompleted
- OnResponseCompleted
- OnDataDownloaded
- SelectClientCertificate
- call_count
- passed_certs
- CreateClientCertStore
- SetClientCertStore
- CreateTemporaryError
- raw_ptr_to_request_
- test_url
- test_data
- WrapResourceHandler
- SetUp
- CreateLoginDelegate
- HandleExternalProtocol
- DidStartRequest
- DidReceiveRedirect
- DidReceiveResponse
- DidFinishLoading
- TEST_F
- TEST_F
- TEST_F
- redirect_to_file_resource_handler_
- temp_path
- deletable_file
- file_stream
- redirect_to_file_resource_handler
- ReleaseLoader
- WrapResourceHandler
- PostCallback
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "content/browser/loader/resource_loader.h"
#include "base/file_util.h"
#include "base/files/file.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/platform_file.h"
#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/loader/redirect_to_file_resource_handler.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_response.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_message.h"
#include "net/base/mock_file_stream.h"
#include "net/base/request_priority.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/common/blob/shareable_file_reference.h"
using webkit_blob::ShareableFileReference;
namespace content {
namespace {
class ClientCertStoreStub : public net::ClientCertStore {
public:
ClientCertStoreStub(const net::CertificateList& certs)
: response_(certs),
request_count_(0) {}
virtual ~ClientCertStoreStub() {}
std::vector<std::string> requested_authorities() {
return requested_authorities_;
}
int request_count() {
return request_count_;
}
virtual void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
net::CertificateList* selected_certs,
const base::Closure& callback) OVERRIDE {
++request_count_;
requested_authorities_ = cert_request_info.cert_authorities;
*selected_certs = response_;
callback.Run();
}
private:
const net::CertificateList response_;
int request_count_;
std::vector<std::string> requested_authorities_;
};
class ResourceHandlerStub : public ResourceHandler {
public:
explicit ResourceHandlerStub(net::URLRequest* request)
: ResourceHandler(request),
defer_request_on_will_start_(false),
received_response_completed_(false),
total_bytes_downloaded_(0) {
}
void set_defer_request_on_will_start(bool defer_request_on_will_start) {
defer_request_on_will_start_ = defer_request_on_will_start;
}
const GURL& start_url() const { return start_url_; }
ResourceResponse* response() const { return response_.get(); }
bool received_response_completed() const {
return received_response_completed_;
}
const net::URLRequestStatus& status() const { return status_; }
int total_bytes_downloaded() const { return total_bytes_downloaded_; }
void Resume() {
controller()->Resume();
}
virtual bool OnUploadProgress(int request_id,
uint64 position,
uint64 size) OVERRIDE {
NOTREACHED();
return true;
}
virtual bool OnRequestRedirected(int request_id,
const GURL& url,
ResourceResponse* response,
bool* defer) OVERRIDE {
NOTREACHED();
return true;
}
virtual bool OnResponseStarted(int request_id,
ResourceResponse* response,
bool* defer) OVERRIDE {
EXPECT_FALSE(response_);
response_ = response;
return true;
}
virtual bool OnWillStart(int request_id,
const GURL& url,
bool* defer) OVERRIDE {
EXPECT_TRUE(start_url_.is_empty());
start_url_ = url;
*defer = defer_request_on_will_start_;
return true;
}
virtual bool OnBeforeNetworkStart(int request_id,
const GURL& url,
bool* defer) OVERRIDE {
return true;
}
virtual bool OnWillRead(int request_id,
scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE {
NOTREACHED();
return false;
}
virtual bool OnReadCompleted(int request_id,
int bytes_read,
bool* defer) OVERRIDE {
NOTREACHED();
return false;
}
virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
const std::string& security_info,
bool* defer) OVERRIDE {
received_response_completed_ = true;
status_ = status;
}
virtual void OnDataDownloaded(int request_id,
int bytes_downloaded) OVERRIDE {
total_bytes_downloaded_ += bytes_downloaded;
}
private:
bool defer_request_on_will_start_;
GURL start_url_;
scoped_refptr<ResourceResponse> response_;
bool received_response_completed_;
net::URLRequestStatus status_;
int total_bytes_downloaded_;
};
class SelectCertificateBrowserClient : public TestContentBrowserClient {
public:
SelectCertificateBrowserClient() : call_count_(0) {}
virtual void SelectClientCertificate(
int render_process_id,
int render_view_id,
const net::HttpNetworkSession* network_session,
net::SSLCertRequestInfo* cert_request_info,
const base::Callback<void(net::X509Certificate*)>& callback) OVERRIDE {
++call_count_;
passed_certs_ = cert_request_info->client_certs;
}
int call_count() {
return call_count_;
}
net::CertificateList passed_certs() {
return passed_certs_;
}
private:
net::CertificateList passed_certs_;
int call_count_;
};
class ResourceContextStub : public MockResourceContext {
public:
explicit ResourceContextStub(net::URLRequestContext* test_request_context)
: MockResourceContext(test_request_context) {}
virtual scoped_ptr<net::ClientCertStore> CreateClientCertStore() OVERRIDE {
return dummy_cert_store_.Pass();
}
void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
dummy_cert_store_ = store.Pass();
}
private:
scoped_ptr<net::ClientCertStore> dummy_cert_store_;
};
void CreateTemporaryError(
base::File::Error error,
const CreateTemporaryFileStreamCallback& callback) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
scoped_refptr<ShareableFileReference>()));
}
}
class ResourceLoaderTest : public testing::Test,
public ResourceLoaderDelegate {
protected:
ResourceLoaderTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
resource_context_(&test_url_request_context_),
raw_ptr_resource_handler_(NULL),
raw_ptr_to_request_(NULL) {
job_factory_.SetProtocolHandler(
"test", net::URLRequestTestJob::CreateProtocolHandler());
test_url_request_context_.set_job_factory(&job_factory_);
}
GURL test_url() const {
return net::URLRequestTestJob::test_url_1();
}
std::string test_data() const {
return net::URLRequestTestJob::test_data_1();
}
virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
scoped_ptr<ResourceHandlerStub> leaf_handler,
net::URLRequest* request) {
return leaf_handler.PassAs<ResourceHandler>();
}
virtual void SetUp() OVERRIDE {
const int kRenderProcessId = 1;
const int kRenderViewId = 2;
scoped_ptr<net::URLRequest> request(
new net::URLRequest(test_url(),
net::DEFAULT_PRIORITY,
NULL,
resource_context_.GetRequestContext()));
raw_ptr_to_request_ = request.get();
ResourceRequestInfo::AllocateForTesting(request.get(),
ResourceType::MAIN_FRAME,
&resource_context_,
kRenderProcessId,
kRenderViewId,
MSG_ROUTING_NONE,
false);
scoped_ptr<ResourceHandlerStub> resource_handler(
new ResourceHandlerStub(request.get()));
raw_ptr_resource_handler_ = resource_handler.get();
loader_.reset(new ResourceLoader(
request.Pass(),
WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
this));
}
virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
ResourceLoader* loader,
net::AuthChallengeInfo* auth_info) OVERRIDE {
return NULL;
}
virtual bool HandleExternalProtocol(ResourceLoader* loader,
const GURL& url) OVERRIDE {
return false;
}
virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {}
virtual void DidReceiveRedirect(ResourceLoader* loader,
const GURL& new_url) OVERRIDE {}
virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {}
virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {}
content::TestBrowserThreadBundle thread_bundle_;
net::URLRequestJobFactoryImpl job_factory_;
net::TestURLRequestContext test_url_request_context_;
ResourceContextStub resource_context_;
ResourceHandlerStub* raw_ptr_resource_handler_;
net::URLRequest* raw_ptr_to_request_;
scoped_ptr<ResourceLoader> loader_;
};
TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
new net::X509Certificate("test", "test", base::Time(), base::Time())));
scoped_ptr<ClientCertStoreStub> test_store(
new ClientCertStoreStub(dummy_certs));
EXPECT_EQ(0, test_store->request_count());
ClientCertStoreStub* raw_ptr_to_store = test_store.get();
resource_context_.SetClientCertStore(
test_store.PassAs<net::ClientCertStore>());
scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
new net::SSLCertRequestInfo());
std::vector<std::string> dummy_authority(1, "dummy");
cert_request_info->cert_authorities = dummy_authority;
SelectCertificateBrowserClient test_client;
ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
base::RunLoop().RunUntilIdle();
SetBrowserClientForTesting(old_client);
EXPECT_EQ(1, raw_ptr_to_store->request_count());
EXPECT_EQ(dummy_authority, raw_ptr_to_store->requested_authorities());
EXPECT_EQ(1, test_client.call_count());
EXPECT_EQ(dummy_certs, test_client.passed_certs());
}
TEST_F(ResourceLoaderTest, ClientCertStoreNull) {
scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
new net::SSLCertRequestInfo());
std::vector<std::string> dummy_authority(1, "dummy");
cert_request_info->cert_authorities = dummy_authority;
SelectCertificateBrowserClient test_client;
ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
base::RunLoop().RunUntilIdle();
SetBrowserClientForTesting(old_client);
EXPECT_EQ(1, test_client.call_count());
EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
}
TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
loader_->StartRequest();
loader_->CancelRequest(true);
static_cast<ResourceController*>(loader_.get())->Resume();
}
class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
public:
ResourceLoaderRedirectToFileTest()
: file_stream_(NULL),
redirect_to_file_resource_handler_(NULL) {
}
base::FilePath temp_path() const { return temp_path_; }
ShareableFileReference* deletable_file() const {
return deletable_file_.get();
}
net::testing::MockFileStream* file_stream() const { return file_stream_; }
RedirectToFileResourceHandler* redirect_to_file_resource_handler() const {
return redirect_to_file_resource_handler_;
}
void ReleaseLoader() {
file_stream_ = NULL;
deletable_file_ = NULL;
loader_.reset();
}
virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
scoped_ptr<ResourceHandlerStub> leaf_handler,
net::URLRequest* request) OVERRIDE {
CHECK(base::CreateTemporaryFile(&temp_path_));
int flags = base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_ASYNC;
base::File file(temp_path_, flags);
CHECK(file.IsValid());
scoped_ptr<net::testing::MockFileStream> file_stream(
new net::testing::MockFileStream(file.Pass(), NULL,
base::MessageLoopProxy::current()));
file_stream_ = file_stream.get();
deletable_file_ = ShareableFileReference::GetOrCreate(
temp_path_,
ShareableFileReference::DELETE_ON_FINAL_RELEASE,
BrowserThread::GetMessageLoopProxyForThread(
BrowserThread::FILE).get());
scoped_ptr<RedirectToFileResourceHandler> handler(
new RedirectToFileResourceHandler(
leaf_handler.PassAs<ResourceHandler>(), request));
redirect_to_file_resource_handler_ = handler.get();
handler->SetCreateTemporaryFileStreamFunctionForTesting(
base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
base::Unretained(this),
base::Passed(file_stream.PassAs<net::FileStream>())));
return handler.PassAs<ResourceHandler>();
}
private:
void PostCallback(
scoped_ptr<net::FileStream> file_stream,
const CreateTemporaryFileStreamCallback& callback) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(callback, base::File::FILE_OK,
base::Passed(&file_stream), deletable_file_));
}
base::FilePath temp_path_;
scoped_refptr<ShareableFileReference> deletable_file_;
net::testing::MockFileStream* file_stream_;
RedirectToFileResourceHandler* redirect_to_file_resource_handler_;
};
TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
loader_->StartRequest();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(temp_path(),
raw_ptr_resource_handler_->response()->head.download_file_path);
EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(net::URLRequestStatus::SUCCESS,
raw_ptr_resource_handler_->status().status());
EXPECT_EQ(test_data().size(), static_cast<size_t>(
raw_ptr_resource_handler_->total_bytes_downloaded()));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
EXPECT_EQ(test_data(), contents);
ReleaseLoader();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(temp_path()));
}
TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) {
redirect_to_file_resource_handler()->
SetCreateTemporaryFileStreamFunctionForTesting(
base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
loader_->StartRequest();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(net::URLRequestStatus::CANCELED,
raw_ptr_resource_handler_->status().status());
EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
}
TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
file_stream()->set_forced_error(net::ERR_FAILED);
loader_->StartRequest();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(temp_path(),
raw_ptr_resource_handler_->response()->head.download_file_path);
EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(net::URLRequestStatus::CANCELED,
raw_ptr_resource_handler_->status().status());
EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
ReleaseLoader();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(temp_path()));
}
TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
file_stream()->set_forced_error_async(net::ERR_FAILED);
loader_->StartRequest();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(temp_path(),
raw_ptr_resource_handler_->response()->head.download_file_path);
EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(net::URLRequestStatus::CANCELED,
raw_ptr_resource_handler_->status().status());
EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
ReleaseLoader();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(temp_path()));
}
TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) {
file_stream()->set_forced_error_async(net::ERR_FAILED);
file_stream()->ThrottleCallbacks();
loader_->StartRequest();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(net::URLRequestStatus::SUCCESS,
raw_ptr_to_request_->status().status());
EXPECT_EQ(temp_path(),
raw_ptr_resource_handler_->response()->head.download_file_path);
EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
file_stream()->ReleaseCallbacks();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(net::URLRequestStatus::CANCELED,
raw_ptr_resource_handler_->status().status());
ReleaseLoader();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(temp_path()));
}
TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
loader_->StartRequest();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
EXPECT_FALSE(raw_ptr_resource_handler_->response());
EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
raw_ptr_resource_handler_->Resume();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(temp_path(),
raw_ptr_resource_handler_->response()->head.download_file_path);
EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
EXPECT_EQ(net::URLRequestStatus::SUCCESS,
raw_ptr_resource_handler_->status().status());
EXPECT_EQ(test_data().size(), static_cast<size_t>(
raw_ptr_resource_handler_->total_bytes_downloaded()));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
EXPECT_EQ(test_data(), contents);
ReleaseLoader();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(temp_path()));
}
}