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

Unified Diff: net/base/upload_data_stream.cc

Issue 9350060: net: Make UploadDataStream::Init() asynchronous. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 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
« no previous file with comments | « net/base/upload_data_stream.h ('k') | net/base/upload_data_stream_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/upload_data_stream.cc
diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc
index 5b2e5d30b659cbf7410da85b41898ee604819fb4..19118b603b4185a0b748701f34bf9c2f631a1d2f 100644
--- a/net/base/upload_data_stream.cc
+++ b/net/base/upload_data_stream.cc
@@ -7,55 +7,91 @@
#include "base/file_util.h"
#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
+#include "base/threading/worker_pool.h"
+#include "base/tracked_objects.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
namespace net {
-bool UploadDataStream::merge_chunks_ = true;
-
-UploadDataStream::UploadDataStream(UploadData* upload_data)
- : upload_data_(upload_data),
- element_index_(0),
- element_offset_(0),
- element_file_bytes_remaining_(0),
- total_size_(0),
- current_position_(0),
- initialized_successfully_(false) {
-}
-
-UploadDataStream::~UploadDataStream() {
-}
-
-int UploadDataStream::Init() {
- DCHECK(!initialized_successfully_);
-
- {
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- total_size_ = upload_data_->GetContentLengthSync();
- }
+namespace {
+// Checks if any file in |upload_file| is modified since we initially
+// observed. Stores ERR_UPLOAD_FILE_CHANGED in |result| if such a
+// modification is detected. Otherwise, stores OK in |result|.
+void CheckModifiedFiles(scoped_refptr<UploadData> upload_data, int* result) {
// If the underlying file has been changed and the expected file
// modification time is set, treat it as error. Note that the expected
// modification time from WebKit is based on time_t precision. So we
// have to convert both to time_t to compare. This check is used for
// sliced files.
- const std::vector<UploadData::Element>& elements = *upload_data_->elements();
+ const std::vector<UploadData::Element>& elements = *upload_data->elements();
for (size_t i = 0; i < elements.size(); ++i) {
const UploadData::Element& element = elements[i];
if (element.type() == UploadData::TYPE_FILE &&
!element.expected_file_modification_time().is_null()) {
- // Temporarily allow until fix: http://crbug.com/72001.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
base::PlatformFileInfo info;
if (file_util::GetFileInfo(element.file_path(), &info) &&
element.expected_file_modification_time().ToTimeT() !=
info.last_modified.ToTimeT()) {
- return ERR_UPLOAD_FILE_CHANGED;
+ *result = ERR_UPLOAD_FILE_CHANGED;
+ return;
}
}
}
+ *result = OK;
+ return;
+}
+
+} // namespace
+
+bool UploadDataStream::merge_chunks_ = true;
+
+UploadDataStream::UploadDataStream(UploadData* upload_data)
+ : upload_data_(upload_data),
+ element_index_(0),
+ element_offset_(0),
+ element_file_bytes_remaining_(0),
+ total_size_(0),
+ current_position_(0),
+ initialized_successfully_(false),
+ weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+UploadDataStream::~UploadDataStream() {
+}
+
+int UploadDataStream::Init(const CompletionCallback& on_completion) {
+ DCHECK(!initialized_successfully_);
+ DCHECK(user_callback_.is_null());
+
+ // Fast path. Initialize synchronously if the data is in memory.
+ if (upload_data_->IsInMemory())
+ return InitSync();
+
+ // The asynchronous initialization is performed in the following steps:
+ // 1. GetContentLength() computes the content length in the background.
+ // 2. OnGetContentLengthComplete() is called once it's done.
+ // 3. CheckModifiedFiles() checks the modified files in the background.
+ // 4. OnCheckModifiedFilesComplete() is called once it's done.
+ // 5. user_callback_ is run with the initialization result.
+ user_callback_ = on_completion;
+ upload_data_->GetContentLength(
+ base::Bind(&UploadDataStream::OnGetContentLengthComplete,
+ weak_ptr_factory_.GetWeakPtr()));
+ return ERR_IO_PENDING;
+}
+
+int UploadDataStream::InitSync() {
+ DCHECK(!initialized_successfully_);
+
+ total_size_ = upload_data_->GetContentLengthSync();
+
+ int result = OK;
+ CheckModifiedFiles(upload_data_, &result);
+ if (result != OK)
+ return result;
initialized_successfully_ = true;
return OK;
@@ -164,6 +200,31 @@ void UploadDataStream::AdvanceToNextElement() {
}
}
+void UploadDataStream::OnGetContentLengthComplete(uint64 content_length) {
+ total_size_ = content_length;
+ int* result = new int(OK);
+ const bool posted = base::WorkerPool::PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&CheckModifiedFiles, upload_data_, result),
+ base::Bind(&UploadDataStream::OnCheckModifiedFilesComplete,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(result)),
+ true /* task_is_slow */);
+ DCHECK(posted);
+}
+
+void UploadDataStream::OnCheckModifiedFilesComplete(int* result) {
+ if (*result == OK)
+ initialized_successfully_ = true;
+
+ // Tell the caller of Init() that the initialization is done. Run() may
+ // triger other asynchronous operations so user_callback_ is reset before
+ // running it.
+ CompletionCallback copied_user_callback = user_callback_;
+ user_callback_.Reset();
+ copied_user_callback.Run(*result);
+}
+
bool UploadDataStream::IsEOF() const {
const std::vector<UploadData::Element>& elements = *upload_data_->elements();
« no previous file with comments | « net/base/upload_data_stream.h ('k') | net/base/upload_data_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698