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

Side by Side Diff: net/http/partial_data.cc

Issue 197016: Http Cache: Add support for resuming downloading a... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 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
« no previous file with comments | « net/http/partial_data.h ('k') | net/tools/dump_cache/cache_dumper.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/http/partial_data.h" 5 #include "net/http/partial_data.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "net/base/net_errors.h" 9 #include "net/base/net_errors.h"
10 #include "net/disk_cache/disk_cache.h" 10 #include "net/disk_cache/disk_cache.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 if (range_len > kint32max) 58 if (range_len > kint32max)
59 range_len = kint32max; 59 range_len = kint32max;
60 int len = static_cast<int32>(range_len); 60 int len = static_cast<int32>(range_len);
61 if (!len) 61 if (!len)
62 return 0; 62 return 0;
63 range_present_ = false; 63 range_present_ = false;
64 64
65 if (sparse_entry_) { 65 if (sparse_entry_) {
66 cached_min_len_ = entry->GetAvailableRange(current_range_start_, len, 66 cached_min_len_ = entry->GetAvailableRange(current_range_start_, len,
67 &cached_start_); 67 &cached_start_);
68 } else if (truncated_) {
69 if (!current_range_start_) {
70 // Update the cached range only the first time.
71 cached_min_len_ = static_cast<int32>(byte_range_.first_byte_position());
72 cached_start_ = 0;
73 }
68 } else { 74 } else {
69 cached_min_len_ = len; 75 cached_min_len_ = len;
70 cached_start_ = current_range_start_; 76 cached_start_ = current_range_start_;
71 } 77 }
72 78
73 if (cached_min_len_ < 0) { 79 if (cached_min_len_ < 0) {
74 DCHECK(cached_min_len_ != ERR_IO_PENDING); 80 DCHECK(cached_min_len_ != ERR_IO_PENDING);
75 return cached_min_len_; 81 return cached_min_len_;
76 } 82 }
77 83
78 headers->assign(extra_headers_); 84 headers->assign(extra_headers_);
79 85
80 if (!cached_min_len_) { 86 if (!cached_min_len_) {
81 // We don't have anything else stored. 87 // We don't have anything else stored.
82 final_range_ = true; 88 final_range_ = true;
83 cached_start_ = current_range_start_ + len; 89 cached_start_ =
90 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0;
84 } 91 }
85 92
86 if (current_range_start_ == cached_start_) { 93 if (current_range_start_ == cached_start_) {
87 // The data lives in the cache. 94 // The data lives in the cache.
88 range_present_ = true; 95 range_present_ = true;
89 if (len == cached_min_len_) 96 if (len == cached_min_len_)
90 final_range_ = true; 97 final_range_ = true;
91 AddRangeHeader(current_range_start_, cached_start_ + cached_min_len_ - 1, 98 AddRangeHeader(current_range_start_, cached_start_ + cached_min_len_ - 1,
92 headers); 99 headers);
93 } else { 100 } else {
94 // This range is not in the cache. 101 // This range is not in the cache.
95 AddRangeHeader(current_range_start_, cached_start_ - 1, headers); 102 AddRangeHeader(current_range_start_, cached_start_ - 1, headers);
96 } 103 }
97 104
98 // Return a positive number to indicate success (versus error or finished). 105 // Return a positive number to indicate success (versus error or finished).
99 return 1; 106 return 1;
100 } 107 }
101 108
102 bool PartialData::IsCurrentRangeCached() const { 109 bool PartialData::IsCurrentRangeCached() const {
103 return range_present_; 110 return range_present_;
104 } 111 }
105 112
106 bool PartialData::IsLastRange() const { 113 bool PartialData::IsLastRange() const {
107 return final_range_; 114 return final_range_;
108 } 115 }
109 116
110 bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers, 117 bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
111 disk_cache::Entry* entry) { 118 disk_cache::Entry* entry,
112 std::string length_value; 119 bool truncated) {
113 resource_size_ = 0; 120 resource_size_ = 0;
121 if (truncated) {
122 DCHECK_EQ(headers->response_code(), 200);
123 truncated_ = true;
124 sparse_entry_ = false;
125
126 // We don't have the real length and the user may be trying to create a
127 // sparse entry so let's not write to this entry.
128 if (byte_range_.IsValid())
129 return false;
130
131 byte_range_.set_first_byte_position(entry->GetDataSize(kDataStream));
132 current_range_start_ = 0;
133 return true;
134 }
135
114 if (headers->response_code() == 200) { 136 if (headers->response_code() == 200) {
115 DCHECK(byte_range_.IsValid()); 137 DCHECK(byte_range_.IsValid());
116 sparse_entry_ = false; 138 sparse_entry_ = false;
117 resource_size_ = entry->GetDataSize(kDataStream); 139 resource_size_ = entry->GetDataSize(kDataStream);
118 return true; 140 return true;
119 } 141 }
120 142
143 std::string length_value;
121 if (!headers->GetNormalizedHeader(kLengthHeader, &length_value)) 144 if (!headers->GetNormalizedHeader(kLengthHeader, &length_value))
122 return false; // We must have stored the resource length. 145 return false; // We must have stored the resource length.
123 146
124 if (!StringToInt64(length_value, &resource_size_) || !resource_size_) 147 if (!StringToInt64(length_value, &resource_size_) || !resource_size_)
125 return false; 148 return false;
126 149
127 // Make sure that this is really a sparse entry. 150 // Make sure that this is really a sparse entry.
128 int64 n; 151 int64 n;
129 if (ERR_CACHE_OPERATION_NOT_SUPPORTED == entry->GetAvailableRange(0, 5, &n)) 152 if (ERR_CACHE_OPERATION_NOT_SUPPORTED == entry->GetAvailableRange(0, 5, &n))
130 return false; 153 return false;
131 154
132 return true; 155 return true;
133 } 156 }
134 157
135 bool PartialData::IsRequestedRangeOK() { 158 bool PartialData::IsRequestedRangeOK() {
136 if (byte_range_.IsValid()) { 159 if (byte_range_.IsValid()) {
160 if (truncated_)
161 return true;
137 if (!byte_range_.ComputeBounds(resource_size_)) 162 if (!byte_range_.ComputeBounds(resource_size_))
138 return false; 163 return false;
139 164
140 if (current_range_start_ < 0) 165 if (current_range_start_ < 0)
141 current_range_start_ = byte_range_.first_byte_position(); 166 current_range_start_ = byte_range_.first_byte_position();
142 } else { 167 } else {
143 // This is not a range request but we have partial data stored. 168 // This is not a range request but we have partial data stored.
144 current_range_start_ = 0; 169 current_range_start_ = 0;
145 byte_range_.set_last_byte_position(resource_size_ - 1); 170 byte_range_.set_last_byte_position(resource_size_ - 1);
146 } 171 }
147 172
148 bool rv = current_range_start_ >= 0; 173 bool rv = current_range_start_ >= 0;
149 if (!rv) 174 if (!rv)
150 current_range_start_ = 0; 175 current_range_start_ = 0;
151 176
152 return rv; 177 return rv;
153 } 178 }
154 179
155 bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) { 180 bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) {
156 if (headers->response_code() == 304) { 181 if (headers->response_code() == 304) {
182 if (truncated_)
183 return true;
184
157 // We must have a complete range here. 185 // We must have a complete range here.
158 return byte_range_.HasFirstBytePosition() && 186 return byte_range_.HasFirstBytePosition() &&
159 byte_range_.HasLastBytePosition(); 187 byte_range_.HasLastBytePosition();
160 } 188 }
161 189
162 int64 start, end, total_length; 190 int64 start, end, total_length;
163 if (!headers->GetContentRange(&start, &end, &total_length)) 191 if (!headers->GetContentRange(&start, &end, &total_length))
164 return false; 192 return false;
165 if (total_length <= 0) 193 if (total_length <= 0)
166 return false; 194 return false;
(...skipping 17 matching lines...) Expand all
184 if (byte_range_.IsValid() && end > byte_range_.last_byte_position()) 212 if (byte_range_.IsValid() && end > byte_range_.last_byte_position())
185 return false; 213 return false;
186 214
187 return true; 215 return true;
188 } 216 }
189 217
190 // We are making multiple requests to complete the range requested by the user. 218 // We are making multiple requests to complete the range requested by the user.
191 // Just assume that everything is fine and say that we are returning what was 219 // Just assume that everything is fine and say that we are returning what was
192 // requested. 220 // requested.
193 void PartialData::FixResponseHeaders(HttpResponseHeaders* headers) { 221 void PartialData::FixResponseHeaders(HttpResponseHeaders* headers) {
222 if (truncated_)
223 return;
224
194 headers->RemoveHeader(kLengthHeader); 225 headers->RemoveHeader(kLengthHeader);
195 headers->RemoveHeader(kRangeHeader); 226 headers->RemoveHeader(kRangeHeader);
196 227
197 int64 range_len; 228 int64 range_len;
198 if (byte_range_.IsValid()) { 229 if (byte_range_.IsValid()) {
199 if (!sparse_entry_) 230 if (!sparse_entry_)
200 headers->ReplaceStatusLine("HTTP/1.1 206 Partial Content"); 231 headers->ReplaceStatusLine("HTTP/1.1 206 Partial Content");
201 232
202 DCHECK(byte_range_.HasFirstBytePosition()); 233 DCHECK(byte_range_.HasFirstBytePosition());
203 DCHECK(byte_range_.HasLastBytePosition()); 234 DCHECK(byte_range_.HasLastBytePosition());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 int PartialData::CacheWrite(disk_cache::Entry* entry, IOBuffer* data, 273 int PartialData::CacheWrite(disk_cache::Entry* entry, IOBuffer* data,
243 int data_len, CompletionCallback* callback) { 274 int data_len, CompletionCallback* callback) {
244 if (sparse_entry_) { 275 if (sparse_entry_) {
245 return entry->WriteSparseData(current_range_start_, data, data_len, 276 return entry->WriteSparseData(current_range_start_, data, data_len,
246 callback); 277 callback);
247 } else { 278 } else {
248 if (current_range_start_ > kint32max) 279 if (current_range_start_ > kint32max)
249 return ERR_INVALID_ARGUMENT; 280 return ERR_INVALID_ARGUMENT;
250 281
251 return entry->WriteData(kDataStream, static_cast<int>(current_range_start_), 282 return entry->WriteData(kDataStream, static_cast<int>(current_range_start_),
252 data, data_len, callback, false); 283 data, data_len, callback, true);
253 } 284 }
254 } 285 }
255 286
256 void PartialData::OnCacheReadCompleted(int result) { 287 void PartialData::OnCacheReadCompleted(int result) {
257 if (result > 0) { 288 if (result > 0) {
258 current_range_start_ += result; 289 current_range_start_ += result;
259 cached_min_len_ -= result; 290 cached_min_len_ -= result;
260 DCHECK(cached_min_len_ >= 0); 291 DCHECK(cached_min_len_ >= 0);
261 } 292 }
262 } 293 }
(...skipping 10 matching lines...) Expand all
273 if (start >= 0) 304 if (start >= 0)
274 my_start = Int64ToString(start); 305 my_start = Int64ToString(start);
275 if (end >= 0) 306 if (end >= 0)
276 my_end = Int64ToString(end); 307 my_end = Int64ToString(end);
277 308
278 headers->append(StringPrintf("Range: bytes=%s-%s\r\n", my_start.c_str(), 309 headers->append(StringPrintf("Range: bytes=%s-%s\r\n", my_start.c_str(),
279 my_end.c_str())); 310 my_end.c_str()));
280 } 311 }
281 312
282 } // namespace net 313 } // namespace net
OLDNEW
« no previous file with comments | « net/http/partial_data.h ('k') | net/tools/dump_cache/cache_dumper.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698