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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/upload_data_stream.h" 5 #include "net/base/upload_data_stream.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h" 9 #include "base/threading/thread_restrictions.h"
10 #include "base/threading/worker_pool.h"
11 #include "base/tracked_objects.h"
10 #include "net/base/file_stream.h" 12 #include "net/base/file_stream.h"
11 #include "net/base/io_buffer.h" 13 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
13 15
14 namespace net { 16 namespace net {
15 17
18 namespace {
19
20 // Checks if any file in |upload_file| is modified since we initially
21 // observed. Stores ERR_UPLOAD_FILE_CHANGED in |result| if such a
22 // modification is detected. Otherwise, stores OK in |result|.
23 void CheckModifiedFiles(scoped_refptr<UploadData> upload_data, int* result) {
24 // If the underlying file has been changed and the expected file
25 // modification time is set, treat it as error. Note that the expected
26 // modification time from WebKit is based on time_t precision. So we
27 // have to convert both to time_t to compare. This check is used for
28 // sliced files.
29 const std::vector<UploadData::Element>& elements = *upload_data->elements();
30 for (size_t i = 0; i < elements.size(); ++i) {
31 const UploadData::Element& element = elements[i];
32 if (element.type() == UploadData::TYPE_FILE &&
33 !element.expected_file_modification_time().is_null()) {
34 base::PlatformFileInfo info;
35 if (file_util::GetFileInfo(element.file_path(), &info) &&
36 element.expected_file_modification_time().ToTimeT() !=
37 info.last_modified.ToTimeT()) {
38 *result = ERR_UPLOAD_FILE_CHANGED;
39 return;
40 }
41 }
42 }
43 *result = OK;
44 return;
45 }
46
47 } // namespace
48
16 bool UploadDataStream::merge_chunks_ = true; 49 bool UploadDataStream::merge_chunks_ = true;
17 50
18 UploadDataStream::UploadDataStream(UploadData* upload_data) 51 UploadDataStream::UploadDataStream(UploadData* upload_data)
19 : upload_data_(upload_data), 52 : upload_data_(upload_data),
20 element_index_(0), 53 element_index_(0),
21 element_offset_(0), 54 element_offset_(0),
22 element_file_bytes_remaining_(0), 55 element_file_bytes_remaining_(0),
23 total_size_(0), 56 total_size_(0),
24 current_position_(0), 57 current_position_(0),
25 initialized_successfully_(false) { 58 initialized_successfully_(false),
59 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
26 } 60 }
27 61
28 UploadDataStream::~UploadDataStream() { 62 UploadDataStream::~UploadDataStream() {
29 } 63 }
30 64
31 int UploadDataStream::Init() { 65 int UploadDataStream::Init(const CompletionCallback& on_completion) {
66 DCHECK(!initialized_successfully_);
67 DCHECK(user_callback_.is_null());
68
69 // Fast path. Initialize synchronously if the data is in memory.
70 if (upload_data_->IsInMemory())
71 return InitSync();
72
73 // The asynchronous initialization is performed in the following steps:
74 // 1. GetContentLength() computes the content length in the background.
75 // 2. OnGetContentLengthComplete() is called once it's done.
76 // 3. CheckModifiedFiles() checks the modified files in the background.
77 // 4. OnCheckModifiedFilesComplete() is called once it's done.
78 // 5. user_callback_ is run with the initialization result.
79 user_callback_ = on_completion;
80 upload_data_->GetContentLength(
81 base::Bind(&UploadDataStream::OnGetContentLengthComplete,
82 weak_ptr_factory_.GetWeakPtr()));
83 return ERR_IO_PENDING;
84 }
85
86 int UploadDataStream::InitSync() {
32 DCHECK(!initialized_successfully_); 87 DCHECK(!initialized_successfully_);
33 88
34 { 89 total_size_ = upload_data_->GetContentLengthSync();
35 base::ThreadRestrictions::ScopedAllowIO allow_io;
36 total_size_ = upload_data_->GetContentLengthSync();
37 }
38 90
39 // If the underlying file has been changed and the expected file 91 int result = OK;
40 // modification time is set, treat it as error. Note that the expected 92 CheckModifiedFiles(upload_data_, &result);
41 // modification time from WebKit is based on time_t precision. So we 93 if (result != OK)
42 // have to convert both to time_t to compare. This check is used for 94 return result;
43 // sliced files.
44 const std::vector<UploadData::Element>& elements = *upload_data_->elements();
45 for (size_t i = 0; i < elements.size(); ++i) {
46 const UploadData::Element& element = elements[i];
47 if (element.type() == UploadData::TYPE_FILE &&
48 !element.expected_file_modification_time().is_null()) {
49 // Temporarily allow until fix: http://crbug.com/72001.
50 base::ThreadRestrictions::ScopedAllowIO allow_io;
51 base::PlatformFileInfo info;
52 if (file_util::GetFileInfo(element.file_path(), &info) &&
53 element.expected_file_modification_time().ToTimeT() !=
54 info.last_modified.ToTimeT()) {
55 return ERR_UPLOAD_FILE_CHANGED;
56 }
57 }
58 }
59 95
60 initialized_successfully_ = true; 96 initialized_successfully_ = true;
61 return OK; 97 return OK;
62 } 98 }
63 99
64 int UploadDataStream::Read(IOBuffer* buf, int buf_len) { 100 int UploadDataStream::Read(IOBuffer* buf, int buf_len) {
65 std::vector<UploadData::Element>& elements = *upload_data_->elements(); 101 std::vector<UploadData::Element>& elements = *upload_data_->elements();
66 102
67 int bytes_copied = 0; 103 int bytes_copied = 0;
68 while (bytes_copied < buf_len && element_index_ < elements.size()) { 104 while (bytes_copied < buf_len && element_index_ < elements.size()) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 element_offset_ = 0; 193 element_offset_ = 0;
158 element_file_bytes_remaining_ = 0; 194 element_file_bytes_remaining_ = 0;
159 if (element_file_stream_.get()) { 195 if (element_file_stream_.get()) {
160 // Temporarily allow until fix: http://crbug.com/72001. 196 // Temporarily allow until fix: http://crbug.com/72001.
161 base::ThreadRestrictions::ScopedAllowIO allow_io; 197 base::ThreadRestrictions::ScopedAllowIO allow_io;
162 element_file_stream_->CloseSync(); 198 element_file_stream_->CloseSync();
163 element_file_stream_.reset(); 199 element_file_stream_.reset();
164 } 200 }
165 } 201 }
166 202
203 void UploadDataStream::OnGetContentLengthComplete(uint64 content_length) {
204 total_size_ = content_length;
205 int* result = new int(OK);
206 const bool posted = base::WorkerPool::PostTaskAndReply(
207 FROM_HERE,
208 base::Bind(&CheckModifiedFiles, upload_data_, result),
209 base::Bind(&UploadDataStream::OnCheckModifiedFilesComplete,
210 weak_ptr_factory_.GetWeakPtr(),
211 base::Owned(result)),
212 true /* task_is_slow */);
213 DCHECK(posted);
214 }
215
216 void UploadDataStream::OnCheckModifiedFilesComplete(int* result) {
217 if (*result == OK)
218 initialized_successfully_ = true;
219
220 // Tell the caller of Init() that the initialization is done. Run() may
221 // triger other asynchronous operations so user_callback_ is reset before
222 // running it.
223 CompletionCallback copied_user_callback = user_callback_;
224 user_callback_.Reset();
225 copied_user_callback.Run(*result);
226 }
227
167 bool UploadDataStream::IsEOF() const { 228 bool UploadDataStream::IsEOF() const {
168 const std::vector<UploadData::Element>& elements = *upload_data_->elements(); 229 const std::vector<UploadData::Element>& elements = *upload_data_->elements();
169 230
170 // Check if all elements are consumed. 231 // Check if all elements are consumed.
171 if (element_index_ == elements.size()) { 232 if (element_index_ == elements.size()) {
172 // If the upload data is chunked, check if the last element is the 233 // If the upload data is chunked, check if the last element is the
173 // last chunk. 234 // last chunk.
174 if (!upload_data_->is_chunked() || 235 if (!upload_data_->is_chunked() ||
175 (!elements.empty() && elements.back().is_last_chunk())) { 236 (!elements.empty() && elements.back().is_last_chunk())) {
176 return true; 237 return true;
177 } 238 }
178 } 239 }
179 return false; 240 return false;
180 } 241 }
181 242
182 bool UploadDataStream::IsInMemory() const { 243 bool UploadDataStream::IsInMemory() const {
183 DCHECK(initialized_successfully_); 244 DCHECK(initialized_successfully_);
184 245
185 return upload_data_->IsInMemory(); 246 return upload_data_->IsInMemory();
186 } 247 }
187 248
188 } // namespace net 249 } // namespace net
OLDNEW
« 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