- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / tests / nacl_io_test / fake_pepper_interface_html5fs.cc
1 // Copyright (c) 2013 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 "fake_pepper_interface_html5fs.h"
6
7 #include <string.h>
8
9 #include <algorithm>
10
11 #include <ppapi/c/pp_completion_callback.h>
12 #include <ppapi/c/pp_errors.h>
13
14 #include "gtest/gtest.h"
15
16 namespace {
17
18 class FakeInstanceResource : public FakeResource {
19  public:
20   FakeInstanceResource() : filesystem_template(NULL) {}
21   static const char* classname() { return "FakeInstanceResource"; }
22
23   FakeHtml5FsFilesystem* filesystem_template;  // Weak reference.
24 };
25
26 class FakeFileSystemResource : public FakeResource {
27  public:
28   FakeFileSystemResource() : filesystem(NULL), opened(false) {}
29   ~FakeFileSystemResource() { delete filesystem; }
30   static const char* classname() { return "FakeFileSystemResource"; }
31
32   FakeHtml5FsFilesystem* filesystem;  // Owned.
33   bool opened;
34 };
35
36 class FakeFileRefResource : public FakeResource {
37  public:
38   FakeFileRefResource() : filesystem(NULL) {}
39   static const char* classname() { return "FakeFileRefResource"; }
40
41   FakeHtml5FsFilesystem* filesystem;  // Weak reference.
42   FakeHtml5FsFilesystem::Path path;
43 };
44
45 class FakeFileIoResource : public FakeResource {
46  public:
47   FakeFileIoResource() : node(NULL), open_flags(0) {}
48   static const char* classname() { return "FakeFileIoResource"; }
49
50   FakeHtml5FsNode* node;  // Weak reference.
51   int32_t open_flags;
52 };
53
54 // Helper function to call the completion callback if it is defined (an
55 // asynchronous call), or return the result directly if it isn't (a synchronous
56 // call).
57 //
58 // Use like this:
59 //   if (<some error condition>)
60 //     return RunCompletionCallback(callback, PP_ERROR_FUBAR);
61 //
62 //   /* Everything worked OK */
63 //   return RunCompletionCallback(callback, PP_OK);
64 int32_t RunCompletionCallback(PP_CompletionCallback* callback, int32_t result) {
65   if (callback->func) {
66     PP_RunCompletionCallback(callback, result);
67     return PP_OK_COMPLETIONPENDING;
68   }
69   return result;
70 }
71
72 }  // namespace
73
74 FakeHtml5FsNode::FakeHtml5FsNode(const PP_FileInfo& info) : info_(info) {}
75
76 FakeHtml5FsNode::FakeHtml5FsNode(const PP_FileInfo& info,
77                                  const std::vector<uint8_t>& contents)
78     : info_(info), contents_(contents) {}
79
80 FakeHtml5FsNode::FakeHtml5FsNode(const PP_FileInfo& info,
81                                  const std::string& contents)
82     : info_(info) {
83   std::copy(contents.begin(), contents.end(), std::back_inserter(contents_));
84 }
85
86 int32_t FakeHtml5FsNode::Read(int64_t offset,
87                               char* buffer,
88                               int32_t bytes_to_read) {
89   if (offset < 0)
90     return PP_ERROR_FAILED;
91
92   bytes_to_read =
93       std::max(0, std::min<int32_t>(bytes_to_read, contents_.size() - offset));
94   memcpy(buffer, contents_.data() + offset, bytes_to_read);
95   return bytes_to_read;
96 }
97
98 int32_t FakeHtml5FsNode::Write(int64_t offset,
99                                const char* buffer,
100                                int32_t bytes_to_write) {
101   if (offset < 0)
102     return PP_ERROR_FAILED;
103
104   size_t new_size = offset + bytes_to_write;
105   if (new_size > contents_.size())
106     contents_.resize(new_size);
107
108   memcpy(contents_.data() + offset, buffer, bytes_to_write);
109   info_.size = new_size;
110   return bytes_to_write;
111 }
112
113 int32_t FakeHtml5FsNode::Append(const char* buffer, int32_t bytes_to_write) {
114   return Write(contents_.size(), buffer, bytes_to_write);
115 }
116
117 int32_t FakeHtml5FsNode::SetLength(int64_t length) {
118   contents_.resize(length);
119   info_.size = length;
120   return PP_OK;
121 }
122
123 void FakeHtml5FsNode::GetInfo(PP_FileInfo* out_info) { *out_info = info_; }
124
125 bool FakeHtml5FsNode::IsRegular() const {
126   return info_.type == PP_FILETYPE_REGULAR;
127 }
128
129 bool FakeHtml5FsNode::IsDirectory() const {
130   return info_.type == PP_FILETYPE_DIRECTORY;
131 }
132
133 FakeHtml5FsFilesystem::FakeHtml5FsFilesystem()
134     : filesystem_type_(PP_FILESYSTEMTYPE_INVALID) {
135   Clear();
136 }
137
138 FakeHtml5FsFilesystem::FakeHtml5FsFilesystem(PP_FileSystemType type)
139     : filesystem_type_(type) {
140   Clear();
141 }
142
143 FakeHtml5FsFilesystem::FakeHtml5FsFilesystem(
144     const FakeHtml5FsFilesystem& filesystem,
145     PP_FileSystemType type)
146     : node_map_(filesystem.node_map_), filesystem_type_(type) {}
147
148 void FakeHtml5FsFilesystem::Clear() {
149   node_map_.clear();
150   // Always have a root node.
151   AddDirectory("/", NULL);
152 }
153
154 bool FakeHtml5FsFilesystem::AddEmptyFile(const Path& path,
155                                          FakeHtml5FsNode** out_node) {
156   return AddFile(path, std::vector<uint8_t>(), out_node);
157 }
158
159 bool FakeHtml5FsFilesystem::AddFile(const Path& path,
160                                     const std::string& contents,
161                                     FakeHtml5FsNode** out_node) {
162   std::vector<uint8_t> data;
163   std::copy(contents.begin(), contents.end(), std::back_inserter(data));
164   return AddFile(path, data, out_node);
165 }
166
167 bool FakeHtml5FsFilesystem::AddFile(const Path& path,
168                                     const std::vector<uint8_t>& contents,
169                                     FakeHtml5FsNode** out_node) {
170   NodeMap::iterator iter = node_map_.find(path);
171   if (iter != node_map_.end()) {
172     if (out_node)
173       *out_node = NULL;
174     return false;
175   }
176
177   PP_FileInfo info;
178   info.size = contents.size();
179   info.type = PP_FILETYPE_REGULAR;
180   info.system_type = filesystem_type_;
181   info.creation_time = 0;
182   info.last_access_time = 0;
183   info.last_modified_time = 0;
184
185   FakeHtml5FsNode node(info, contents);
186   std::pair<NodeMap::iterator, bool> result =
187       node_map_.insert(NodeMap::value_type(path, node));
188
189   EXPECT_EQ(true, result.second);
190   if (out_node)
191     *out_node = &result.first->second;
192   return true;
193 }
194
195 bool FakeHtml5FsFilesystem::AddDirectory(const Path& path,
196                                          FakeHtml5FsNode** out_node) {
197   NodeMap::iterator iter = node_map_.find(path);
198   if (iter != node_map_.end()) {
199     if (out_node)
200       *out_node = NULL;
201     return false;
202   }
203
204   PP_FileInfo info;
205   info.size = 0;
206   info.type = PP_FILETYPE_DIRECTORY;
207   info.system_type = filesystem_type_;
208   info.creation_time = 0;
209   info.last_access_time = 0;
210   info.last_modified_time = 0;
211
212   FakeHtml5FsNode node(info);
213   std::pair<NodeMap::iterator, bool> result =
214       node_map_.insert(NodeMap::value_type(path, node));
215
216   EXPECT_EQ(true, result.second);
217   if (out_node)
218     *out_node = &result.first->second;
219   return true;
220 }
221
222 bool FakeHtml5FsFilesystem::RemoveNode(const Path& path) {
223   return node_map_.erase(path) >= 1;
224 }
225
226 FakeHtml5FsNode* FakeHtml5FsFilesystem::GetNode(const Path& path) {
227   NodeMap::iterator iter = node_map_.find(path);
228   if (iter == node_map_.end())
229     return NULL;
230   return &iter->second;
231 }
232
233 bool FakeHtml5FsFilesystem::GetDirectoryEntries(
234     const Path& path,
235     DirectoryEntries* out_dir_entries) const {
236   out_dir_entries->clear();
237
238   NodeMap::const_iterator iter = node_map_.find(path);
239   if (iter == node_map_.end())
240     return false;
241
242   const FakeHtml5FsNode& dir_node = iter->second;
243   if (!dir_node.IsDirectory())
244     return false;
245
246   for (NodeMap::const_iterator iter = node_map_.begin();
247        iter != node_map_.end();
248        ++iter) {
249     const Path& node_path = iter->first;
250     if (node_path.find(path) == std::string::npos)
251       continue;
252
253     // A node is not a child of itself.
254     if (&iter->second == &dir_node)
255       continue;
256
257     // Only consider children, not descendants. If we find a forward slash, then
258     // the node must be in a subdirectory.
259     if (node_path.find('/', path.size() + 1) != std::string::npos)
260       continue;
261
262     // The directory entry names do not include the path.
263     Path entry_path = node_path;
264     size_t last_slash = node_path.rfind('/');
265     if (last_slash != std::string::npos)
266       entry_path.erase(0, last_slash + 1);
267
268     DirectoryEntry entry;
269     entry.path = entry_path;
270     entry.node = &iter->second;
271     out_dir_entries->push_back(entry);
272   }
273
274   return true;
275 }
276
277 // static
278 FakeHtml5FsFilesystem::Path FakeHtml5FsFilesystem::GetParentPath(
279     const Path& path) {
280   size_t last_slash = path.rfind('/');
281   if (last_slash == 0)
282     return "/";
283
284   EXPECT_EQ(std::string::npos, last_slash);
285   return path.substr(0, last_slash);
286 }
287
288 FakeFileIoInterface::FakeFileIoInterface(FakeCoreInterface* core_interface)
289     : core_interface_(core_interface) {}
290
291 PP_Resource FakeFileIoInterface::Create(PP_Resource) {
292   return CREATE_RESOURCE(core_interface_->resource_manager(),
293                          FakeFileIoResource,
294                          new FakeFileIoResource);
295 }
296
297 int32_t FakeFileIoInterface::Open(PP_Resource file_io,
298                                   PP_Resource file_ref,
299                                   int32_t open_flags,
300                                   PP_CompletionCallback callback) {
301   FakeFileIoResource* file_io_resource =
302       core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io);
303   if (file_io_resource == NULL)
304     return PP_ERROR_BADRESOURCE;
305
306   bool flag_write = !!(open_flags & PP_FILEOPENFLAG_WRITE);
307   bool flag_create = !!(open_flags & PP_FILEOPENFLAG_CREATE);
308   bool flag_truncate = !!(open_flags & PP_FILEOPENFLAG_TRUNCATE);
309   bool flag_exclusive = !!(open_flags & PP_FILEOPENFLAG_EXCLUSIVE);
310   bool flag_append = !!(open_flags & PP_FILEOPENFLAG_APPEND);
311
312   if ((flag_append && flag_write) || (flag_truncate && !flag_write))
313     return PP_ERROR_BADARGUMENT;
314
315   FakeFileRefResource* file_ref_resource =
316       core_interface_->resource_manager()->Get<FakeFileRefResource>(file_ref);
317   if (file_ref_resource == NULL)
318     return PP_ERROR_BADRESOURCE;
319
320   const FakeHtml5FsFilesystem::Path& path = file_ref_resource->path;
321   FakeHtml5FsFilesystem* filesystem = file_ref_resource->filesystem;
322   FakeHtml5FsNode* node = filesystem->GetNode(path);
323   bool node_exists = node != NULL;
324
325   if (!node_exists) {
326     if (!flag_create)
327       return RunCompletionCallback(&callback, PP_ERROR_FILENOTFOUND);
328
329     bool result = filesystem->AddEmptyFile(path, &node);
330     EXPECT_EQ(true, result);
331   } else {
332     if (flag_create && flag_exclusive)
333       return RunCompletionCallback(&callback, PP_ERROR_FILEEXISTS);
334   }
335
336   file_io_resource->node = node;
337   file_io_resource->open_flags = open_flags;
338
339   if (flag_truncate)
340     return RunCompletionCallback(&callback, node->SetLength(0));
341
342   return RunCompletionCallback(&callback, PP_OK);
343 }
344
345 int32_t FakeFileIoInterface::Query(PP_Resource file_io,
346                                    PP_FileInfo* info,
347                                    PP_CompletionCallback callback) {
348   FakeFileIoResource* file_io_resource =
349       core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io);
350   if (file_io_resource == NULL)
351     return PP_ERROR_BADRESOURCE;
352
353   if (!file_io_resource->node)
354     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
355
356   file_io_resource->node->GetInfo(info);
357   return RunCompletionCallback(&callback, PP_OK);
358 }
359
360 int32_t FakeFileIoInterface::Read(PP_Resource file_io,
361                                   int64_t offset,
362                                   char* buffer,
363                                   int32_t bytes_to_read,
364                                   PP_CompletionCallback callback) {
365   FakeFileIoResource* file_io_resource =
366       core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io);
367   if (file_io_resource == NULL)
368     return PP_ERROR_BADRESOURCE;
369
370   if (bytes_to_read < 0)
371     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
372
373   if ((file_io_resource->open_flags & PP_FILEOPENFLAG_READ) !=
374       PP_FILEOPENFLAG_READ) {
375     return RunCompletionCallback(&callback, PP_ERROR_NOACCESS);
376   }
377
378   if (!file_io_resource->node)
379     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
380
381   int32_t result = file_io_resource->node->Read(offset, buffer, bytes_to_read);
382   return RunCompletionCallback(&callback, result);
383 }
384
385 int32_t FakeFileIoInterface::Write(PP_Resource file_io,
386                                    int64_t offset,
387                                    const char* buffer,
388                                    int32_t bytes_to_write,
389                                    PP_CompletionCallback callback) {
390   FakeFileIoResource* file_io_resource =
391       core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io);
392   if (file_io_resource == NULL)
393     return PP_ERROR_BADRESOURCE;
394
395   if ((file_io_resource->open_flags & PP_FILEOPENFLAG_WRITE) !=
396       PP_FILEOPENFLAG_WRITE) {
397     return RunCompletionCallback(&callback, PP_ERROR_NOACCESS);
398   }
399
400   if (!file_io_resource->node)
401     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
402
403   int32_t result;
404   if ((file_io_resource->open_flags & PP_FILEOPENFLAG_APPEND) ==
405       PP_FILEOPENFLAG_APPEND) {
406     result = file_io_resource->node->Append(buffer, bytes_to_write);
407   } else {
408     result = file_io_resource->node->Write(offset, buffer, bytes_to_write);
409   }
410
411   return RunCompletionCallback(&callback, result);
412 }
413
414 int32_t FakeFileIoInterface::SetLength(PP_Resource file_io,
415                                        int64_t length,
416                                        PP_CompletionCallback callback) {
417   FakeFileIoResource* file_io_resource =
418       core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io);
419   if (file_io_resource == NULL)
420     return PP_ERROR_BADRESOURCE;
421
422   if ((file_io_resource->open_flags & PP_FILEOPENFLAG_WRITE) !=
423       PP_FILEOPENFLAG_WRITE) {
424     return RunCompletionCallback(&callback, PP_ERROR_NOACCESS);
425   }
426
427   if (!file_io_resource->node)
428     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
429
430   int32_t result = file_io_resource->node->SetLength(length);
431   return RunCompletionCallback(&callback, result);
432 }
433
434 int32_t FakeFileIoInterface::Flush(PP_Resource file_io,
435                                    PP_CompletionCallback callback) {
436   FakeFileIoResource* file_io_resource =
437       core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io);
438   if (file_io_resource == NULL)
439     return PP_ERROR_BADRESOURCE;
440
441   if (!file_io_resource->node)
442     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
443
444   return RunCompletionCallback(&callback, PP_OK);
445 }
446
447 void FakeFileIoInterface::Close(PP_Resource file_io) {
448   FakeFileIoResource* file_io_resource =
449       core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io);
450   if (file_io_resource == NULL)
451     return;
452
453   file_io_resource->node = NULL;
454   file_io_resource->open_flags = 0;
455 }
456
457 FakeFileRefInterface::FakeFileRefInterface(FakeCoreInterface* core_interface,
458                                            FakeVarInterface* var_interface)
459     : core_interface_(core_interface), var_interface_(var_interface) {}
460
461 PP_Resource FakeFileRefInterface::Create(PP_Resource file_system,
462                                          const char* path) {
463   FakeFileSystemResource* file_system_resource =
464       core_interface_->resource_manager()->Get<FakeFileSystemResource>(
465           file_system);
466   if (file_system_resource == NULL)
467     return PP_ERROR_BADRESOURCE;
468
469   if (!file_system_resource->opened)
470     return PP_ERROR_FAILED;
471
472   if (path == NULL)
473     return PP_ERROR_FAILED;
474
475   size_t path_len = strlen(path);
476   if (path_len == 0)
477     return PP_ERROR_FAILED;
478
479   FakeFileRefResource* file_ref_resource = new FakeFileRefResource;
480   file_ref_resource->filesystem = file_system_resource->filesystem;
481   file_ref_resource->path = path;
482
483   // Remove a trailing slash from the path, unless it is the root path.
484   if (path_len > 1 && file_ref_resource->path[path_len - 1] == '/')
485     file_ref_resource->path.erase(path_len - 1);
486
487   return CREATE_RESOURCE(core_interface_->resource_manager(),
488                          FakeFileRefResource,
489                          file_ref_resource);
490 }
491
492 PP_Var FakeFileRefInterface::GetName(PP_Resource file_ref) {
493   FakeFileRefResource* file_ref_resource =
494       core_interface_->resource_manager()->Get<FakeFileRefResource>(file_ref);
495   if (file_ref_resource == NULL)
496     return PP_MakeUndefined();
497
498   return var_interface_->VarFromUtf8(file_ref_resource->path.c_str(),
499                                      file_ref_resource->path.size());
500 }
501
502 int32_t FakeFileRefInterface::MakeDirectory(PP_Resource directory_ref,
503                                             PP_Bool make_ancestors,
504                                             PP_CompletionCallback callback) {
505   FakeFileRefResource* directory_ref_resource =
506       core_interface_->resource_manager()->Get<FakeFileRefResource>(
507           directory_ref);
508   if (directory_ref_resource == NULL)
509     return PP_ERROR_BADRESOURCE;
510
511   // TODO(binji): We don't currently use make_ancestors==PP_TRUE in nacl_io, so
512   // I won't bother implementing it.
513   if (make_ancestors == PP_TRUE)
514     return PP_ERROR_FAILED;
515
516   FakeHtml5FsFilesystem* filesystem = directory_ref_resource->filesystem;
517   FakeHtml5FsFilesystem::Path path = directory_ref_resource->path;
518
519   // Pepper returns PP_ERROR_NOACCESS when trying to create the root directory,
520   // not PP_ERROR_FILEEXISTS, as you might expect.
521   if (path == "/")
522     return RunCompletionCallback(&callback, PP_ERROR_NOACCESS);
523
524   FakeHtml5FsNode* node = filesystem->GetNode(path);
525   if (node != NULL)
526     return RunCompletionCallback(&callback, PP_ERROR_FILEEXISTS);
527
528   FakeHtml5FsFilesystem::Path parent_path = filesystem->GetParentPath(path);
529   FakeHtml5FsNode* parent_node = filesystem->GetNode(parent_path);
530   if (parent_node == NULL)
531     return RunCompletionCallback(&callback, PP_ERROR_FILENOTFOUND);
532
533   if (!parent_node->IsDirectory())
534     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
535
536   bool result = filesystem->AddDirectory(directory_ref_resource->path, NULL);
537   EXPECT_EQ(true, result);
538   return RunCompletionCallback(&callback, PP_OK);
539 }
540
541 int32_t FakeFileRefInterface::Delete(PP_Resource file_ref,
542                                      PP_CompletionCallback callback) {
543   FakeFileRefResource* file_ref_resource =
544       core_interface_->resource_manager()->Get<FakeFileRefResource>(file_ref);
545   if (file_ref_resource == NULL)
546     return PP_ERROR_BADRESOURCE;
547
548   FakeHtml5FsFilesystem* filesystem = file_ref_resource->filesystem;
549   FakeHtml5FsFilesystem::Path path = file_ref_resource->path;
550   FakeHtml5FsNode* node = filesystem->GetNode(path);
551   if (node == NULL)
552     return RunCompletionCallback(&callback, PP_ERROR_FILENOTFOUND);
553
554   filesystem->RemoveNode(path);
555   return RunCompletionCallback(&callback, PP_OK);
556 }
557
558 int32_t FakeFileRefInterface::Query(PP_Resource file_ref,
559                                     PP_FileInfo* info,
560                                     PP_CompletionCallback callback) {
561   FakeFileRefResource* file_ref_resource =
562       core_interface_->resource_manager()->Get<FakeFileRefResource>(file_ref);
563   if (file_ref_resource == NULL)
564     return PP_ERROR_BADRESOURCE;
565
566   FakeHtml5FsFilesystem* filesystem = file_ref_resource->filesystem;
567   FakeHtml5FsFilesystem::Path path = file_ref_resource->path;
568   FakeHtml5FsNode* node = filesystem->GetNode(path);
569   if (node == NULL)
570     return RunCompletionCallback(&callback, PP_ERROR_FILENOTFOUND);
571
572   node->GetInfo(info);
573   return RunCompletionCallback(&callback, PP_OK);
574 }
575
576 int32_t FakeFileRefInterface::ReadDirectoryEntries(
577     PP_Resource directory_ref,
578     const PP_ArrayOutput& output,
579     PP_CompletionCallback callback) {
580   FakeFileRefResource* directory_ref_resource =
581       core_interface_->resource_manager()->Get<FakeFileRefResource>(
582           directory_ref);
583   if (directory_ref_resource == NULL)
584     return PP_ERROR_BADRESOURCE;
585
586   FakeHtml5FsFilesystem* filesystem = directory_ref_resource->filesystem;
587   FakeHtml5FsFilesystem::Path path = directory_ref_resource->path;
588   FakeHtml5FsNode* node = filesystem->GetNode(path);
589   if (node == NULL)
590     return RunCompletionCallback(&callback, PP_ERROR_FILENOTFOUND);
591
592   if (!node->IsDirectory())
593     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
594
595   FakeHtml5FsFilesystem::DirectoryEntries fake_dir_entries;
596   filesystem->GetDirectoryEntries(path, &fake_dir_entries);
597
598   uint32_t element_count = fake_dir_entries.size();
599   uint32_t element_size = sizeof(fake_dir_entries[0]);
600   void* data_buffer =
601       (*output.GetDataBuffer)(output.user_data, element_count, element_size);
602
603   if (data_buffer == NULL)
604     return RunCompletionCallback(&callback, PP_ERROR_FAILED);
605
606   PP_DirectoryEntry* dir_entries = static_cast<PP_DirectoryEntry*>(data_buffer);
607   for (uint32_t i = 0; i < element_count; ++i) {
608     const FakeHtml5FsFilesystem::DirectoryEntry& fake_dir_entry =
609         fake_dir_entries[i];
610
611     FakeFileRefResource* file_ref_resource = new FakeFileRefResource;
612     file_ref_resource->filesystem = directory_ref_resource->filesystem;
613     file_ref_resource->path = fake_dir_entry.path;
614     PP_Resource file_ref = CREATE_RESOURCE(core_interface_->resource_manager(),
615                                            FakeFileRefResource,
616                                            file_ref_resource);
617
618     dir_entries[i].file_ref = file_ref;
619     dir_entries[i].file_type = fake_dir_entry.node->file_type();
620   }
621
622   return RunCompletionCallback(&callback, PP_OK);
623 }
624
625 FakeFileSystemInterface::FakeFileSystemInterface(
626     FakeCoreInterface* core_interface)
627     : core_interface_(core_interface) {}
628
629 PP_Resource FakeFileSystemInterface::Create(PP_Instance instance,
630                                             PP_FileSystemType filesystem_type) {
631   FakeInstanceResource* instance_resource =
632       core_interface_->resource_manager()->Get<FakeInstanceResource>(instance);
633   if (instance_resource == NULL)
634     return PP_ERROR_BADRESOURCE;
635
636   FakeFileSystemResource* file_system_resource = new FakeFileSystemResource;
637   file_system_resource->filesystem = new FakeHtml5FsFilesystem(
638       *instance_resource->filesystem_template, filesystem_type);
639
640   return CREATE_RESOURCE(core_interface_->resource_manager(),
641                          FakeFileSystemResource,
642                          file_system_resource);
643 }
644
645 int32_t FakeFileSystemInterface::Open(PP_Resource file_system,
646                                       int64_t expected_size,
647                                       PP_CompletionCallback callback) {
648   FakeFileSystemResource* file_system_resource =
649       core_interface_->resource_manager()->Get<FakeFileSystemResource>(
650           file_system);
651   if (file_system_resource == NULL)
652     return PP_ERROR_BADRESOURCE;
653
654   file_system_resource->opened = true;
655   return RunCompletionCallback(&callback, PP_OK);
656 }
657
658 FakePepperInterfaceHtml5Fs::FakePepperInterfaceHtml5Fs()
659     : file_system_interface_(&core_interface_),
660       file_ref_interface_(&core_interface_, &var_interface_),
661       file_io_interface_(&core_interface_) {
662   Init();
663 }
664
665 FakePepperInterfaceHtml5Fs::FakePepperInterfaceHtml5Fs(
666     const FakeHtml5FsFilesystem& filesystem)
667     : filesystem_template_(filesystem),
668       file_system_interface_(&core_interface_),
669       file_ref_interface_(&core_interface_, &var_interface_),
670       file_io_interface_(&core_interface_),
671       instance_(0) {
672   Init();
673 }
674
675 void FakePepperInterfaceHtml5Fs::Init() {
676   FakeInstanceResource* instance_resource = new FakeInstanceResource;
677   instance_resource->filesystem_template = &filesystem_template_;
678
679   instance_ = CREATE_RESOURCE(core_interface_.resource_manager(),
680                               FakeInstanceResource,
681                               instance_resource);
682 }
683
684 FakePepperInterfaceHtml5Fs::~FakePepperInterfaceHtml5Fs() {
685   core_interface_.ReleaseResource(instance_);
686 }
687
688 nacl_io::CoreInterface* FakePepperInterfaceHtml5Fs::GetCoreInterface() {
689   return &core_interface_;
690 }
691
692 nacl_io::FileSystemInterface*
693 FakePepperInterfaceHtml5Fs::GetFileSystemInterface() {
694   return &file_system_interface_;
695 }
696
697 nacl_io::FileRefInterface* FakePepperInterfaceHtml5Fs::GetFileRefInterface() {
698   return &file_ref_interface_;
699 }
700
701 nacl_io::FileIoInterface* FakePepperInterfaceHtml5Fs::GetFileIoInterface() {
702   return &file_io_interface_;
703 }
704
705 nacl_io::VarInterface* FakePepperInterfaceHtml5Fs::GetVarInterface() {
706   return &var_interface_;
707 }