1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// found in the LICENSE file.
4a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include <string>
6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
7a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/c/ppb_file_io.h"
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/cpp/file_io.h"
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/cpp/file_ref.h"
10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/cpp/file_system.h"
11a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/cpp/instance.h"
12a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/cpp/module.h"
13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/cpp/var.h"
14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/cpp/var_dictionary.h"
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ppapi/tests/test_utils.h"
16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/// The Instance class. Receives the file through HandleMessage(), and returns
18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/// data to the plugin with PostMessage().
19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass FilePassingInstance : public pp::Instance {
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch public:
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  /// The constructor creates the plugin-side instance.
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  /// @param[in] instance the handle to the browser-side plugin instance.
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  explicit FilePassingInstance(PP_Instance instance);
24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual ~FilePassingInstance();
25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch private:
29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  /// Handler for messages coming in from the browser via postMessage().
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  /// @param[in] var_message The message posted by the browser.
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual void HandleMessage(const pp::Var& var_message);
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  /// Takes a fileEntry-dictionary message received from JavaScript and converts
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  /// it into a pp::FileRef. On failure, returns a null FileRef.
35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::FileRef ParseMessage(const pp::Var& var_message, std::string* test_type);
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  void TestRead(pp::FileRef file_ref);
38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  void TestWrite(pp::FileRef file_ref);
39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
41a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochFilePassingInstance::FilePassingInstance(PP_Instance instance)
42a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : pp::Instance(instance) {}
43a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
44a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochFilePassingInstance::~FilePassingInstance() {}
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool FilePassingInstance::Init(uint32_t argc,
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                               const char* argn[],
48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                               const char* argv[]) {
49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("ready");
50a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return true;
51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochpp::FileRef FilePassingInstance::ParseMessage(const pp::Var& var_message,
54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                              std::string* test_type) {
55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!var_message.is_dictionary()) {
56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("Message was not a dictionary.");
57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return pp::FileRef();
58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::VarDictionary var_dictionary_message(var_message);
60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::Var var_filesystem = var_dictionary_message.Get("filesystem");
61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::Var var_fullpath = var_dictionary_message.Get("fullPath");
62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::Var var_testtype = var_dictionary_message.Get("testType");
63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!var_filesystem.is_resource()) {
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("Filesystem was missing or not a resource.");
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return pp::FileRef();
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::Resource resource_filesystem = var_filesystem.AsResource();
69a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!var_fullpath.is_string()) {
70a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("FullPath was missing or not a string.");
71a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return pp::FileRef();
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::string fullpath = var_fullpath.AsString();
74a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!var_testtype.is_string()) {
75a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("TestType was missing or not a string.");
76a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return pp::FileRef();
77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::string name_of_test = var_testtype.AsString();
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pp::FileSystem::IsFileSystem(resource_filesystem)) {
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("Filesystem was not a file system.");
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return pp::FileRef();
83a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
84a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  *test_type = name_of_test;
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::FileSystem filesystem(resource_filesystem);
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Note: The filesystem is already open (there is no need to call Open again).
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return pp::FileRef(filesystem, fullpath.c_str());
90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid FilePassingInstance::HandleMessage(const pp::Var& var_message) {
93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Extract the filesystem and fullPath from the message.
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::string test_type;
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::FileRef file_ref = ParseMessage(var_message, &test_type);
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (file_ref.is_null())
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (test_type == "read_test") {
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    TestRead(file_ref);
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else if (test_type == "write_test") {
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    TestWrite(file_ref);
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else {
104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("Unknown test type");
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid FilePassingInstance::TestRead(pp::FileRef file_ref) {
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::FileIO file_io(pp::InstanceHandle(this));
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  {
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    TestCompletionCallback callback(pp_instance(), PP_REQUIRED);
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    callback.WaitForResult(
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        file_io.Open(file_ref, PP_FILEOPENFLAG_READ, callback.GetCallback()));
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (callback.result() != PP_OK) {
116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      PostMessage("Could not open file");
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      return;
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  {
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    TestCompletionCallbackWithOutput<std::vector<char> > callback(pp_instance(),
122a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                                                  PP_REQUIRED);
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    callback.WaitForResult(
124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        file_io.Read(0, 1024, callback.GetCallback()));
125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (callback.result() < 0) {
126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      PostMessage("Could not read file");
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      return;
128a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (callback.output().size() != 306) {
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      PostMessage("Read the wrong number of bytes");
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      return;
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PostMessage("read_success");
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid FilePassingInstance::TestWrite(pp::FileRef file_ref) {
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  pp::FileIO file_io(pp::InstanceHandle(this));
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  TestCompletionCallback callback(pp_instance(), PP_REQUIRED);
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  callback.WaitForResult(
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE, callback.GetCallback()));
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (callback.result() != PP_ERROR_NOACCESS) {
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    PostMessage("Opening for write should have failed");
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PostMessage("write_success");
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass FilePassingModule : public pp::Module {
151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch public:
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  FilePassingModule() : pp::Module() {}
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual ~FilePassingModule() {}
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual pp::Instance* CreateInstance(PP_Instance instance) {
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return new FilePassingInstance(instance);
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace pp {
161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
162a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochModule* CreateModule() {
163a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return new FilePassingModule();
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace pp
167