OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium OS 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 #ifndef VOLUME_H_ | |
6 #define VOLUME_H_ | |
7 | |
8 #include <pthread.h> | |
9 | |
10 #include "archive.h" | |
11 #include "ppapi/cpp/instance_handle.h" | |
12 #include "ppapi/cpp/var_array_buffer.h" | |
13 #include "ppapi/cpp/var_dictionary.h" | |
14 #include "ppapi/utility/completion_callback_factory.h" | |
15 #include "ppapi/utility/threading/lock.h" | |
16 #include "ppapi/utility/threading/simple_thread.h" | |
17 | |
18 #include "javascript_requestor_interface.h" | |
19 #include "javascript_message_sender_interface.h" | |
20 #include "volume_archive.h" | |
21 | |
22 // A factory that creates VolumeArchive(s). Useful for testing. | |
23 class VolumeArchiveFactoryInterface { | |
24 public: | |
25 virtual ~VolumeArchiveFactoryInterface() {} | |
26 | |
27 // Creates a new VolumeArchive. | |
28 virtual VolumeArchive* Create(VolumeReader* reader) = 0; | |
29 }; | |
30 | |
31 // A factory that creates VolumeReader(s). Useful for testing. | |
32 class VolumeReaderFactoryInterface { | |
33 public: | |
34 virtual ~VolumeReaderFactoryInterface() {} | |
35 | |
36 // Creates a new VolumeReader. Returns NULL if failed. | |
37 // Passes VolumeReader ownership to the implementation of | |
38 // VolumeArchiveInterfaceInterface. | |
39 virtual VolumeReader* Create(int64_t archive_size) = 0; | |
40 }; | |
41 | |
42 // Handles all operations like reading metadata and reading files from a single | |
43 // Volume. | |
44 class Volume { | |
45 public: | |
46 Volume(const pp::InstanceHandle& instance_handle /* Used for workers. */, | |
47 const std::string& file_system_id, | |
48 JavaScriptMessageSenderInterface* message_sender); | |
49 | |
50 // Used by tests to create custom VolumeArchive and VolumeReader objects. | |
51 // VolumeArchiveFactory and VolumeReaderFactory should be allocated with new | |
52 // and the ownership will be passed to Volume on constructing it. | |
53 Volume(const pp::InstanceHandle& instance_handle /* Used for workers. */, | |
54 const std::string& file_system_id, | |
55 JavaScriptMessageSenderInterface* message_sender, | |
56 VolumeArchiveFactoryInterface* volume_archive_factory, | |
57 VolumeReaderFactoryInterface* volume_reader_factory); | |
58 | |
59 virtual ~Volume(); | |
60 | |
61 // Initializes the volume. | |
62 bool Init(); | |
63 | |
64 // Reads archive metadata using libarchive. | |
65 void ReadMetadata(const std::string& request_id, | |
66 const std::string& encoding, | |
67 int64_t archive_size); | |
68 | |
69 // Processes a successful archive chunk read from JavaScript. Read offset | |
70 // represents the offset from where the data contained in array_buffer starts. | |
71 void ReadChunkDone(const std::string& nacl_request_id, | |
72 const pp::VarArrayBuffer& array_buffer, | |
73 int64_t read_offset); | |
74 | |
75 // Processes an invalid archive chunk read from JavaScript. | |
76 void ReadChunkError(const std::string& nacl_request_id); | |
77 | |
78 // Processes a successful passphrase read from JavaScript. | |
79 void ReadPassphraseDone(const std::string& nacl_request_id, | |
80 const std::string& passphrase); | |
81 | |
82 // Processes an error when requesting a passphrase from JavaScript. | |
83 void ReadPassphraseError(const std::string& nacl_request_id); | |
84 | |
85 // Opens a file. | |
86 void OpenFile(const std::string& request_id, | |
87 int64_t index, | |
88 const std::string& encoding, | |
89 int64_t archive_size); | |
90 | |
91 // Closes a file. | |
92 void CloseFile(const std::string& request_id, | |
93 const std::string& open_request_id); | |
94 | |
95 // Reads a file contents from offset to offset + length. dictionary | |
96 // should contain the open_request_id, the offset and the length with | |
97 // the keys as defined in "request" namespace, and they should have | |
98 // valid types. The reason for not passing them directly is that | |
99 // pp::CompletionCallbackFactory can create a callback with a maximum of | |
100 // 3 parameters, not 4 as needed here (including request_id). | |
101 void ReadFile(const std::string& request_id, | |
102 const pp::VarDictionary& dictionary); | |
103 | |
104 JavaScriptMessageSenderInterface* message_sender() { return message_sender_; } | |
105 JavaScriptRequestorInterface* requestor() { return requestor_; } | |
106 std::string file_system_id() { return file_system_id_; } | |
107 | |
108 private: | |
109 // Encapsulates arguments to OpenFileCallback, as NewCallback supports binding | |
110 // up to three arguments, while here we have four. | |
111 struct OpenFileArgs; | |
112 | |
113 // A callback helper for ReadMetadata. | |
114 void ReadMetadataCallback(int32_t result, | |
115 const std::string& request_id, | |
116 const std::string& encoding, | |
117 int64_t archive_size); | |
118 | |
119 // A calback helper for OpenFile. | |
120 void OpenFileCallback(int32_t result, | |
121 const OpenFileArgs& args); | |
122 | |
123 // A callback helper for CloseFile. | |
124 void CloseFileCallback(int32_t result, | |
125 const std::string& request_id, | |
126 const std::string& open_request_id); | |
127 | |
128 // A calback helper for ReadFile. | |
129 void ReadFileCallback(int32_t result, | |
130 const std::string& request_id, | |
131 const pp::VarDictionary& dictionary); | |
132 | |
133 // Creates a new archive object for this volume. | |
134 VolumeArchive* CreateVolumeArchive(const std::string& request_id, | |
135 const std::string& encoding, | |
136 int64_t archive_size); | |
137 | |
138 // Clears job. | |
139 void ClearJob(); | |
140 | |
141 // Libarchive wrapper instance per volume, shared across all operations. | |
142 VolumeArchive* volume_archive_; | |
143 | |
144 // The file system id for this volume. | |
145 std::string file_system_id_; | |
146 | |
147 // An object that sends messages to JavaScript. | |
148 JavaScriptMessageSenderInterface* message_sender_; | |
149 | |
150 // A worker for jobs that require blocking operations or a lot of processing | |
151 // time. Those shouldn't be done on the main thread. The jobs submitted to | |
152 // this thread are executed in order, so a new job must wait for the last job | |
153 // to finish. | |
154 // TODO(cmihail): Consider using multiple workers in case of many jobs to | |
155 // improve execution speedup. In case multiple workers are added | |
156 // synchronization between workers might be needed. | |
157 pp::SimpleThread worker_; | |
158 | |
159 // Callback factory used to submit jobs to worker_. | |
160 // See "Detailed Description" Note at: | |
161 // https://developer.chrome.com/native-client/ | |
162 // pepper_dev/cpp/classpp_1_1_completion_callback_factory | |
163 // | |
164 // As a minus this would require ugly synchronization between the main thread | |
165 // and the function that is executed on worker_ construction. Current | |
166 // implementation is simimlar to examples in $NACL_SDK_ROOT and according to | |
167 // https://chromiumcodereview.appspot.com/lint_patch/issue10790078_24001_25013 | |
168 // it should be safe (see TODO(dmichael)). That's because both worker_ and | |
169 // callback_factory_ will be alive during the life of Volume and deleting a | |
170 // Volume is permitted only if there are no requests in progress on | |
171 // JavaScript side (this means no Callbacks in progress). | |
172 pp::CompletionCallbackFactory<Volume> callback_factory_; | |
173 | |
174 // Request ID of the current reader instance. | |
175 std::string reader_request_id_; | |
176 | |
177 pp::Lock job_lock_; // A lock for guarding members related to jobs. | |
178 | |
179 // A requestor for making calls to JavaScript. | |
180 JavaScriptRequestorInterface* requestor_; | |
181 | |
182 // A factory for creating VolumeArchive. | |
183 VolumeArchiveFactoryInterface* volume_archive_factory_; | |
184 | |
185 // A factory for creating VolumeReader. | |
186 VolumeReaderFactoryInterface* volume_reader_factory_; | |
187 }; | |
188 | |
189 #endif /// VOLUME_H_ | |
OLD | NEW |