| 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 11 matching lines...) Expand all Loading... |
| 22 using content::BrowserThread; | 22 using content::BrowserThread; |
| 23 | 23 |
| 24 namespace drive { | 24 namespace drive { |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 // Converts FileError code to net::Error code. | 27 // Converts FileError code to net::Error code. |
| 28 int FileErrorToNetError(FileError error) { | 28 int FileErrorToNetError(FileError error) { |
| 29 return net::FileErrorToNetError(FileErrorToBaseFileError(error)); | 29 return net::FileErrorToNetError(FileErrorToBaseFileError(error)); |
| 30 } | 30 } |
| 31 | 31 |
| 32 // Runs task on UI thread. | |
| 33 void RunTaskOnUIThread(const base::Closure& task) { | |
| 34 google_apis::RunTaskOnThread( | |
| 35 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), task); | |
| 36 } | |
| 37 | |
| 38 // Computes the concrete |start| offset and the |length| of |range| in a file | 32 // Computes the concrete |start| offset and the |length| of |range| in a file |
| 39 // of |total| size. | 33 // of |total| size. |
| 40 // | 34 // |
| 41 // This is a thin wrapper of HttpByteRange::ComputeBounds, extended to allow | 35 // 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 | 36 // 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 | 37 // 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 | 38 // operation of stream reader. HTTP doesn't allow such ranges but we want to |
| 45 // treat such seeking as valid. | 39 // treat such seeking as valid. |
| 46 bool ComputeConcretePosition(net::HttpByteRange range, int64 total, | 40 bool ComputeConcretePosition(net::HttpByteRange range, int64 total, |
| 47 int64* start, int64* length) { | 41 int64* start, int64* length) { |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 base::ResetAndReturn(&callback_).Run(error_code_); | 260 base::ResetAndReturn(&callback_).Run(error_code_); |
| 267 } | 261 } |
| 268 | 262 |
| 269 } // namespace internal | 263 } // namespace internal |
| 270 | 264 |
| 271 namespace { | 265 namespace { |
| 272 | 266 |
| 273 // Calls FileSystemInterface::GetFileContent if the file system | 267 // Calls FileSystemInterface::GetFileContent if the file system |
| 274 // is available. If not, the |completion_callback| is invoked with | 268 // is available. If not, the |completion_callback| is invoked with |
| 275 // FILE_ERROR_FAILED. | 269 // FILE_ERROR_FAILED. |
| 276 void GetFileContentOnUIThread( | 270 base::Closure GetFileContentOnUIThread( |
| 277 const DriveFileStreamReader::FileSystemGetter& file_system_getter, | 271 const DriveFileStreamReader::FileSystemGetter& file_system_getter, |
| 278 const base::FilePath& drive_file_path, | 272 const base::FilePath& drive_file_path, |
| 279 const GetFileContentInitializedCallback& initialized_callback, | 273 const GetFileContentInitializedCallback& initialized_callback, |
| 280 const google_apis::GetContentCallback& get_content_callback, | 274 const google_apis::GetContentCallback& get_content_callback, |
| 281 const FileOperationCallback& completion_callback) { | 275 const FileOperationCallback& completion_callback) { |
| 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 283 | 277 |
| 284 FileSystemInterface* file_system = file_system_getter.Run(); | 278 FileSystemInterface* file_system = file_system_getter.Run(); |
| 285 if (!file_system) { | 279 if (!file_system) { |
| 286 completion_callback.Run(FILE_ERROR_FAILED); | 280 completion_callback.Run(FILE_ERROR_FAILED); |
| 287 return; | 281 return base::Closure(); |
| 288 } | 282 } |
| 289 | 283 |
| 290 file_system->GetFileContent(drive_file_path, | 284 return google_apis::CreateRelayCallback( |
| 291 initialized_callback, | 285 file_system->GetFileContent(drive_file_path, |
| 292 get_content_callback, | 286 initialized_callback, |
| 293 completion_callback); | 287 get_content_callback, |
| 288 completion_callback)); |
| 294 } | 289 } |
| 295 | 290 |
| 296 // Helper to run FileSystemInterface::GetFileContent on UI thread. | 291 // Helper to run FileSystemInterface::GetFileContent on UI thread. |
| 297 void GetFileContent( | 292 void GetFileContent( |
| 298 const DriveFileStreamReader::FileSystemGetter& file_system_getter, | 293 const DriveFileStreamReader::FileSystemGetter& file_system_getter, |
| 299 const base::FilePath& drive_file_path, | 294 const base::FilePath& drive_file_path, |
| 300 const GetFileContentInitializedCallback& initialized_callback, | 295 const GetFileContentInitializedCallback& initialized_callback, |
| 301 const google_apis::GetContentCallback& get_content_callback, | 296 const google_apis::GetContentCallback& get_content_callback, |
| 302 const FileOperationCallback& completion_callback) { | 297 const FileOperationCallback& completion_callback, |
| 298 const base::Callback<void(const base::Closure&)>& reply_callback) { |
| 303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 304 | 300 |
| 305 BrowserThread::PostTask( | 301 BrowserThread::PostTaskAndReplyWithResult( |
| 306 BrowserThread::UI, | 302 BrowserThread::UI, |
| 307 FROM_HERE, | 303 FROM_HERE, |
| 308 base::Bind(&GetFileContentOnUIThread, | 304 base::Bind(&GetFileContentOnUIThread, |
| 309 file_system_getter, | 305 file_system_getter, |
| 310 drive_file_path, | 306 drive_file_path, |
| 311 google_apis::CreateRelayCallback(initialized_callback), | 307 google_apis::CreateRelayCallback(initialized_callback), |
| 312 google_apis::CreateRelayCallback(get_content_callback), | 308 google_apis::CreateRelayCallback(get_content_callback), |
| 313 google_apis::CreateRelayCallback(completion_callback))); | 309 google_apis::CreateRelayCallback(completion_callback)), |
| 310 reply_callback); |
| 314 } | 311 } |
| 315 | 312 |
| 316 } // namespace | 313 } // namespace |
| 317 | 314 |
| 318 DriveFileStreamReader::DriveFileStreamReader( | 315 DriveFileStreamReader::DriveFileStreamReader( |
| 319 const FileSystemGetter& file_system_getter, | 316 const FileSystemGetter& file_system_getter, |
| 320 base::SequencedTaskRunner* file_task_runner) | 317 base::SequencedTaskRunner* file_task_runner) |
| 321 : file_system_getter_(file_system_getter), | 318 : file_system_getter_(file_system_getter), |
| 322 file_task_runner_(file_task_runner), | 319 file_task_runner_(file_task_runner), |
| 323 weak_ptr_factory_(this) { | 320 weak_ptr_factory_(this) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 344 drive_file_path, | 341 drive_file_path, |
| 345 base::Bind(&DriveFileStreamReader | 342 base::Bind(&DriveFileStreamReader |
| 346 ::InitializeAfterGetFileContentInitialized, | 343 ::InitializeAfterGetFileContentInitialized, |
| 347 weak_ptr_factory_.GetWeakPtr(), | 344 weak_ptr_factory_.GetWeakPtr(), |
| 348 byte_range, | 345 byte_range, |
| 349 callback), | 346 callback), |
| 350 base::Bind(&DriveFileStreamReader::OnGetContent, | 347 base::Bind(&DriveFileStreamReader::OnGetContent, |
| 351 weak_ptr_factory_.GetWeakPtr()), | 348 weak_ptr_factory_.GetWeakPtr()), |
| 352 base::Bind(&DriveFileStreamReader::OnGetFileContentCompletion, | 349 base::Bind(&DriveFileStreamReader::OnGetFileContentCompletion, |
| 353 weak_ptr_factory_.GetWeakPtr(), | 350 weak_ptr_factory_.GetWeakPtr(), |
| 354 callback)); | 351 callback), |
| 352 base::Bind(&DriveFileStreamReader::StoreCancelDownloadClosure, |
| 353 weak_ptr_factory_.GetWeakPtr())); |
| 355 } | 354 } |
| 356 | 355 |
| 357 int DriveFileStreamReader::Read(net::IOBuffer* buffer, int buffer_length, | 356 int DriveFileStreamReader::Read(net::IOBuffer* buffer, int buffer_length, |
| 358 const net::CompletionCallback& callback) { | 357 const net::CompletionCallback& callback) { |
| 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 360 DCHECK(reader_proxy_); | 359 DCHECK(reader_proxy_); |
| 361 DCHECK(buffer); | 360 DCHECK(buffer); |
| 362 DCHECK(!callback.is_null()); | 361 DCHECK(!callback.is_null()); |
| 363 return reader_proxy_->Read(buffer, buffer_length, callback); | 362 return reader_proxy_->Read(buffer, buffer_length, callback); |
| 364 } | 363 } |
| 365 | 364 |
| 365 void DriveFileStreamReader::StoreCancelDownloadClosure( |
| 366 const base::Closure& cancel_download_closure) { |
| 367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 368 cancel_download_closure_ = cancel_download_closure; |
| 369 } |
| 370 |
| 366 void DriveFileStreamReader::InitializeAfterGetFileContentInitialized( | 371 void DriveFileStreamReader::InitializeAfterGetFileContentInitialized( |
| 367 const net::HttpByteRange& byte_range, | 372 const net::HttpByteRange& byte_range, |
| 368 const InitializeCompletionCallback& callback, | 373 const InitializeCompletionCallback& callback, |
| 369 FileError error, | 374 FileError error, |
| 370 scoped_ptr<ResourceEntry> entry, | |
| 371 const base::FilePath& local_cache_file_path, | 375 const base::FilePath& local_cache_file_path, |
| 372 const base::Closure& ui_cancel_download_closure) { | 376 scoped_ptr<ResourceEntry> entry) { |
| 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 378 // StoreCancelDownloadClosure() should be called before this function. |
| 379 DCHECK(!cancel_download_closure_.is_null()); |
| 374 | 380 |
| 375 if (error != FILE_ERROR_OK) { | 381 if (error != FILE_ERROR_OK) { |
| 376 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); | 382 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); |
| 377 return; | 383 return; |
| 378 } | 384 } |
| 379 DCHECK(entry); | 385 DCHECK(entry); |
| 380 | 386 |
| 381 int64 range_start = 0, range_length = 0; | 387 int64 range_start = 0, range_length = 0; |
| 382 if (!ComputeConcretePosition(byte_range, entry->file_info().size(), | 388 if (!ComputeConcretePosition(byte_range, entry->file_info().size(), |
| 383 &range_start, &range_length)) { | 389 &range_start, &range_length)) { |
| 384 // If |byte_range| is invalid (e.g. out of bounds), return with an error. | 390 // If |byte_range| is invalid (e.g. out of bounds), return with an error. |
| 385 // At the same time, we cancel the in-flight downloading operation if | 391 // At the same time, we cancel the in-flight downloading operation if |
| 386 // needed and and invalidate weak pointers so that we won't | 392 // needed and and invalidate weak pointers so that we won't |
| 387 // receive unwanted callbacks. | 393 // receive unwanted callbacks. |
| 388 if (!ui_cancel_download_closure.is_null()) | 394 cancel_download_closure_.Run(); |
| 389 RunTaskOnUIThread(ui_cancel_download_closure); | |
| 390 weak_ptr_factory_.InvalidateWeakPtrs(); | 395 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 391 callback.Run( | 396 callback.Run( |
| 392 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, scoped_ptr<ResourceEntry>()); | 397 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, scoped_ptr<ResourceEntry>()); |
| 393 return; | 398 return; |
| 394 } | 399 } |
| 395 | 400 |
| 396 if (local_cache_file_path.empty()) { | 401 if (local_cache_file_path.empty()) { |
| 397 // The file is not cached, and being downloaded. | 402 // The file is not cached, and being downloaded. |
| 398 DCHECK(!ui_cancel_download_closure.is_null()); | |
| 399 reader_proxy_.reset( | 403 reader_proxy_.reset( |
| 400 new internal::NetworkReaderProxy( | 404 new internal::NetworkReaderProxy( |
| 401 range_start, range_length, | 405 range_start, range_length, cancel_download_closure_)); |
| 402 base::Bind(&RunTaskOnUIThread, ui_cancel_download_closure))); | |
| 403 callback.Run(net::OK, entry.Pass()); | 406 callback.Run(net::OK, entry.Pass()); |
| 404 return; | 407 return; |
| 405 } | 408 } |
| 406 | 409 |
| 407 // Otherwise, open the stream for file. | 410 // Otherwise, open the stream for file. |
| 408 scoped_ptr<util::LocalFileReader> file_reader( | 411 scoped_ptr<util::LocalFileReader> file_reader( |
| 409 new util::LocalFileReader(file_task_runner_.get())); | 412 new util::LocalFileReader(file_task_runner_.get())); |
| 410 util::LocalFileReader* file_reader_ptr = file_reader.get(); | 413 util::LocalFileReader* file_reader_ptr = file_reader.get(); |
| 411 file_reader_ptr->Open( | 414 file_reader_ptr->Open( |
| 412 local_cache_file_path, | 415 local_cache_file_path, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 // Note: due to the same reason, LocalReaderProxy::OnCompleted may | 466 // Note: due to the same reason, LocalReaderProxy::OnCompleted may |
| 464 // or may not be called. This is timing issue, and it is difficult to avoid | 467 // or may not be called. This is timing issue, and it is difficult to avoid |
| 465 // unfortunately. | 468 // unfortunately. |
| 466 if (error != FILE_ERROR_OK) { | 469 if (error != FILE_ERROR_OK) { |
| 467 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); | 470 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); |
| 468 } | 471 } |
| 469 } | 472 } |
| 470 } | 473 } |
| 471 | 474 |
| 472 } // namespace drive | 475 } // namespace drive |
| OLD | NEW |