| Index: content/browser/loader/resource_loader_unittest.cc
|
| diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc
|
| index 8f962118a79976833f6a2ce31c8aadfc8d28b232..17af650a1f1bd8f23527bf09649d8ace246618fe 100644
|
| --- a/content/browser/loader/resource_loader_unittest.cc
|
| +++ b/content/browser/loader/resource_loader_unittest.cc
|
| @@ -4,20 +4,31 @@
|
|
|
| #include "content/browser/loader/resource_loader.h"
|
|
|
| +#include "base/file_util.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 "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 {
|
| @@ -68,11 +79,32 @@ class ClientCertStoreStub : public net::ClientCertStore {
|
| // initialize ResourceLoader.
|
| class ResourceHandlerStub : public ResourceHandler {
|
| public:
|
| - ResourceHandlerStub() : ResourceHandler(NULL) {}
|
| + explicit ResourceHandlerStub(net::URLRequest* request)
|
| + : ResourceHandler(request),
|
| + defer_start_(false),
|
| + received_response_completed_(false),
|
| + total_bytes_downloaded_(0) {
|
| + }
|
| +
|
| + void set_defer_start(bool defer_start) { defer_start_ = defer_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();
|
| + }
|
| +
|
| + // ResourceHandler implementation:
|
| virtual bool OnUploadProgress(int request_id,
|
| uint64 position,
|
| uint64 size) OVERRIDE {
|
| + NOTREACHED();
|
| return true;
|
| }
|
|
|
| @@ -80,16 +112,24 @@ class ResourceHandlerStub : public ResourceHandler {
|
| const GURL& url,
|
| ResourceResponse* response,
|
| bool* defer) OVERRIDE {
|
| + NOTREACHED();
|
| return true;
|
| }
|
|
|
| virtual bool OnResponseStarted(int request_id,
|
| ResourceResponse* response,
|
| - bool* defer) OVERRIDE { return true; }
|
| + 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_start_;
|
| return true;
|
| }
|
|
|
| @@ -97,23 +137,40 @@ class ResourceHandlerStub : public ResourceHandler {
|
| scoped_refptr<net::IOBuffer>* buf,
|
| int* buf_size,
|
| int min_size) OVERRIDE {
|
| - return true;
|
| + NOTREACHED();
|
| + return false;
|
| }
|
|
|
| virtual bool OnReadCompleted(int request_id,
|
| int bytes_read,
|
| bool* defer) OVERRIDE {
|
| - return true;
|
| + NOTREACHED();
|
| + return false;
|
| }
|
|
|
| virtual void OnResponseCompleted(int request_id,
|
| const net::URLRequestStatus& status,
|
| const std::string& security_info,
|
| bool* defer) OVERRIDE {
|
| + // TODO(davidben): This DCHECK currently fires everywhere. Fix the places in
|
| + // ResourceLoader where OnResponseCompleted is signaled twice.
|
| + // DCHECK(!received_response_completed_);
|
| + received_response_completed_ = true;
|
| + status_ = status;
|
| }
|
|
|
| virtual void OnDataDownloaded(int request_id,
|
| - int bytes_downloaded) OVERRIDE {}
|
| + int bytes_downloaded) OVERRIDE {
|
| + total_bytes_downloaded_ += bytes_downloaded;
|
| + }
|
| +
|
| + private:
|
| + bool defer_start_;
|
| + GURL start_url_;
|
| + scoped_refptr<ResourceResponse> response_;
|
| + bool received_response_completed_;
|
| + net::URLRequestStatus status_;
|
| + int total_bytes_downloaded_;
|
| };
|
|
|
| // Test browser client that captures calls to SelectClientCertificates and
|
| @@ -162,6 +219,86 @@ class ResourceContextStub : public MockResourceContext {
|
| scoped_ptr<net::ClientCertStore> dummy_cert_store_;
|
| };
|
|
|
| +class MockTemporaryFileManager
|
| + : public RedirectToFileResourceHandler::Delegate {
|
| + public:
|
| + MockTemporaryFileManager() : error_(base::PLATFORM_FILE_OK) {
|
| + CreateNextTemporary();
|
| + }
|
| +
|
| + net::testing::MockFileStream* next_file_stream() const {
|
| + return next_file_stream_.get();
|
| + }
|
| + ShareableFileReference* next_deletable_file() const {
|
| + return next_deletable_file_.get();
|
| + }
|
| +
|
| + void set_next_error(base::PlatformFileError error) {
|
| + DCHECK_EQ(base::PLATFORM_FILE_OK, error_);
|
| + error_ = error;
|
| + }
|
| +
|
| + // RedirectToFileResourceHandler::Delegate implementation:
|
| + virtual void CreateTemporary(
|
| + int child_id,
|
| + int request_id,
|
| + base::WeakPtr<RedirectToFileResourceHandler> handler) OVERRIDE {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&MockTemporaryFileManager::DoCallback,
|
| + base::Unretained(this), handler));
|
| + }
|
| +
|
| + private:
|
| + void CreateNextTemporary() {
|
| + DCHECK(!next_file_stream_);
|
| +
|
| + base::FilePath file_path;
|
| + ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
|
| + base::PlatformFile platform_file =
|
| + base::CreatePlatformFile(file_path,
|
| + base::PLATFORM_FILE_WRITE |
|
| + base::PLATFORM_FILE_TEMPORARY |
|
| + base::PLATFORM_FILE_CREATE_ALWAYS |
|
| + base::PLATFORM_FILE_ASYNC,
|
| + NULL, NULL);
|
| + ASSERT_NE(base::kInvalidPlatformFileValue, platform_file);
|
| + next_file_stream_.reset(
|
| + new net::testing::MockFileStream(
|
| + platform_file,
|
| + base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC,
|
| + NULL, base::MessageLoopProxy::current()));
|
| + next_deletable_file_ =
|
| + ShareableFileReference::GetOrCreate(
|
| + file_path,
|
| + ShareableFileReference::DELETE_ON_FINAL_RELEASE,
|
| + BrowserThread::GetMessageLoopProxyForThread(
|
| + BrowserThread::FILE).get());
|
| + }
|
| +
|
| + void DoCallback(base::WeakPtr<RedirectToFileResourceHandler> handler) {
|
| + if (!handler)
|
| + return;
|
| +
|
| + if (error_ != base::PLATFORM_FILE_OK) {
|
| + handler->DidCreateTemporaryFile(
|
| + error_, scoped_ptr<net::FileStream>(), NULL);
|
| + error_ = base::PLATFORM_FILE_OK;
|
| + } else {
|
| + DCHECK(next_file_stream_);
|
| + handler->DidCreateTemporaryFile(
|
| + base::PLATFORM_FILE_OK,
|
| + next_file_stream_.PassAs<net::FileStream>(),
|
| + next_deletable_file_.get());
|
| + next_deletable_file_ = NULL;
|
| + }
|
| + }
|
| +
|
| + base::PlatformFileError error_;
|
| + scoped_ptr<net::testing::MockFileStream> next_file_stream_;
|
| + scoped_refptr<ShareableFileReference> next_deletable_file_;
|
| +};
|
| +
|
| } // namespace
|
|
|
| class ResourceLoaderTest : public testing::Test,
|
| @@ -170,6 +307,25 @@ class ResourceLoaderTest : public testing::Test,
|
| ResourceLoaderTest()
|
| : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
|
| resource_context_(&test_url_request_context_) {
|
| + job_factory_.SetProtocolHandler(
|
| + "test", net::URLRequestTestJob::CreateProtocolHandler());
|
| + test_url_request_context_.set_job_factory(&job_factory_);
|
| + }
|
| +
|
| + scoped_ptr<net::URLRequest> CreateTestRequest(const GURL& url) {
|
| + const int kRenderProcessId = 1;
|
| + const int kRenderViewId = 2;
|
| +
|
| + scoped_ptr<net::URLRequest> request(
|
| + new net::URLRequest(url, net::DEFAULT_PRIORITY, NULL,
|
| + resource_context_.GetRequestContext()));
|
| + ResourceRequestInfo::AllocateForTesting(request.get(),
|
| + ResourceType::MAIN_FRAME,
|
| + &resource_context_,
|
| + kRenderProcessId,
|
| + kRenderViewId,
|
| + false);
|
| + return request.Pass();
|
| }
|
|
|
| // ResourceLoaderDelegate:
|
| @@ -200,6 +356,7 @@ class ResourceLoaderTest : public testing::Test,
|
|
|
| content::TestBrowserThreadBundle thread_bundle_;
|
|
|
| + net::URLRequestJobFactoryImpl job_factory_;
|
| net::TestURLRequestContext test_url_request_context_;
|
| ResourceContextStub resource_context_;
|
| };
|
| @@ -209,20 +366,7 @@ class ResourceLoaderTest : public testing::Test,
|
| // certificates are correctly passed to the content browser client for
|
| // selection.
|
| TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
|
| - const int kRenderProcessId = 1;
|
| - const int kRenderViewId = 2;
|
| -
|
| - scoped_ptr<net::URLRequest> request(
|
| - new net::URLRequest(GURL("dummy"),
|
| - net::DEFAULT_PRIORITY,
|
| - NULL,
|
| - resource_context_.GetRequestContext()));
|
| - ResourceRequestInfo::AllocateForTesting(request.get(),
|
| - ResourceType::MAIN_FRAME,
|
| - &resource_context_,
|
| - kRenderProcessId,
|
| - kRenderViewId,
|
| - false);
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(GURL("dummy"));
|
|
|
| // Set up the test client cert store.
|
| net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
|
| @@ -239,7 +383,8 @@ TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
|
| resource_context_.SetClientCertStore(
|
| test_store.PassAs<net::ClientCertStore>());
|
|
|
| - scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub());
|
| + scoped_ptr<ResourceHandler> resource_handler(
|
| + new ResourceHandlerStub(request.get()));
|
| ResourceLoader loader(request.Pass(), resource_handler.Pass(), this);
|
|
|
| // Prepare a dummy certificate request.
|
| @@ -274,26 +419,14 @@ TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
|
| // on a platform with a NULL client cert store still calls the content browser
|
| // client for selection.
|
| TEST_F(ResourceLoaderTest, ClientCertStoreNull) {
|
| - const int kRenderProcessId = 1;
|
| - const int kRenderViewId = 2;
|
| -
|
| - scoped_ptr<net::URLRequest> request(
|
| - new net::URLRequest(GURL("dummy"),
|
| - net::DEFAULT_PRIORITY,
|
| - NULL,
|
| - resource_context_.GetRequestContext()));
|
| - ResourceRequestInfo::AllocateForTesting(request.get(),
|
| - ResourceType::MAIN_FRAME,
|
| - &resource_context_,
|
| - kRenderProcessId,
|
| - kRenderViewId,
|
| - false);
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(GURL("dummy"));
|
|
|
| // Ownership of the |request| is about to be turned over to ResourceLoader. We
|
| // need to keep a raw pointer copy to access this object later.
|
| net::URLRequest* raw_ptr_to_request = request.get();
|
|
|
| - scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub());
|
| + scoped_ptr<ResourceHandler> resource_handler(
|
| + new ResourceHandlerStub(request.get()));
|
| ResourceLoader loader(request.Pass(), resource_handler.Pass(), this);
|
|
|
| // Prepare a dummy certificate request.
|
| @@ -320,4 +453,242 @@ TEST_F(ResourceLoaderTest, ClientCertStoreNull) {
|
| EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
|
| }
|
|
|
| +// Tests that a RedirectToFileResourceHandler works and forwards everything
|
| +// downstream.
|
| +TEST_F(ResourceLoaderTest, RedirectToFile) {
|
| + MockTemporaryFileManager temporary_file_manager;
|
| + base::FilePath temp_path =
|
| + temporary_file_manager.next_deletable_file()->path();
|
| +
|
| + // Set up the request.
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(
|
| + net::URLRequestTestJob::test_url_1());
|
| + ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
|
| + scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
|
| + resource_handler.reset(
|
| + new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(),
|
| + &temporary_file_manager));
|
| + scoped_ptr<ResourceLoader> loader(new ResourceLoader(
|
| + request.Pass(), resource_handler.Pass(), this));
|
| +
|
| + // Run it to completion.
|
| + loader->StartRequest();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Check that the handler forwarded all information to the downstream handler.
|
| + EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
|
| + EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
|
| + EXPECT_TRUE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(net::URLRequestStatus::SUCCESS, leaf_handler->status().status());
|
| + EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(),
|
| + static_cast<size_t>(leaf_handler->total_bytes_downloaded()));
|
| +
|
| + // Check that the data was written to the file.
|
| + std::string contents;
|
| + ASSERT_TRUE(base::ReadFileToString(temp_path, &contents));
|
| + EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents);
|
| +
|
| + // Release the loader. The file should be gone now.
|
| + loader.reset();
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(base::PathExists(temp_path));
|
| +}
|
| +
|
| +// Tests that RedirectToFileResourceHandler handles errors in creating the
|
| +// temporary file.
|
| +TEST_F(ResourceLoaderTest, RedirectToFileCreateTemporaryError) {
|
| + MockTemporaryFileManager temporary_file_manager;
|
| + temporary_file_manager.set_next_error(base::PLATFORM_FILE_ERROR_FAILED);
|
| +
|
| + // Set up the request.
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(
|
| + net::URLRequestTestJob::test_url_1());
|
| + ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
|
| + scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
|
| + resource_handler.reset(
|
| + new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(),
|
| + &temporary_file_manager));
|
| + scoped_ptr<ResourceLoader> loader(new ResourceLoader(
|
| + request.Pass(), resource_handler.Pass(), this));
|
| +
|
| + // Run it to completion.
|
| + loader->StartRequest();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // To downstream, the request was canceled.
|
| + EXPECT_TRUE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
|
| + EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
|
| +}
|
| +
|
| +// Tests that RedirectToFileResourceHandler handles synchronous write errors.
|
| +TEST_F(ResourceLoaderTest, RedirectToFileWriteError) {
|
| + MockTemporaryFileManager temporary_file_manager;
|
| + base::FilePath temp_path =
|
| + temporary_file_manager.next_deletable_file()->path();
|
| + net::testing::MockFileStream* mock_file_stream =
|
| + temporary_file_manager.next_file_stream();
|
| + mock_file_stream->set_forced_error(net::ERR_FAILED);
|
| +
|
| + // Set up the request.
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(
|
| + net::URLRequestTestJob::test_url_1());
|
| + ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
|
| + scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
|
| + resource_handler.reset(
|
| + new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(),
|
| + &temporary_file_manager));
|
| + scoped_ptr<ResourceLoader> loader(new ResourceLoader(
|
| + request.Pass(), resource_handler.Pass(), this));
|
| +
|
| + // Run it to completion.
|
| + loader->StartRequest();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // To downstream, the request was canceled sometime after it started, but
|
| + // before any data was written.
|
| + EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
|
| + EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
|
| + EXPECT_TRUE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
|
| + EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
|
| +}
|
| +
|
| +// Tests that RedirectToFileResourceHandler handles asynchronous write errors.
|
| +TEST_F(ResourceLoaderTest, RedirectToFileWriteErrorAsync) {
|
| + MockTemporaryFileManager temporary_file_manager;
|
| + base::FilePath temp_path =
|
| + temporary_file_manager.next_deletable_file()->path();
|
| + net::testing::MockFileStream* mock_file_stream =
|
| + temporary_file_manager.next_file_stream();
|
| + mock_file_stream->set_forced_error_async(net::ERR_FAILED);
|
| +
|
| + // Set up the request.
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(
|
| + net::URLRequestTestJob::test_url_1());
|
| + ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
|
| + scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
|
| + resource_handler.reset(
|
| + new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(),
|
| + &temporary_file_manager));
|
| + scoped_ptr<ResourceLoader> loader(new ResourceLoader(
|
| + request.Pass(), resource_handler.Pass(), this));
|
| +
|
| + // Run it to completion.
|
| + loader->StartRequest();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // To downstream, the request was canceled sometime after it started, but
|
| + // before any data was written.
|
| + EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
|
| + EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
|
| + EXPECT_TRUE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
|
| + EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
|
| +}
|
| +
|
| +// Tests that RedirectToFileHandler defers completion if there are outstanding
|
| +// writes and accounts for errors which occur in that time.
|
| +TEST_F(ResourceLoaderTest, RedirectToFileDeferCompletion) {
|
| + // Program the MockFileStream to error asynchronously, but throttle the
|
| + // callback.
|
| + MockTemporaryFileManager temporary_file_manager;
|
| + base::FilePath temp_path =
|
| + temporary_file_manager.next_deletable_file()->path();
|
| + net::testing::MockFileStream* mock_file_stream =
|
| + temporary_file_manager.next_file_stream();
|
| + mock_file_stream->set_forced_error_async(net::ERR_FAILED);
|
| + mock_file_stream->ThrottleCallbacks();
|
| +
|
| + // Set up the request.
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(
|
| + net::URLRequestTestJob::test_url_1());
|
| + net::URLRequest* raw_ptr_to_request = request.get();
|
| + ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
|
| + scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
|
| + resource_handler.reset(
|
| + new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(),
|
| + &temporary_file_manager));
|
| + scoped_ptr<ResourceLoader> loader(new ResourceLoader(
|
| + request.Pass(), resource_handler.Pass(), this));
|
| +
|
| + // Run it as far as it will go.
|
| + loader->StartRequest();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // At this point, the request should have completed.
|
| + EXPECT_EQ(net::URLRequestStatus::SUCCESS,
|
| + raw_ptr_to_request->status().status());
|
| +
|
| + // However, the resource loader stack is stuck somewhere after receiving the
|
| + // response.
|
| + EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
|
| + EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
|
| + EXPECT_FALSE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
|
| +
|
| + // Now, release the floodgates.
|
| + mock_file_stream->ReleaseCallbacks();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Although the URLRequest was successful, the leaf handler sees a failure
|
| + // because the write never completed.
|
| + EXPECT_TRUE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
|
| +}
|
| +
|
| +// Tests that a RedirectToFileResourceHandler behaves properly when the
|
| +// downstream handler defers OnWillStart.
|
| +TEST_F(ResourceLoaderTest, RedirectToFileDownstreamDeferStart) {
|
| + MockTemporaryFileManager temporary_file_manager;
|
| + base::FilePath temp_path =
|
| + temporary_file_manager.next_deletable_file()->path();
|
| +
|
| + // Set up the request.
|
| + scoped_ptr<net::URLRequest> request = CreateTestRequest(
|
| + net::URLRequestTestJob::test_url_1());
|
| + ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
|
| + scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
|
| + resource_handler.reset(
|
| + new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(),
|
| + &temporary_file_manager));
|
| + scoped_ptr<ResourceLoader> loader(new ResourceLoader(
|
| + request.Pass(), resource_handler.Pass(), this));
|
| +
|
| + // Defer OnWillStart.
|
| + leaf_handler->set_defer_start(true);
|
| +
|
| + // Run as far as we'll go.
|
| + loader->StartRequest();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The request should have stopped at OnWillStart.
|
| + EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
|
| + EXPECT_FALSE(leaf_handler->response());
|
| + EXPECT_FALSE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
|
| +
|
| + // Now resume the request. Now we complete.
|
| + leaf_handler->Resume();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Check that the handler forwarded all information to the downstream handler.
|
| + EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
|
| + EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
|
| + EXPECT_TRUE(leaf_handler->received_response_completed());
|
| + EXPECT_EQ(net::URLRequestStatus::SUCCESS, leaf_handler->status().status());
|
| + EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(),
|
| + static_cast<size_t>(leaf_handler->total_bytes_downloaded()));
|
| +
|
| + // Check that the data was written to the file.
|
| + std::string contents;
|
| + ASSERT_TRUE(base::ReadFileToString(temp_path, &contents));
|
| + EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents);
|
| +
|
| + // Release the loader. The file should be gone now.
|
| + loader.reset();
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(base::PathExists(temp_path));
|
| +}
|
| +
|
| } // namespace content
|
|
|