OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome/browser/chromeos/drive/drive_file_stream_reader.h" | 5 #include "chrome/browser/chromeos/drive/drive_file_stream_reader.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 | 9 |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 int FileErrorToNetError(FileError error) { | 28 int FileErrorToNetError(FileError error) { |
29 return net::PlatformFileErrorToNetError(FileErrorToPlatformError(error)); | 29 return net::PlatformFileErrorToNetError(FileErrorToPlatformError(error)); |
30 } | 30 } |
31 | 31 |
32 // Runs task on UI thread. | 32 // Runs task on UI thread. |
33 void RunTaskOnUIThread(const base::Closure& task) { | 33 void RunTaskOnUIThread(const base::Closure& task) { |
34 google_apis::RunTaskOnThread( | 34 google_apis::RunTaskOnThread( |
35 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), task); | 35 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), task); |
36 } | 36 } |
37 | 37 |
| 38 // Computes the concrete |start| offset and the |length| of |range| in a file |
| 39 // of |total| size. |
| 40 // |
| 41 // This is a thin wrapper of HttpByteRange::ComputeBounds, extended to allow |
| 42 // an empty range at the end of the file, like "Range: bytes 0-" on a zero byte |
| 43 // file. This is for convenience in unifying implementation with the seek |
| 44 // operation of stream reader. HTTP doesn't allow such ranges but we want to |
| 45 // treat such seeking as valid. |
| 46 bool ComputeConcretePosition(net::HttpByteRange range, int64 total, |
| 47 int64* start, int64* length) { |
| 48 // The special case when empty range in the end of the file is selected. |
| 49 if (range.HasFirstBytePosition() && range.first_byte_position() == total) { |
| 50 *start = range.first_byte_position(); |
| 51 *length = 0; |
| 52 return true; |
| 53 } |
| 54 |
| 55 // Otherwise forward to HttpByteRange::ComputeBounds. |
| 56 if (!range.ComputeBounds(total)) |
| 57 return false; |
| 58 *start = range.first_byte_position(); |
| 59 *length = range.last_byte_position() - range.first_byte_position() + 1; |
| 60 return true; |
| 61 } |
| 62 |
38 } // namespace | 63 } // namespace |
39 | 64 |
40 namespace internal { | 65 namespace internal { |
41 namespace { | 66 namespace { |
42 | 67 |
43 // Copies the content in |pending_data| into |buffer| at most | 68 // Copies the content in |pending_data| into |buffer| at most |
44 // |buffer_length| bytes, and erases the copied data from | 69 // |buffer_length| bytes, and erases the copied data from |
45 // |pending_data|. Returns the number of copied bytes. | 70 // |pending_data|. Returns the number of copied bytes. |
46 int ReadInternal(ScopedVector<std::string>* pending_data, | 71 int ReadInternal(ScopedVector<std::string>* pending_data, |
47 net::IOBuffer* buffer, int buffer_length) { | 72 net::IOBuffer* buffer, int buffer_length) { |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 int DriveFileStreamReader::Read(net::IOBuffer* buffer, int buffer_length, | 357 int DriveFileStreamReader::Read(net::IOBuffer* buffer, int buffer_length, |
333 const net::CompletionCallback& callback) { | 358 const net::CompletionCallback& callback) { |
334 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
335 DCHECK(reader_proxy_); | 360 DCHECK(reader_proxy_); |
336 DCHECK(buffer); | 361 DCHECK(buffer); |
337 DCHECK(!callback.is_null()); | 362 DCHECK(!callback.is_null()); |
338 return reader_proxy_->Read(buffer, buffer_length, callback); | 363 return reader_proxy_->Read(buffer, buffer_length, callback); |
339 } | 364 } |
340 | 365 |
341 void DriveFileStreamReader::InitializeAfterGetFileContentInitialized( | 366 void DriveFileStreamReader::InitializeAfterGetFileContentInitialized( |
342 const net::HttpByteRange& in_byte_range, | 367 const net::HttpByteRange& byte_range, |
343 const InitializeCompletionCallback& callback, | 368 const InitializeCompletionCallback& callback, |
344 FileError error, | 369 FileError error, |
345 scoped_ptr<ResourceEntry> entry, | 370 scoped_ptr<ResourceEntry> entry, |
346 const base::FilePath& local_cache_file_path, | 371 const base::FilePath& local_cache_file_path, |
347 const base::Closure& ui_cancel_download_closure) { | 372 const base::Closure& ui_cancel_download_closure) { |
348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
349 | 374 |
350 if (error != FILE_ERROR_OK) { | 375 if (error != FILE_ERROR_OK) { |
351 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); | 376 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); |
352 return; | 377 return; |
353 } | 378 } |
354 DCHECK(entry); | 379 DCHECK(entry); |
355 | 380 |
356 net::HttpByteRange byte_range = in_byte_range; | 381 int64 range_start = 0, range_length = 0; |
357 if (!byte_range.ComputeBounds(entry->file_info().size())) { | 382 if (!ComputeConcretePosition(byte_range, entry->file_info().size(), |
| 383 &range_start, &range_length)) { |
358 // If |byte_range| is invalid (e.g. out of bounds), return with an error. | 384 // If |byte_range| is invalid (e.g. out of bounds), return with an error. |
359 // At the same time, we cancel the in-flight downloading operation if | 385 // At the same time, we cancel the in-flight downloading operation if |
360 // needed and and invalidate weak pointers so that we won't | 386 // needed and and invalidate weak pointers so that we won't |
361 // receive unwanted callbacks. | 387 // receive unwanted callbacks. |
362 if (!ui_cancel_download_closure.is_null()) | 388 if (!ui_cancel_download_closure.is_null()) |
363 RunTaskOnUIThread(ui_cancel_download_closure); | 389 RunTaskOnUIThread(ui_cancel_download_closure); |
364 weak_ptr_factory_.InvalidateWeakPtrs(); | 390 weak_ptr_factory_.InvalidateWeakPtrs(); |
365 callback.Run( | 391 callback.Run( |
366 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, scoped_ptr<ResourceEntry>()); | 392 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, scoped_ptr<ResourceEntry>()); |
367 return; | 393 return; |
368 } | 394 } |
369 | 395 |
370 // Note: both boundary of |byte_range| are inclusive. | |
371 int64 range_length = | |
372 byte_range.last_byte_position() - byte_range.first_byte_position() + 1; | |
373 DCHECK_GE(range_length, 0); | |
374 | |
375 if (local_cache_file_path.empty()) { | 396 if (local_cache_file_path.empty()) { |
376 // The file is not cached, and being downloaded. | 397 // The file is not cached, and being downloaded. |
377 DCHECK(!ui_cancel_download_closure.is_null()); | 398 DCHECK(!ui_cancel_download_closure.is_null()); |
378 reader_proxy_.reset( | 399 reader_proxy_.reset( |
379 new internal::NetworkReaderProxy( | 400 new internal::NetworkReaderProxy( |
380 byte_range.first_byte_position(), range_length, | 401 range_start, range_length, |
381 base::Bind(&RunTaskOnUIThread, ui_cancel_download_closure))); | 402 base::Bind(&RunTaskOnUIThread, ui_cancel_download_closure))); |
382 callback.Run(net::OK, entry.Pass()); | 403 callback.Run(net::OK, entry.Pass()); |
383 return; | 404 return; |
384 } | 405 } |
385 | 406 |
386 // Otherwise, open the stream for file. | 407 // Otherwise, open the stream for file. |
387 scoped_ptr<util::LocalFileReader> file_reader( | 408 scoped_ptr<util::LocalFileReader> file_reader( |
388 new util::LocalFileReader(file_task_runner_.get())); | 409 new util::LocalFileReader(file_task_runner_.get())); |
389 util::LocalFileReader* file_reader_ptr = file_reader.get(); | 410 util::LocalFileReader* file_reader_ptr = file_reader.get(); |
390 file_reader_ptr->Open( | 411 file_reader_ptr->Open( |
391 local_cache_file_path, | 412 local_cache_file_path, |
392 byte_range.first_byte_position(), | 413 range_start, |
393 base::Bind( | 414 base::Bind( |
394 &DriveFileStreamReader::InitializeAfterLocalFileOpen, | 415 &DriveFileStreamReader::InitializeAfterLocalFileOpen, |
395 weak_ptr_factory_.GetWeakPtr(), | 416 weak_ptr_factory_.GetWeakPtr(), |
396 range_length, | 417 range_length, |
397 callback, | 418 callback, |
398 base::Passed(&entry), | 419 base::Passed(&entry), |
399 base::Passed(&file_reader))); | 420 base::Passed(&file_reader))); |
400 } | 421 } |
401 | 422 |
402 void DriveFileStreamReader::InitializeAfterLocalFileOpen( | 423 void DriveFileStreamReader::InitializeAfterLocalFileOpen( |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 // Note: due to the same reason, LocalReaderProxy::OnCompleted may | 463 // Note: due to the same reason, LocalReaderProxy::OnCompleted may |
443 // or may not be called. This is timing issue, and it is difficult to avoid | 464 // or may not be called. This is timing issue, and it is difficult to avoid |
444 // unfortunately. | 465 // unfortunately. |
445 if (error != FILE_ERROR_OK) { | 466 if (error != FILE_ERROR_OK) { |
446 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); | 467 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); |
447 } | 468 } |
448 } | 469 } |
449 } | 470 } |
450 | 471 |
451 } // namespace drive | 472 } // namespace drive |
OLD | NEW |