| Index: net/base/upload_data_stream.cc
 | 
| diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc
 | 
| index b96680efc3eeaf056276a44b1c2942d4f42f1378..e46f2e62718479c71dadccfd7727e191b35581aa 100644
 | 
| --- a/net/base/upload_data_stream.cc
 | 
| +++ b/net/base/upload_data_stream.cc
 | 
| @@ -4,12 +4,10 @@
 | 
|  
 | 
|  #include "net/base/upload_data_stream.h"
 | 
|  
 | 
| -#include "base/file_util.h"
 | 
|  #include "base/logging.h"
 | 
| -#include "base/threading/thread_restrictions.h"
 | 
| -#include "net/base/file_stream.h"
 | 
|  #include "net/base/io_buffer.h"
 | 
|  #include "net/base/net_errors.h"
 | 
| +#include "net/base/upload_element_reader.h"
 | 
|  
 | 
|  namespace net {
 | 
|  
 | 
| @@ -27,6 +25,9 @@ UploadDataStream::UploadDataStream(UploadData* upload_data)
 | 
|        total_size_(0),
 | 
|        current_position_(0),
 | 
|        initialized_successfully_(false) {
 | 
| +  const std::vector<UploadElement>& elements = *upload_data_->elements();
 | 
| +  for (size_t i = 0; i < elements.size(); ++i)
 | 
| +    element_readers_.push_back(UploadElementReader::Create(elements[i]));
 | 
|  }
 | 
|  
 | 
|  UploadDataStream::~UploadDataStream() {
 | 
| @@ -34,57 +35,47 @@ UploadDataStream::~UploadDataStream() {
 | 
|  
 | 
|  int UploadDataStream::Init() {
 | 
|    DCHECK(!initialized_successfully_);
 | 
| -  std::vector<UploadElement>* elements = upload_data_->elements_mutable();
 | 
| -  {
 | 
| -    base::ThreadRestrictions::ScopedAllowIO allow_io;
 | 
| -    total_size_ = 0;
 | 
| -    if (!is_chunked()) {
 | 
| -      for (size_t i = 0; i < elements->size(); ++i)
 | 
| -        total_size_ += (*elements)[i].GetContentLength();
 | 
| -    }
 | 
| -  }
 | 
|  
 | 
| -  // 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.
 | 
| -  for (size_t i = 0; i < elements->size(); ++i) {
 | 
| -    const UploadElement& element = (*elements)[i];
 | 
| -    if (element.type() == UploadElement::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;
 | 
| -      }
 | 
| -    }
 | 
| +  uint64 total_size = 0;
 | 
| +  for (size_t i = 0; i < element_readers_.size(); ++i) {
 | 
| +    UploadElementReader* reader = element_readers_[i];
 | 
| +    const int result = reader->InitSync();
 | 
| +    if (result != OK)
 | 
| +      return result;
 | 
| +    if (!is_chunked())
 | 
| +      total_size += reader->GetContentLength();
 | 
|    }
 | 
| -
 | 
| -  // Reset the offset, as upload_data_ may already be read (i.e. UploadData
 | 
| -  // can be reused for a new UploadDataStream).
 | 
| -  for (size_t i = 0; i < elements->size(); ++i)
 | 
| -    (*elements)[i].ResetOffset();
 | 
| +  total_size_ = total_size;
 | 
|  
 | 
|    initialized_successfully_ = true;
 | 
|    return OK;
 | 
|  }
 | 
|  
 | 
|  int UploadDataStream::Read(IOBuffer* buf, int buf_len) {
 | 
| -  std::vector<UploadElement>& elements =
 | 
| -      *upload_data_->elements_mutable();
 | 
| +  DCHECK(initialized_successfully_);
 | 
|  
 | 
| -  int bytes_copied = 0;
 | 
| -  while (bytes_copied < buf_len && element_index_ < elements.size()) {
 | 
| -    UploadElement& element = elements[element_index_];
 | 
| +  // Initialize readers for newly appended chunks.
 | 
| +  if (is_chunked()) {
 | 
| +    const std::vector<UploadElement>& elements = *upload_data_->elements();
 | 
| +    DCHECK_LE(element_readers_.size(), elements.size());
 | 
|  
 | 
| -    bytes_copied += element.ReadSync(buf->data() + bytes_copied,
 | 
| -                                     buf_len - bytes_copied);
 | 
| +    for (size_t i = element_readers_.size(); i < elements.size(); ++i) {
 | 
| +      const UploadElement& element = elements[i];
 | 
| +      DCHECK_EQ(UploadElement::TYPE_BYTES, element.type());
 | 
| +      UploadElementReader* reader = UploadElementReader::Create(element);
 | 
|  
 | 
| -    if (element.BytesRemaining() == 0)
 | 
| +      const int rv = reader->InitSync();
 | 
| +      DCHECK_EQ(rv, OK);
 | 
| +      element_readers_.push_back(reader);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  int bytes_copied = 0;
 | 
| +  while (bytes_copied < buf_len && element_index_ < element_readers_.size()) {
 | 
| +    UploadElementReader* reader = element_readers_[element_index_];
 | 
| +    bytes_copied += reader->ReadSync(buf->data() + bytes_copied,
 | 
| +                                     buf_len - bytes_copied);
 | 
| +    if (reader->BytesRemaining() == 0)
 | 
|        ++element_index_;
 | 
|  
 | 
|      if (is_chunked() && !merge_chunks_)
 | 
| @@ -99,6 +90,7 @@ int UploadDataStream::Read(IOBuffer* buf, int buf_len) {
 | 
|  }
 | 
|  
 | 
|  bool UploadDataStream::IsEOF() const {
 | 
| +  DCHECK(initialized_successfully_);
 | 
|    const std::vector<UploadElement>& elements = *upload_data_->elements();
 | 
|  
 | 
|    // Check if all elements are consumed.
 | 
| @@ -119,9 +111,8 @@ bool UploadDataStream::IsInMemory() const {
 | 
|    if (is_chunked())
 | 
|      return false;
 | 
|  
 | 
| -  const std::vector<UploadElement>& elements = *upload_data_->elements();
 | 
| -  for (size_t i = 0; i < elements.size(); ++i) {
 | 
| -    if (elements[i].type() != UploadElement::TYPE_BYTES)
 | 
| +  for (size_t i = 0; i < element_readers_.size(); ++i) {
 | 
| +    if (!element_readers_[i]->IsInMemory())
 | 
|        return false;
 | 
|    }
 | 
|    return true;
 | 
| 
 |