fake_provided_file_system.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1// Copyright 2014 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 "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h" 6 7#include <string> 8 9#include "base/files/file.h" 10#include "base/message_loop/message_loop_proxy.h" 11#include "extensions/browser/event_router.h" 12#include "net/base/io_buffer.h" 13 14namespace chromeos { 15namespace file_system_provider { 16namespace { 17 18// Adds a fake entry to the entry list. 19void AddDirectoryEntry(fileapi::AsyncFileUtil::EntryList* entry_list, 20 const std::string& name, 21 fileapi::DirectoryEntry::DirectoryEntryType type, 22 int64 size, 23 std::string last_modified_time_string) { 24 base::Time last_modified_time; 25 const bool result = base::Time::FromString(last_modified_time_string.c_str(), 26 &last_modified_time); 27 DCHECK(result); 28 entry_list->push_back( 29 fileapi::DirectoryEntry(name, type, size, last_modified_time)); 30} 31 32} // namespace 33 34const char kFakeFileName[] = "hello.txt"; 35const char kFakeFilePath[] = "/hello.txt"; 36const char kFakeFileText[] = 37 "This is a testing file. Lorem ipsum dolor sit amet est."; 38const size_t kFakeFileSize = sizeof(kFakeFileText) - 1u; 39 40FakeProvidedFileSystem::FakeProvidedFileSystem( 41 const ProvidedFileSystemInfo& file_system_info) 42 : file_system_info_(file_system_info), 43 last_file_handle_(0), 44 weak_ptr_factory_(this) { 45} 46 47FakeProvidedFileSystem::~FakeProvidedFileSystem() {} 48 49void FakeProvidedFileSystem::RequestUnmount( 50 const fileapi::AsyncFileUtil::StatusCallback& callback) { 51 base::MessageLoopProxy::current()->PostTask( 52 FROM_HERE, base::Bind(callback, base::File::FILE_OK)); 53} 54 55void FakeProvidedFileSystem::GetMetadata( 56 const base::FilePath& entry_path, 57 const fileapi::AsyncFileUtil::GetFileInfoCallback& callback) { 58 if (entry_path.AsUTF8Unsafe() == "/") { 59 base::File::Info file_info; 60 file_info.size = 0; 61 file_info.is_directory = true; 62 file_info.is_symbolic_link = false; 63 base::Time last_modified_time; 64 const bool result = base::Time::FromString("Thu Apr 24 00:46:52 UTC 2014", 65 &last_modified_time); 66 DCHECK(result); 67 file_info.last_modified = last_modified_time; 68 69 base::MessageLoopProxy::current()->PostTask( 70 FROM_HERE, base::Bind(callback, base::File::FILE_OK, file_info)); 71 return; 72 } 73 74 if (entry_path.AsUTF8Unsafe() == kFakeFilePath) { 75 base::File::Info file_info; 76 file_info.size = kFakeFileSize; 77 file_info.is_directory = false; 78 file_info.is_symbolic_link = false; 79 base::Time last_modified_time; 80 const bool result = base::Time::FromString("Fri Apr 25 01:47:53 UTC 2014", 81 &last_modified_time); 82 DCHECK(result); 83 file_info.last_modified = last_modified_time; 84 85 base::MessageLoopProxy::current()->PostTask( 86 FROM_HERE, base::Bind(callback, base::File::FILE_OK, file_info)); 87 return; 88 } 89 90 base::MessageLoopProxy::current()->PostTask( 91 FROM_HERE, 92 base::Bind( 93 callback, base::File::FILE_ERROR_NOT_FOUND, base::File::Info())); 94} 95 96void FakeProvidedFileSystem::ReadDirectory( 97 const base::FilePath& directory_path, 98 const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback) { 99 // Return fake contents for the root directory only. 100 if (directory_path.AsUTF8Unsafe() != "/") { 101 base::MessageLoopProxy::current()->PostTask( 102 FROM_HERE, 103 base::Bind(callback, 104 base::File::FILE_ERROR_NOT_FOUND, 105 fileapi::AsyncFileUtil::EntryList(), 106 false /* has_more */)); 107 return; 108 } 109 110 { 111 fileapi::AsyncFileUtil::EntryList entry_list; 112 AddDirectoryEntry(&entry_list, 113 kFakeFileName, 114 fileapi::DirectoryEntry::FILE, 115 kFakeFileSize, 116 "Thu Apr 24 00:46:52 UTC 2014"); 117 118 AddDirectoryEntry(&entry_list, 119 "world.txt", 120 fileapi::DirectoryEntry::FILE, 121 1024 /* size */, 122 "Wed Apr 23 00:20:30 UTC 2014"); 123 124 base::MessageLoopProxy::current()->PostTask( 125 FROM_HERE, 126 base::Bind( 127 callback, base::File::FILE_OK, entry_list, true /* has_more */)); 128 } 129 130 { 131 fileapi::AsyncFileUtil::EntryList entry_list; 132 AddDirectoryEntry(&entry_list, 133 "pictures", 134 fileapi::DirectoryEntry::DIRECTORY, 135 0 /* size */, 136 "Tue May 22 00:40:50 UTC 2014"); 137 138 base::MessageLoopProxy::current()->PostTask( 139 FROM_HERE, 140 base::Bind( 141 callback, base::File::FILE_OK, entry_list, false /* has_more */)); 142 } 143} 144 145void FakeProvidedFileSystem::OpenFile(const base::FilePath& file_path, 146 OpenFileMode mode, 147 bool create, 148 const OpenFileCallback& callback) { 149 if (mode == OPEN_FILE_MODE_WRITE || create) { 150 base::MessageLoopProxy::current()->PostTask( 151 FROM_HERE, 152 base::Bind(callback, 153 0 /* file_handle */, 154 base::File::FILE_ERROR_ACCESS_DENIED)); 155 } 156 157 if (file_path.AsUTF8Unsafe() != "/hello.txt") { 158 base::MessageLoopProxy::current()->PostTask( 159 FROM_HERE, 160 base::Bind( 161 callback, 0 /* file_handle */, base::File::FILE_ERROR_NOT_FOUND)); 162 return; 163 } 164 165 const int file_handle = ++last_file_handle_; 166 opened_files_[file_handle] = file_path; 167 base::MessageLoopProxy::current()->PostTask( 168 FROM_HERE, base::Bind(callback, file_handle, base::File::FILE_OK)); 169} 170 171void FakeProvidedFileSystem::CloseFile( 172 int file_handle, 173 const fileapi::AsyncFileUtil::StatusCallback& callback) { 174 const OpenedFilesMap::iterator opened_file_it = 175 opened_files_.find(file_handle); 176 if (opened_file_it == opened_files_.end()) { 177 base::MessageLoopProxy::current()->PostTask( 178 FROM_HERE, base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND)); 179 return; 180 } 181 182 opened_files_.erase(opened_file_it); 183 base::MessageLoopProxy::current()->PostTask( 184 FROM_HERE, base::Bind(callback, base::File::FILE_OK)); 185} 186 187void FakeProvidedFileSystem::ReadFile( 188 int file_handle, 189 net::IOBuffer* buffer, 190 int64 offset, 191 int length, 192 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) { 193 const OpenedFilesMap::iterator opened_file_it = 194 opened_files_.find(file_handle); 195 if (opened_file_it == opened_files_.end() || 196 opened_file_it->second.AsUTF8Unsafe() != kFakeFilePath) { 197 base::MessageLoopProxy::current()->PostTask( 198 FROM_HERE, 199 base::Bind(callback, 200 0 /* chunk_length */, 201 false /* has_more */, 202 base::File::FILE_ERROR_INVALID_OPERATION)); 203 return; 204 } 205 206 // Send the response byte by byte. 207 size_t current_offset = static_cast<size_t>(offset); 208 size_t current_length = static_cast<size_t>(length); 209 210 // Reading behind EOF is fine, it will just return 0 bytes. 211 if (current_offset >= kFakeFileSize || !current_length) { 212 base::MessageLoopProxy::current()->PostTask( 213 FROM_HERE, 214 base::Bind(callback, 215 0 /* chunk_length */, 216 false /* has_more */, 217 base::File::FILE_OK)); 218 } 219 220 while (current_offset < kFakeFileSize && current_length) { 221 buffer->data()[current_offset - offset] = kFakeFileText[current_offset]; 222 const bool has_more = 223 (current_offset + 1 < kFakeFileSize) && (current_length - 1); 224 base::MessageLoopProxy::current()->PostTask( 225 FROM_HERE, 226 base::Bind( 227 callback, 1 /* chunk_length */, has_more, base::File::FILE_OK)); 228 current_offset++; 229 current_length--; 230 } 231} 232 233const ProvidedFileSystemInfo& FakeProvidedFileSystem::GetFileSystemInfo() 234 const { 235 return file_system_info_; 236} 237 238RequestManager* FakeProvidedFileSystem::GetRequestManager() { 239 NOTREACHED(); 240 return NULL; 241} 242 243ProvidedFileSystemInterface* FakeProvidedFileSystem::Create( 244 extensions::EventRouter* event_router, 245 const ProvidedFileSystemInfo& file_system_info) { 246 return new FakeProvidedFileSystem(file_system_info); 247} 248 249base::WeakPtr<ProvidedFileSystemInterface> 250FakeProvidedFileSystem::GetWeakPtr() { 251 return weak_ptr_factory_.GetWeakPtr(); 252} 253 254} // namespace file_system_provider 255} // namespace chromeos 256