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

Side by Side Diff: net/base/upload_data.cc

Issue 9321003: net: Make UploadData::GetContentLength() asynchronous. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased 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
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.h" 5 #include "net/base/upload_data.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h"
9 #include "base/file_util.h" 10 #include "base/file_util.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
12 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
14 #include "base/threading/worker_pool.h"
15 #include "base/tracked_objects.h"
13 #include "net/base/file_stream.h" 16 #include "net/base/file_stream.h"
14 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
15 18
16 namespace net { 19 namespace net {
17 20
21 namespace {
22
23 // Helper function for GetContentLength().
24 void OnGetContentLengthComplete(
25 const UploadData::ContentLengthCallback& callback,
26 uint64* content_length) {
27 callback.Run(*content_length);
28 }
29
30 } // namespace
31
18 UploadData::Element::Element() 32 UploadData::Element::Element()
19 : type_(TYPE_BYTES), 33 : type_(TYPE_BYTES),
20 file_range_offset_(0), 34 file_range_offset_(0),
21 file_range_length_(kuint64max), 35 file_range_length_(kuint64max),
22 is_last_chunk_(false), 36 is_last_chunk_(false),
23 override_content_length_(false), 37 override_content_length_(false),
24 content_length_computed_(false), 38 content_length_computed_(false),
25 content_length_(-1), 39 content_length_(-1),
26 file_stream_(NULL) { 40 file_stream_(NULL) {
27 } 41 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 content_length_ = 0; 80 content_length_ = 0;
67 81
68 // We need to open the file here to decide if we should report the file's 82 // We need to open the file here to decide if we should report the file's
69 // size or zero. We cache the open file, so that we can still read it when 83 // size or zero. We cache the open file, so that we can still read it when
70 // it comes time to. 84 // it comes time to.
71 file_stream_ = NewFileStreamForReading(); 85 file_stream_ = NewFileStreamForReading();
72 if (!file_stream_) 86 if (!file_stream_)
73 return 0; 87 return 0;
74 88
75 int64 length = 0; 89 int64 length = 0;
76 90 if (!file_util::GetFileSize(file_path_, &length))
77 {
78 // TODO(tzik):
79 // file_util::GetFileSize may cause blocking IO.
80 // Temporary allow until fix: http://crbug.com/72001.
81 base::ThreadRestrictions::ScopedAllowIO allow_io;
82 if (!file_util::GetFileSize(file_path_, &length))
83 return 0; 91 return 0;
84 }
85 92
86 if (file_range_offset_ >= static_cast<uint64>(length)) 93 if (file_range_offset_ >= static_cast<uint64>(length))
87 return 0; // range is beyond eof 94 return 0; // range is beyond eof
88 95
89 // compensate for the offset and clip file_range_length_ to eof 96 // compensate for the offset and clip file_range_length_ to eof
90 content_length_ = std::min(length - file_range_offset_, file_range_length_); 97 content_length_ = std::min(length - file_range_offset_, file_range_length_);
91 return content_length_; 98 return content_length_;
92 } 99 }
93 100
94 FileStream* UploadData::Element::NewFileStreamForReading() { 101 FileStream* UploadData::Element::NewFileStreamForReading() {
95 // In common usage GetContentLength() will call this first and store the 102 // In common usage GetContentLength() will call this first and store the
96 // result into |file_| and a subsequent call (from UploadDataStream) will 103 // result into |file_| and a subsequent call (from UploadDataStream) will
97 // get the cached open FileStream. 104 // get the cached open FileStream.
98 if (file_stream_) { 105 if (file_stream_) {
99 FileStream* file = file_stream_; 106 FileStream* file = file_stream_;
100 file_stream_ = NULL; 107 file_stream_ = NULL;
101 return file; 108 return file;
102 } 109 }
103 110
104 // TODO(tzik):
105 // FileStream::Open and FileStream::Seek may cause blocking IO.
106 // Temporary allow until fix: http://crbug.com/72001.
107 base::ThreadRestrictions::ScopedAllowIO allow_io;
108
109 scoped_ptr<FileStream> file(new FileStream(NULL)); 111 scoped_ptr<FileStream> file(new FileStream(NULL));
110 int64 rv = file->OpenSync( 112 int64 rv = file->OpenSync(
111 file_path_, 113 file_path_,
112 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); 114 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
113 if (rv != OK) { 115 if (rv != OK) {
114 // If the file can't be opened, we'll just upload an empty file. 116 // If the file can't be opened, we'll just upload an empty file.
115 DLOG(WARNING) << "Failed to open \"" << file_path_.value() 117 DLOG(WARNING) << "Failed to open \"" << file_path_.value()
116 << "\" for reading: " << rv; 118 << "\" for reading: " << rv;
117 return NULL; 119 return NULL;
118 } 120 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 elements_.push_back(Element()); 167 elements_.push_back(Element());
166 elements_.back().SetToChunk(bytes, bytes_len, is_last_chunk); 168 elements_.back().SetToChunk(bytes, bytes_len, is_last_chunk);
167 if (chunk_callback_) 169 if (chunk_callback_)
168 chunk_callback_->OnChunkAvailable(); 170 chunk_callback_->OnChunkAvailable();
169 } 171 }
170 172
171 void UploadData::set_chunk_callback(ChunkCallback* callback) { 173 void UploadData::set_chunk_callback(ChunkCallback* callback) {
172 chunk_callback_ = callback; 174 chunk_callback_ = callback;
173 } 175 }
174 176
175 uint64 UploadData::GetContentLength() { 177 void UploadData::GetContentLength(const ContentLengthCallback& callback) {
176 if (is_chunked_) 178 uint64* result = new uint64(0);
177 return 0; 179 const bool task_is_slow = true;
180 const bool posted = base::WorkerPool::PostTaskAndReply(
181 FROM_HERE,
182 base::Bind(&UploadData::DoGetContentLength, this, result),
183 base::Bind(&OnGetContentLengthComplete, callback, base::Owned(result)),
184 task_is_slow);
185 DCHECK(posted);
186 }
178 187
179 uint64 len = 0; 188 uint64 UploadData::GetContentLengthSync() {
180 std::vector<Element>::iterator it = elements_.begin(); 189 uint64 content_length = 0;
181 for (; it != elements_.end(); ++it) 190 DoGetContentLength(&content_length);
182 len += (*it).GetContentLength(); 191 return content_length;
183 return len;
184 } 192 }
185 193
186 bool UploadData::IsInMemory() const { 194 bool UploadData::IsInMemory() const {
187 // Chunks are in memory, but UploadData does not have all the chunks at 195 // Chunks are in memory, but UploadData does not have all the chunks at
188 // once. Chunks are provided progressively with AppendChunk() as chunks 196 // once. Chunks are provided progressively with AppendChunk() as chunks
189 // are ready. Check is_chunked_ here, rather than relying on the loop 197 // are ready. Check is_chunked_ here, rather than relying on the loop
190 // below, as there is a case that is_chunked_ is set to true, but the 198 // below, as there is a case that is_chunked_ is set to true, but the
191 // first chunk is not yet delivered. 199 // first chunk is not yet delivered.
192 if (is_chunked_) 200 if (is_chunked_)
193 return false; 201 return false;
194 202
195 for (size_t i = 0; i < elements_.size(); ++i) { 203 for (size_t i = 0; i < elements_.size(); ++i) {
196 if (elements_[i].type() != TYPE_BYTES) 204 if (elements_[i].type() != TYPE_BYTES)
197 return false; 205 return false;
198 } 206 }
199 return true; 207 return true;
200 } 208 }
201 209
202 void UploadData::SetElements(const std::vector<Element>& elements) { 210 void UploadData::SetElements(const std::vector<Element>& elements) {
203 elements_ = elements; 211 elements_ = elements;
204 } 212 }
205 213
214 void UploadData::DoGetContentLength(uint64* content_length) {
215 *content_length = 0;
216
217 if (is_chunked_)
218 return;
219
220 for (size_t i = 0; i < elements_.size(); ++i)
221 *content_length += elements_[i].GetContentLength();
222 }
223
206 UploadData::~UploadData() { 224 UploadData::~UploadData() {
207 } 225 }
208 226
209 } // namespace net 227 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698