Move StartsWith[ASCII] to base namespace.
[chromium-blink-merge.git] / chrome / browser / chromeos / file_system_provider / fake_provided_file_system.cc
blobe8b55ee88eb2242e34566aa7e4da673ec9d45d50
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.
5 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
7 #include "base/thread_task_runner_handle.h"
8 #include "net/base/io_buffer.h"
10 namespace chromeos {
11 namespace file_system_provider {
12 namespace {
14 const char kFakeFileName[] = "hello.txt";
15 const char kFakeFileText[] =
16 "This is a testing file. Lorem ipsum dolor sit amet est.";
17 const size_t kFakeFileSize = sizeof(kFakeFileText) - 1u;
18 const char kFakeFileModificationTime[] = "Fri Apr 25 01:47:53 UTC 2014";
19 const char kFakeFileMimeType[] = "text/plain";
21 } // namespace
23 const base::FilePath::CharType kFakeFilePath[] =
24 FILE_PATH_LITERAL("/hello.txt");
26 FakeEntry::FakeEntry() {
29 FakeEntry::FakeEntry(scoped_ptr<EntryMetadata> metadata,
30 const std::string& contents)
31 : metadata(metadata.Pass()), contents(contents) {
34 FakeEntry::~FakeEntry() {
37 FakeProvidedFileSystem::FakeProvidedFileSystem(
38 const ProvidedFileSystemInfo& file_system_info)
39 : file_system_info_(file_system_info),
40 last_file_handle_(0),
41 weak_ptr_factory_(this) {
42 AddEntry(base::FilePath(FILE_PATH_LITERAL("/")), true, "", 0, base::Time(),
43 "", "");
45 base::Time modification_time;
46 DCHECK(base::Time::FromString(kFakeFileModificationTime, &modification_time));
47 AddEntry(base::FilePath(kFakeFilePath), false, kFakeFileName, kFakeFileSize,
48 modification_time, kFakeFileMimeType, kFakeFileText);
51 FakeProvidedFileSystem::~FakeProvidedFileSystem() {}
53 void FakeProvidedFileSystem::AddEntry(const base::FilePath& entry_path,
54 bool is_directory,
55 const std::string& name,
56 int64 size,
57 base::Time modification_time,
58 std::string mime_type,
59 std::string contents) {
60 DCHECK(entries_.find(entry_path) == entries_.end());
61 scoped_ptr<EntryMetadata> metadata(new EntryMetadata);
63 metadata->is_directory = is_directory;
64 metadata->name = name;
65 metadata->size = size;
66 metadata->modification_time = modification_time;
67 metadata->mime_type = mime_type;
69 entries_[entry_path] =
70 make_linked_ptr(new FakeEntry(metadata.Pass(), contents));
73 const FakeEntry* FakeProvidedFileSystem::GetEntry(
74 const base::FilePath& entry_path) const {
75 const Entries::const_iterator entry_it = entries_.find(entry_path);
76 if (entry_it == entries_.end())
77 return NULL;
79 return entry_it->second.get();
82 AbortCallback FakeProvidedFileSystem::RequestUnmount(
83 const storage::AsyncFileUtil::StatusCallback& callback) {
84 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
87 AbortCallback FakeProvidedFileSystem::GetMetadata(
88 const base::FilePath& entry_path,
89 ProvidedFileSystemInterface::MetadataFieldMask fields,
90 const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
91 const Entries::const_iterator entry_it = entries_.find(entry_path);
93 if (entry_it == entries_.end()) {
94 return PostAbortableTask(
95 base::Bind(callback,
96 base::Passed(make_scoped_ptr<EntryMetadata>(NULL)),
97 base::File::FILE_ERROR_NOT_FOUND));
100 scoped_ptr<EntryMetadata> metadata(new EntryMetadata);
101 metadata->is_directory = entry_it->second->metadata->is_directory;
102 metadata->name = entry_it->second->metadata->name;
103 metadata->size = entry_it->second->metadata->size;
104 metadata->modification_time = entry_it->second->metadata->modification_time;
105 metadata->mime_type = entry_it->second->metadata->mime_type;
106 metadata->thumbnail = entry_it->second->metadata->thumbnail;
108 return PostAbortableTask(
109 base::Bind(callback, base::Passed(&metadata), base::File::FILE_OK));
112 AbortCallback FakeProvidedFileSystem::ReadDirectory(
113 const base::FilePath& directory_path,
114 const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
115 storage::AsyncFileUtil::EntryList entry_list;
117 for (Entries::const_iterator it = entries_.begin(); it != entries_.end();
118 ++it) {
119 const base::FilePath file_path = it->first;
120 if (file_path == directory_path || directory_path.IsParent(file_path)) {
121 const EntryMetadata* const metadata = it->second->metadata.get();
122 entry_list.push_back(storage::DirectoryEntry(
123 metadata->name,
124 metadata->is_directory ? storage::DirectoryEntry::DIRECTORY
125 : storage::DirectoryEntry::FILE,
126 metadata->size,
127 metadata->modification_time));
131 return PostAbortableTask(base::Bind(
132 callback, base::File::FILE_OK, entry_list, false /* has_more */));
135 AbortCallback FakeProvidedFileSystem::OpenFile(
136 const base::FilePath& entry_path,
137 OpenFileMode mode,
138 const OpenFileCallback& callback) {
139 const Entries::const_iterator entry_it = entries_.find(entry_path);
141 if (entry_it == entries_.end()) {
142 return PostAbortableTask(base::Bind(
143 callback, 0 /* file_handle */, base::File::FILE_ERROR_NOT_FOUND));
146 const int file_handle = ++last_file_handle_;
147 opened_files_[file_handle] = OpenedFile(entry_path, mode);
148 return PostAbortableTask(
149 base::Bind(callback, file_handle, base::File::FILE_OK));
152 AbortCallback FakeProvidedFileSystem::CloseFile(
153 int file_handle,
154 const storage::AsyncFileUtil::StatusCallback& callback) {
155 const auto opened_file_it = opened_files_.find(file_handle);
157 if (opened_file_it == opened_files_.end()) {
158 return PostAbortableTask(
159 base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND));
162 opened_files_.erase(opened_file_it);
163 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
166 AbortCallback FakeProvidedFileSystem::ReadFile(
167 int file_handle,
168 net::IOBuffer* buffer,
169 int64 offset,
170 int length,
171 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
172 const auto opened_file_it = opened_files_.find(file_handle);
174 if (opened_file_it == opened_files_.end() ||
175 opened_file_it->second.file_path.AsUTF8Unsafe() != kFakeFilePath) {
176 return PostAbortableTask(
177 base::Bind(callback,
178 0 /* chunk_length */,
179 false /* has_more */,
180 base::File::FILE_ERROR_INVALID_OPERATION));
183 const Entries::const_iterator entry_it =
184 entries_.find(opened_file_it->second.file_path);
185 if (entry_it == entries_.end()) {
186 return PostAbortableTask(
187 base::Bind(callback,
188 0 /* chunk_length */,
189 false /* has_more */,
190 base::File::FILE_ERROR_INVALID_OPERATION));
193 // Send the response byte by byte.
194 int64 current_offset = offset;
195 int current_length = length;
197 // Reading behind EOF is fine, it will just return 0 bytes.
198 if (current_offset >= entry_it->second->metadata->size || !current_length) {
199 return PostAbortableTask(base::Bind(callback,
200 0 /* chunk_length */,
201 false /* has_more */,
202 base::File::FILE_OK));
205 const FakeEntry* const entry = entry_it->second.get();
206 std::vector<int> task_ids;
207 while (current_offset < entry->metadata->size && current_length) {
208 buffer->data()[current_offset - offset] = entry->contents[current_offset];
209 const bool has_more =
210 (current_offset + 1 < entry->metadata->size) && (current_length - 1);
211 const int task_id =
212 tracker_.PostTask(base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE,
213 base::Bind(callback, 1 /* chunk_length */, has_more,
214 base::File::FILE_OK));
215 task_ids.push_back(task_id);
216 current_offset++;
217 current_length--;
220 return base::Bind(&FakeProvidedFileSystem::AbortMany,
221 weak_ptr_factory_.GetWeakPtr(),
222 task_ids);
225 AbortCallback FakeProvidedFileSystem::CreateDirectory(
226 const base::FilePath& directory_path,
227 bool recursive,
228 const storage::AsyncFileUtil::StatusCallback& callback) {
229 // TODO(mtomasz): Implement it once needed.
230 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
233 AbortCallback FakeProvidedFileSystem::DeleteEntry(
234 const base::FilePath& entry_path,
235 bool recursive,
236 const storage::AsyncFileUtil::StatusCallback& callback) {
237 // TODO(mtomasz): Implement it once needed.
238 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
241 AbortCallback FakeProvidedFileSystem::CreateFile(
242 const base::FilePath& file_path,
243 const storage::AsyncFileUtil::StatusCallback& callback) {
244 const base::File::Error result = file_path.AsUTF8Unsafe() != kFakeFilePath
245 ? base::File::FILE_ERROR_EXISTS
246 : base::File::FILE_OK;
248 return PostAbortableTask(base::Bind(callback, result));
251 AbortCallback FakeProvidedFileSystem::CopyEntry(
252 const base::FilePath& source_path,
253 const base::FilePath& target_path,
254 const storage::AsyncFileUtil::StatusCallback& callback) {
255 // TODO(mtomasz): Implement it once needed.
256 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
259 AbortCallback FakeProvidedFileSystem::MoveEntry(
260 const base::FilePath& source_path,
261 const base::FilePath& target_path,
262 const storage::AsyncFileUtil::StatusCallback& callback) {
263 // TODO(mtomasz): Implement it once needed.
264 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
267 AbortCallback FakeProvidedFileSystem::Truncate(
268 const base::FilePath& file_path,
269 int64 length,
270 const storage::AsyncFileUtil::StatusCallback& callback) {
271 // TODO(mtomasz): Implement it once needed.
272 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
275 AbortCallback FakeProvidedFileSystem::WriteFile(
276 int file_handle,
277 net::IOBuffer* buffer,
278 int64 offset,
279 int length,
280 const storage::AsyncFileUtil::StatusCallback& callback) {
281 const auto opened_file_it = opened_files_.find(file_handle);
283 if (opened_file_it == opened_files_.end() ||
284 opened_file_it->second.file_path.AsUTF8Unsafe() != kFakeFilePath) {
285 return PostAbortableTask(
286 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
289 const Entries::iterator entry_it =
290 entries_.find(opened_file_it->second.file_path);
291 if (entry_it == entries_.end()) {
292 return PostAbortableTask(
293 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
296 FakeEntry* const entry = entry_it->second.get();
297 if (offset > entry->metadata->size) {
298 return PostAbortableTask(
299 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
302 // Allocate the string size in advance.
303 if (offset + length > entry->metadata->size) {
304 entry->metadata->size = offset + length;
305 entry->contents.resize(entry->metadata->size);
308 entry->contents.replace(offset, length, buffer->data(), length);
310 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
313 AbortCallback FakeProvidedFileSystem::AddWatcher(
314 const GURL& origin,
315 const base::FilePath& entry_watcher,
316 bool recursive,
317 bool persistent,
318 const storage::AsyncFileUtil::StatusCallback& callback,
319 const storage::WatcherManager::NotificationCallback&
320 notification_callback) {
321 // TODO(mtomasz): Implement it once needed.
322 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
325 void FakeProvidedFileSystem::RemoveWatcher(
326 const GURL& origin,
327 const base::FilePath& entry_path,
328 bool recursive,
329 const storage::AsyncFileUtil::StatusCallback& callback) {
330 // TODO(mtomasz): Implement it once needed.
331 callback.Run(base::File::FILE_OK);
334 const ProvidedFileSystemInfo& FakeProvidedFileSystem::GetFileSystemInfo()
335 const {
336 return file_system_info_;
339 RequestManager* FakeProvidedFileSystem::GetRequestManager() {
340 NOTREACHED();
341 return NULL;
344 Watchers* FakeProvidedFileSystem::GetWatchers() {
345 return &watchers_;
348 const OpenedFiles& FakeProvidedFileSystem::GetOpenedFiles() const {
349 return opened_files_;
352 void FakeProvidedFileSystem::AddObserver(ProvidedFileSystemObserver* observer) {
353 DCHECK(observer);
354 observers_.AddObserver(observer);
357 void FakeProvidedFileSystem::RemoveObserver(
358 ProvidedFileSystemObserver* observer) {
359 DCHECK(observer);
360 observers_.RemoveObserver(observer);
363 void FakeProvidedFileSystem::Notify(
364 const base::FilePath& entry_path,
365 bool recursive,
366 storage::WatcherManager::ChangeType change_type,
367 scoped_ptr<ProvidedFileSystemObserver::Changes> changes,
368 const std::string& tag,
369 const storage::AsyncFileUtil::StatusCallback& callback) {
370 NOTREACHED();
371 callback.Run(base::File::FILE_ERROR_SECURITY);
374 void FakeProvidedFileSystem::Configure(
375 const storage::AsyncFileUtil::StatusCallback& callback) {
376 NOTREACHED();
377 callback.Run(base::File::FILE_ERROR_SECURITY);
380 ProvidedFileSystemInterface* FakeProvidedFileSystem::Create(
381 Profile* profile,
382 const ProvidedFileSystemInfo& file_system_info) {
383 return new FakeProvidedFileSystem(file_system_info);
386 base::WeakPtr<ProvidedFileSystemInterface>
387 FakeProvidedFileSystem::GetWeakPtr() {
388 return weak_ptr_factory_.GetWeakPtr();
391 AbortCallback FakeProvidedFileSystem::PostAbortableTask(
392 const base::Closure& callback) {
393 const int task_id = tracker_.PostTask(
394 base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, callback);
395 return base::Bind(
396 &FakeProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), task_id);
399 void FakeProvidedFileSystem::Abort(int task_id) {
400 tracker_.TryCancel(task_id);
403 void FakeProvidedFileSystem::AbortMany(const std::vector<int>& task_ids) {
404 for (size_t i = 0; i < task_ids.size(); ++i) {
405 tracker_.TryCancel(task_ids[i]);
409 } // namespace file_system_provider
410 } // namespace chromeos