Chromium Code Reviews| Index: net/url_request/url_request_file_job.cc |
| =================================================================== |
| --- net/url_request/url_request_file_job.cc (revision 151422) |
| +++ net/url_request/url_request_file_job.cc (working copy) |
| @@ -42,54 +42,20 @@ |
| namespace net { |
| -class URLRequestFileJob::AsyncResolver |
| - : public base::RefCountedThreadSafe<URLRequestFileJob::AsyncResolver> { |
| - public: |
| - explicit AsyncResolver(URLRequestFileJob* owner) |
| - : owner_(owner), owner_loop_(MessageLoop::current()) { |
| - } |
| +URLRequestFileJob::FileMetaInfo::FileMetaInfo() |
| + : file_size(-1), |
| + mime_type_result(false), |
| + file_exists(false), |
| + is_directory(false) { |
| +} |
| - void Resolve(const FilePath& file_path) { |
| - base::PlatformFileInfo file_info; |
| - bool exists = file_util::GetFileInfo(file_path, &file_info); |
| - base::AutoLock locked(lock_); |
| - if (owner_loop_) { |
| - owner_loop_->PostTask( |
| - FROM_HERE, |
| - base::Bind(&AsyncResolver::ReturnResults, this, exists, file_info)); |
| - } |
| - } |
| - |
| - void Cancel() { |
| - owner_ = NULL; |
| - |
| - base::AutoLock locked(lock_); |
| - owner_loop_ = NULL; |
| - } |
| - |
| - private: |
| - friend class base::RefCountedThreadSafe<URLRequestFileJob::AsyncResolver>; |
| - |
| - ~AsyncResolver() {} |
| - |
| - void ReturnResults(bool exists, const base::PlatformFileInfo& file_info) { |
| - if (owner_) |
| - owner_->DidResolve(exists, file_info); |
| - } |
| - |
| - URLRequestFileJob* owner_; |
| - |
| - base::Lock lock_; |
| - MessageLoop* owner_loop_; |
| -}; |
| - |
| URLRequestFileJob::URLRequestFileJob(URLRequest* request, |
| const FilePath& file_path) |
| : URLRequestJob(request, request->context()->network_delegate()), |
| file_path_(file_path), |
| - stream_(NULL), |
| - is_directory_(false), |
| - remaining_bytes_(0) { |
| + stream_(new FileStream(NULL)), |
| + remaining_bytes_(0), |
| + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| } |
| // static |
| @@ -119,25 +85,21 @@ |
| } |
| void URLRequestFileJob::Start() { |
| - DCHECK(!async_resolver_); |
| - async_resolver_ = new AsyncResolver(this); |
| - base::WorkerPool::PostTask( |
| + FileMetaInfo* meta_info = new FileMetaInfo; |
| + base::WorkerPool::PostTaskAndReply( |
| FROM_HERE, |
| - base::Bind(&AsyncResolver::Resolve, async_resolver_.get(), file_path_), |
| + base::Bind(&URLRequestFileJob::FetchMetaInfo, file_path_, |
| + base::Unretained(meta_info)), |
| + base::Bind(&URLRequestFileJob::DidFetchMetaInfo, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + base::Owned(meta_info)), |
| true); |
| } |
| void URLRequestFileJob::Kill() { |
| - // URL requests should not block on the disk! |
| - // http://code.google.com/p/chromium/issues/detail?id=59849 |
| - base::ThreadRestrictions::ScopedAllowIO allow_io; |
| - stream_.CloseSync(); |
| + stream_.reset(); |
|
wtc
2012/08/14 18:00:40
Could you explain why it is necessary to delete th
pivanof
2012/08/15 06:36:50
We can't call CloseSync() because it will make IO
|
| + weak_ptr_factory_.InvalidateWeakPtrs(); |
| - if (async_resolver_) { |
| - async_resolver_->Cancel(); |
| - async_resolver_ = NULL; |
| - } |
| - |
| URLRequestJob::Kill(); |
| } |
| @@ -157,9 +119,9 @@ |
| return true; |
| } |
| - int rv = stream_.Read(dest, dest_size, |
| - base::Bind(&URLRequestFileJob::DidRead, |
| - base::Unretained(this))); |
| + int rv = stream_->Read(dest, dest_size, |
| + base::Bind(&URLRequestFileJob::DidRead, |
| + weak_ptr_factory_.GetWeakPtr())); |
| if (rv >= 0) { |
| // Data is immediately available. |
| *bytes_read = rv; |
| @@ -179,7 +141,7 @@ |
| bool URLRequestFileJob::IsRedirectResponse(GURL* location, |
| int* http_status_code) { |
| - if (is_directory_) { |
| + if (meta_info_.is_directory) { |
| // This happens when we discovered the file is a directory, so needs a |
| // slash at the end of the path. |
| std::string new_path = request_->url().path(); |
| @@ -221,12 +183,12 @@ |
| } |
| bool URLRequestFileJob::GetMimeType(std::string* mime_type) const { |
| - // URL requests should not block on the disk! On Windows this goes to the |
| - // registry. |
| - // http://code.google.com/p/chromium/issues/detail?id=59849 |
| - base::ThreadRestrictions::ScopedAllowIO allow_io; |
| DCHECK(request_); |
| - return GetMimeTypeFromFile(file_path_, mime_type); |
| + if (meta_info_.mime_type_result) { |
| + *mime_type = meta_info_.mime_type; |
| + return true; |
| + } |
| + return false; |
|
wtc
2012/08/14 18:00:40
Nit: this can be rewritten as:
if (meta_info_.m
|
| } |
| void URLRequestFileJob::SetExtraRequestHeaders( |
| @@ -260,20 +222,23 @@ |
| } |
| URLRequestFileJob::~URLRequestFileJob() { |
| - DCHECK(!async_resolver_); |
| } |
| -void URLRequestFileJob::DidResolve( |
| - bool exists, const base::PlatformFileInfo& file_info) { |
| - async_resolver_ = NULL; |
| +void URLRequestFileJob::FetchMetaInfo(const FilePath& file_path, |
| + FileMetaInfo* meta_info) { |
| + base::PlatformFileInfo platform_info; |
| + meta_info->file_exists = file_util::GetFileInfo(file_path, &platform_info); |
| + meta_info->file_size = platform_info.size; |
| + meta_info->is_directory = platform_info.is_directory; |
|
wtc
2012/08/14 18:00:40
It seems that platform_info may contain junk if th
wtc
2012/11/14 21:05:01
This change is probably worth making. I am not 100
wtc
2012/11/17 02:15:29
pivanof wrote:
|
| + // On Windows GetMimeTypeFromFile() goes to the registry. Thus it should be |
| + // done in WorkerPool. |
| + meta_info->mime_type_result = GetMimeTypeFromFile(file_path, |
| + &meta_info->mime_type); |
| +} |
| - // We may have been orphaned... |
| - if (!request_) |
| - return; |
| +void URLRequestFileJob::DidFetchMetaInfo(const FileMetaInfo* meta_info) { |
| + meta_info_ = *meta_info; |
| - is_directory_ = file_info.is_directory; |
| - |
| - int rv = OK; |
| // We use URLRequestFileJob to handle files as well as directories without |
| // trailing slash. |
| // If a directory does not exist, we return ERR_FILE_NOT_FOUND. Otherwise, |
| @@ -282,25 +247,32 @@ |
| // However, Windows resolves "\" to "C:\", thus reports it as existent. |
| // So what happens is we append it with trailing slash and redirect it to |
| // FileDirJob where it is resolved as invalid. |
| - if (!exists) { |
| - rv = ERR_FILE_NOT_FOUND; |
| - } else if (!is_directory_) { |
| - // URL requests should not block on the disk! |
| - // http://code.google.com/p/chromium/issues/detail?id=59849 |
| - base::ThreadRestrictions::ScopedAllowIO allow_io; |
| - |
| - int flags = base::PLATFORM_FILE_OPEN | |
| - base::PLATFORM_FILE_READ | |
| - base::PLATFORM_FILE_ASYNC; |
| - rv = stream_.OpenSync(file_path_, flags); |
| + if (!meta_info_.file_exists) { |
| + DidOpen(ERR_FILE_NOT_FOUND); |
| + return; |
| } |
| + if (meta_info_.is_directory) { |
| + DidOpen(OK); |
| + return; |
| + } |
| - if (rv != OK) { |
| - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |
| + int flags = base::PLATFORM_FILE_OPEN | |
| + base::PLATFORM_FILE_READ | |
| + base::PLATFORM_FILE_ASYNC; |
| + int rv = stream_->Open(file_path_, flags, |
| + base::Bind(&URLRequestFileJob::DidOpen, |
| + weak_ptr_factory_.GetWeakPtr())); |
| + if (rv != ERR_IO_PENDING) |
| + DidOpen(rv); |
| +} |
| + |
| +void URLRequestFileJob::DidOpen(int result) { |
| + if (result != OK) { |
| + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); |
| return; |
| } |
| - if (!byte_range_.ComputeBounds(file_info.size)) { |
| + if (!byte_range_.ComputeBounds(meta_info_.file_size)) { |
| NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, |
| ERR_REQUEST_RANGE_NOT_SATISFIABLE)); |
| return; |
| @@ -310,21 +282,30 @@ |
| byte_range_.first_byte_position() + 1; |
| DCHECK_GE(remaining_bytes_, 0); |
| - // URL requests should not block on the disk! |
| - // http://code.google.com/p/chromium/issues/detail?id=59849 |
| - { |
| - base::ThreadRestrictions::ScopedAllowIO allow_io; |
| - // Do the seek at the beginning of the request. |
| - if (remaining_bytes_ > 0 && |
| - byte_range_.first_byte_position() != 0 && |
| - byte_range_.first_byte_position() != |
| - stream_.SeekSync(FROM_BEGIN, byte_range_.first_byte_position())) { |
| - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, |
| - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); |
| - return; |
| + if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0) { |
| + int rv = stream_->Seek(FROM_BEGIN, byte_range_.first_byte_position(), |
| + base::Bind(&URLRequestFileJob::DidSeek, |
| + weak_ptr_factory_.GetWeakPtr())); |
| + if (rv != ERR_IO_PENDING) { |
| + // stream_->Seek() didn't finish successfully, so pass an intentionally |
|
wtc
2012/08/14 18:00:40
Nit: didn't finish successfully => failed
|
| + // erroneous value into DidSeek(). |
| + DidSeek(-1); |
| } |
| + } else { |
| + // We didn't need to call stream_->Seek() at all, so let's pretend we |
| + // actually did that and the FileStream has positioned where we need it |
| + // to be (it won't be true only when remaining_bytes_ <= 0). |
|
wtc
2012/08/14 18:00:40
I don't understand the sentence in parentheses
(
pivanof
2012/08/15 06:36:50
What I meant is that statement before parenthesis
wtc
2012/08/17 00:24:04
I suggest something like this:
// We didn't need
|
| + DidSeek(byte_range_.first_byte_position()); |
| } |
| +} |
| +void URLRequestFileJob::DidSeek(int64 result) { |
| + if (result != byte_range_.first_byte_position()) { |
| + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, |
| + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); |
| + return; |
| + } |
| + |
| set_expected_content_size(remaining_bytes_); |
| NotifyHeadersComplete(); |
| } |