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

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

Issue 10823180: net: Make UploadDataStream::Init() asynchronous. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 4 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_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/location.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h" 10 #include "base/threading/thread_restrictions.h"
11 #include "base/threading/worker_pool.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 // This function is used to implement UploadDataStream::Init().
21 void InitInternal(scoped_refptr<UploadData> upload_data,
eroman 2012/08/09 05:29:33 UploadData is not threadsafe, however now it is be
hashimoto 2012/08/09 13:35:02 Oh I thought touching UploadData on a worker threa
22 uint64* total_size,
23 int* result) {
24 *total_size = upload_data->GetContentLengthSync();
25
26 // If the underlying file has been changed and the expected file
27 // modification time is set, treat it as error. Note that the expected
28 // modification time from WebKit is based on time_t precision. So we
29 // have to convert both to time_t to compare. This check is used for
30 // sliced files.
31 const std::vector<UploadData::Element>& elements = *upload_data->elements();
32 for (size_t i = 0; i < elements.size(); ++i) {
33 const UploadData::Element& element = elements[i];
34 if (element.type() == UploadData::TYPE_FILE &&
35 !element.expected_file_modification_time().is_null()) {
36 base::PlatformFileInfo info;
37 if (file_util::GetFileInfo(element.file_path(), &info) &&
38 element.expected_file_modification_time().ToTimeT() !=
39 info.last_modified.ToTimeT()) {
40 *result = ERR_UPLOAD_FILE_CHANGED;
41 return;
42 }
43 }
44 }
45
46 // Reset the offset, as upload_data_ may already be read (i.e. UploadData
47 // can be reused for a new UploadDataStream).
48 upload_data->ResetOffset();
49
50 *result = OK;
51 return;
eroman 2012/08/09 05:29:33 delete this
52 }
53
54 } // namespace
55
16 bool UploadDataStream::merge_chunks_ = true; 56 bool UploadDataStream::merge_chunks_ = true;
17 57
18 // static 58 // static
19 void UploadDataStream::ResetMergeChunks() { 59 void UploadDataStream::ResetMergeChunks() {
20 // WARNING: merge_chunks_ must match the above initializer. 60 // WARNING: merge_chunks_ must match the above initializer.
21 merge_chunks_ = true; 61 merge_chunks_ = true;
22 } 62 }
23 63
24 UploadDataStream::UploadDataStream(UploadData* upload_data) 64 UploadDataStream::UploadDataStream(UploadData* upload_data)
25 : upload_data_(upload_data), 65 : upload_data_(upload_data),
26 element_index_(0), 66 element_index_(0),
27 total_size_(0), 67 total_size_(0),
28 current_position_(0), 68 current_position_(0),
29 initialized_successfully_(false) { 69 initialized_successfully_(false),
70 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
30 } 71 }
31 72
32 UploadDataStream::~UploadDataStream() { 73 UploadDataStream::~UploadDataStream() {
33 } 74 }
34 75
35 int UploadDataStream::Init() { 76 int UploadDataStream::Init(const CompletionCallback& callback) {
36 DCHECK(!initialized_successfully_); 77 DCHECK(!initialized_successfully_);
78 // Fast path. Initialize synchronously if the data is in memory.
79 if (upload_data_->IsInMemory())
80 return InitSync();
37 81
82 uint64* total_size = new uint64(0);
83 int* result = new int(OK);
84 const bool posted = base::WorkerPool::PostTaskAndReply(
85 FROM_HERE,
86 base::Bind(&InitInternal, upload_data_, total_size, result),
87 base::Bind(&UploadDataStream::OnInitComplete,
88 weak_ptr_factory_.GetWeakPtr(),
89 callback,
90 base::Owned(total_size),
91 base::Owned(result)),
92 true /* task_is_slow */);
93 DCHECK(posted);
94 return ERR_IO_PENDING;
95 }
96
97 int UploadDataStream::InitSync() {
98 DCHECK(!initialized_successfully_);
99 int result = OK;
38 { 100 {
39 base::ThreadRestrictions::ScopedAllowIO allow_io; 101 base::ThreadRestrictions::ScopedAllowIO allow_io;
40 total_size_ = upload_data_->GetContentLengthSync(); 102 InitInternal(upload_data_, &total_size_, &result);
41 } 103 }
42 104 // Passing a null callback to OnInitComplete() since we return the result
43 // If the underlying file has been changed and the expected file 105 // synchronously here and there is no need to run callback.
44 // modification time is set, treat it as error. Note that the expected 106 CompletionCallback null_callback;
45 // modification time from WebKit is based on time_t precision. So we 107 OnInitComplete(null_callback, &total_size_, &result);
46 // have to convert both to time_t to compare. This check is used for 108 return result;
47 // sliced files.
48 const std::vector<UploadData::Element>& elements = *upload_data_->elements();
49 for (size_t i = 0; i < elements.size(); ++i) {
50 const UploadData::Element& element = elements[i];
51 if (element.type() == UploadData::TYPE_FILE &&
52 !element.expected_file_modification_time().is_null()) {
53 // Temporarily allow until fix: http://crbug.com/72001.
54 base::ThreadRestrictions::ScopedAllowIO allow_io;
55 base::PlatformFileInfo info;
56 if (file_util::GetFileInfo(element.file_path(), &info) &&
57 element.expected_file_modification_time().ToTimeT() !=
58 info.last_modified.ToTimeT()) {
59 return ERR_UPLOAD_FILE_CHANGED;
60 }
61 }
62 }
63
64 // Reset the offset, as upload_data_ may already be read (i.e. UploadData
65 // can be reused for a new UploadDataStream).
66 upload_data_->ResetOffset();
67
68 initialized_successfully_ = true;
69 return OK;
70 } 109 }
71 110
72 int UploadDataStream::Read(IOBuffer* buf, int buf_len) { 111 int UploadDataStream::Read(IOBuffer* buf, int buf_len) {
73 std::vector<UploadData::Element>& elements = 112 std::vector<UploadData::Element>& elements =
74 *upload_data_->elements_mutable(); 113 *upload_data_->elements_mutable();
75 114
76 int bytes_copied = 0; 115 int bytes_copied = 0;
77 while (bytes_copied < buf_len && element_index_ < elements.size()) { 116 while (bytes_copied < buf_len && element_index_ < elements.size()) {
78 UploadData::Element& element = elements[element_index_]; 117 UploadData::Element& element = elements[element_index_];
79 118
80 bytes_copied += element.ReadSync(buf->data() + bytes_copied, 119 bytes_copied += element.ReadSync(buf->data() + bytes_copied,
81 buf_len - bytes_copied); 120 buf_len - bytes_copied);
82 121
83 if (element.BytesRemaining() == 0) 122 if (element.BytesRemaining() == 0)
84 ++element_index_; 123 ++element_index_;
85 124
86 if (is_chunked() && !merge_chunks_) 125 if (is_chunked() && !merge_chunks_)
87 break; 126 break;
88 } 127 }
89 128
90 current_position_ += bytes_copied; 129 current_position_ += bytes_copied;
91 if (is_chunked() && !IsEOF() && bytes_copied == 0) 130 if (is_chunked() && !IsEOF() && bytes_copied == 0)
92 return ERR_IO_PENDING; 131 return ERR_IO_PENDING;
93 132
94 return bytes_copied; 133 return bytes_copied;
95 } 134 }
96 135
136 void UploadDataStream::OnInitComplete(const CompletionCallback& callback,
137 uint64* total_size,
138 int* result) {
139 total_size_ = *total_size;
140 if (*result == OK)
141 initialized_successfully_ = true;
142
143 if (!callback.is_null())
144 callback.Run(*result);
145 }
146
97 bool UploadDataStream::IsEOF() const { 147 bool UploadDataStream::IsEOF() const {
98 const std::vector<UploadData::Element>& elements = *upload_data_->elements(); 148 const std::vector<UploadData::Element>& elements = *upload_data_->elements();
99 149
100 // Check if all elements are consumed. 150 // Check if all elements are consumed.
101 if (element_index_ == elements.size()) { 151 if (element_index_ == elements.size()) {
102 // If the upload data is chunked, check if the last element is the 152 // If the upload data is chunked, check if the last element is the
103 // last chunk. 153 // last chunk.
104 if (!upload_data_->is_chunked() || 154 if (!upload_data_->is_chunked() ||
105 (!elements.empty() && elements.back().is_last_chunk())) { 155 (!elements.empty() && elements.back().is_last_chunk())) {
106 return true; 156 return true;
107 } 157 }
108 } 158 }
109 return false; 159 return false;
110 } 160 }
111 161
112 bool UploadDataStream::IsInMemory() const { 162 bool UploadDataStream::IsInMemory() const {
113 DCHECK(initialized_successfully_); 163 DCHECK(initialized_successfully_);
114 164
115 return upload_data_->IsInMemory(); 165 return upload_data_->IsInMemory();
116 } 166 }
117 167
118 } // namespace net 168 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698