diff options
author | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-13 00:00:12 +0000 |
---|---|---|
committer | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-13 00:00:12 +0000 |
commit | 1a8b5cfbd8327be9d424204d73c0fa1adec2fbec (patch) | |
tree | 605bc96791f30ac2661b2b7770e614db483bacbc | |
parent | 534eb62782c2cf6d0f719a434c28f7efe11e9383 (diff) | |
download | chromium_src-1a8b5cfbd8327be9d424204d73c0fa1adec2fbec.zip chromium_src-1a8b5cfbd8327be9d424204d73c0fa1adec2fbec.tar.gz chromium_src-1a8b5cfbd8327be9d424204d73c0fa1adec2fbec.tar.bz2 |
Revert 256688 "Fix various issues in RedirectToFileResourceHandler."
The linux asan bot went red
ResourceDispatcherHostTest.DownloadToFile (run #1):
[ RUN ] ResourceDispatcherHostTest.DownloadToFile
[ OK ] ResourceDispatcherHostTest.DownloadToFile (212 ms)
[----------] 1 test from ResourceDispatcherHostTest (212 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (213 ms total)
[ PASSED ] 1 test.
YOU HAVE 5 DISABLED TESTS
=================================================================
==9125==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x49be81 in operator new(unsigned long) /usr/local/google/work/chromium/src/third_party/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:54
#1 0x23ce695 in content::ResourceDispatcherHostImpl::BeginRequest(int, ResourceHostMsg_Request const&, IPC::Message*, int) content/browser/loader/resource_dispatcher_host_impl.cc:1045
#2 0x23cba80 in OnRequestResource content/browser/loader/resource_dispatcher_host_impl.cc:879
#3 0x23cba80 in Dispatch\u003Ccontent::ResourceDispatcherHostImpl, content::ResourceDispatcherHostImpl, int, const ResourceHostMsg_Request &> content/common/resource_messages.h:305
#4 0x23cba80 in content::ResourceDispatcherHostImpl::OnMessageReceived(IPC::Message const&, content::ResourceMessageFilter*, bool*) content/browser/loader/resource_dispatcher_host_impl.cc:841
#5 0xe04954 in content::ResourceDispatcherHostTest_DownloadToFile_Test::TestBody() content/browser/loader/resource_dispatcher_host_unittest.cc:2840
#6 0x2c10c9a in HandleExceptionsInMethodIfSupported\u003Ctesting::Test, void> testing/gtest/src/gtest.cc:2045
#7 0x2c10c9a in testing::Test::Run() testing/gtest/src/gtest.cc:2061
#8 0x2c12dea in testing::TestInfo::Run() testing/gtest/src/gtest.cc:2237
#9 0x2c13bb3 in testing::TestCase::Run() testing/gtest/src/gtest.cc:2344
#10 0x2c24c6a in testing::internal::UnitTestImpl::RunAllTests() testing/gtest/src/gtest.cc:4065
#11 0x2c24250 in HandleExceptionsInMethodIfSupported\u003Ctesting::internal::UnitTestImpl, bool> testing/gtest/src/gtest.cc:2045
#12 0x2c24250 in testing::UnitTest::Run() testing/gtest/src/gtest.cc:3697
#13 0x2b9ed2c in RUN_ALL_TESTS testing/gtest/include/gtest/gtest.h:2231
#14 0x2b9ed2c in base::TestSuite::Run() base/test/test_suite.cc:213
#15 0x2b92bcb in Run base/callback.h:401
#16 0x2b92bcb in base::(anonymous namespace)::LaunchUnitTestsInternal(int, char**, base::Callback\u003Cint ()> const&, int) base/test/launcher/unit_test_launcher.cc:494
#17 0x199a83e in main content/test/run_all_unittests.cc:14
#18 0x7f6e898bf76c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
SUMMARY: AddressSanitizer: 16 byte(s) leaked in 1 allocation(s).
http://build.chromium.org/p/chromium.memory/builders/Linux%20ASan%2BLSan%20Tests%20%282%29/builds/409
> Fix various issues in RedirectToFileResourceHandler.
>
> - Handle errors in creating temporary files.
> - Cancel on write failure instead of resuming. This used to work, but got
> lost in some refactoring in r142108.
> - Fix the OnResponseCompleted resume logic to account for partial writes.
> - Don't lose write errors which occur after OnResponseCompleted is received.
> - WeakPtrFactory goes after other members.
> - OnWillStart was never forwarded to downstream handlers.
> - Make sure the file is closed before deleting it.
>
> Also add a lot of machinery so we can better unit test this stack.
>
> BUG=316634,347663
> TEST=ResourceDispatcherHostTest.DownloadToFile
> ResourceDispatcherHostTest.RegisterDownloadedTempFile
> ResourceLoaderTest.RedirectToFile*
> TemporaryFileStreamTest.Basic
>
> Review URL: https://codereview.chromium.org/82273002
TBR=davidben@chromium.org
Review URL: https://codereview.chromium.org/196533013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@256704 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/loader/async_resource_handler.cc | 9 | ||||
-rw-r--r-- | content/browser/loader/redirect_to_file_resource_handler.cc | 209 | ||||
-rw-r--r-- | content/browser/loader/redirect_to_file_resource_handler.h | 67 | ||||
-rw-r--r-- | content/browser/loader/resource_dispatcher_host_impl.cc | 22 | ||||
-rw-r--r-- | content/browser/loader/resource_dispatcher_host_impl.h | 2 | ||||
-rw-r--r-- | content/browser/loader/resource_dispatcher_host_unittest.cc | 232 | ||||
-rw-r--r-- | content/browser/loader/resource_loader_unittest.cc | 355 | ||||
-rw-r--r-- | content/browser/loader/sync_resource_handler.cc | 12 | ||||
-rw-r--r-- | content/browser/loader/temporary_file_stream.cc | 61 | ||||
-rw-r--r-- | content/browser/loader/temporary_file_stream.h | 46 | ||||
-rw-r--r-- | content/browser/loader/temporary_file_stream_unittest.cc | 120 | ||||
-rw-r--r-- | content/content_browser.gypi | 2 | ||||
-rw-r--r-- | content/content_tests.gypi | 1 | ||||
-rw-r--r-- | net/base/mock_file_stream.cc | 126 | ||||
-rw-r--r-- | net/base/mock_file_stream.h | 47 | ||||
-rw-r--r-- | net/url_request/url_request_test_job.cc | 16 | ||||
-rw-r--r-- | net/url_request/url_request_test_job.h | 5 |
17 files changed, 128 insertions, 1204 deletions
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc index 7014a47..5326b66 100644 --- a/content/browser/loader/async_resource_handler.cc +++ b/content/browser/loader/async_resource_handler.cc @@ -200,15 +200,6 @@ bool AsyncResourceHandler::OnResponseStarted(int request_id, net::GetHostOrSpecFromURL(request_url)))); } - // If the parent handler downloaded the resource to a file, grant the child - // read permissions on it. Note: there is similar logic in - // SyncResourceHandler. - if (!response->head.download_file_path.empty()) { - rdh_->RegisterDownloadedTempFile( - info->GetChildID(), info->GetRequestID(), - response->head.download_file_path); - } - response->head.request_start = request()->creation_time(); response->head.response_start = TimeTicks::Now(); info->filter()->Send(new ResourceMsg_ReceivedResponse(request_id, diff --git a/content/browser/loader/redirect_to_file_resource_handler.cc b/content/browser/loader/redirect_to_file_resource_handler.cc index 84cc930..74848b6 100644 --- a/content/browser/loader/redirect_to_file_resource_handler.cc +++ b/content/browser/loader/redirect_to_file_resource_handler.cc @@ -5,12 +5,14 @@ #include "content/browser/loader/redirect_to_file_resource_handler.h" #include "base/bind.h" +#include "base/files/file_util_proxy.h" #include "base/logging.h" +#include "base/message_loop/message_loop_proxy.h" #include "base/platform_file.h" #include "base/threading/thread_restrictions.h" +#include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_request_info_impl.h" -#include "content/browser/loader/temporary_file_stream.h" -#include "content/public/browser/resource_controller.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/resource_response.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" @@ -51,108 +53,23 @@ namespace content { static const int kInitialReadBufSize = 32768; static const int kMaxReadBufSize = 524288; -// A separate IO thread object to manage the lifetime of the net::FileStream and -// the ShareableFileReference. When the handler is destroyed, it asynchronously -// closes net::FileStream after all pending writes complete. Only after the -// stream is closed is the ShareableFileReference released, to ensure the -// temporary is not deleted before it is closed. -class RedirectToFileResourceHandler::Writer { - public: - Writer(RedirectToFileResourceHandler* handler, - scoped_ptr<net::FileStream> file_stream, - ShareableFileReference* deletable_file) - : handler_(handler), - file_stream_(file_stream.Pass()), - is_writing_(false), - deletable_file_(deletable_file) { - DCHECK(!deletable_file_->path().empty()); - } - - bool is_writing() const { return is_writing_; } - const base::FilePath& path() const { return deletable_file_->path(); } - - int Write(net::IOBuffer* buf, int buf_len) { - DCHECK(!is_writing_); - DCHECK(handler_); - int result = file_stream_->Write( - buf, buf_len, - base::Bind(&Writer::DidWriteToFile, base::Unretained(this))); - if (result == net::ERR_IO_PENDING) - is_writing_ = true; - return result; - } - - void Close() { - handler_ = NULL; - if (!is_writing_) - CloseAndDelete(); - } - - private: - // Only DidClose can delete this. - ~Writer() { - } - - void DidWriteToFile(int result) { - DCHECK(is_writing_); - is_writing_ = false; - if (handler_) { - handler_->DidWriteToFile(result); - } else { - CloseAndDelete(); - } - } - - void CloseAndDelete() { - DCHECK(!is_writing_); - int result = file_stream_->Close(base::Bind(&Writer::DidClose, - base::Unretained(this))); - if (result != net::ERR_IO_PENDING) - DidClose(result); - } - - void DidClose(int result) { - delete this; - } - - RedirectToFileResourceHandler* handler_; - - scoped_ptr<net::FileStream> file_stream_; - bool is_writing_; - - // We create a ShareableFileReference that's deletable for the temp file - // created as a result of the download. - scoped_refptr<webkit_blob::ShareableFileReference> deletable_file_; - - DISALLOW_COPY_AND_ASSIGN(Writer); -}; - RedirectToFileResourceHandler::RedirectToFileResourceHandler( scoped_ptr<ResourceHandler> next_handler, - net::URLRequest* request) + net::URLRequest* request, + ResourceDispatcherHostImpl* host) : LayeredResourceHandler(request, next_handler.Pass()), + weak_factory_(this), + host_(host), buf_(new net::GrowableIOBuffer()), buf_write_pending_(false), write_cursor_(0), - writer_(NULL), + write_callback_pending_(false), next_buffer_size_(kInitialReadBufSize), did_defer_(false), - completed_during_write_(false), - weak_factory_(this) { + completed_during_write_(false) { } RedirectToFileResourceHandler::~RedirectToFileResourceHandler() { - // Orphan the writer to asynchronously close and release the temporary file. - if (writer_) { - writer_->Close(); - writer_ = NULL; - } -} - -void RedirectToFileResourceHandler:: - SetCreateTemporaryFileStreamFunctionForTesting( - const CreateTemporaryFileStreamFunction& create_temporary_file_stream) { - create_temporary_file_stream_ = create_temporary_file_stream; } bool RedirectToFileResourceHandler::OnResponseStarted( @@ -161,8 +78,8 @@ bool RedirectToFileResourceHandler::OnResponseStarted( bool* defer) { if (response->head.error_code == net::OK || response->head.error_code == net::ERR_IO_PENDING) { - DCHECK(writer_); - response->head.download_file_path = writer_->path(); + DCHECK(deletable_file_.get() && !deletable_file_->path().empty()); + response->head.download_file_path = deletable_file_->path(); } return next_handler_->OnResponseStarted(request_id, response, defer); } @@ -170,23 +87,19 @@ bool RedirectToFileResourceHandler::OnResponseStarted( bool RedirectToFileResourceHandler::OnWillStart(int request_id, const GURL& url, bool* defer) { - DCHECK(!writer_); - - // Defer starting the request until we have created the temporary file. - // TODO(darin): This is sub-optimal. We should not delay starting the - // network request like this. - will_start_url_ = url; - did_defer_ = *defer = true; - if (create_temporary_file_stream_.is_null()) { - CreateTemporaryFileStream( - base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile, - weak_factory_.GetWeakPtr())); - } else { - create_temporary_file_stream_.Run( + if (!deletable_file_.get()) { + // Defer starting the request until we have created the temporary file. + // TODO(darin): This is sub-optimal. We should not delay starting the + // network request like this. + did_defer_ = *defer = true; + base::FileUtilProxy::CreateTemporary( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(), + base::PLATFORM_FILE_ASYNC, base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile, weak_factory_.GetWeakPtr())); + return true; } - return true; + return next_handler_->OnWillStart(request_id, url, defer); } bool RedirectToFileResourceHandler::OnWillRead( @@ -238,7 +151,7 @@ void RedirectToFileResourceHandler::OnResponseCompleted( const net::URLRequestStatus& status, const std::string& security_info, bool* defer) { - if (writer_ && writer_->is_writing()) { + if (write_callback_pending_) { completed_during_write_ = true; completed_status_ = status; completed_security_info_ = security_info; @@ -250,31 +163,25 @@ void RedirectToFileResourceHandler::OnResponseCompleted( } void RedirectToFileResourceHandler::DidCreateTemporaryFile( - base::File::Error error_code, - scoped_ptr<net::FileStream> file_stream, - ShareableFileReference* deletable_file) { - DCHECK(!writer_); - if (error_code != base::File::FILE_OK) { - controller()->CancelWithError(net::FileErrorToNetError(error_code)); - return; - } - - writer_ = new Writer(this, file_stream.Pass(), deletable_file); - - // Resume the request. - DCHECK(did_defer_); - bool defer = false; - if (!next_handler_->OnWillStart(GetRequestID(), will_start_url_, &defer)) { - controller()->Cancel(); - } else if (!defer) { - ResumeIfDeferred(); - } else { - did_defer_ = false; - } - will_start_url_ = GURL(); + base::File::Error /*error_code*/, + base::PassPlatformFile file_handle, + const base::FilePath& file_path) { + deletable_file_ = ShareableFileReference::GetOrCreate( + file_path, + ShareableFileReference::DELETE_ON_FINAL_RELEASE, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get()); + file_stream_.reset( + new net::FileStream(file_handle.ReleaseValue(), + base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, + NULL)); + const ResourceRequestInfo* info = GetRequestInfo(); + host_->RegisterDownloadedTempFile( + info->GetChildID(), info->GetRequestID(), deletable_file_.get()); + ResumeIfDeferred(); } void RedirectToFileResourceHandler::DidWriteToFile(int result) { + write_callback_pending_ = false; int request_id = GetRequestID(); bool failed = false; @@ -287,38 +194,20 @@ void RedirectToFileResourceHandler::DidWriteToFile(int result) { } if (failed) { - DCHECK(!writer_->is_writing()); - // TODO(davidben): Recover the error code from WriteMore or |result|, as - // appropriate. - if (completed_during_write_ && completed_status_.is_success()) { - // If the request successfully completed mid-write, but the write failed, - // convert the status to a failure for downstream. - completed_status_.set_status(net::URLRequestStatus::CANCELED); - completed_status_.set_error(net::ERR_FAILED); - } - if (!completed_during_write_) - controller()->CancelWithError(net::ERR_FAILED); - } - - if (completed_during_write_ && !writer_->is_writing()) { - // Resume shutdown now that all data has been written to disk. Note that - // this should run even in the |failed| case above, otherwise a failed write - // leaves the handler stuck. + ResumeIfDeferred(); + } else if (completed_during_write_) { bool defer = false; next_handler_->OnResponseCompleted(request_id, completed_status_, completed_security_info_, &defer); - if (!defer) { + if (!defer) ResumeIfDeferred(); - } else { - did_defer_ = false; - } } } bool RedirectToFileResourceHandler::WriteMore() { - DCHECK(writer_); + DCHECK(file_stream_.get()); for (;;) { if (write_cursor_ == buf_->offset()) { // We've caught up to the network load, but it may be in the process of @@ -331,7 +220,7 @@ bool RedirectToFileResourceHandler::WriteMore() { } return true; } - if (writer_->is_writing()) + if (write_callback_pending_) return true; DCHECK(write_cursor_ < buf_->offset()); @@ -353,9 +242,15 @@ bool RedirectToFileResourceHandler::WriteMore() { buf_.get(), buf_->StartOfBuffer() + write_cursor_); int write_len = buf_->offset() - write_cursor_; - int rv = writer_->Write(wrapped.get(), write_len); - if (rv == net::ERR_IO_PENDING) + int rv = file_stream_->Write( + wrapped.get(), + write_len, + base::Bind(&RedirectToFileResourceHandler::DidWriteToFile, + base::Unretained(this))); + if (rv == net::ERR_IO_PENDING) { + write_callback_pending_ = true; return true; + } if (rv <= 0) return false; next_handler_->OnDataDownloaded(GetRequestID(), rv); diff --git a/content/browser/loader/redirect_to_file_resource_handler.h b/content/browser/loader/redirect_to_file_resource_handler.h index 6ad2c66..f83dd54 100644 --- a/content/browser/loader/redirect_to_file_resource_handler.h +++ b/content/browser/loader/redirect_to_file_resource_handler.h @@ -5,9 +5,6 @@ #ifndef CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_ #define CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_ -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" @@ -15,11 +12,8 @@ #include "base/memory/weak_ptr.h" #include "base/platform_file.h" #include "content/browser/loader/layered_resource_handler.h" -#include "content/browser/loader/temporary_file_stream.h" -#include "content/common/content_export.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_status.h" -#include "url/gurl.h" namespace net { class FileStream; @@ -31,32 +25,19 @@ class ShareableFileReference; } namespace content { +class ResourceDispatcherHostImpl; -// Redirects network data to a file. This is intended to be layered in front of -// either the AsyncResourceHandler or the SyncResourceHandler. The downstream -// resource handler does not see OnWillRead or OnReadCompleted calls. Instead, -// the ResourceResponse contains the path to a temporary file and -// OnDataDownloaded is called as the file downloads. -class CONTENT_EXPORT RedirectToFileResourceHandler - : public LayeredResourceHandler { +// Redirects network data to a file. This is intended to be layered in front +// of either the AsyncResourceHandler or the SyncResourceHandler. +class RedirectToFileResourceHandler : public LayeredResourceHandler { public: - typedef base::Callback<void(const CreateTemporaryFileStreamCallback&)> - CreateTemporaryFileStreamFunction; - - // Create a RedirectToFileResourceHandler for |request| which wraps - // |next_handler|. - RedirectToFileResourceHandler(scoped_ptr<ResourceHandler> next_handler, - net::URLRequest* request); + RedirectToFileResourceHandler( + scoped_ptr<ResourceHandler> next_handler, + net::URLRequest* request, + ResourceDispatcherHostImpl* resource_dispatcher_host); virtual ~RedirectToFileResourceHandler(); - // Replace the CreateTemporaryFileStream implementation with a mocked one for - // testing purposes. The function should create a net::FileStream and a - // ShareableFileReference and then asynchronously pass them to the - // CreateTemporaryFileStreamCallback. - void SetCreateTemporaryFileStreamFunctionForTesting( - const CreateTemporaryFileStreamFunction& create_temporary_file_stream); - - // LayeredResourceHandler implementation: + // ResourceHandler implementation: virtual bool OnResponseStarted(int request_id, ResourceResponse* response, bool* defer) OVERRIDE; @@ -76,19 +57,17 @@ class CONTENT_EXPORT RedirectToFileResourceHandler bool* defer) OVERRIDE; private: - void DidCreateTemporaryFile( - base::File::Error error_code, - scoped_ptr<net::FileStream> file_stream, - webkit_blob::ShareableFileReference* deletable_file); - - // Called by RedirectToFileResourceHandler::Writer. + void DidCreateTemporaryFile(base::File::Error error_code, + base::PassPlatformFile file_handle, + const base::FilePath& file_path); void DidWriteToFile(int result); - bool WriteMore(); bool BufIsFull() const; void ResumeIfDeferred(); - CreateTemporaryFileStreamFunction create_temporary_file_stream_; + base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_; + + ResourceDispatcherHostImpl* host_; // We allocate a single, fixed-size IO buffer (buf_) used to read from the // network (buf_write_pending_ is true while the system is copying data into @@ -101,11 +80,8 @@ class CONTENT_EXPORT RedirectToFileResourceHandler bool buf_write_pending_; int write_cursor_; - // Helper writer object which maintains references to the net::FileStream and - // webkit_blob::ShareableFileReference. This is maintained separately so that, - // on Windows, the temporary file isn't deleted until after it is closed. - class Writer; - Writer* writer_; + scoped_ptr<net::FileStream> file_stream_; + bool write_callback_pending_; // |next_buffer_size_| is the size of the buffer to be allocated on the next // OnWillRead() call. We exponentially grow the size of the buffer allocated @@ -114,15 +90,16 @@ class CONTENT_EXPORT RedirectToFileResourceHandler // was filled, up to a maximum size of 512k. int next_buffer_size_; - bool did_defer_; + // We create a ShareableFileReference that's deletable for the temp + // file created as a result of the download. + scoped_refptr<webkit_blob::ShareableFileReference> deletable_file_; + + bool did_defer_ ; bool completed_during_write_; - GURL will_start_url_; net::URLRequestStatus completed_status_; std::string completed_security_info_; - base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(RedirectToFileResourceHandler); }; diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index f3b61a5..0058a24 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc @@ -1156,20 +1156,18 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler( handler.reset(new SyncResourceHandler(request, sync_result, this)); } else { handler.reset(new AsyncResourceHandler(request, this)); + if (IsDetachableResourceType(request_data.resource_type)) { + handler.reset(new DetachableResourceHandler( + request, + base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs), + handler.Pass())); + } } // The RedirectToFileResourceHandler depends on being next in the chain. if (request_data.download_to_file) { handler.reset( - new RedirectToFileResourceHandler(handler.Pass(), request)); - } - - // Prefetches and <a ping> requests outlive their child process. - if (!sync_result && IsDetachableResourceType(request_data.resource_type)) { - handler.reset(new DetachableResourceHandler( - request, - base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs), - handler.Pass())); + new RedirectToFileResourceHandler(handler.Pass(), request, this)); } // Install a CrossSiteResourceHandler for all main frame requests. This will @@ -1224,11 +1222,7 @@ void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { } void ResourceDispatcherHostImpl::RegisterDownloadedTempFile( - int child_id, int request_id, const base::FilePath& file_path) { - scoped_refptr<ShareableFileReference> reference = - ShareableFileReference::Get(file_path); - DCHECK(reference); - + int child_id, int request_id, ShareableFileReference* reference) { registered_temp_files_[child_id][request_id] = reference; ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( child_id, reference->path()); diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index abf2ada..8a8bdc3 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h @@ -186,7 +186,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl // no longer needed. void RegisterDownloadedTempFile( int child_id, int request_id, - const base::FilePath& file_path); + webkit_blob::ShareableFileReference* reference); void UnregisterDownloadedTempFile(int child_id, int request_id); // Needed for the sync IPC message dispatcher macros. diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 9a47696..040fe40 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc @@ -4,9 +4,7 @@ #include <vector> -#include "base/basictypes.h" #include "base/bind.h" -#include "base/file_util.h" #include "base/files/file_path.h" #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" @@ -34,7 +32,6 @@ #include "content/public/common/process_type.h" #include "content/public/common/resource_response.h" #include "content/public/test/test_browser_context.h" -#include "content/public/test/test_browser_thread_bundle.h" #include "content/test/test_content_browser_client.h" #include "net/base/net_errors.h" #include "net/base/request_priority.h" @@ -49,13 +46,10 @@ #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/common/appcache/appcache_interfaces.h" -#include "webkit/common/blob/shareable_file_reference.h" // TODO(eroman): Write unit tests for SafeBrowsing that exercise // SafeBrowsingResourceHandler. -using webkit_blob::ShareableFileReference; - namespace content { namespace { @@ -92,7 +86,6 @@ static int RequestIDForMessage(const IPC::Message& msg) { case ResourceMsg_ReceivedRedirect::ID: case ResourceMsg_SetDataBuffer::ID: case ResourceMsg_DataReceived::ID: - case ResourceMsg_DataDownloaded::ID: case ResourceMsg_RequestComplete::ID: { bool result = PickleIterator(msg).ReadInt(&request_id); DCHECK(result); @@ -188,7 +181,6 @@ class ForwardingFilter : public ResourceMessageFilter { base::Unretained(this))), dest_(dest), resource_context_(resource_context) { - ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id()); set_peer_pid_for_testing(base::GetCurrentProcId()); } @@ -567,47 +559,32 @@ class TestResourceDispatcherHostDelegate scoped_ptr<base::SupportsUserData::Data> user_data_; }; -// Waits for a ShareableFileReference to be released. -class ShareableFileReleaseWaiter { - public: - ShareableFileReleaseWaiter(const base::FilePath& path) { - scoped_refptr<ShareableFileReference> file = - ShareableFileReference::Get(path); - file->AddFinalReleaseCallback( - base::Bind(&ShareableFileReleaseWaiter::Released, - base::Unretained(this))); - } - - void Wait() { - loop_.Run(); - } - - private: - void Released(const base::FilePath& path) { - loop_.Quit(); - } - - base::RunLoop loop_; - - DISALLOW_COPY_AND_ASSIGN(ShareableFileReleaseWaiter); -}; - class ResourceDispatcherHostTest : public testing::Test, public IPC::Sender { public: ResourceDispatcherHostTest() - : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), + : ui_thread_(BrowserThread::UI, &message_loop_), + file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_), + cache_thread_(BrowserThread::CACHE, &message_loop_), + io_thread_(BrowserThread::IO, &message_loop_), old_factory_(NULL), send_data_received_acks_(false) { browser_context_.reset(new TestBrowserContext()); BrowserContext::EnsureResourceContextInitialized(browser_context_.get()); - base::RunLoop().RunUntilIdle(); + message_loop_.RunUntilIdle(); ResourceContext* resource_context = browser_context_->GetResourceContext(); filter_ = new ForwardingFilter(this, resource_context); resource_context->GetRequestContext()->set_network_delegate( &network_delegate_); } + virtual ~ResourceDispatcherHostTest() { + for (std::set<int>::iterator it = child_ids_.begin(); + it != child_ids_.end(); ++it) { + host_.CancelRequestsForProcess(*it); + } + } + // IPC::Sender implementation virtual bool Send(IPC::Message* msg) OVERRIDE { accum_.AddMessage(*msg); @@ -617,18 +594,13 @@ class ResourceDispatcherHostTest : public testing::Test, GenerateDataReceivedACK(*msg); } - if (wait_for_request_complete_loop_ && - msg->type() == ResourceMsg_RequestComplete::ID) { - wait_for_request_complete_loop_->Quit(); - } - delete msg; return true; } protected: // testing::Test - virtual void SetUp() OVERRIDE { + virtual void SetUp() { DCHECK(!test_fixture_); test_fixture_ = this; ChildProcessSecurityPolicyImpl::GetInstance()->Add(0); @@ -654,11 +626,6 @@ class ResourceDispatcherHostTest : public testing::Test, DCHECK(test_fixture_ == this); test_fixture_ = NULL; - for (std::set<int>::iterator it = child_ids_.begin(); - it != child_ids_.end(); ++it) { - host_.CancelRequestsForProcess(*it); - } - host_.Shutdown(); ChildProcessSecurityPolicyImpl::GetInstance()->Remove(0); @@ -671,7 +638,7 @@ class ResourceDispatcherHostTest : public testing::Test, WorkerServiceImpl::GetInstance()->PerformTeardownForTesting(); browser_context_.reset(); - base::RunLoop().RunUntilIdle(); + message_loop_.RunUntilIdle(); } // Creates a request using the current test object as the filter and @@ -807,14 +774,11 @@ class ResourceDispatcherHostTest : public testing::Test, return old_filter; } - void WaitForRequestComplete() { - DCHECK(!wait_for_request_complete_loop_); - wait_for_request_complete_loop_.reset(new base::RunLoop); - wait_for_request_complete_loop_->Run(); - wait_for_request_complete_loop_.reset(); - } - - content::TestBrowserThreadBundle thread_bundle_; + base::MessageLoopForIO message_loop_; + BrowserThreadImpl ui_thread_; + BrowserThreadImpl file_thread_; + BrowserThreadImpl cache_thread_; + BrowserThreadImpl io_thread_; scoped_ptr<TestBrowserContext> browser_context_; scoped_refptr<ForwardingFilter> filter_; net::TestNetworkDelegate network_delegate_; @@ -826,7 +790,6 @@ class ResourceDispatcherHostTest : public testing::Test, net::URLRequest::ProtocolFactory* old_factory_; bool send_data_received_acks_; std::set<int> child_ids_; - scoped_ptr<base::RunLoop> wait_for_request_complete_loop_; static ResourceDispatcherHostTest* test_fixture_; static bool delay_start_; static bool delay_complete_; @@ -2749,161 +2712,4 @@ TEST_F(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) { } } -// Tests the dispatcher host's temporary file management. -TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFile) { - const int kRequestID = 1; - - // Create a temporary file. - base::FilePath file_path; - ASSERT_TRUE(base::CreateTemporaryFile(&file_path)); - scoped_refptr<ShareableFileReference> deletable_file = - ShareableFileReference::GetOrCreate( - file_path, - ShareableFileReference::DELETE_ON_FINAL_RELEASE, - BrowserThread::GetMessageLoopProxyForThread( - BrowserThread::FILE).get()); - - // Not readable. - EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), file_path)); - - // Register it for a resource request. - host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path); - - // Should be readable now. - EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), file_path)); - - // The child releases from the request. - bool msg_was_ok = true; - ResourceHostMsg_ReleaseDownloadedFile release_msg(kRequestID); - host_.OnMessageReceived(release_msg, filter_, &msg_was_ok); - ASSERT_TRUE(msg_was_ok); - - // Still readable because there is another reference to the file. (The child - // may take additional blob references.) - EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), file_path)); - - // Release extra references and wait for the file to be deleted. (This relies - // on the delete happening on the FILE thread which is mapped to main thread - // in this test.) - deletable_file = NULL; - base::RunLoop().RunUntilIdle(); - - // The file is no longer readable to the child and has been deleted. - EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), file_path)); - EXPECT_FALSE(base::PathExists(file_path)); -} - -// Tests that temporary files held on behalf of child processes are released -// when the child process dies. -TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) { - const int kRequestID = 1; - - // Create a temporary file. - base::FilePath file_path; - ASSERT_TRUE(base::CreateTemporaryFile(&file_path)); - scoped_refptr<ShareableFileReference> deletable_file = - ShareableFileReference::GetOrCreate( - file_path, - ShareableFileReference::DELETE_ON_FINAL_RELEASE, - BrowserThread::GetMessageLoopProxyForThread( - BrowserThread::FILE).get()); - - // Register it for a resource request. - host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path); - deletable_file = NULL; - - // Should be readable now. - EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), file_path)); - - // Let the process die. - filter_->OnChannelClosing(); - base::RunLoop().RunUntilIdle(); - - // The file is no longer readable to the child and has been deleted. - EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), file_path)); - EXPECT_FALSE(base::PathExists(file_path)); -} - -TEST_F(ResourceDispatcherHostTest, DownloadToFile) { - // Make a request which downloads to file. - ResourceHostMsg_Request request = CreateResourceRequest( - "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1()); - request.download_to_file = true; - ResourceHostMsg_RequestResource request_msg(0, 1, request); - bool msg_was_ok; - host_.OnMessageReceived(request_msg, filter_, &msg_was_ok); - ASSERT_TRUE(msg_was_ok); - - // Running the message loop until idle does not work because - // RedirectToFileResourceHandler posts things to base::WorkerPool. Instead, - // wait for the ResourceMsg_RequestComplete to go out. Then run the event loop - // until idle so the loader is gone. - WaitForRequestComplete(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, host_.pending_requests()); - - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - ASSERT_EQ(1U, msgs.size()); - const std::vector<IPC::Message>& messages = msgs[0]; - - // The request should contain the following messages: - // ReceivedResponse (indicates headers received and filename) - // DataDownloaded* (bytes downloaded and total length) - // RequestComplete (request is done) - - // ReceivedResponse - ResourceResponseHead response_head; - GetResponseHead(messages, &response_head); - ASSERT_FALSE(response_head.download_file_path.empty()); - - // DataDownloaded - size_t total_len = 0; - for (size_t i = 1; i < messages.size() - 1; i++) { - ASSERT_EQ(ResourceMsg_DataDownloaded::ID, messages[i].type()); - PickleIterator iter(messages[i]); - int request_id, data_len; - ASSERT_TRUE(IPC::ReadParam(&messages[i], &iter, &request_id)); - ASSERT_TRUE(IPC::ReadParam(&messages[i], &iter, &data_len)); - total_len += data_len; - } - EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(), total_len); - - // RequestComplete - CheckRequestCompleteErrorCode(messages.back(), net::OK); - - // Verify that the data ended up in the temporary file. - std::string contents; - ASSERT_TRUE(base::ReadFileToString(response_head.download_file_path, - &contents)); - EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents); - - // The file should be readable by the child. - EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), response_head.download_file_path)); - - // When the renderer releases the file, it should be deleted. Again, - // RunUntilIdle doesn't work because base::WorkerPool is involved. - ShareableFileReleaseWaiter waiter(response_head.download_file_path); - ResourceHostMsg_ReleaseDownloadedFile release_msg(1); - host_.OnMessageReceived(release_msg, filter_, &msg_was_ok); - ASSERT_TRUE(msg_was_ok); - waiter.Wait(); - // The release callback runs before the delete is scheduled, so pump the - // message loop for the delete itself. (This relies on the delete happening on - // the FILE thread which is mapped to main thread in this test.) - base::RunLoop().RunUntilIdle(); - - EXPECT_FALSE(base::PathExists(response_head.download_file_path)); - EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( - filter_->child_id(), response_head.download_file_path)); -} - } // namespace content diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc index c4183d0..363c9ff 100644 --- a/content/browser/loader/resource_loader_unittest.cc +++ b/content/browser/loader/resource_loader_unittest.cc @@ -4,33 +4,21 @@ #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 { @@ -81,34 +69,16 @@ class ClientCertStoreStub : public net::ClientCertStore { // initialize ResourceLoader. 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) { - } + ResourceHandlerStub() + : ResourceHandler(NULL), defer_request_on_will_start_(false) {} 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(); - } - - // ResourceHandler implementation: virtual bool OnUploadProgress(int request_id, uint64 position, uint64 size) OVERRIDE { - NOTREACHED(); return true; } @@ -116,23 +86,18 @@ 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 { - 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; } @@ -147,40 +112,26 @@ class ResourceHandlerStub : public ResourceHandler { scoped_refptr<net::IOBuffer>* buf, int* buf_size, int min_size) OVERRIDE { - NOTREACHED(); - return false; + return true; } virtual bool OnReadCompleted(int request_id, int bytes_read, bool* defer) OVERRIDE { - NOTREACHED(); - return false; + return true; } 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 { - total_bytes_downloaded_ += bytes_downloaded; - } + int bytes_downloaded) OVERRIDE {} 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_; }; // Test browser client that captures calls to SelectClientCertificates and @@ -229,16 +180,6 @@ class ResourceContextStub : public MockResourceContext { scoped_ptr<net::ClientCertStore> dummy_cert_store_; }; -// Fails to create a temporary file with the given error. -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>())); -} - } // namespace class ResourceLoaderTest : public testing::Test, @@ -246,26 +187,7 @@ class ResourceLoaderTest : public testing::Test, 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>(); + resource_context_(&test_url_request_context_) { } virtual void SetUp() OVERRIDE { @@ -273,7 +195,7 @@ class ResourceLoaderTest : public testing::Test, const int kRenderViewId = 2; scoped_ptr<net::URLRequest> request( - new net::URLRequest(test_url(), + new net::URLRequest(GURL("dummy"), net::DEFAULT_PRIORITY, NULL, resource_context_.GetRequestContext())); @@ -285,13 +207,10 @@ class ResourceLoaderTest : public testing::Test, kRenderViewId, MSG_ROUTING_NONE, false); - scoped_ptr<ResourceHandlerStub> resource_handler( - new ResourceHandlerStub(request.get())); + scoped_ptr<ResourceHandlerStub> resource_handler(new ResourceHandlerStub()); raw_ptr_resource_handler_ = resource_handler.get(); loader_.reset(new ResourceLoader( - request.Pass(), - WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_), - this)); + request.Pass(), resource_handler.PassAs<ResourceHandler>(), this)); } // ResourceLoaderDelegate: @@ -312,7 +231,6 @@ class ResourceLoaderTest : public testing::Test, content::TestBrowserThreadBundle thread_bundle_; - net::URLRequestJobFactoryImpl job_factory_; net::TestURLRequestContext test_url_request_context_; ResourceContextStub resource_context_; @@ -404,259 +322,4 @@ TEST_F(ResourceLoaderTest, ResumeCancelledRequest) { 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 { - // Make a temporary file. - CHECK(base::CreateTemporaryFile(&temp_path_)); - base::PlatformFile platform_file = - base::CreatePlatformFile(temp_path_, - base::PLATFORM_FILE_WRITE | - base::PLATFORM_FILE_TEMPORARY | - base::PLATFORM_FILE_CREATE_ALWAYS | - base::PLATFORM_FILE_ASYNC, - NULL, NULL); - CHECK_NE(base::kInvalidPlatformFileValue, platform_file); - - // Create mock file streams and a ShareableFileReference. - scoped_ptr<net::testing::MockFileStream> file_stream( - new net::testing::MockFileStream( - platform_file, - base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, - 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()); - - // Inject them into the handler. - 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_; - // These are owned by the ResourceLoader. - net::testing::MockFileStream* file_stream_; - RedirectToFileResourceHandler* redirect_to_file_resource_handler_; -}; - -// Tests that a RedirectToFileResourceHandler works and forwards everything -// downstream. -TEST_F(ResourceLoaderRedirectToFileTest, Basic) { - // Run it to completion. - loader_->StartRequest(); - base::RunLoop().RunUntilIdle(); - - // Check that the handler forwarded all information to the downstream handler. - 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())); - - // Check that the data was written to the file. - std::string contents; - ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents)); - EXPECT_EQ(test_data(), contents); - - // Release the loader and the saved reference to file. The file should be gone - // now. - ReleaseLoader(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(base::PathExists(temp_path())); -} - -// Tests that RedirectToFileResourceHandler handles errors in creating the -// temporary file. -TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) { - // Swap out the create temporary function. - redirect_to_file_resource_handler()-> - SetCreateTemporaryFileStreamFunctionForTesting( - base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED)); - - // Run it to completion. - loader_->StartRequest(); - base::RunLoop().RunUntilIdle(); - - // To downstream, the request was canceled. - 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()); -} - -// Tests that RedirectToFileResourceHandler handles synchronous write errors. -TEST_F(ResourceLoaderRedirectToFileTest, WriteError) { - file_stream()->set_forced_error(net::ERR_FAILED); - - // 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(), - 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()); - - // Release the loader. The file should be gone now. - ReleaseLoader(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(base::PathExists(temp_path())); -} - -// Tests that RedirectToFileResourceHandler handles asynchronous write errors. -TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) { - file_stream()->set_forced_error_async(net::ERR_FAILED); - - // 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(), - 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()); - - // Release the loader. The file should be gone now. - ReleaseLoader(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(base::PathExists(temp_path())); -} - -// Tests that RedirectToFileHandler defers completion if there are outstanding -// writes and accounts for errors which occur in that time. -TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) { - // Program the MockFileStream to error asynchronously, but throttle the - // callback. - file_stream()->set_forced_error_async(net::ERR_FAILED); - file_stream()->ThrottleCallbacks(); - - // 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(), - 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()); - - // Now, release the floodgates. - file_stream()->ReleaseCallbacks(); - base::RunLoop().RunUntilIdle(); - - // Although the URLRequest was successful, the leaf handler sees a failure - // because the write never completed. - EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); - EXPECT_EQ(net::URLRequestStatus::CANCELED, - raw_ptr_resource_handler_->status().status()); - - // Release the loader. The file should be gone now. - ReleaseLoader(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(base::PathExists(temp_path())); -} - -// Tests that a RedirectToFileResourceHandler behaves properly when the -// downstream handler defers OnWillStart. -TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) { - // Defer OnWillStart. - raw_ptr_resource_handler_->set_defer_request_on_will_start(true); - - // Run as far as we'll go. - loader_->StartRequest(); - base::RunLoop().RunUntilIdle(); - - // The request should have stopped at OnWillStart. - 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()); - - // Now resume the request. Now we complete. - raw_ptr_resource_handler_->Resume(); - base::RunLoop().RunUntilIdle(); - - // Check that the handler forwarded all information to the downstream handler. - 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())); - - // Check that the data was written to the file. - std::string contents; - ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents)); - EXPECT_EQ(test_data(), contents); - - // Release the loader. The file should be gone now. - ReleaseLoader(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(base::PathExists(temp_path())); -} - } // namespace content diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc index e39ae1c..865b29e 100644 --- a/content/browser/loader/sync_resource_handler.cc +++ b/content/browser/loader/sync_resource_handler.cc @@ -86,18 +86,6 @@ bool SyncResourceHandler::OnResponseStarted( DevToolsNetLogObserver::PopulateResponseInfo(request(), response); - // If the parent handler downloaded the resource to a file, grant the child - // read permissions on it. Note: there is similar logic in - // AsyncResourceHandler. - // - // TODO(davidben): Can we remove support for download_file in sync requests - // altogether? I don't think Blink ever makes such requests. - if (!response->head.download_file_path.empty()) { - rdh_->RegisterDownloadedTempFile( - info->GetChildID(), info->GetRequestID(), - response->head.download_file_path); - } - // We don't care about copying the status here. result_.headers = response->head.headers; result_.mime_type = response->head.mime_type; diff --git a/content/browser/loader/temporary_file_stream.cc b/content/browser/loader/temporary_file_stream.cc deleted file mode 100644 index 1d23ae9..0000000 --- a/content/browser/loader/temporary_file_stream.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 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 "content/browser/loader/temporary_file_stream.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/files/file_util_proxy.h" -#include "base/memory/ref_counted.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/file_stream.h" -#include "webkit/common/blob/shareable_file_reference.h" - -using webkit_blob::ShareableFileReference; - -namespace content { - -namespace { - -void DidCreateTemporaryFile( - const CreateTemporaryFileStreamCallback& callback, - base::File::Error error_code, - base::PassPlatformFile file_handle, - const base::FilePath& file_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - if (error_code != base::File::FILE_OK) { - callback.Run(error_code, scoped_ptr<net::FileStream>(), NULL); - return; - } - - // Cancelled or not, create the deletable_file so the temporary is cleaned up. - scoped_refptr<ShareableFileReference> deletable_file = - ShareableFileReference::GetOrCreate( - file_path, - ShareableFileReference::DELETE_ON_FINAL_RELEASE, - BrowserThread::GetMessageLoopProxyForThread( - BrowserThread::FILE).get()); - - scoped_ptr<net::FileStream> file_stream(new net::FileStream( - file_handle.ReleaseValue(), - base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, - NULL)); - - callback.Run(error_code, file_stream.Pass(), deletable_file); -} - -} // namespace - -void CreateTemporaryFileStream( - const CreateTemporaryFileStreamCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - base::FileUtilProxy::CreateTemporary( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(), - base::PLATFORM_FILE_ASYNC, - base::Bind(&DidCreateTemporaryFile, callback)); -} - -} // namespace content diff --git a/content/browser/loader/temporary_file_stream.h b/content/browser/loader/temporary_file_stream.h deleted file mode 100644 index 51d524d..0000000 --- a/content/browser/loader/temporary_file_stream.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 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. - -#ifndef CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_ -#define CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_ - -#include "base/callback_forward.h" -#include "base/files/file.h" -#include "base/memory/scoped_ptr.h" -#include "base/platform_file.h" -#include "content/common/content_export.h" - -namespace net { -class FileStream; -} - -namespace webkit_blob { -class ShareableFileReference; -} - -namespace content { - -typedef base::Callback<void(base::File::Error, - scoped_ptr<net::FileStream>, - webkit_blob::ShareableFileReference*)> - CreateTemporaryFileStreamCallback; - -// Creates a temporary file and asynchronously calls |callback| with a -// net::FileStream and webkit_blob::ShareableFileReference. The file is deleted -// when the webkit_blob::ShareableFileReference is deleted. Note it is the -// consumer's responsibility to ensure the webkit_blob::ShareableFileReference -// stays in scope until net::FileStream has finished closing the file. On error, -// |callback| is called with an error in the first parameter. -// -// This function may only be called on the IO thread. -// -// TODO(davidben): Juggling the net::FileStream and -// webkit_blob::ShareableFileReference lifetimes is a nuisance. The two should -// be tied together so the consumer need not deal with it. -CONTENT_EXPORT void CreateTemporaryFileStream( - const CreateTemporaryFileStreamCallback& callback); - -} // namespace content - -#endif // CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_ diff --git a/content/browser/loader/temporary_file_stream_unittest.cc b/content/browser/loader/temporary_file_stream_unittest.cc deleted file mode 100644 index 1903d44..0000000 --- a/content/browser/loader/temporary_file_stream_unittest.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2014 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 "content/browser/loader/temporary_file_stream.h" - -#include <string.h> - -#include <string> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/file_util.h" -#include "base/files/file_path.h" -#include "base/run_loop.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "net/base/file_stream.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/base/test_completion_callback.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/common/blob/shareable_file_reference.h" - -using webkit_blob::ShareableFileReference; - -namespace content { - -namespace { - -const char kTestData[] = "0123456789"; -const int kTestDataSize = arraysize(kTestData) - 1; - -class WaitForFileStream { - public: - base::File::Error error() const { return error_; } - net::FileStream* file_stream() const { return file_stream_.get(); } - ShareableFileReference* deletable_file() const { - return deletable_file_.get(); - } - - void OnFileStreamCreated(base::File::Error error, - scoped_ptr<net::FileStream> file_stream, - ShareableFileReference* deletable_file) { - error_ = error; - file_stream_ = file_stream.Pass(); - deletable_file_ = deletable_file; - loop_.Quit(); - } - - void Wait() { - loop_.Run(); - } - - void Release() { - file_stream_.reset(NULL); - deletable_file_ = NULL; - } - private: - base::RunLoop loop_; - base::File::Error error_; - scoped_ptr<net::FileStream> file_stream_; - scoped_refptr<ShareableFileReference> deletable_file_; -}; - -} // namespace - -TEST(TemporaryFileStreamTest, Basic) { - TestBrowserThreadBundle thread_bundle(TestBrowserThreadBundle::IO_MAINLOOP); - - // Create a temporary. - WaitForFileStream file_stream_waiter; - CreateTemporaryFileStream(base::Bind(&WaitForFileStream::OnFileStreamCreated, - base::Unretained(&file_stream_waiter))); - file_stream_waiter.Wait(); - - // The temporary should exist. - EXPECT_EQ(base::File::FILE_OK, file_stream_waiter.error()); - base::FilePath file_path = file_stream_waiter.deletable_file()->path(); - EXPECT_TRUE(base::PathExists(file_path)); - - // Write some data to the temporary. - int bytes_written = 0; - scoped_refptr<net::IOBufferWithSize> buf = - new net::IOBufferWithSize(kTestDataSize); - memcpy(buf->data(), kTestData, kTestDataSize); - scoped_refptr<net::DrainableIOBuffer> drainable = - new net::DrainableIOBuffer(buf.get(), buf->size()); - while (bytes_written != kTestDataSize) { - net::TestCompletionCallback write_callback; - int rv = file_stream_waiter.file_stream()->Write( - drainable.get(), drainable->BytesRemaining(), - write_callback.callback()); - if (rv == net::ERR_IO_PENDING) - rv = write_callback.WaitForResult(); - ASSERT_LT(0, rv); - drainable->DidConsume(rv); - bytes_written += rv; - } - - // Verify the data matches. - std::string contents; - ASSERT_TRUE(base::ReadFileToString(file_path, &contents)); - EXPECT_EQ(kTestData, contents); - - // Close the file. - net::TestCompletionCallback close_callback; - int rv = file_stream_waiter.file_stream()->Close(close_callback.callback()); - if (rv == net::ERR_IO_PENDING) - rv = close_callback.WaitForResult(); - EXPECT_EQ(net::OK, rv); - - // Release everything. The file should be gone now. - file_stream_waiter.Release(); - base::MessageLoop::current()->RunUntilIdle(); - - // The temporary should be gone now. - EXPECT_FALSE(base::PathExists(file_path)); -} - -} // content diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 8d5f915..eff21e9 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -725,8 +725,6 @@ 'browser/loader/stream_resource_handler.h', 'browser/loader/sync_resource_handler.cc', 'browser/loader/sync_resource_handler.h', - 'browser/loader/temporary_file_stream.cc', - 'browser/loader/temporary_file_stream.h', 'browser/loader/throttling_resource_handler.cc', 'browser/loader/throttling_resource_handler.h', 'browser/loader/upload_data_stream_builder.cc', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 090d359..c3cc0b9 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -418,7 +418,6 @@ 'browser/loader/resource_dispatcher_host_unittest.cc', 'browser/loader/resource_loader_unittest.cc', 'browser/loader/resource_scheduler_unittest.cc', - 'browser/loader/temporary_file_stream_unittest.cc', 'browser/loader/upload_data_stream_builder_unittest.cc', 'browser/mach_broker_mac_unittest.cc', 'browser/media/capture/audio_mirroring_manager_unittest.cc', diff --git a/net/base/mock_file_stream.cc b/net/base/mock_file_stream.cc index 3f05ab4..d160f0c 100644 --- a/net/base/mock_file_stream.cc +++ b/net/base/mock_file_stream.cc @@ -4,46 +4,10 @@ #include "net/base/mock_file_stream.h" -#include "base/bind.h" -#include "base/message_loop/message_loop.h" - namespace net { namespace testing { -MockFileStream::MockFileStream(net::NetLog* net_log) - : net::FileStream(net_log), - forced_error_(net::OK), - async_error_(false), - throttled_(false), - weak_factory_(this) { -} - -MockFileStream::MockFileStream(base::PlatformFile file, - int flags, - net::NetLog* net_log) - : net::FileStream(file, flags, net_log), - forced_error_(net::OK), - async_error_(false), - throttled_(false), - weak_factory_(this) { -} - -MockFileStream::MockFileStream( - base::PlatformFile file, - int flags, - net::NetLog* net_log, - const scoped_refptr<base::TaskRunner>& task_runner) - : net::FileStream(file, flags, net_log, task_runner), - forced_error_(net::OK), - async_error_(false), - throttled_(false), - weak_factory_(this) { -} - -MockFileStream::~MockFileStream() { -} - int MockFileStream::OpenSync(const base::FilePath& path, int open_flags) { path_ = path; return ReturnError(FileStream::OpenSync(path, open_flags)); @@ -51,12 +15,7 @@ int MockFileStream::OpenSync(const base::FilePath& path, int open_flags) { int MockFileStream::Seek(Whence whence, int64 offset, const Int64CompletionCallback& callback) { - Int64CompletionCallback wrapped_callback = - base::Bind(&MockFileStream::DoCallback64, - weak_factory_.GetWeakPtr(), callback); - if (forced_error_ == net::OK) - return FileStream::Seek(whence, offset, wrapped_callback); - return ErrorCallback64(wrapped_callback); + return ReturnError(FileStream::Seek(whence, offset, callback)); } int64 MockFileStream::SeekSync(Whence whence, int64 offset) { @@ -70,12 +29,7 @@ int64 MockFileStream::Available() { int MockFileStream::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback, - weak_factory_.GetWeakPtr(), - callback); - if (forced_error_ == net::OK) - return FileStream::Read(buf, buf_len, wrapped_callback); - return ErrorCallback(wrapped_callback); + return ReturnError(FileStream::Read(buf, buf_len, callback)); } int MockFileStream::ReadSync(char* buf, int buf_len) { @@ -89,12 +43,7 @@ int MockFileStream::ReadUntilComplete(char *buf, int buf_len) { int MockFileStream::Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback, - weak_factory_.GetWeakPtr(), - callback); - if (forced_error_ == net::OK) - return FileStream::Write(buf, buf_len, wrapped_callback); - return ErrorCallback(wrapped_callback); + return ReturnError(FileStream::Write(buf, buf_len, callback)); } int MockFileStream::WriteSync(const char* buf, int buf_len) { @@ -106,80 +55,13 @@ int64 MockFileStream::Truncate(int64 bytes) { } int MockFileStream::Flush(const CompletionCallback& callback) { - CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback, - weak_factory_.GetWeakPtr(), - callback); - if (forced_error_ == net::OK) - return FileStream::Flush(wrapped_callback); - return ErrorCallback(wrapped_callback); + return ReturnError(FileStream::Flush(callback)); } int MockFileStream::FlushSync() { return ReturnError(FileStream::FlushSync()); } -void MockFileStream::ThrottleCallbacks() { - CHECK(!throttled_); - throttled_ = true; -} - -void MockFileStream::ReleaseCallbacks() { - CHECK(throttled_); - throttled_ = false; - - if (!throttled_task_.is_null()) { - base::Closure throttled_task = throttled_task_; - throttled_task_.Reset(); - base::MessageLoop::current()->PostTask(FROM_HERE, throttled_task); - } -} - -void MockFileStream::DoCallback(const CompletionCallback& callback, - int result) { - if (!throttled_) { - callback.Run(result); - return; - } - CHECK(throttled_task_.is_null()); - throttled_task_ = base::Bind(callback, result); -} - -void MockFileStream::DoCallback64(const Int64CompletionCallback& callback, - int64 result) { - if (!throttled_) { - callback.Run(result); - return; - } - CHECK(throttled_task_.is_null()); - throttled_task_ = base::Bind(callback, result); -} - -int MockFileStream::ErrorCallback(const CompletionCallback& callback) { - CHECK_NE(net::OK, forced_error_); - if (async_error_) { - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(callback, forced_error_)); - clear_forced_error(); - return net::ERR_IO_PENDING; - } - int ret = forced_error_; - clear_forced_error(); - return ret; -} - -int64 MockFileStream::ErrorCallback64(const Int64CompletionCallback& callback) { - CHECK_NE(net::OK, forced_error_); - if (async_error_) { - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(callback, forced_error_)); - clear_forced_error(); - return net::ERR_IO_PENDING; - } - int64 ret = forced_error_; - clear_forced_error(); - return ret; -} - } // namespace testing } // namespace net diff --git a/net/base/mock_file_stream.h b/net/base/mock_file_stream.h index 5b779d4..a37b495 100644 --- a/net/base/mock_file_stream.h +++ b/net/base/mock_file_stream.h @@ -10,7 +10,6 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" -#include "base/memory/weak_ptr.h" #include "net/base/file_stream.h" #include "net/base/net_errors.h" @@ -22,11 +21,11 @@ namespace testing { class MockFileStream : public net::FileStream { public: - explicit MockFileStream(net::NetLog* net_log); - MockFileStream(base::PlatformFile file, int flags, net::NetLog* net_log); - MockFileStream(base::PlatformFile file, int flags, net::NetLog* net_log, - const scoped_refptr<base::TaskRunner>& task_runner); - virtual ~MockFileStream(); + MockFileStream(net::NetLog* net_log) + : net::FileStream(net_log), forced_error_(net::OK) {} + + MockFileStream(base::PlatformFile file, int flags, net::NetLog* net_log) + : net::FileStream(file, flags, net_log), forced_error_(net::OK) {} // FileStream methods. virtual int OpenSync(const base::FilePath& path, int open_flags) OVERRIDE; @@ -47,28 +46,11 @@ class MockFileStream : public net::FileStream { virtual int Flush(const CompletionCallback& callback) OVERRIDE; virtual int FlushSync() OVERRIDE; - void set_forced_error_async(int error) { - forced_error_ = error; - async_error_ = true; - } - void set_forced_error(int error) { - forced_error_ = error; - async_error_ = false; - } - void clear_forced_error() { - forced_error_ = net::OK; - async_error_ = false; - } + void set_forced_error(int error) { forced_error_ = error; } + void clear_forced_error() { forced_error_ = net::OK; } int forced_error() const { return forced_error_; } const base::FilePath& get_path() const { return path_; } - // Throttles all asynchronous callbacks, including forced errors, until a - // matching ReleaseCallbacks call. - void ThrottleCallbacks(); - - // Resumes running asynchronous callbacks and runs any throttled callbacks. - void ReleaseCallbacks(); - private: int ReturnError(int function_error) { if (forced_error_ != net::OK) { @@ -90,23 +72,8 @@ class MockFileStream : public net::FileStream { return function_error; } - // Wrappers for callbacks to make them honor ThrottleCallbacks and - // ReleaseCallbacks. - void DoCallback(const CompletionCallback& callback, int result); - void DoCallback64(const Int64CompletionCallback& callback, int64 result); - - // Depending on |async_error_|, either synchronously returns |forced_error_| - // asynchronously calls |callback| with |async_error_|. - int ErrorCallback(const CompletionCallback& callback); - int64 ErrorCallback64(const Int64CompletionCallback& callback); - int forced_error_; - bool async_error_; - bool throttled_; - base::Closure throttled_task_; base::FilePath path_; - - base::WeakPtrFactory<MockFileStream> weak_factory_; }; } // namespace testing diff --git a/net/url_request/url_request_test_job.cc b/net/url_request/url_request_test_job.cc index 422e080..31a07fe 100644 --- a/net/url_request/url_request_test_job.cc +++ b/net/url_request/url_request_test_job.cc @@ -24,15 +24,6 @@ typedef std::list<URLRequestTestJob*> URLRequestJobList; base::LazyInstance<URLRequestJobList>::Leaky g_pending_jobs = LAZY_INSTANCE_INITIALIZER; -class TestJobProtocolHandler : public URLRequestJobFactory::ProtocolHandler { - public: - // URLRequestJobFactory::ProtocolHandler implementation: - virtual URLRequestJob* MaybeCreateJob( - URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE { - return new URLRequestTestJob(request, network_delegate); - } -}; - } // namespace // static getters for known URLs @@ -107,9 +98,10 @@ std::string URLRequestTestJob::test_error_headers() { } // static -URLRequestJobFactory::ProtocolHandler* -URLRequestTestJob::CreateProtocolHandler() { - return new TestJobProtocolHandler(); +URLRequestJob* URLRequestTestJob::Factory(URLRequest* request, + NetworkDelegate* network_delegate, + const std::string& scheme) { + return new URLRequestTestJob(request, network_delegate); } URLRequestTestJob::URLRequestTestJob(URLRequest* request, diff --git a/net/url_request/url_request_test_job.h b/net/url_request/url_request_test_job.h index 1a85fb0..717cc0f 100644 --- a/net/url_request/url_request_test_job.h +++ b/net/url_request/url_request_test_job.h @@ -11,7 +11,6 @@ #include "net/base/load_timing_info.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_job.h" -#include "net/url_request/url_request_job_factory.h" namespace net { @@ -104,8 +103,8 @@ class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob { RequestPriority priority() const { return priority_; } - // Create a protocol handler for callers that don't subclass. - static URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler(); + // Factory method for protocol factory registration if callers don't subclass + static URLRequest::ProtocolFactory Factory; // Job functions virtual void SetPriority(RequestPriority priority) OVERRIDE; |