// 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/blob/file_stream_reader.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 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 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& 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