OLD | NEW |
---|---|
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/bind.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 } // namespace | 30 } // namespace |
31 | 31 |
32 UploadData::Element::Element() | 32 UploadData::Element::Element() |
33 : type_(TYPE_BYTES), | 33 : type_(TYPE_BYTES), |
34 file_range_offset_(0), | 34 file_range_offset_(0), |
35 file_range_length_(kuint64max), | 35 file_range_length_(kuint64max), |
36 is_last_chunk_(false), | 36 is_last_chunk_(false), |
37 override_content_length_(false), | 37 override_content_length_(false), |
38 content_length_computed_(false), | 38 content_length_computed_(false), |
39 content_length_(-1), | 39 content_length_(-1), |
40 offset_(0), | |
40 file_stream_(NULL) { | 41 file_stream_(NULL) { |
41 } | 42 } |
42 | 43 |
43 UploadData::Element::~Element() { | 44 UploadData::Element::~Element() { |
44 // In the common case |file__stream_| will be null. | 45 // In the common case |file__stream_| will be null. |
45 if (file_stream_) { | 46 if (file_stream_) { |
46 // Temporarily allow until fix: http://crbug.com/72001. | 47 // Temporarily allow until fix: http://crbug.com/72001. |
47 base::ThreadRestrictions::ScopedAllowIO allow_io; | 48 base::ThreadRestrictions::ScopedAllowIO allow_io; |
48 file_stream_->CloseSync(); | 49 file_stream_->CloseSync(); |
49 delete file_stream_; | 50 delete file_stream_; |
(...skipping 25 matching lines...) Expand all Loading... | |
75 // TODO(darin): This size calculation could be out of sync with the state of | 76 // TODO(darin): This size calculation could be out of sync with the state of |
76 // the file when we get around to reading it. We should probably find a way | 77 // the file when we get around to reading it. We should probably find a way |
77 // to lock the file or somehow protect against this error condition. | 78 // to lock the file or somehow protect against this error condition. |
78 | 79 |
79 content_length_computed_ = true; | 80 content_length_computed_ = true; |
80 content_length_ = 0; | 81 content_length_ = 0; |
81 | 82 |
82 // We need to open the file here to decide if we should report the file's | 83 // We need to open the file here to decide if we should report the file's |
83 // size or zero. We cache the open file, so that we can still read it when | 84 // size or zero. We cache the open file, so that we can still read it when |
84 // it comes time to. | 85 // it comes time to. |
85 file_stream_ = NewFileStreamForReading(); | 86 file_stream_ = OpenFileStream(); |
86 if (!file_stream_) | 87 if (!file_stream_) |
87 return 0; | 88 return 0; |
88 | 89 |
89 int64 length = 0; | 90 int64 length = 0; |
90 if (!file_util::GetFileSize(file_path_, &length)) | 91 if (!file_util::GetFileSize(file_path_, &length)) |
91 return 0; | 92 return 0; |
92 | 93 |
93 if (file_range_offset_ >= static_cast<uint64>(length)) | 94 if (file_range_offset_ >= static_cast<uint64>(length)) |
94 return 0; // range is beyond eof | 95 return 0; // range is beyond eof |
95 | 96 |
96 // compensate for the offset and clip file_range_length_ to eof | 97 // compensate for the offset and clip file_range_length_ to eof |
97 content_length_ = std::min(length - file_range_offset_, file_range_length_); | 98 content_length_ = std::min(length - file_range_offset_, file_range_length_); |
98 return content_length_; | 99 return content_length_; |
99 } | 100 } |
100 | 101 |
101 FileStream* UploadData::Element::NewFileStreamForReading() { | 102 int UploadData::Element::ReadSync(char* buf, int buf_len) { |
102 // In common usage GetContentLength() will call this first and store the | 103 if (type_ == UploadData::TYPE_BYTES || type_ == UploadData::TYPE_CHUNK) { |
103 // result into |file_| and a subsequent call (from UploadDataStream) will | 104 return ReadFromMemorySync(buf, buf_len); |
104 // get the cached open FileStream. | 105 } else if (type_ == UploadData::TYPE_FILE) { |
105 if (file_stream_) { | 106 return ReadFromFileSync(buf, buf_len); |
106 FileStream* file = file_stream_; | |
107 file_stream_ = NULL; | |
108 return file; | |
109 } | 107 } |
110 | 108 |
109 NOTREACHED(); | |
110 return 0; | |
111 } | |
112 | |
113 uint64 UploadData::Element::BytesRemaining() { | |
114 return GetContentLength() - offset_; | |
115 } | |
116 | |
117 FileStream* UploadData::Element::OpenFileStream() { | |
111 scoped_ptr<FileStream> file(new FileStream(NULL)); | 118 scoped_ptr<FileStream> file(new FileStream(NULL)); |
112 int64 rv = file->OpenSync( | 119 int64 rv = file->OpenSync( |
113 file_path_, | 120 file_path_, |
114 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); | 121 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); |
115 if (rv != OK) { | 122 if (rv != OK) { |
116 // If the file can't be opened, we'll just upload an empty file. | 123 // If the file can't be opened, we'll just upload an empty file. |
117 DLOG(WARNING) << "Failed to open \"" << file_path_.value() | 124 DLOG(WARNING) << "Failed to open \"" << file_path_.value() |
118 << "\" for reading: " << rv; | 125 << "\" for reading: " << rv; |
119 return NULL; | 126 return NULL; |
120 } | 127 } |
121 if (file_range_offset_) { | 128 if (file_range_offset_) { |
122 rv = file->Seek(FROM_BEGIN, file_range_offset_); | 129 rv = file->Seek(FROM_BEGIN, file_range_offset_); |
123 if (rv < 0) { | 130 if (rv < 0) { |
124 DLOG(WARNING) << "Failed to seek \"" << file_path_.value() | 131 DLOG(WARNING) << "Failed to seek \"" << file_path_.value() |
125 << "\" to offset: " << file_range_offset_ << " (" << rv | 132 << "\" to offset: " << file_range_offset_ << " (" << rv |
126 << ")"; | 133 << ")"; |
127 return NULL; | 134 return NULL; |
128 } | 135 } |
129 } | 136 } |
130 | 137 |
131 return file.release(); | 138 return file.release(); |
132 } | 139 } |
133 | 140 |
141 int UploadData::Element::ReadFromMemorySync(char* buf, int buf_len) { | |
willchan no longer on Chromium
2012/02/24 21:54:40
Can you DCHECK that buf_len is positive (it should
satorux1
2012/02/24 22:35:22
Done. Updated the comment as well.
| |
142 DCHECK(type_ == UploadData::TYPE_BYTES || type_ == UploadData::TYPE_CHUNK); | |
143 | |
144 const size_t num_bytes_to_read = std::min(BytesRemaining(), | |
145 static_cast<size_t>(buf_len)); | |
146 | |
147 // Check if we have anything to copy first, because we are getting | |
148 // the address of an element in |bytes_| and that will throw an | |
149 // exception if |bytes_| is an empty vector. | |
150 if (num_bytes_to_read > 0) { | |
151 memcpy(buf, &bytes_[offset_], num_bytes_to_read); | |
152 } | |
153 | |
154 offset_ += num_bytes_to_read; | |
155 return num_bytes_to_read; | |
156 } | |
157 | |
158 int UploadData::Element::ReadFromFileSync(char* buf, int buf_len) { | |
willchan no longer on Chromium
2012/02/24 21:54:40
Ditto on DCHECK'ing |buf_len|'s values.
satorux1
2012/02/24 22:35:22
Done.
| |
159 DCHECK_EQ(UploadData::TYPE_FILE, type_); | |
160 | |
161 // Open the file of the current element if not yet opened. | |
162 // In common usage, GetContentLength() opened it already. | |
163 if (!file_stream_) { | |
164 // Temporarily allow until fix: http://crbug.com/72001. | |
165 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
166 file_stream_ = OpenFileStream(); | |
167 } | |
168 | |
169 const int num_bytes_to_read = | |
170 static_cast<int>(std::min(BytesRemaining(), | |
171 static_cast<uint64>(buf_len))); | |
172 if (num_bytes_to_read > 0) { | |
173 int num_bytes_consumed = 0; | |
174 // Temporarily allow until fix: http://crbug.com/72001. | |
175 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
176 // file_stream_ is NULL if the target file is | |
177 // missing or not readable. | |
178 if (file_stream_) { | |
179 num_bytes_consumed = | |
180 file_stream_->ReadSync(buf, num_bytes_to_read); | |
181 } | |
182 if (num_bytes_consumed <= 0) { | |
183 // If there's less data to read than we initially observed, then | |
184 // pad with zero. Otherwise the server will hang waiting for the | |
185 // rest of the data. | |
186 memset(buf, 0, num_bytes_to_read); | |
187 } | |
188 } | |
189 | |
190 offset_ += num_bytes_to_read; | |
191 return num_bytes_to_read; | |
192 } | |
193 | |
134 UploadData::UploadData() | 194 UploadData::UploadData() |
135 : identifier_(0), | 195 : identifier_(0), |
136 chunk_callback_(NULL), | 196 chunk_callback_(NULL), |
137 is_chunked_(false) { | 197 is_chunked_(false) { |
138 } | 198 } |
139 | 199 |
140 void UploadData::AppendBytes(const char* bytes, int bytes_len) { | 200 void UploadData::AppendBytes(const char* bytes, int bytes_len) { |
141 DCHECK(!is_chunked_); | 201 DCHECK(!is_chunked_); |
142 if (bytes_len > 0) { | 202 if (bytes_len > 0) { |
143 elements_.push_back(Element()); | 203 elements_.push_back(Element()); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 return; | 278 return; |
219 | 279 |
220 for (size_t i = 0; i < elements_.size(); ++i) | 280 for (size_t i = 0; i < elements_.size(); ++i) |
221 *content_length += elements_[i].GetContentLength(); | 281 *content_length += elements_[i].GetContentLength(); |
222 } | 282 } |
223 | 283 |
224 UploadData::~UploadData() { | 284 UploadData::~UploadData() { |
225 } | 285 } |
226 | 286 |
227 } // namespace net | 287 } // namespace net |
OLD | NEW |