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