Roll src/third_party/WebKit 8b42d1d:744641d (svn 186770:186771)
[chromium-blink-merge.git] / chrome / browser / chromeos / file_system_provider / fake_provided_file_system.cc
blobcc676f810231c148b820c2eeaab30c12b99d840d
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/files/file.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "net/base/io_buffer.h"
11 namespace chromeos {
12 namespace file_system_provider {
13 namespace {
15 const char kFakeFileName[] = "hello.txt";
16 const char kFakeFileText[] =
17 "This is a testing file. Lorem ipsum dolor sit amet est.";
18 const size_t kFakeFileSize = sizeof(kFakeFileText) - 1u;
19 const char kFakeFileModificationTime[] = "Fri Apr 25 01:47:53 UTC 2014";
20 const char kFakeFileMimeType[] = "text/plain";
22 } // namespace
24 const char kFakeFilePath[] = "/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(
43 base::FilePath::FromUTF8Unsafe("/"), true, "", 0, base::Time(), "", "");
45 base::Time modification_time;
46 DCHECK(base::Time::FromString(kFakeFileModificationTime, &modification_time));
47 AddEntry(base::FilePath::FromUTF8Unsafe(kFakeFilePath),
48 false,
49 kFakeFileName,
50 kFakeFileSize,
51 modification_time,
52 kFakeFileMimeType,
53 kFakeFileText);
56 FakeProvidedFileSystem::~FakeProvidedFileSystem() {}
58 void FakeProvidedFileSystem::AddEntry(const base::FilePath& entry_path,
59 bool is_directory,
60 const std::string& name,
61 int64 size,
62 base::Time modification_time,
63 std::string mime_type,
64 std::string contents) {
65 DCHECK(entries_.find(entry_path) == entries_.end());
66 scoped_ptr<EntryMetadata> metadata(new EntryMetadata);
68 metadata->is_directory = is_directory;
69 metadata->name = name;
70 metadata->size = size;
71 metadata->modification_time = modification_time;
72 metadata->mime_type = mime_type;
74 entries_[entry_path] =
75 make_linked_ptr(new FakeEntry(metadata.Pass(), contents));
78 const FakeEntry* FakeProvidedFileSystem::GetEntry(
79 const base::FilePath& entry_path) const {
80 const Entries::const_iterator entry_it = entries_.find(entry_path);
81 if (entry_it == entries_.end())
82 return NULL;
84 return entry_it->second.get();
87 ProvidedFileSystemInterface::AbortCallback
88 FakeProvidedFileSystem::RequestUnmount(
89 const storage::AsyncFileUtil::StatusCallback& callback) {
90 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
93 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::GetMetadata(
94 const base::FilePath& entry_path,
95 ProvidedFileSystemInterface::MetadataFieldMask fields,
96 const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
97 const Entries::const_iterator entry_it = entries_.find(entry_path);
99 if (entry_it == entries_.end()) {
100 return PostAbortableTask(
101 base::Bind(callback,
102 base::Passed(make_scoped_ptr<EntryMetadata>(NULL)),
103 base::File::FILE_ERROR_NOT_FOUND));
106 scoped_ptr<EntryMetadata> metadata(new EntryMetadata);
107 metadata->is_directory = entry_it->second->metadata->is_directory;
108 metadata->name = entry_it->second->metadata->name;
109 metadata->size = entry_it->second->metadata->size;
110 metadata->modification_time = entry_it->second->metadata->modification_time;
111 metadata->mime_type = entry_it->second->metadata->mime_type;
112 metadata->thumbnail = entry_it->second->metadata->thumbnail;
114 return PostAbortableTask(
115 base::Bind(callback, base::Passed(&metadata), base::File::FILE_OK));
118 ProvidedFileSystemInterface::AbortCallback
119 FakeProvidedFileSystem::ReadDirectory(
120 const base::FilePath& directory_path,
121 const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
122 storage::AsyncFileUtil::EntryList entry_list;
124 for (Entries::const_iterator it = entries_.begin(); it != entries_.end();
125 ++it) {
126 const base::FilePath file_path = it->first;
127 if (file_path == directory_path || directory_path.IsParent(file_path)) {
128 const EntryMetadata* const metadata = it->second->metadata.get();
129 entry_list.push_back(storage::DirectoryEntry(
130 metadata->name,
131 metadata->is_directory ? storage::DirectoryEntry::DIRECTORY
132 : storage::DirectoryEntry::FILE,
133 metadata->size,
134 metadata->modification_time));
138 return PostAbortableTask(base::Bind(
139 callback, base::File::FILE_OK, entry_list, false /* has_more */));
142 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::OpenFile(
143 const base::FilePath& entry_path,
144 OpenFileMode mode,
145 const OpenFileCallback& callback) {
146 const Entries::const_iterator entry_it = entries_.find(entry_path);
148 if (entry_it == entries_.end()) {
149 return PostAbortableTask(base::Bind(
150 callback, 0 /* file_handle */, base::File::FILE_ERROR_NOT_FOUND));
153 const int file_handle = ++last_file_handle_;
154 opened_files_[file_handle] = entry_path;
155 return PostAbortableTask(
156 base::Bind(callback, file_handle, base::File::FILE_OK));
159 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::CloseFile(
160 int file_handle,
161 const storage::AsyncFileUtil::StatusCallback& callback) {
162 const OpenedFilesMap::iterator opened_file_it =
163 opened_files_.find(file_handle);
165 if (opened_file_it == opened_files_.end()) {
166 return PostAbortableTask(
167 base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND));
170 opened_files_.erase(opened_file_it);
171 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
174 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::ReadFile(
175 int file_handle,
176 net::IOBuffer* buffer,
177 int64 offset,
178 int length,
179 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
180 const OpenedFilesMap::iterator opened_file_it =
181 opened_files_.find(file_handle);
183 if (opened_file_it == opened_files_.end() ||
184 opened_file_it->second.AsUTF8Unsafe() != kFakeFilePath) {
185 return PostAbortableTask(
186 base::Bind(callback,
187 0 /* chunk_length */,
188 false /* has_more */,
189 base::File::FILE_ERROR_INVALID_OPERATION));
192 const Entries::const_iterator entry_it =
193 entries_.find(opened_file_it->second);
194 if (entry_it == entries_.end()) {
195 return PostAbortableTask(
196 base::Bind(callback,
197 0 /* chunk_length */,
198 false /* has_more */,
199 base::File::FILE_ERROR_INVALID_OPERATION));
202 // Send the response byte by byte.
203 int64 current_offset = offset;
204 int current_length = length;
206 // Reading behind EOF is fine, it will just return 0 bytes.
207 if (current_offset >= entry_it->second->metadata->size || !current_length) {
208 return PostAbortableTask(base::Bind(callback,
209 0 /* chunk_length */,
210 false /* has_more */,
211 base::File::FILE_OK));
214 const FakeEntry* const entry = entry_it->second.get();
215 std::vector<int> task_ids;
216 while (current_offset < entry->metadata->size && current_length) {
217 buffer->data()[current_offset - offset] = entry->contents[current_offset];
218 const bool has_more =
219 (current_offset + 1 < entry->metadata->size) && (current_length - 1);
220 const int task_id = tracker_.PostTask(
221 base::MessageLoopProxy::current().get(),
222 FROM_HERE,
223 base::Bind(
224 callback, 1 /* chunk_length */, has_more, base::File::FILE_OK));
225 task_ids.push_back(task_id);
226 current_offset++;
227 current_length--;
230 return base::Bind(&FakeProvidedFileSystem::AbortMany,
231 weak_ptr_factory_.GetWeakPtr(),
232 task_ids);
235 ProvidedFileSystemInterface::AbortCallback
236 FakeProvidedFileSystem::CreateDirectory(
237 const base::FilePath& directory_path,
238 bool recursive,
239 const storage::AsyncFileUtil::StatusCallback& callback) {
240 // TODO(mtomasz): Implement it once needed.
241 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
244 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::DeleteEntry(
245 const base::FilePath& entry_path,
246 bool recursive,
247 const storage::AsyncFileUtil::StatusCallback& callback) {
248 // TODO(mtomasz): Implement it once needed.
249 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
252 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::CreateFile(
253 const base::FilePath& file_path,
254 const storage::AsyncFileUtil::StatusCallback& callback) {
255 const base::File::Error result = file_path.AsUTF8Unsafe() != kFakeFilePath
256 ? base::File::FILE_ERROR_EXISTS
257 : base::File::FILE_OK;
259 return PostAbortableTask(base::Bind(callback, result));
262 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::CopyEntry(
263 const base::FilePath& source_path,
264 const base::FilePath& target_path,
265 const storage::AsyncFileUtil::StatusCallback& callback) {
266 // TODO(mtomasz): Implement it once needed.
267 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
270 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::MoveEntry(
271 const base::FilePath& source_path,
272 const base::FilePath& target_path,
273 const storage::AsyncFileUtil::StatusCallback& callback) {
274 // TODO(mtomasz): Implement it once needed.
275 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
278 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::Truncate(
279 const base::FilePath& file_path,
280 int64 length,
281 const storage::AsyncFileUtil::StatusCallback& callback) {
282 // TODO(mtomasz): Implement it once needed.
283 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
286 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::WriteFile(
287 int file_handle,
288 net::IOBuffer* buffer,
289 int64 offset,
290 int length,
291 const storage::AsyncFileUtil::StatusCallback& callback) {
292 const OpenedFilesMap::iterator opened_file_it =
293 opened_files_.find(file_handle);
295 if (opened_file_it == opened_files_.end() ||
296 opened_file_it->second.AsUTF8Unsafe() != kFakeFilePath) {
297 return PostAbortableTask(
298 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
301 const Entries::iterator entry_it = entries_.find(opened_file_it->second);
302 if (entry_it == entries_.end()) {
303 return PostAbortableTask(
304 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
307 FakeEntry* const entry = entry_it->second.get();
308 if (offset > entry->metadata->size) {
309 return PostAbortableTask(
310 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
313 // Allocate the string size in advance.
314 if (offset + length > entry->metadata->size) {
315 entry->metadata->size = offset + length;
316 entry->contents.resize(entry->metadata->size);
319 entry->contents.replace(offset, length, buffer->data(), length);
321 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
324 ProvidedFileSystemInterface::AbortCallback FakeProvidedFileSystem::AddWatcher(
325 const GURL& origin,
326 const base::FilePath& entry_watcher,
327 bool recursive,
328 bool persistent,
329 const storage::AsyncFileUtil::StatusCallback& callback,
330 const storage::WatcherManager::NotificationCallback&
331 notification_callback) {
332 // TODO(mtomasz): Implement it once needed.
333 return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
336 void FakeProvidedFileSystem::RemoveWatcher(
337 const GURL& origin,
338 const base::FilePath& entry_path,
339 bool recursive,
340 const storage::AsyncFileUtil::StatusCallback& callback) {
341 // TODO(mtomasz): Implement it once needed.
342 callback.Run(base::File::FILE_OK);
345 const ProvidedFileSystemInfo& FakeProvidedFileSystem::GetFileSystemInfo()
346 const {
347 return file_system_info_;
350 RequestManager* FakeProvidedFileSystem::GetRequestManager() {
351 NOTREACHED();
352 return NULL;
355 Watchers* FakeProvidedFileSystem::GetWatchers() {
356 return &watchers_;
359 void FakeProvidedFileSystem::AddObserver(ProvidedFileSystemObserver* observer) {
360 DCHECK(observer);
361 observers_.AddObserver(observer);
364 void FakeProvidedFileSystem::RemoveObserver(
365 ProvidedFileSystemObserver* observer) {
366 DCHECK(observer);
367 observers_.RemoveObserver(observer);
370 void FakeProvidedFileSystem::Notify(
371 const base::FilePath& entry_path,
372 bool recursive,
373 storage::WatcherManager::ChangeType change_type,
374 scoped_ptr<ProvidedFileSystemObserver::Changes> changes,
375 const std::string& tag,
376 const storage::AsyncFileUtil::StatusCallback& callback) {
377 NOTREACHED();
378 callback.Run(base::File::FILE_ERROR_SECURITY);
381 ProvidedFileSystemInterface* FakeProvidedFileSystem::Create(
382 Profile* profile,
383 const ProvidedFileSystemInfo& file_system_info) {
384 return new FakeProvidedFileSystem(file_system_info);
387 base::WeakPtr<ProvidedFileSystemInterface>
388 FakeProvidedFileSystem::GetWeakPtr() {
389 return weak_ptr_factory_.GetWeakPtr();
392 ProvidedFileSystemInterface::AbortCallback
393 FakeProvidedFileSystem::PostAbortableTask(const base::Closure& callback) {
394 const int task_id = tracker_.PostTask(
395 base::MessageLoopProxy::current().get(), FROM_HERE, callback);
396 return base::Bind(
397 &FakeProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), task_id);
400 void FakeProvidedFileSystem::Abort(
401 int task_id,
402 const storage::AsyncFileUtil::StatusCallback& callback) {
403 tracker_.TryCancel(task_id);
404 callback.Run(base::File::FILE_OK);
407 void FakeProvidedFileSystem::AbortMany(
408 const std::vector<int>& task_ids,
409 const storage::AsyncFileUtil::StatusCallback& callback) {
410 for (size_t i = 0; i < task_ids.size(); ++i) {
411 tracker_.TryCancel(task_ids[i]);
413 callback.Run(base::File::FILE_OK);
416 } // namespace file_system_provider
417 } // namespace chromeos