| 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 "webkit/blob/blob_url_request_job.h" | 5 #include "webkit/blob/blob_url_request_job.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/file_util_proxy.h" | 9 #include "base/file_util_proxy.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/message_loop_proxy.h" | 11 #include "base/message_loop_proxy.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
| 14 #include "net/base/io_buffer.h" | 14 #include "net/base/io_buffer.h" |
| 15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
| 16 #include "net/http/http_request_headers.h" | 16 #include "net/http/http_request_headers.h" |
| 17 #include "net/http/http_response_headers.h" | 17 #include "net/http/http_response_headers.h" |
| 18 #include "net/http/http_response_info.h" | 18 #include "net/http/http_response_info.h" |
| 19 #include "net/http/http_util.h" | 19 #include "net/http/http_util.h" |
| 20 #include "net/url_request/url_request.h" | 20 #include "net/url_request/url_request.h" |
| 21 #include "net/url_request/url_request_context.h" | 21 #include "net/url_request/url_request_context.h" |
| 22 #include "net/url_request/url_request_error_job.h" | 22 #include "net/url_request/url_request_error_job.h" |
| 23 #include "net/url_request/url_request_status.h" | 23 #include "net/url_request/url_request_status.h" |
| 24 #include "webkit/blob/local_file_stream_reader.h" | 24 #include "webkit/blob/local_file_stream_reader.h" |
| 25 #include "webkit/fileapi/file_system_context.h" |
| 26 #include "webkit/fileapi/file_system_url.h" |
| 25 | 27 |
| 26 namespace webkit_blob { | 28 namespace webkit_blob { |
| 27 | 29 |
| 28 namespace { | 30 namespace { |
| 29 | 31 |
| 30 const int kHTTPOk = 200; | 32 const int kHTTPOk = 200; |
| 31 const int kHTTPPartialContent = 206; | 33 const int kHTTPPartialContent = 206; |
| 32 const int kHTTPNotAllowed = 403; | 34 const int kHTTPNotAllowed = 403; |
| 33 const int kHTTPNotFound = 404; | 35 const int kHTTPNotFound = 404; |
| 34 const int kHTTPMethodNotAllow = 405; | 36 const int kHTTPMethodNotAllow = 405; |
| 35 const int kHTTPRequestedRangeNotSatisfiable = 416; | 37 const int kHTTPRequestedRangeNotSatisfiable = 416; |
| 36 const int kHTTPInternalError = 500; | 38 const int kHTTPInternalError = 500; |
| 37 | 39 |
| 38 const char kHTTPOKText[] = "OK"; | 40 const char kHTTPOKText[] = "OK"; |
| 39 const char kHTTPPartialContentText[] = "Partial Content"; | 41 const char kHTTPPartialContentText[] = "Partial Content"; |
| 40 const char kHTTPNotAllowedText[] = "Not Allowed"; | 42 const char kHTTPNotAllowedText[] = "Not Allowed"; |
| 41 const char kHTTPNotFoundText[] = "Not Found"; | 43 const char kHTTPNotFoundText[] = "Not Found"; |
| 42 const char kHTTPMethodNotAllowText[] = "Method Not Allowed"; | 44 const char kHTTPMethodNotAllowText[] = "Method Not Allowed"; |
| 43 const char kHTTPRequestedRangeNotSatisfiableText[] = | 45 const char kHTTPRequestedRangeNotSatisfiableText[] = |
| 44 "Requested Range Not Satisfiable"; | 46 "Requested Range Not Satisfiable"; |
| 45 const char kHTTPInternalErrorText[] = "Internal Server Error"; | 47 const char kHTTPInternalErrorText[] = "Internal Server Error"; |
| 46 | 48 |
| 49 bool IsFileType(BlobData::Item::Type type) { |
| 50 switch (type) { |
| 51 case BlobData::Item::TYPE_FILE: |
| 52 case BlobData::Item::TYPE_FILE_FILESYSTEM: |
| 53 return true; |
| 54 default: |
| 55 return false; |
| 56 } |
| 57 } |
| 58 |
| 47 } // namespace | 59 } // namespace |
| 48 | 60 |
| 49 BlobURLRequestJob::BlobURLRequestJob( | 61 BlobURLRequestJob::BlobURLRequestJob( |
| 50 net::URLRequest* request, | 62 net::URLRequest* request, |
| 51 net::NetworkDelegate* network_delegate, | 63 net::NetworkDelegate* network_delegate, |
| 52 BlobData* blob_data, | 64 BlobData* blob_data, |
| 65 fileapi::FileSystemContext* file_system_context, |
| 53 base::MessageLoopProxy* file_thread_proxy) | 66 base::MessageLoopProxy* file_thread_proxy) |
| 54 : net::URLRequestJob(request, network_delegate), | 67 : net::URLRequestJob(request, network_delegate), |
| 55 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 68 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 56 blob_data_(blob_data), | 69 blob_data_(blob_data), |
| 70 file_system_context_(file_system_context), |
| 57 file_thread_proxy_(file_thread_proxy), | 71 file_thread_proxy_(file_thread_proxy), |
| 58 total_size_(0), | 72 total_size_(0), |
| 59 remaining_bytes_(0), | 73 remaining_bytes_(0), |
| 60 pending_get_file_info_count_(0), | 74 pending_get_file_info_count_(0), |
| 61 current_item_index_(0), | 75 current_item_index_(0), |
| 62 current_item_offset_(0), | 76 current_item_offset_(0), |
| 63 error_(false), | 77 error_(false), |
| 64 headers_set_(false), | 78 headers_set_(false), |
| 65 byte_range_set_(false) { | 79 byte_range_set_(false) { |
| 66 DCHECK(file_thread_proxy_); | 80 DCHECK(file_thread_proxy_); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 } | 184 } |
| 171 | 185 |
| 172 void BlobURLRequestJob::CountSize() { | 186 void BlobURLRequestJob::CountSize() { |
| 173 error_ = false; | 187 error_ = false; |
| 174 pending_get_file_info_count_ = 0; | 188 pending_get_file_info_count_ = 0; |
| 175 total_size_ = 0; | 189 total_size_ = 0; |
| 176 item_length_list_.resize(blob_data_->items().size()); | 190 item_length_list_.resize(blob_data_->items().size()); |
| 177 | 191 |
| 178 for (size_t i = 0; i < blob_data_->items().size(); ++i) { | 192 for (size_t i = 0; i < blob_data_->items().size(); ++i) { |
| 179 const BlobData::Item& item = blob_data_->items().at(i); | 193 const BlobData::Item& item = blob_data_->items().at(i); |
| 180 if (item.type() == BlobData::Item::TYPE_FILE) { | 194 if (IsFileType(item.type())) { |
| 181 ++pending_get_file_info_count_; | 195 ++pending_get_file_info_count_; |
| 182 GetFileStreamReader(i)->GetLength( | 196 GetFileStreamReader(i)->GetLength( |
| 183 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, | 197 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, |
| 184 weak_factory_.GetWeakPtr(), i)); | 198 weak_factory_.GetWeakPtr(), i)); |
| 185 continue; | 199 continue; |
| 186 } | 200 } |
| 187 // Cache the size and add it to the total size. | 201 // Cache the size and add it to the total size. |
| 188 int64 item_length = static_cast<int64>(item.length()); | 202 int64 item_length = static_cast<int64>(item.length()); |
| 189 item_length_list_[i] = item_length; | 203 item_length_list_[i] = item_length; |
| 190 total_size_ += item_length; | 204 total_size_ += item_length; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 if (result == net::ERR_UPLOAD_FILE_CHANGED) { | 242 if (result == net::ERR_UPLOAD_FILE_CHANGED) { |
| 229 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 243 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
| 230 return; | 244 return; |
| 231 } else if (result < 0) { | 245 } else if (result < 0) { |
| 232 NotifyFailure(result); | 246 NotifyFailure(result); |
| 233 return; | 247 return; |
| 234 } | 248 } |
| 235 | 249 |
| 236 DCHECK_LT(index, blob_data_->items().size()); | 250 DCHECK_LT(index, blob_data_->items().size()); |
| 237 const BlobData::Item& item = blob_data_->items().at(index); | 251 const BlobData::Item& item = blob_data_->items().at(index); |
| 238 DCHECK(item.type() == BlobData::Item::TYPE_FILE); | 252 DCHECK(IsFileType(item.type())); |
| 239 | 253 |
| 240 // If item length is -1, we need to use the file size being resolved | 254 // If item length is -1, we need to use the file size being resolved |
| 241 // in the real time. | 255 // in the real time. |
| 242 int64 item_length = static_cast<int64>(item.length()); | 256 int64 item_length = static_cast<int64>(item.length()); |
| 243 if (item_length == -1) | 257 if (item_length == -1) |
| 244 item_length = result - item.offset(); | 258 item_length = result - item.offset(); |
| 245 | 259 |
| 246 // Cache the size and add it to the total size. | 260 // Cache the size and add it to the total size. |
| 247 DCHECK_LT(index, item_length_list_.size()); | 261 DCHECK_LT(index, item_length_list_.size()); |
| 248 item_length_list_[index] = item_length; | 262 item_length_list_[index] = item_length; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 262 } | 276 } |
| 263 | 277 |
| 264 // Set the offset that need to jump to for the first item in the range. | 278 // Set the offset that need to jump to for the first item in the range. |
| 265 current_item_offset_ = offset; | 279 current_item_offset_ = offset; |
| 266 | 280 |
| 267 if (offset == 0) | 281 if (offset == 0) |
| 268 return; | 282 return; |
| 269 | 283 |
| 270 // Adjust the offset of the first stream if it is of file type. | 284 // Adjust the offset of the first stream if it is of file type. |
| 271 const BlobData::Item& item = blob_data_->items().at(current_item_index_); | 285 const BlobData::Item& item = blob_data_->items().at(current_item_index_); |
| 272 if (item.type() == BlobData::Item::TYPE_FILE) { | 286 if (IsFileType(item.type())) { |
| 273 DeleteCurrentFileReader(); | 287 DeleteCurrentFileReader(); |
| 274 CreateFileStreamReader(current_item_index_, offset); | 288 CreateFileStreamReader(current_item_index_, offset); |
| 275 } | 289 } |
| 276 } | 290 } |
| 277 | 291 |
| 278 bool BlobURLRequestJob::ReadItem() { | 292 bool BlobURLRequestJob::ReadItem() { |
| 279 // Are we done with reading all the blob data? | 293 // Are we done with reading all the blob data? |
| 280 if (remaining_bytes_ == 0) | 294 if (remaining_bytes_ == 0) |
| 281 return true; | 295 return true; |
| 282 | 296 |
| 283 // If we get to the last item but still expect something to read, bail out | 297 // If we get to the last item but still expect something to read, bail out |
| 284 // since something is wrong. | 298 // since something is wrong. |
| 285 if (current_item_index_ >= blob_data_->items().size()) { | 299 if (current_item_index_ >= blob_data_->items().size()) { |
| 286 NotifyFailure(net::ERR_FAILED); | 300 NotifyFailure(net::ERR_FAILED); |
| 287 return false; | 301 return false; |
| 288 } | 302 } |
| 289 | 303 |
| 290 // Compute the bytes to read for current item. | 304 // Compute the bytes to read for current item. |
| 291 int bytes_to_read = ComputeBytesToRead(); | 305 int bytes_to_read = ComputeBytesToRead(); |
| 292 | 306 |
| 293 // If nothing to read for current item, advance to next item. | 307 // If nothing to read for current item, advance to next item. |
| 294 if (bytes_to_read == 0) { | 308 if (bytes_to_read == 0) { |
| 295 AdvanceItem(); | 309 AdvanceItem(); |
| 296 return ReadItem(); | 310 return ReadItem(); |
| 297 } | 311 } |
| 298 | 312 |
| 299 // Do the reading. | 313 // Do the reading. |
| 300 const BlobData::Item& item = blob_data_->items().at(current_item_index_); | 314 const BlobData::Item& item = blob_data_->items().at(current_item_index_); |
| 301 switch (item.type()) { | 315 if (item.type() == BlobData::Item::TYPE_BYTES) |
| 302 case BlobData::Item::TYPE_BYTES: | 316 return ReadBytesItem(item, bytes_to_read); |
| 303 return ReadBytesItem(item, bytes_to_read); | 317 if (IsFileType(item.type())) { |
| 304 case BlobData::Item::TYPE_FILE: | 318 return ReadFileItem(GetFileStreamReader(current_item_index_), |
| 305 return ReadFileItem(GetFileStreamReader(current_item_index_), | 319 bytes_to_read); |
| 306 bytes_to_read); | |
| 307 case BlobData::Item::TYPE_FILE_FILESYSTEM: | |
| 308 // TODO(kinuko): Support TYPE_FILE_FILESYSTEM case. | |
| 309 // http://crbug.com/141835 | |
| 310 default: | |
| 311 DCHECK(false); | |
| 312 return false; | |
| 313 } | 320 } |
| 321 NOTREACHED(); |
| 322 return false; |
| 314 } | 323 } |
| 315 | 324 |
| 316 void BlobURLRequestJob::AdvanceItem() { | 325 void BlobURLRequestJob::AdvanceItem() { |
| 317 // Close the file if the current item is a file. | 326 // Close the file if the current item is a file. |
| 318 DeleteCurrentFileReader(); | 327 DeleteCurrentFileReader(); |
| 319 | 328 |
| 320 // Advance to the next item. | 329 // Advance to the next item. |
| 321 current_item_index_++; | 330 current_item_index_++; |
| 322 current_item_offset_ = 0; | 331 current_item_offset_ = 0; |
| 323 } | 332 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 344 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); | 353 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); |
| 345 | 354 |
| 346 memcpy(read_buf_->data(), | 355 memcpy(read_buf_->data(), |
| 347 item.bytes() + item.offset() + current_item_offset_, | 356 item.bytes() + item.offset() + current_item_offset_, |
| 348 bytes_to_read); | 357 bytes_to_read); |
| 349 | 358 |
| 350 AdvanceBytesRead(bytes_to_read); | 359 AdvanceBytesRead(bytes_to_read); |
| 351 return true; | 360 return true; |
| 352 } | 361 } |
| 353 | 362 |
| 354 bool BlobURLRequestJob::ReadFileItem(LocalFileStreamReader* reader, | 363 bool BlobURLRequestJob::ReadFileItem(FileStreamReader* reader, |
| 355 int bytes_to_read) { | 364 int bytes_to_read) { |
| 356 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); | 365 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); |
| 357 DCHECK(reader); | 366 DCHECK(reader); |
| 358 const int result = reader->Read( | 367 const int result = reader->Read( |
| 359 read_buf_, bytes_to_read, | 368 read_buf_, bytes_to_read, |
| 360 base::Bind(&BlobURLRequestJob::DidReadFile, | 369 base::Bind(&BlobURLRequestJob::DidReadFile, |
| 361 base::Unretained(this))); | 370 base::Unretained(this))); |
| 362 if (result >= 0) { | 371 if (result >= 0) { |
| 363 // Data is immediately available. | 372 // Data is immediately available. |
| 364 if (GetStatus().is_io_pending()) | 373 if (GetStatus().is_io_pending()) |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 | 526 |
| 518 response_info_.reset(new net::HttpResponseInfo()); | 527 response_info_.reset(new net::HttpResponseInfo()); |
| 519 response_info_->headers = headers; | 528 response_info_->headers = headers; |
| 520 | 529 |
| 521 set_expected_content_size(remaining_bytes_); | 530 set_expected_content_size(remaining_bytes_); |
| 522 headers_set_ = true; | 531 headers_set_ = true; |
| 523 | 532 |
| 524 NotifyHeadersComplete(); | 533 NotifyHeadersComplete(); |
| 525 } | 534 } |
| 526 | 535 |
| 527 LocalFileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { | 536 FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { |
| 528 DCHECK_LT(index, blob_data_->items().size()); | 537 DCHECK_LT(index, blob_data_->items().size()); |
| 529 const BlobData::Item& item = blob_data_->items().at(index); | 538 const BlobData::Item& item = blob_data_->items().at(index); |
| 530 if (item.type() != BlobData::Item::TYPE_FILE) | 539 if (!IsFileType(item.type())) |
| 531 return NULL; | 540 return NULL; |
| 532 if (index_to_reader_.find(index) == index_to_reader_.end()) | 541 if (index_to_reader_.find(index) == index_to_reader_.end()) |
| 533 CreateFileStreamReader(index, 0); | 542 CreateFileStreamReader(index, 0); |
| 534 DCHECK(index_to_reader_[index]); | 543 DCHECK(index_to_reader_[index]); |
| 535 return index_to_reader_[index]; | 544 return index_to_reader_[index]; |
| 536 } | 545 } |
| 537 | 546 |
| 538 void BlobURLRequestJob::CreateFileStreamReader(size_t index, | 547 void BlobURLRequestJob::CreateFileStreamReader(size_t index, |
| 539 int64 additional_offset) { | 548 int64 additional_offset) { |
| 540 DCHECK_LT(index, blob_data_->items().size()); | 549 DCHECK_LT(index, blob_data_->items().size()); |
| 541 const BlobData::Item& item = blob_data_->items().at(index); | 550 const BlobData::Item& item = blob_data_->items().at(index); |
| 542 DCHECK_EQ(BlobData::Item::TYPE_FILE, item.type()); | 551 DCHECK(IsFileType(item.type())); |
| 543 DCHECK_EQ(0U, index_to_reader_.count(index)); | 552 DCHECK_EQ(0U, index_to_reader_.count(index)); |
| 544 // TODO(kinuko): Create appropriate FileStreamReader for TYPE_FILE_FILESYSTEM. | 553 |
| 545 // http://crbug.com/141835 | 554 FileStreamReader* reader = NULL; |
| 546 index_to_reader_[index] = new LocalFileStreamReader( | 555 switch (item.type()) { |
| 547 file_thread_proxy_, | 556 case BlobData::Item::TYPE_FILE: |
| 548 item.path(), | 557 reader = new LocalFileStreamReader( |
| 549 item.offset() + additional_offset, | 558 file_thread_proxy_, |
| 550 item.expected_modification_time()); | 559 item.path(), |
| 560 item.offset() + additional_offset, |
| 561 item.expected_modification_time()); |
| 562 break; |
| 563 case BlobData::Item::TYPE_FILE_FILESYSTEM: |
| 564 reader = file_system_context_->CreateFileStreamReader( |
| 565 fileapi::FileSystemURL(item.url()), |
| 566 item.offset() + additional_offset, |
| 567 item.expected_modification_time()); |
| 568 break; |
| 569 default: |
| 570 NOTREACHED(); |
| 571 } |
| 572 DCHECK(reader); |
| 573 index_to_reader_[index] = reader; |
| 551 } | 574 } |
| 552 | 575 |
| 553 } // namespace webkit_blob | 576 } // namespace webkit_blob |
| OLD | NEW |