| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "storage/browser/fileapi/file_system_file_stream_reader.h" |
| |
| #include "base/files/file_util_proxy.h" |
| #include "base/single_thread_task_runner.h" |
| #include "net/base/file_stream.h" |
| #include "net/base/io_buffer.h" |
| #include "net/base/net_errors.h" |
| #include "storage/browser/fileapi/file_system_context.h" |
| #include "storage/browser/fileapi/file_system_operation_runner.h" |
| |
| using storage::FileStreamReader; |
| |
| // TODO(kinuko): Remove this temporary namespace hack after we move both |
| // blob and fileapi into content namespace. |
| namespace storage { |
| |
| FileStreamReader* FileStreamReader::CreateForFileSystemFile( |
| storage::FileSystemContext* file_system_context, |
| const storage::FileSystemURL& url, |
| int64 initial_offset, |
| const base::Time& expected_modification_time) { |
| return new storage::FileSystemFileStreamReader( |
| file_system_context, url, initial_offset, expected_modification_time); |
| } |
| |
| } // namespace storage |
| |
| namespace storage { |
| |
| namespace { |
| |
| void ReadAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, |
| net::IOBuffer* buf, int buf_len, |
| const net::CompletionCallback& callback) { |
| if (!reader.get()) |
| return; |
| int rv = reader->Read(buf, buf_len, callback); |
| if (rv != net::ERR_IO_PENDING) |
| callback.Run(rv); |
| } |
| |
| void GetLengthAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, |
| const net::Int64CompletionCallback& callback) { |
| if (!reader.get()) |
| return; |
| int rv = reader->GetLength(callback); |
| if (rv != net::ERR_IO_PENDING) |
| callback.Run(rv); |
| } |
| |
| void Int64CallbackAdapter(const net::Int64CompletionCallback& callback, |
| int value) { |
| callback.Run(value); |
| } |
| |
| } // namespace |
| |
| FileSystemFileStreamReader::~FileSystemFileStreamReader() { |
| } |
| |
| int FileSystemFileStreamReader::Read( |
| net::IOBuffer* buf, int buf_len, |
| const net::CompletionCallback& callback) { |
| if (local_file_reader_) |
| return local_file_reader_->Read(buf, buf_len, callback); |
| return CreateSnapshot( |
| base::Bind(&ReadAdapter, weak_factory_.GetWeakPtr(), |
| make_scoped_refptr(buf), buf_len, callback), |
| callback); |
| } |
| |
| int64 FileSystemFileStreamReader::GetLength( |
| const net::Int64CompletionCallback& callback) { |
| if (local_file_reader_) |
| return local_file_reader_->GetLength(callback); |
| return CreateSnapshot( |
| base::Bind(&GetLengthAdapter, weak_factory_.GetWeakPtr(), callback), |
| base::Bind(&Int64CallbackAdapter, callback)); |
| } |
| |
| FileSystemFileStreamReader::FileSystemFileStreamReader( |
| FileSystemContext* file_system_context, |
| const FileSystemURL& url, |
| int64 initial_offset, |
| const base::Time& expected_modification_time) |
| : file_system_context_(file_system_context), |
| url_(url), |
| initial_offset_(initial_offset), |
| expected_modification_time_(expected_modification_time), |
| has_pending_create_snapshot_(false), |
| weak_factory_(this) { |
| } |
| |
| int FileSystemFileStreamReader::CreateSnapshot( |
| const base::Closure& callback, |
| const net::CompletionCallback& error_callback) { |
| DCHECK(!has_pending_create_snapshot_); |
| has_pending_create_snapshot_ = true; |
| file_system_context_->operation_runner()->CreateSnapshotFile( |
| url_, |
| base::Bind(&FileSystemFileStreamReader::DidCreateSnapshot, |
| weak_factory_.GetWeakPtr(), |
| callback, |
| error_callback)); |
| return net::ERR_IO_PENDING; |
| } |
| |
| void FileSystemFileStreamReader::DidCreateSnapshot( |
| const base::Closure& callback, |
| const net::CompletionCallback& error_callback, |
| base::File::Error file_error, |
| const base::File::Info& file_info, |
| const base::FilePath& platform_path, |
| const scoped_refptr<storage::ShareableFileReference>& file_ref) { |
| DCHECK(has_pending_create_snapshot_); |
| DCHECK(!local_file_reader_.get()); |
| has_pending_create_snapshot_ = false; |
| |
| if (file_error != base::File::FILE_OK) { |
| error_callback.Run(net::FileErrorToNetError(file_error)); |
| return; |
| } |
| |
| // Keep the reference (if it's non-null) so that the file won't go away. |
| snapshot_ref_ = file_ref; |
| |
| local_file_reader_.reset( |
| FileStreamReader::CreateForLocalFile( |
| file_system_context_->default_file_task_runner(), |
| platform_path, initial_offset_, expected_modification_time_)); |
| |
| callback.Run(); |
| } |
| |
| } // namespace storage |