1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "webkit/browser/fileapi/file_system_file_stream_reader.h" 6 7 #include "base/files/file_util_proxy.h" 8 #include "base/platform_file.h" 9 #include "base/single_thread_task_runner.h" 10 #include "net/base/file_stream.h" 11 #include "net/base/io_buffer.h" 12 #include "net/base/net_errors.h" 13 #include "webkit/browser/blob/local_file_stream_reader.h" 14 #include "webkit/browser/fileapi/file_system_context.h" 15 #include "webkit/browser/fileapi/file_system_operation_runner.h" 16 17 using webkit_blob::LocalFileStreamReader; 18 19 namespace fileapi { 20 21 namespace { 22 23 void ReadAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, 24 net::IOBuffer* buf, int buf_len, 25 const net::CompletionCallback& callback) { 26 if (!reader.get()) 27 return; 28 int rv = reader->Read(buf, buf_len, callback); 29 if (rv != net::ERR_IO_PENDING) 30 callback.Run(rv); 31 } 32 33 void GetLengthAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, 34 const net::Int64CompletionCallback& callback) { 35 if (!reader.get()) 36 return; 37 int rv = reader->GetLength(callback); 38 if (rv != net::ERR_IO_PENDING) 39 callback.Run(rv); 40 } 41 42 void Int64CallbackAdapter(const net::Int64CompletionCallback& callback, 43 int value) { 44 callback.Run(value); 45 } 46 47 } // namespace 48 49 FileSystemFileStreamReader::FileSystemFileStreamReader( 50 FileSystemContext* file_system_context, 51 const FileSystemURL& url, 52 int64 initial_offset, 53 const base::Time& expected_modification_time) 54 : file_system_context_(file_system_context), 55 url_(url), 56 initial_offset_(initial_offset), 57 expected_modification_time_(expected_modification_time), 58 has_pending_create_snapshot_(false), 59 weak_factory_(this) { 60 } 61 62 FileSystemFileStreamReader::~FileSystemFileStreamReader() { 63 } 64 65 int FileSystemFileStreamReader::Read( 66 net::IOBuffer* buf, int buf_len, 67 const net::CompletionCallback& callback) { 68 if (local_file_reader_) 69 return local_file_reader_->Read(buf, buf_len, callback); 70 return CreateSnapshot( 71 base::Bind(&ReadAdapter, weak_factory_.GetWeakPtr(), 72 make_scoped_refptr(buf), buf_len, callback), 73 callback); 74 } 75 76 int64 FileSystemFileStreamReader::GetLength( 77 const net::Int64CompletionCallback& callback) { 78 if (local_file_reader_) 79 return local_file_reader_->GetLength(callback); 80 return CreateSnapshot( 81 base::Bind(&GetLengthAdapter, weak_factory_.GetWeakPtr(), callback), 82 base::Bind(&Int64CallbackAdapter, callback)); 83 } 84 85 int FileSystemFileStreamReader::CreateSnapshot( 86 const base::Closure& callback, 87 const net::CompletionCallback& error_callback) { 88 DCHECK(!has_pending_create_snapshot_); 89 has_pending_create_snapshot_ = true; 90 file_system_context_->operation_runner()->CreateSnapshotFile( 91 url_, 92 base::Bind(&FileSystemFileStreamReader::DidCreateSnapshot, 93 weak_factory_.GetWeakPtr(), 94 callback, 95 error_callback)); 96 return net::ERR_IO_PENDING; 97 } 98 99 void FileSystemFileStreamReader::DidCreateSnapshot( 100 const base::Closure& callback, 101 const net::CompletionCallback& error_callback, 102 base::PlatformFileError file_error, 103 const base::PlatformFileInfo& file_info, 104 const base::FilePath& platform_path, 105 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { 106 DCHECK(has_pending_create_snapshot_); 107 DCHECK(!local_file_reader_.get()); 108 has_pending_create_snapshot_ = false; 109 110 if (file_error != base::PLATFORM_FILE_OK) { 111 error_callback.Run(net::PlatformFileErrorToNetError(file_error)); 112 return; 113 } 114 115 // Keep the reference (if it's non-null) so that the file won't go away. 116 snapshot_ref_ = file_ref; 117 118 local_file_reader_.reset( 119 new LocalFileStreamReader( 120 file_system_context_->default_file_task_runner(), 121 platform_path, initial_offset_, expected_modification_time_)); 122 123 callback.Run(); 124 } 125 126 } // namespace fileapi 127