Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/file_util_proxy.h" | 10 #include "base/file_util_proxy.h" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
| 13 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
| 14 #include "net/base/file_stream.h" | |
| 14 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
| 15 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 16 #include "net/http/http_request_headers.h" | 17 #include "net/http/http_request_headers.h" |
| 17 #include "net/http/http_response_headers.h" | 18 #include "net/http/http_response_headers.h" |
| 18 #include "net/http/http_response_info.h" | 19 #include "net/http/http_response_info.h" |
| 19 #include "net/http/http_util.h" | 20 #include "net/http/http_util.h" |
| 20 #include "net/url_request/url_request.h" | 21 #include "net/url_request/url_request.h" |
| 21 #include "net/url_request/url_request_error_job.h" | 22 #include "net/url_request/url_request_error_job.h" |
| 22 #include "net/url_request/url_request_status.h" | 23 #include "net/url_request/url_request_status.h" |
| 23 | 24 |
| 24 namespace webkit_blob { | 25 namespace webkit_blob { |
| 25 | 26 |
| 26 static const int kHTTPOk = 200; | 27 static const int kHTTPOk = 200; |
| 27 static const int kHTTPPartialContent = 206; | 28 static const int kHTTPPartialContent = 206; |
| 28 static const int kHTTPNotAllowed = 403; | 29 static const int kHTTPNotAllowed = 403; |
| 29 static const int kHTTPNotFound = 404; | 30 static const int kHTTPNotFound = 404; |
| 30 static const int kHTTPMethodNotAllow = 405; | 31 static const int kHTTPMethodNotAllow = 405; |
| 31 static const int kHTTPRequestedRangeNotSatisfiable = 416; | 32 static const int kHTTPRequestedRangeNotSatisfiable = 416; |
| 32 static const int kHTTPInternalError = 500; | 33 static const int kHTTPInternalError = 500; |
| 33 | 34 |
| 34 static const char kHTTPOKText[] = "OK"; | 35 static const char kHTTPOKText[] = "OK"; |
| 35 static const char kHTTPPartialContentText[] = "Partial Content"; | 36 static const char kHTTPPartialContentText[] = "Partial Content"; |
| 36 static const char kHTTPNotAllowedText[] = "Not Allowed"; | 37 static const char kHTTPNotAllowedText[] = "Not Allowed"; |
| 37 static const char kHTTPNotFoundText[] = "Not Found"; | 38 static const char kHTTPNotFoundText[] = "Not Found"; |
| 38 static const char kHTTPMethodNotAllowText[] = "Method Not Allowed"; | 39 static const char kHTTPMethodNotAllowText[] = "Method Not Allowed"; |
| 39 static const char kHTTPRequestedRangeNotSatisfiableText[] = | 40 static const char kHTTPRequestedRangeNotSatisfiableText[] = |
| 40 "Requested Range Not Satisfiable"; | 41 "Requested Range Not Satisfiable"; |
| 41 static const char kHTTPInternalErrorText[] = "Internal Server Error"; | 42 static const char kHTTPInternalErrorText[] = "Internal Server Error"; |
| 42 | 43 |
| 44 static const int kFileOpenFlags = base::PLATFORM_FILE_OPEN | | |
| 45 base::PLATFORM_FILE_READ | | |
| 46 base::PLATFORM_FILE_ASYNC; | |
| 47 | |
| 43 BlobURLRequestJob::BlobURLRequestJob( | 48 BlobURLRequestJob::BlobURLRequestJob( |
| 44 net::URLRequest* request, | 49 net::URLRequest* request, |
| 45 BlobData* blob_data, | 50 BlobData* blob_data, |
| 46 base::MessageLoopProxy* file_thread_proxy) | 51 base::MessageLoopProxy* file_thread_proxy) |
| 47 : net::URLRequestJob(request), | 52 : net::URLRequestJob(request), |
| 48 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 53 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 49 blob_data_(blob_data), | 54 blob_data_(blob_data), |
| 50 file_thread_proxy_(file_thread_proxy), | 55 file_thread_proxy_(file_thread_proxy), |
| 51 ALLOW_THIS_IN_INITIALIZER_LIST( | 56 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 52 io_callback_(this, &BlobURLRequestJob::DidRead)), | 57 io_callback_(this, &BlobURLRequestJob::DidRead)), |
| 53 item_index_(0), | 58 item_index_(0), |
| 54 total_size_(0), | 59 total_size_(0), |
| 55 current_item_offset_(0), | 60 current_item_offset_(0), |
| 56 remaining_bytes_(0), | 61 remaining_bytes_(0), |
| 57 read_buf_offset_(0), | 62 read_buf_offset_(0), |
| 58 read_buf_size_(0), | 63 read_buf_size_(0), |
| 59 read_buf_remaining_bytes_(0), | 64 read_buf_remaining_bytes_(0), |
| 65 bytes_to_read_(0), | |
| 60 error_(false), | 66 error_(false), |
| 61 headers_set_(false), | 67 headers_set_(false), |
| 62 byte_range_set_(false), | 68 byte_range_set_(false), |
| 63 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 69 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
| 64 } | 70 } |
| 65 | 71 |
| 66 BlobURLRequestJob::~BlobURLRequestJob() { | 72 BlobURLRequestJob::~BlobURLRequestJob() { |
| 73 // FileStream's destructor won't close it for us because we passed in our own | |
| 74 // file handle. | |
| 75 CloseStream(); | |
| 67 } | 76 } |
| 68 | 77 |
| 69 void BlobURLRequestJob::Start() { | 78 void BlobURLRequestJob::Start() { |
| 70 // Continue asynchronously. | 79 // Continue asynchronously. |
| 71 MessageLoop::current()->PostTask( | 80 MessageLoop::current()->PostTask( |
| 72 FROM_HERE, | 81 FROM_HERE, |
| 73 method_factory_.NewRunnableMethod(&BlobURLRequestJob::DidStart)); | 82 method_factory_.NewRunnableMethod(&BlobURLRequestJob::DidStart)); |
| 74 } | 83 } |
| 75 | 84 |
| 76 void BlobURLRequestJob::DidStart() { | 85 void BlobURLRequestJob::DidStart() { |
| 77 // We only support GET request per the spec. | 86 // We only support GET request per the spec. |
| 78 if (request()->method() != "GET") { | 87 if (request()->method() != "GET") { |
| 79 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); | 88 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); |
| 80 return; | 89 return; |
| 81 } | 90 } |
| 82 | 91 |
| 83 // If the blob data is not present, bail out. | 92 // If the blob data is not present, bail out. |
| 84 if (!blob_data_) { | 93 if (!blob_data_) { |
| 85 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 94 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
| 86 return; | 95 return; |
| 87 } | 96 } |
| 88 | 97 |
| 89 CountSize(); | 98 CountSize(); |
| 90 } | 99 } |
| 91 | 100 |
| 101 void BlobURLRequestJob::CloseStream() { | |
| 102 if (stream_ != NULL) { | |
| 103 stream_->Close(); | |
| 104 stream_.reset(NULL); | |
| 105 } | |
| 106 } | |
| 107 | |
| 92 void BlobURLRequestJob::Kill() { | 108 void BlobURLRequestJob::Kill() { |
| 93 stream_.Close(); | 109 CloseStream(); |
| 94 | 110 |
| 95 net::URLRequestJob::Kill(); | 111 net::URLRequestJob::Kill(); |
| 96 callback_factory_.RevokeAll(); | 112 callback_factory_.RevokeAll(); |
| 97 method_factory_.RevokeAll(); | 113 method_factory_.RevokeAll(); |
| 98 } | 114 } |
| 99 | 115 |
| 100 void BlobURLRequestJob::ResolveFile(const FilePath& file_path) { | 116 void BlobURLRequestJob::ResolveFile(const FilePath& file_path) { |
|
michaeln
2011/03/11 06:03:47
nit: maybe DCHECK(file_thread_proxy_)
adamk
2011/03/14 17:42:14
Added that DCHECK to the constructor (that'll make
| |
| 101 // If the file thread proxy is provided, we can use it get the file info. | 117 base::FileUtilProxy::GetFileInfo( |
| 102 if (file_thread_proxy_) { | 118 file_thread_proxy_, |
| 103 base::FileUtilProxy::GetFileInfo( | 119 file_path, |
| 104 file_thread_proxy_, | 120 callback_factory_.NewCallback(&BlobURLRequestJob::DidResolve)); |
| 105 file_path, | |
| 106 callback_factory_.NewCallback(&BlobURLRequestJob::DidResolve)); | |
| 107 return; | |
| 108 } | |
| 109 | |
| 110 // Otherwise, we use current thread, i.e. IO thread, as this is the case when | |
| 111 // we run the unittest or test shell. | |
| 112 // TODO(jianli): Consider using the proxy of current thread. | |
| 113 base::PlatformFileInfo file_info; | |
| 114 bool exists = file_util::GetFileInfo(file_path, &file_info); | |
| 115 | |
| 116 // Continue asynchronously. | |
| 117 MessageLoop::current()->PostTask( | |
| 118 FROM_HERE, | |
| 119 method_factory_.NewRunnableMethod( | |
| 120 &BlobURLRequestJob::DidResolve, | |
| 121 exists ? base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
| 122 file_info)); | |
| 123 } | 121 } |
| 124 | 122 |
| 125 void BlobURLRequestJob::DidResolve(base::PlatformFileError rv, | 123 void BlobURLRequestJob::DidResolve(base::PlatformFileError rv, |
| 126 const base::PlatformFileInfo& file_info) { | 124 const base::PlatformFileInfo& file_info) { |
| 127 // If an error occured, bail out. | 125 // If an error occured, bail out. |
| 128 if (rv == base::PLATFORM_FILE_ERROR_NOT_FOUND) { | 126 if (rv == base::PLATFORM_FILE_ERROR_NOT_FOUND) { |
| 129 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 127 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
| 130 return; | 128 return; |
| 131 } else if (rv != base::PLATFORM_FILE_OK) { | 129 } else if (rv != base::PLATFORM_FILE_OK) { |
| 132 NotifyFailure(net::ERR_FAILED); | 130 NotifyFailure(net::ERR_FAILED); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 // Read until we encounter an error or could not get the data immediately. | 245 // Read until we encounter an error or could not get the data immediately. |
| 248 while (remaining_bytes_ > 0 && read_buf_remaining_bytes_ > 0) { | 246 while (remaining_bytes_ > 0 && read_buf_remaining_bytes_ > 0) { |
| 249 if (!ReadItem()) | 247 if (!ReadItem()) |
| 250 return false; | 248 return false; |
| 251 } | 249 } |
| 252 | 250 |
| 253 *bytes_read = ReadCompleted(); | 251 *bytes_read = ReadCompleted(); |
| 254 return true; | 252 return true; |
| 255 } | 253 } |
| 256 | 254 |
| 255 int BlobURLRequestJob::ComputeBytesToRead() const { | |
| 256 int64 current_item_remaining_bytes = | |
| 257 item_length_list_[item_index_] - current_item_offset_; | |
| 258 int bytes_to_read = (read_buf_remaining_bytes_ > current_item_remaining_bytes) | |
| 259 ? static_cast<int>(current_item_remaining_bytes) | |
| 260 : read_buf_remaining_bytes_; | |
| 261 if (bytes_to_read > remaining_bytes_) | |
| 262 bytes_to_read = static_cast<int>(remaining_bytes_); | |
| 263 return bytes_to_read; | |
| 264 } | |
| 265 | |
| 257 bool BlobURLRequestJob::ReadItem() { | 266 bool BlobURLRequestJob::ReadItem() { |
| 258 // Are we done with reading all the blob data? | 267 // Are we done with reading all the blob data? |
| 259 if (remaining_bytes_ == 0) | 268 if (remaining_bytes_ == 0) |
| 260 return true; | 269 return true; |
| 261 | 270 |
| 262 // If we get to the last item but still expect something to read, bail out | 271 // If we get to the last item but still expect something to read, bail out |
| 263 // since something is wrong. | 272 // since something is wrong. |
| 264 if (item_index_ >= blob_data_->items().size()) { | 273 if (item_index_ >= blob_data_->items().size()) { |
| 265 NotifyFailure(net::ERR_FAILED); | 274 NotifyFailure(net::ERR_FAILED); |
| 266 return false; | 275 return false; |
| 267 } | 276 } |
| 268 | 277 |
| 269 const BlobData::Item& item = blob_data_->items().at(item_index_); | |
| 270 | |
| 271 // Compute the bytes to read for current item. | 278 // Compute the bytes to read for current item. |
| 272 int64 current_item_remaining_bytes = | 279 bytes_to_read_ = ComputeBytesToRead(); |
| 273 item_length_list_[item_index_] - current_item_offset_; | |
| 274 int bytes_to_read = (read_buf_remaining_bytes_ > current_item_remaining_bytes) | |
| 275 ? static_cast<int>(current_item_remaining_bytes) | |
| 276 : read_buf_remaining_bytes_; | |
| 277 if (bytes_to_read > remaining_bytes_) | |
| 278 bytes_to_read = static_cast<int>(remaining_bytes_); | |
| 279 | 280 |
| 280 // If nothing to read for current item, advance to next item. | 281 // If nothing to read for current item, advance to next item. |
| 281 if (bytes_to_read == 0) { | 282 if (bytes_to_read_ == 0) { |
| 282 AdvanceItem(); | 283 AdvanceItem(); |
| 283 return ReadItem(); | 284 return ReadItem(); |
| 284 } | 285 } |
| 285 | 286 |
| 286 // Do the reading. | 287 // Do the reading. |
| 288 const BlobData::Item& item = blob_data_->items().at(item_index_); | |
| 287 switch (item.type()) { | 289 switch (item.type()) { |
| 288 case BlobData::TYPE_DATA: | 290 case BlobData::TYPE_DATA: |
| 289 return ReadBytes(item, bytes_to_read); | 291 return ReadBytes(item); |
| 290 case BlobData::TYPE_FILE: | 292 case BlobData::TYPE_FILE: |
| 291 return ReadFile(item, bytes_to_read); | 293 return DispatchReadFile(item); |
| 292 default: | 294 default: |
| 293 DCHECK(false); | 295 DCHECK(false); |
| 294 return false; | 296 return false; |
| 295 } | 297 } |
| 296 } | 298 } |
| 297 | 299 |
| 298 bool BlobURLRequestJob::ReadBytes(const BlobData::Item& item, | 300 bool BlobURLRequestJob::ReadBytes(const BlobData::Item& item) { |
| 299 int bytes_to_read) { | 301 DCHECK(read_buf_remaining_bytes_ >= bytes_to_read_); |
| 300 DCHECK(read_buf_remaining_bytes_ >= bytes_to_read); | |
| 301 | 302 |
| 302 memcpy(read_buf_->data() + read_buf_offset_, | 303 memcpy(read_buf_->data() + read_buf_offset_, |
| 303 &item.data().at(0) + item.offset() + current_item_offset_, | 304 &item.data().at(0) + item.offset() + current_item_offset_, |
| 304 bytes_to_read); | 305 bytes_to_read_); |
| 305 | 306 |
| 306 AdvanceBytesRead(bytes_to_read); | 307 AdvanceBytesRead(bytes_to_read_); |
| 307 return true; | 308 return true; |
| 308 } | 309 } |
| 309 | 310 |
| 310 bool BlobURLRequestJob::ReadFile(const BlobData::Item& item, | 311 bool BlobURLRequestJob::DispatchReadFile(const BlobData::Item& item) { |
| 311 int bytes_to_read) { | 312 // If the stream already exists, keep reading from it. |
| 312 DCHECK(read_buf_remaining_bytes_ >= bytes_to_read); | 313 if (stream_ != NULL) |
| 314 return ReadFile(item); | |
| 313 | 315 |
| 314 // Open the file if not yet. | 316 base::FileUtilProxy::CreateOrOpen( |
| 315 if (!stream_.IsOpen()) { | 317 file_thread_proxy_, item.file_path(), kFileOpenFlags, |
| 316 int rv = stream_.Open(item.file_path(), base::PLATFORM_FILE_OPEN | | 318 callback_factory_.NewCallback(&BlobURLRequestJob::DidOpen)); |
| 317 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC); | 319 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| 318 if (rv != net::OK) { | 320 return false; |
| 319 NotifyFailure(net::ERR_FAILED); | 321 } |
| 320 return false; | |
| 321 } | |
| 322 | 322 |
| 323 // Seek the file if needed. | 323 void BlobURLRequestJob::DidOpen(base::PlatformFileError rv, |
| 324 int64 offset = current_item_offset_ + static_cast<int64>(item.offset()); | 324 base::PassPlatformFile file, |
| 325 if (offset > 0) { | 325 bool created) { |
| 326 if (offset != stream_.Seek(net::FROM_BEGIN, offset)) { | 326 if (rv != base::PLATFORM_FILE_OK) { |
| 327 NotifyFailure(net::ERR_FAILED); | 327 NotifyFailure(net::ERR_FAILED); |
| 328 return false; | 328 return; |
| 329 } | |
| 330 } | |
| 331 } | 329 } |
| 332 | 330 |
| 331 DCHECK(!stream_.get()); | |
| 332 stream_.reset(new net::FileStream(file.ReleaseValue(), kFileOpenFlags)); | |
| 333 | |
| 334 // Seek the file if needed. | |
| 335 const BlobData::Item& item = blob_data_->items().at(item_index_); | |
| 336 int64 offset = current_item_offset_ + static_cast<int64>(item.offset()); | |
| 337 if (offset > 0 && offset != stream_->Seek(net::FROM_BEGIN, offset)) { | |
| 338 NotifyFailure(net::ERR_FAILED); | |
| 339 return; | |
| 340 } | |
| 341 | |
| 342 ReadFile(item); | |
| 343 } | |
| 344 | |
| 345 bool BlobURLRequestJob::ReadFile(const BlobData::Item& item) { | |
| 346 DCHECK(stream_.get()); | |
| 347 DCHECK(stream_->IsOpen()); | |
| 348 DCHECK(read_buf_remaining_bytes_ >= bytes_to_read_); | |
| 349 | |
| 333 // Start the asynchronous reading. | 350 // Start the asynchronous reading. |
| 334 int rv = stream_.Read(read_buf_->data() + read_buf_offset_, | 351 int rv = stream_->Read(read_buf_->data() + read_buf_offset_, |
| 335 bytes_to_read, | 352 bytes_to_read_, |
| 336 &io_callback_); | 353 &io_callback_); |
| 337 | 354 |
| 338 // If I/O pending error is returned, we just need to wait. | 355 // If I/O pending error is returned, we just need to wait. |
| 339 if (rv == net::ERR_IO_PENDING) { | 356 if (rv == net::ERR_IO_PENDING) { |
| 340 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | 357 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| 341 return false; | 358 return false; |
| 342 } | 359 } |
| 343 | 360 |
| 344 // For all other errors, bail out. | 361 // For all other errors, bail out. |
| 345 if (rv < 0) { | 362 if (rv < 0) { |
| 346 NotifyFailure(net::ERR_FAILED); | 363 NotifyFailure(net::ERR_FAILED); |
| 347 return false; | 364 return false; |
| 348 } | 365 } |
| 349 | 366 |
| 350 // Otherwise, data is immediately available. | 367 // Otherwise, data is immediately available. |
| 351 AdvanceBytesRead(rv); | 368 if (GetStatus().is_io_pending()) |
| 369 DidRead(rv); | |
|
michaeln
2011/03/11 06:03:47
ah... is this what your new large test is about...
adamk
2011/03/14 17:42:14
Added something to the CL description. There wasn
| |
| 370 else | |
| 371 AdvanceBytesRead(rv); | |
| 372 | |
| 352 return true; | 373 return true; |
| 353 } | 374 } |
| 354 | 375 |
| 355 void BlobURLRequestJob::DidRead(int result) { | 376 void BlobURLRequestJob::DidRead(int result) { |
| 356 if (result < 0) { | 377 if (result < 0) { |
| 357 NotifyFailure(net::ERR_FAILED); | 378 NotifyFailure(net::ERR_FAILED); |
| 358 return; | 379 return; |
| 359 } | 380 } |
| 360 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status | 381 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status |
| 361 | 382 |
| 362 AdvanceBytesRead(result); | 383 AdvanceBytesRead(result); |
| 363 | 384 |
| 364 // If the read buffer is completely filled, we're done. | 385 // If the read buffer is completely filled, we're done. |
| 365 if (!read_buf_remaining_bytes_) { | 386 if (!read_buf_remaining_bytes_) { |
| 366 int bytes_read = ReadCompleted(); | 387 int bytes_read = ReadCompleted(); |
| 367 NotifyReadComplete(bytes_read); | 388 NotifyReadComplete(bytes_read); |
| 368 return; | 389 return; |
| 369 } | 390 } |
| 370 | 391 |
| 371 // Otherwise, continue the reading. | 392 // Otherwise, continue the reading. |
| 372 int bytes_read = 0; | 393 int bytes_read = 0; |
| 373 if (ReadLoop(&bytes_read)) | 394 if (ReadLoop(&bytes_read)) |
| 374 NotifyReadComplete(bytes_read); | 395 NotifyReadComplete(bytes_read); |
| 375 } | 396 } |
| 376 | 397 |
| 377 void BlobURLRequestJob::AdvanceItem() { | 398 void BlobURLRequestJob::AdvanceItem() { |
| 378 // Close the stream if the current item is a file. | 399 // Close the stream if the current item is a file. |
| 379 if (stream_.IsOpen()) | 400 CloseStream(); |
| 380 stream_.Close(); | |
| 381 | 401 |
| 382 // Advance to the next item. | 402 // Advance to the next item. |
| 383 item_index_++; | 403 item_index_++; |
| 384 current_item_offset_ = 0; | 404 current_item_offset_ = 0; |
| 385 } | 405 } |
| 386 | 406 |
| 387 void BlobURLRequestJob::AdvanceBytesRead(int result) { | 407 void BlobURLRequestJob::AdvanceBytesRead(int result) { |
| 388 DCHECK_GT(result, 0); | 408 DCHECK_GT(result, 0); |
| 389 | 409 |
| 390 // Do we finish reading the current item? | 410 // Do we finish reading the current item? |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 // We don't support multiple range requests in one single URL request, | 556 // We don't support multiple range requests in one single URL request, |
| 537 // because we need to do multipart encoding here. | 557 // because we need to do multipart encoding here. |
| 538 // TODO(jianli): Support multipart byte range requests. | 558 // TODO(jianli): Support multipart byte range requests. |
| 539 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); | 559 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); |
| 540 } | 560 } |
| 541 } | 561 } |
| 542 } | 562 } |
| 543 } | 563 } |
| 544 | 564 |
| 545 } // namespace webkit_blob | 565 } // namespace webkit_blob |
| OLD | NEW |