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