Chromium Code Reviews| 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 |