Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1915)

Unified Diff: net/url_request/url_request_file_job.cc

Issue 10695110: Avoid disk accesses on the wrong thread in URLRequestFileJob (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Avoid disk accesses on the wrong thread in URLRequestFileJob Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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();
}

Powered by Google App Engine
This is Rietveld 408576698