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

Side by Side Diff: chrome/browser/chromeos/drive/drive_file_stream_reader.cc

Issue 93883006: Fix failure of reading zero-byte files on Drive via StreamReader. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review fix. Created 7 years 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
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698