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/single_thread_task_runner.h" 9 #include "net/base/file_stream.h" 10 #include "net/base/io_buffer.h" 11 #include "net/base/net_errors.h" 12 #include "webkit/browser/blob/file_stream_reader.h" 13 #include "webkit/browser/fileapi/file_system_context.h" 14 #include "webkit/browser/fileapi/file_system_operation_runner.h" 15 16 using webkit_blob::FileStreamReader; 17 18 // TODO(kinuko): Remove this temporary namespace hack after we move both 19 // blob and fileapi into content namespace. 20 namespace webkit_blob { 21 22 FileStreamReader* FileStreamReader::CreateForFileSystemFile( 23 fileapi::FileSystemContext* file_system_context, 24 const fileapi::FileSystemURL& url, 25 int64 initial_offset, 26 const base::Time& expected_modification_time) { 27 return new fileapi::FileSystemFileStreamReader( 28 file_system_context, 29 url, 30 initial_offset, 31 expected_modification_time); 32 } 33 34 } // namespace webkit_blob 35 36 namespace fileapi { 37 38 namespace { 39 40 void ReadAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, 41 net::IOBuffer* buf, int buf_len, 42 const net::CompletionCallback& callback) { 43 if (!reader.get()) 44 return; 45 int rv = reader->Read(buf, buf_len, callback); 46 if (rv != net::ERR_IO_PENDING) 47 callback.Run(rv); 48 } 49 50 void GetLengthAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, 51 const net::Int64CompletionCallback& callback) { 52 if (!reader.get()) 53 return; 54 int rv = reader->GetLength(callback); 55 if (rv != net::ERR_IO_PENDING) 56 callback.Run(rv); 57 } 58 59 void Int64CallbackAdapter(const net::Int64CompletionCallback& callback, 60 int value) { 61 callback.Run(value); 62 } 63 64 } // namespace 65 66 FileSystemFileStreamReader::~FileSystemFileStreamReader() { 67 } 68 69 int FileSystemFileStreamReader::Read( 70 net::IOBuffer* buf, int buf_len, 71 const net::CompletionCallback& callback) { 72 if (local_file_reader_) 73 return local_file_reader_->Read(buf, buf_len, callback); 74 return CreateSnapshot( 75 base::Bind(&ReadAdapter, weak_factory_.GetWeakPtr(), 76 make_scoped_refptr(buf), buf_len, callback), 77 callback); 78 } 79 80 int64 FileSystemFileStreamReader::GetLength( 81 const net::Int64CompletionCallback& callback) { 82 if (local_file_reader_) 83 return local_file_reader_->GetLength(callback); 84 return CreateSnapshot( 85 base::Bind(&GetLengthAdapter, weak_factory_.GetWeakPtr(), callback), 86 base::Bind(&Int64CallbackAdapter, callback)); 87 } 88 89 FileSystemFileStreamReader::FileSystemFileStreamReader( 90 FileSystemContext* file_system_context, 91 const FileSystemURL& url, 92 int64 initial_offset, 93 const base::Time& expected_modification_time) 94 : file_system_context_(file_system_context), 95 url_(url), 96 initial_offset_(initial_offset), 97 expected_modification_time_(expected_modification_time), 98 has_pending_create_snapshot_(false), 99 weak_factory_(this) { 100 } 101 102 int FileSystemFileStreamReader::CreateSnapshot( 103 const base::Closure& callback, 104 const net::CompletionCallback& error_callback) { 105 DCHECK(!has_pending_create_snapshot_); 106 has_pending_create_snapshot_ = true; 107 file_system_context_->operation_runner()->CreateSnapshotFile( 108 url_, 109 base::Bind(&FileSystemFileStreamReader::DidCreateSnapshot, 110 weak_factory_.GetWeakPtr(), 111 callback, 112 error_callback)); 113 return net::ERR_IO_PENDING; 114 } 115 116 void FileSystemFileStreamReader::DidCreateSnapshot( 117 const base::Closure& callback, 118 const net::CompletionCallback& error_callback, 119 base::File::Error file_error, 120 const base::File::Info& file_info, 121 const base::FilePath& platform_path, 122 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { 123 DCHECK(has_pending_create_snapshot_); 124 DCHECK(!local_file_reader_.get()); 125 has_pending_create_snapshot_ = false; 126 127 if (file_error != base::File::FILE_OK) { 128 error_callback.Run(net::FileErrorToNetError(file_error)); 129 return; 130 } 131 132 // Keep the reference (if it's non-null) so that the file won't go away. 133 snapshot_ref_ = file_ref; 134 135 local_file_reader_.reset( 136 FileStreamReader::CreateForLocalFile( 137 file_system_context_->default_file_task_runner(), 138 platform_path, initial_offset_, expected_modification_time_)); 139 140 callback.Run(); 141 } 142 143 } // namespace fileapi 144