| 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_path.h" | 9 #include "base/file_path.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 BlobData* blob_data, | 52 BlobData* blob_data, |
| 53 base::MessageLoopProxy* file_thread_proxy) | 53 base::MessageLoopProxy* file_thread_proxy) |
| 54 : net::URLRequestJob(request), | 54 : net::URLRequestJob(request), |
| 55 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 55 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 56 blob_data_(blob_data), | 56 blob_data_(blob_data), |
| 57 file_thread_proxy_(file_thread_proxy), | 57 file_thread_proxy_(file_thread_proxy), |
| 58 item_index_(0), | 58 item_index_(0), |
| 59 total_size_(0), | 59 total_size_(0), |
| 60 current_item_offset_(0), | 60 current_item_offset_(0), |
| 61 remaining_bytes_(0), | 61 remaining_bytes_(0), |
| 62 read_buf_offset_(0), | |
| 63 read_buf_size_(0), | |
| 64 read_buf_remaining_bytes_(0), | |
| 65 bytes_to_read_(0), | 62 bytes_to_read_(0), |
| 66 error_(false), | 63 error_(false), |
| 67 headers_set_(false), | 64 headers_set_(false), |
| 68 byte_range_set_(false) { | 65 byte_range_set_(false) { |
| 69 DCHECK(file_thread_proxy_); | 66 DCHECK(file_thread_proxy_); |
| 70 } | 67 } |
| 71 | 68 |
| 72 BlobURLRequestJob::~BlobURLRequestJob() { | 69 BlobURLRequestJob::~BlobURLRequestJob() { |
| 73 // FileStream's destructor won't close it for us because we passed in our own | 70 // FileStream's destructor won't close it for us because we passed in our own |
| 74 // file handle. | 71 // file handle. |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 | 223 |
| 227 // If we should copy zero bytes because |remaining_bytes_| is zero, short | 224 // If we should copy zero bytes because |remaining_bytes_| is zero, short |
| 228 // circuit here. | 225 // circuit here. |
| 229 if (!dest_size) { | 226 if (!dest_size) { |
| 230 *bytes_read = 0; | 227 *bytes_read = 0; |
| 231 return true; | 228 return true; |
| 232 } | 229 } |
| 233 | 230 |
| 234 // Keep track of the buffer. | 231 // Keep track of the buffer. |
| 235 DCHECK(!read_buf_); | 232 DCHECK(!read_buf_); |
| 236 read_buf_ = dest; | 233 read_buf_ = new net::DrainableIOBuffer(dest, dest_size); |
| 237 read_buf_offset_ = 0; | |
| 238 read_buf_size_ = dest_size; | |
| 239 read_buf_remaining_bytes_ = dest_size; | |
| 240 | 234 |
| 241 return ReadLoop(bytes_read); | 235 return ReadLoop(bytes_read); |
| 242 } | 236 } |
| 243 | 237 |
| 244 bool BlobURLRequestJob::ReadLoop(int* bytes_read) { | 238 bool BlobURLRequestJob::ReadLoop(int* bytes_read) { |
| 245 // Read until we encounter an error or could not get the data immediately. | 239 // Read until we encounter an error or could not get the data immediately. |
| 246 while (remaining_bytes_ > 0 && read_buf_remaining_bytes_ > 0) { | 240 while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) { |
| 247 if (!ReadItem()) | 241 if (!ReadItem()) |
| 248 return false; | 242 return false; |
| 249 } | 243 } |
| 250 | 244 |
| 251 *bytes_read = ReadCompleted(); | 245 *bytes_read = ReadCompleted(); |
| 252 return true; | 246 return true; |
| 253 } | 247 } |
| 254 | 248 |
| 255 int BlobURLRequestJob::ComputeBytesToRead() const { | 249 int BlobURLRequestJob::ComputeBytesToRead() const { |
| 256 int64 current_item_remaining_bytes = | 250 int64 current_item_remaining_bytes = |
| 257 item_length_list_[item_index_] - current_item_offset_; | 251 item_length_list_[item_index_] - current_item_offset_; |
| 258 int bytes_to_read = (read_buf_remaining_bytes_ > current_item_remaining_bytes) | 252 int bytes_to_read = (read_buf_->BytesRemaining() > |
| 253 current_item_remaining_bytes) |
| 259 ? static_cast<int>(current_item_remaining_bytes) | 254 ? static_cast<int>(current_item_remaining_bytes) |
| 260 : read_buf_remaining_bytes_; | 255 : read_buf_->BytesRemaining(); |
| 261 if (bytes_to_read > remaining_bytes_) | 256 if (bytes_to_read > remaining_bytes_) |
| 262 bytes_to_read = static_cast<int>(remaining_bytes_); | 257 bytes_to_read = static_cast<int>(remaining_bytes_); |
| 263 return bytes_to_read; | 258 return bytes_to_read; |
| 264 } | 259 } |
| 265 | 260 |
| 266 bool BlobURLRequestJob::ReadItem() { | 261 bool BlobURLRequestJob::ReadItem() { |
| 267 // Are we done with reading all the blob data? | 262 // Are we done with reading all the blob data? |
| 268 if (remaining_bytes_ == 0) | 263 if (remaining_bytes_ == 0) |
| 269 return true; | 264 return true; |
| 270 | 265 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 291 return ReadBytes(item); | 286 return ReadBytes(item); |
| 292 case BlobData::TYPE_FILE: | 287 case BlobData::TYPE_FILE: |
| 293 return DispatchReadFile(item); | 288 return DispatchReadFile(item); |
| 294 default: | 289 default: |
| 295 DCHECK(false); | 290 DCHECK(false); |
| 296 return false; | 291 return false; |
| 297 } | 292 } |
| 298 } | 293 } |
| 299 | 294 |
| 300 bool BlobURLRequestJob::ReadBytes(const BlobData::Item& item) { | 295 bool BlobURLRequestJob::ReadBytes(const BlobData::Item& item) { |
| 301 DCHECK(read_buf_remaining_bytes_ >= bytes_to_read_); | 296 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read_); |
| 302 | 297 |
| 303 memcpy(read_buf_->data() + read_buf_offset_, | 298 memcpy(read_buf_->data(), |
| 304 &item.data.at(0) + item.offset + current_item_offset_, | 299 &item.data.at(0) + item.offset + current_item_offset_, |
| 305 bytes_to_read_); | 300 bytes_to_read_); |
| 306 | 301 |
| 307 AdvanceBytesRead(bytes_to_read_); | 302 AdvanceBytesRead(bytes_to_read_); |
| 308 return true; | 303 return true; |
| 309 } | 304 } |
| 310 | 305 |
| 311 bool BlobURLRequestJob::DispatchReadFile(const BlobData::Item& item) { | 306 bool BlobURLRequestJob::DispatchReadFile(const BlobData::Item& item) { |
| 312 // If the stream already exists, keep reading from it. | 307 // If the stream already exists, keep reading from it. |
| 313 if (stream_ != NULL) | 308 if (stream_ != NULL) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 341 return; | 336 return; |
| 342 } | 337 } |
| 343 } | 338 } |
| 344 | 339 |
| 345 ReadFile(item); | 340 ReadFile(item); |
| 346 } | 341 } |
| 347 | 342 |
| 348 bool BlobURLRequestJob::ReadFile(const BlobData::Item& item) { | 343 bool BlobURLRequestJob::ReadFile(const BlobData::Item& item) { |
| 349 DCHECK(stream_.get()); | 344 DCHECK(stream_.get()); |
| 350 DCHECK(stream_->IsOpen()); | 345 DCHECK(stream_->IsOpen()); |
| 351 DCHECK(read_buf_remaining_bytes_ >= bytes_to_read_); | 346 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read_); |
| 352 | 347 |
| 353 // Start the asynchronous reading. | 348 // Start the asynchronous reading. |
| 354 int rv = stream_->Read(read_buf_->data() + read_buf_offset_, | 349 int rv = stream_->Read(read_buf_, |
| 355 bytes_to_read_, | 350 bytes_to_read_, |
| 356 base::Bind(&BlobURLRequestJob::DidRead, | 351 base::Bind(&BlobURLRequestJob::DidRead, |
| 357 base::Unretained(this))); | 352 base::Unretained(this))); |
| 358 | 353 |
| 359 // If I/O pending error is returned, we just need to wait. | 354 // If I/O pending error is returned, we just need to wait. |
| 360 if (rv == net::ERR_IO_PENDING) { | 355 if (rv == net::ERR_IO_PENDING) { |
| 361 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | 356 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| 362 return false; | 357 return false; |
| 363 } | 358 } |
| 364 | 359 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 380 void BlobURLRequestJob::DidRead(int result) { | 375 void BlobURLRequestJob::DidRead(int result) { |
| 381 if (result < 0) { | 376 if (result < 0) { |
| 382 NotifyFailure(net::ERR_FAILED); | 377 NotifyFailure(net::ERR_FAILED); |
| 383 return; | 378 return; |
| 384 } | 379 } |
| 385 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status | 380 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status |
| 386 | 381 |
| 387 AdvanceBytesRead(result); | 382 AdvanceBytesRead(result); |
| 388 | 383 |
| 389 // If the read buffer is completely filled, we're done. | 384 // If the read buffer is completely filled, we're done. |
| 390 if (!read_buf_remaining_bytes_) { | 385 if (!read_buf_->BytesRemaining()) { |
| 391 int bytes_read = ReadCompleted(); | 386 int bytes_read = ReadCompleted(); |
| 392 NotifyReadComplete(bytes_read); | 387 NotifyReadComplete(bytes_read); |
| 393 return; | 388 return; |
| 394 } | 389 } |
| 395 | 390 |
| 396 // Otherwise, continue the reading. | 391 // Otherwise, continue the reading. |
| 397 int bytes_read = 0; | 392 int bytes_read = 0; |
| 398 if (ReadLoop(&bytes_read)) | 393 if (ReadLoop(&bytes_read)) |
| 399 NotifyReadComplete(bytes_read); | 394 NotifyReadComplete(bytes_read); |
| 400 } | 395 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 414 // Do we finish reading the current item? | 409 // Do we finish reading the current item? |
| 415 current_item_offset_ += result; | 410 current_item_offset_ += result; |
| 416 if (current_item_offset_ == item_length_list_[item_index_]) | 411 if (current_item_offset_ == item_length_list_[item_index_]) |
| 417 AdvanceItem(); | 412 AdvanceItem(); |
| 418 | 413 |
| 419 // Subtract the remaining bytes. | 414 // Subtract the remaining bytes. |
| 420 remaining_bytes_ -= result; | 415 remaining_bytes_ -= result; |
| 421 DCHECK_GE(remaining_bytes_, 0); | 416 DCHECK_GE(remaining_bytes_, 0); |
| 422 | 417 |
| 423 // Adjust the read buffer. | 418 // Adjust the read buffer. |
| 424 read_buf_offset_ += result; | 419 read_buf_->DidConsume(result); |
| 425 read_buf_remaining_bytes_ -= result; | 420 DCHECK_GE(read_buf_->BytesRemaining(), 0); |
| 426 DCHECK_GE(read_buf_remaining_bytes_, 0); | |
| 427 } | 421 } |
| 428 | 422 |
| 429 int BlobURLRequestJob::ReadCompleted() { | 423 int BlobURLRequestJob::ReadCompleted() { |
| 430 int bytes_read = read_buf_size_ - read_buf_remaining_bytes_; | 424 int bytes_read = read_buf_->BytesConsumed(); |
| 431 read_buf_ = NULL; | 425 read_buf_ = NULL; |
| 432 read_buf_offset_ = 0; | |
| 433 read_buf_size_ = 0; | |
| 434 read_buf_remaining_bytes_ = 0; | |
| 435 return bytes_read; | 426 return bytes_read; |
| 436 } | 427 } |
| 437 | 428 |
| 438 void BlobURLRequestJob::HeadersCompleted(int status_code, | 429 void BlobURLRequestJob::HeadersCompleted(int status_code, |
| 439 const std::string& status_text) { | 430 const std::string& status_text) { |
| 440 std::string status("HTTP/1.1 "); | 431 std::string status("HTTP/1.1 "); |
| 441 status.append(base::IntToString(status_code)); | 432 status.append(base::IntToString(status_code)); |
| 442 status.append(" "); | 433 status.append(" "); |
| 443 status.append(status_text); | 434 status.append(status_text); |
| 444 status.append("\0\0", 2); | 435 status.append("\0\0", 2); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 // We don't support multiple range requests in one single URL request, | 551 // We don't support multiple range requests in one single URL request, |
| 561 // because we need to do multipart encoding here. | 552 // because we need to do multipart encoding here. |
| 562 // TODO(jianli): Support multipart byte range requests. | 553 // TODO(jianli): Support multipart byte range requests. |
| 563 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); | 554 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); |
| 564 } | 555 } |
| 565 } | 556 } |
| 566 } | 557 } |
| 567 } | 558 } |
| 568 | 559 |
| 569 } // namespace webkit_blob | 560 } // namespace webkit_blob |
| OLD | NEW |