Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_system_provider / fake_provided_file_system.cc
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 "base/files/file.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "net/base/io_buffer.h"
10
11 namespace chromeos {
12 namespace file_system_provider {
13 namespace {
14
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";
21
22 }  // namespace
23
24 const char kFakeFilePath[] = "/hello.txt";
25
26 FakeEntry::FakeEntry() {
27 }
28
29 FakeEntry::FakeEntry(scoped_ptr<EntryMetadata> metadata,
30                      const std::string& contents)
31     : metadata(metadata.Pass()), contents(contents) {
32 }
33
34 FakeEntry::~FakeEntry() {
35 }
36
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(), "", "");
44
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);
54 }
55
56 FakeProvidedFileSystem::~FakeProvidedFileSystem() {}
57
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);
67
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;
73
74   entries_[entry_path] =
75       make_linked_ptr(new FakeEntry(metadata.Pass(), contents));
76 }
77
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;
83
84   return entry_it->second.get();
85 }
86
87 ProvidedFileSystemInterface::AbortCallback
88 FakeProvidedFileSystem::RequestUnmount(
89     const storage::AsyncFileUtil::StatusCallback& callback) {
90   return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
91 }
92
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);
98
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));
104   }
105
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;
113
114   return PostAbortableTask(
115       base::Bind(callback, base::Passed(&metadata), base::File::FILE_OK));
116 }
117
118 ProvidedFileSystemInterface::AbortCallback
119 FakeProvidedFileSystem::ReadDirectory(
120     const base::FilePath& directory_path,
121     const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
122   storage::AsyncFileUtil::EntryList entry_list;
123
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));
135     }
136   }
137
138   return PostAbortableTask(base::Bind(
139       callback, base::File::FILE_OK, entry_list, false /* has_more */));
140 }
141
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);
147
148   if (entry_it == entries_.end()) {
149     return PostAbortableTask(base::Bind(
150         callback, 0 /* file_handle */, base::File::FILE_ERROR_NOT_FOUND));
151   }
152
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));
157 }
158
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);
164
165   if (opened_file_it == opened_files_.end()) {
166     return PostAbortableTask(
167         base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND));
168   }
169
170   opened_files_.erase(opened_file_it);
171   return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
172 }
173
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);
182
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));
190   }
191
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));
200   }
201
202   // Send the response byte by byte.
203   int64 current_offset = offset;
204   int current_length = length;
205
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));
212   }
213
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--;
228   }
229
230   return base::Bind(&FakeProvidedFileSystem::AbortMany,
231                     weak_ptr_factory_.GetWeakPtr(),
232                     task_ids);
233 }
234
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));
242 }
243
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));
250 }
251
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;
258
259   return PostAbortableTask(base::Bind(callback, result));
260 }
261
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));
268 }
269
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));
276 }
277
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));
284 }
285
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);
294
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));
299   }
300
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));
305   }
306
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));
311   }
312
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);
317   }
318
319   entry->contents.replace(offset, length, buffer->data(), length);
320
321   return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
322 }
323
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));
334 }
335
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);
343 }
344
345 const ProvidedFileSystemInfo& FakeProvidedFileSystem::GetFileSystemInfo()
346     const {
347   return file_system_info_;
348 }
349
350 RequestManager* FakeProvidedFileSystem::GetRequestManager() {
351   NOTREACHED();
352   return NULL;
353 }
354
355 Watchers* FakeProvidedFileSystem::GetWatchers() {
356   return &watchers_;
357 }
358
359 void FakeProvidedFileSystem::AddObserver(ProvidedFileSystemObserver* observer) {
360   DCHECK(observer);
361   observers_.AddObserver(observer);
362 }
363
364 void FakeProvidedFileSystem::RemoveObserver(
365     ProvidedFileSystemObserver* observer) {
366   DCHECK(observer);
367   observers_.RemoveObserver(observer);
368 }
369
370 bool 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   NOTREACHED();
377   return false;
378 }
379
380 ProvidedFileSystemInterface* FakeProvidedFileSystem::Create(
381     Profile* profile,
382     const ProvidedFileSystemInfo& file_system_info) {
383   return new FakeProvidedFileSystem(file_system_info);
384 }
385
386 base::WeakPtr<ProvidedFileSystemInterface>
387 FakeProvidedFileSystem::GetWeakPtr() {
388   return weak_ptr_factory_.GetWeakPtr();
389 }
390
391 ProvidedFileSystemInterface::AbortCallback
392 FakeProvidedFileSystem::PostAbortableTask(const base::Closure& callback) {
393   const int task_id = tracker_.PostTask(
394       base::MessageLoopProxy::current().get(), FROM_HERE, callback);
395   return base::Bind(
396       &FakeProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), task_id);
397 }
398
399 void FakeProvidedFileSystem::Abort(
400     int task_id,
401     const storage::AsyncFileUtil::StatusCallback& callback) {
402   tracker_.TryCancel(task_id);
403   callback.Run(base::File::FILE_OK);
404 }
405
406 void FakeProvidedFileSystem::AbortMany(
407     const std::vector<int>& task_ids,
408     const storage::AsyncFileUtil::StatusCallback& callback) {
409   for (size_t i = 0; i < task_ids.size(); ++i) {
410     tracker_.TryCancel(task_ids[i]);
411   }
412   callback.Run(base::File::FILE_OK);
413 }
414
415 }  // namespace file_system_provider
416 }  // namespace chromeos