Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/FileSystemJsObject.cpp

Issue 29449592: Issue 5183 - Provide async interface for FileSystem (Closed) Base URL: https://hg.adblockplus.org/libadblockplus/
Patch Set: Make read write deal with binary buffers. Created July 6, 2017, 12:19 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include <AdblockPlus/FileSystem.h> 18 #include <AdblockPlus/FileSystem.h>
19 #include <stdexcept> 19 #include <stdexcept>
20 #include <sstream> 20 #include <sstream>
21 #include <vector> 21 #include <vector>
22 22
23 #include <AdblockPlus/JsValue.h> 23 #include <AdblockPlus/JsValue.h>
24 #include "FileSystemJsObject.h" 24 #include "FileSystemJsObject.h"
25 #include "JsContext.h" 25 #include "JsContext.h"
26 #include "Thread.h"
27 #include "Utils.h" 26 #include "Utils.h"
28 27
29 using namespace AdblockPlus; 28 using namespace AdblockPlus;
30 using AdblockPlus::Utils::ThrowExceptionInJS; 29 using AdblockPlus::Utils::ThrowExceptionInJS;
31 30
32 namespace 31 namespace
33 { 32 {
34 class IoThread : public Thread
35 {
36 public:
37 IoThread(const JsEnginePtr& jsEngine, const JsValue& callback)
38 : Thread(true), jsEngine(jsEngine), fileSystem(jsEngine->GetFileSystem()),
39 callback(callback)
40 {
41 }
42
43 protected:
44 JsEnginePtr jsEngine;
45 FileSystemPtr fileSystem;
46 JsValue callback;
47 };
48
49 class ReadThread : public IoThread
50 {
51 public:
52 ReadThread(const JsEnginePtr& jsEngine, const JsValue& callback,
53 const std::string& path)
54 : IoThread(jsEngine, callback), path(path)
55 {
56 }
57
58 void Run()
59 {
60 std::string content;
61 std::string error;
62 try
63 {
64 std::shared_ptr<std::istream> stream = fileSystem->Read(path);
65 content = Utils::Slurp(*stream);
66 }
67 catch (std::exception& e)
68 {
69 error = e.what();
70 }
71 catch (...)
72 {
73 error = "Unknown error while reading from " + path;
74 }
75
76 const JsContext context(*jsEngine);
77 auto result = jsEngine->NewObject();
78 result.SetProperty("content", content);
79 result.SetProperty("error", error);
80 JsValueList params;
81 params.push_back(result);
82 callback.Call(params);
83 }
84
85 private:
86 std::string path;
87 };
88
89 class WriteThread : public IoThread
90 {
91 public:
92 WriteThread(const JsEnginePtr& jsEngine, const JsValue& callback,
93 const std::string& path, const std::string& content)
94 : IoThread(jsEngine, callback), path(path), content(content)
95 {
96 }
97
98 void Run()
99 {
100 std::string error;
101 try
102 {
103 std::stringstream stream;
104 stream << content;
105 fileSystem->Write(path, stream);
106 }
107 catch (std::exception& e)
108 {
109 error = e.what();
110 }
111 catch (...)
112 {
113 error = "Unknown error while writing to " + path;
114 }
115
116 const JsContext context(*jsEngine);
117 auto errorValue = jsEngine->NewValue(error);
118 JsValueList params;
119 params.push_back(errorValue);
120 callback.Call(params);
121 }
122
123 private:
124 std::string path;
125 std::string content;
126 };
127
128 class MoveThread : public IoThread
129 {
130 public:
131 MoveThread(const JsEnginePtr& jsEngine, const JsValue& callback,
132 const std::string& fromPath, const std::string& toPath)
133 : IoThread(jsEngine, callback), fromPath(fromPath), toPath(toPath)
134 {
135 }
136
137 void Run()
138 {
139 std::string error;
140 try
141 {
142 fileSystem->Move(fromPath, toPath);
143 }
144 catch (std::exception& e)
145 {
146 error = e.what();
147 }
148 catch (...)
149 {
150 error = "Unknown error while moving " + fromPath + " to " + toPath;
151 }
152
153 const JsContext context(*jsEngine);
154 auto errorValue = jsEngine->NewValue(error);
155 JsValueList params;
156 params.push_back(errorValue);
157 callback.Call(params);
158 }
159
160 private:
161 std::string fromPath;
162 std::string toPath;
163 };
164
165 class RemoveThread : public IoThread
166 {
167 public:
168 RemoveThread(const JsEnginePtr& jsEngine, const JsValue& callback,
169 const std::string& path)
170 : IoThread(jsEngine, callback), path(path)
171 {
172 }
173
174 void Run()
175 {
176 std::string error;
177 try
178 {
179 fileSystem->Remove(path);
180 }
181 catch (std::exception& e)
182 {
183 error = e.what();
184 }
185 catch (...)
186 {
187 error = "Unknown error while removing " + path;
188 }
189
190 const JsContext context(*jsEngine);
191 auto errorValue = jsEngine->NewValue(error);
192 JsValueList params;
193 params.push_back(errorValue);
194 callback.Call(params);
195 }
196
197 private:
198 std::string path;
199 };
200
201
202 class StatThread : public IoThread
203 {
204 public:
205 StatThread(const JsEnginePtr& jsEngine, const JsValue& callback,
206 const std::string& path)
207 : IoThread(jsEngine, callback), path(path)
208 {
209 }
210
211 void Run()
212 {
213 std::string error;
214 FileSystem::StatResult statResult;
215 try
216 {
217 statResult = fileSystem->Stat(path);
218 }
219 catch (std::exception& e)
220 {
221 error = e.what();
222 }
223 catch (...)
224 {
225 error = "Unknown error while calling stat on " + path;
226 }
227
228 const JsContext context(*jsEngine);
229 auto result = jsEngine->NewObject();
230 result.SetProperty("exists", statResult.exists);
231 result.SetProperty("isFile", statResult.isFile);
232 result.SetProperty("isDirectory", statResult.isDirectory);
233 result.SetProperty("lastModified", statResult.lastModified);
234 result.SetProperty("error", error);
235
236 JsValueList params;
237 params.push_back(result);
238 callback.Call(params);
239 }
240
241 private:
242 std::string path;
243 };
244
245 void ReadCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 33 void ReadCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
246 { 34 {
247 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 35 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
248 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 36 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
249 37
250 v8::Isolate* isolate = arguments.GetIsolate(); 38 v8::Isolate* isolate = arguments.GetIsolate();
251 if (converted.size() != 2) 39 if (converted.size() != 2)
252 return ThrowExceptionInJS(isolate, "_fileSystem.read requires 2 parameters "); 40 return ThrowExceptionInJS(isolate, "_fileSystem.read requires 2 parameters ");
253 if (!converted[1].IsFunction()) 41 if (!converted[1].IsFunction())
254 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.read mu st be a function"); 42 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.read mu st be a function");
255 ReadThread* const readThread = new ReadThread(jsEngine, converted[1], 43
256 converted[0].AsString()); 44 JsValueList values;
257 readThread->Start(); 45 values.push_back(converted[1]);
46 auto weakCallback = jsEngine->StoreJsValues(values);
47 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
48 jsEngine->GetAsyncFileSystem()->Read(converted[0].AsString(),
49 [weakJsEngine, weakCallback]
50 (std::vector<char>&& content, const std::string& error)
51 {
52 auto jsEngine = weakJsEngine.lock();
53 if (!jsEngine)
54 return;
55
56 const JsContext context(*jsEngine);
57 auto result = jsEngine->NewObject();
58 result.SetProperty("content", std::move(content));
59 if (!error.empty())
60 result.SetProperty("error", error);
61 jsEngine->TakeJsValues(weakCallback)[0].Call(result);
62 });
258 } 63 }
259 64
260 void WriteCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 65 void WriteCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
261 { 66 {
262 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 67 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
263 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 68 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
264 69
265 v8::Isolate* isolate = arguments.GetIsolate(); 70 v8::Isolate* isolate = arguments.GetIsolate();
266 if (converted.size() != 3) 71 if (converted.size() != 3)
267 return ThrowExceptionInJS(isolate, "_fileSystem.write requires 3 parameter s"); 72 return ThrowExceptionInJS(isolate, "_fileSystem.write requires 3 parameter s");
268 if (!converted[2].IsFunction()) 73 if (!converted[2].IsFunction())
269 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.write mu st be a function"); 74 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.write mu st be a function");
270 WriteThread* const writeThread = new WriteThread(jsEngine, converted[2], 75
271 converted[0].AsString(), converted[1].AsString()); 76 JsValueList values;
272 writeThread->Start(); 77 values.push_back(converted[2]);
78 auto weakCallback = jsEngine->StoreJsValues(values);
79 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
80 auto content = converted[1].AsBuffer();
81 jsEngine->GetAsyncFileSystem()->Write(converted[0].AsString(),
82 content,
83 [weakJsEngine, weakCallback](const std::string& error)
84 {
85 auto jsEngine = weakJsEngine.lock();
86 if (!jsEngine)
87 return;
88
89 const JsContext context(*jsEngine);
90 JsValueList params;
91 if (!error.empty())
92 params.push_back(jsEngine->NewValue(error));
93 jsEngine->TakeJsValues(weakCallback)[0].Call(params);
94 });
273 } 95 }
274 96
275 void MoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 97 void MoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
276 { 98 {
277 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 99 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
278 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 100 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
279 101
280 v8::Isolate* isolate = arguments.GetIsolate(); 102 v8::Isolate* isolate = arguments.GetIsolate();
281 if (converted.size() != 3) 103 if (converted.size() != 3)
282 return ThrowExceptionInJS(isolate, "_fileSystem.move requires 3 parameters "); 104 return ThrowExceptionInJS(isolate, "_fileSystem.move requires 3 parameters ");
283 if (!converted[2].IsFunction()) 105 if (!converted[2].IsFunction())
284 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.move mus t be a function"); 106 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.move mus t be a function");
285 MoveThread* const moveThread = new MoveThread(jsEngine, converted[2], 107
286 converted[0].AsString(), converted[1].AsString()); 108 JsValueList values;
287 moveThread->Start(); 109 values.push_back(converted[2]);
110 auto weakCallback = jsEngine->StoreJsValues(values);
111 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
112 jsEngine->GetAsyncFileSystem()->Move(converted[0].AsString(),
113 converted[1].AsString(),
114 [weakJsEngine, weakCallback](const std::string& error)
115 {
116 auto jsEngine = weakJsEngine.lock();
117 if (!jsEngine)
118 return;
119
120 const JsContext context(*jsEngine);
121 JsValueList params;
122 if (!error.empty())
123 params.push_back(jsEngine->NewValue(error));
124 jsEngine->TakeJsValues(weakCallback)[0].Call(params);
125 });
288 } 126 }
289 127
290 void RemoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 128 void RemoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
291 { 129 {
292 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 130 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
293 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 131 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
294 132
295 v8::Isolate* isolate = arguments.GetIsolate(); 133 v8::Isolate* isolate = arguments.GetIsolate();
296 if (converted.size() != 2) 134 if (converted.size() != 2)
297 return ThrowExceptionInJS(isolate, "_fileSystem.remove requires 2 paramete rs"); 135 return ThrowExceptionInJS(isolate, "_fileSystem.remove requires 2 paramete rs");
298 if (!converted[1].IsFunction()) 136 if (!converted[1].IsFunction())
299 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.remove must be a function"); 137 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.remove must be a function");
300 RemoveThread* const removeThread = new RemoveThread(jsEngine, converted[1], 138
301 converted[0].AsString()); 139 JsValueList values;
302 removeThread->Start(); 140 values.push_back(converted[1]);
141 auto weakCallback = jsEngine->StoreJsValues(values);
142 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
143 jsEngine->GetAsyncFileSystem()->Remove(converted[0].AsString(),
144 [weakJsEngine, weakCallback](const std::string& error)
145 {
146 auto jsEngine = weakJsEngine.lock();
147 if (!jsEngine)
148 return;
149
150 const JsContext context(*jsEngine);
151 JsValueList params;
152 if (!error.empty())
153 params.push_back(jsEngine->NewValue(error));
154 jsEngine->TakeJsValues(weakCallback)[0].Call(params);
155 });
303 } 156 }
304 157
305 void StatCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 158 void StatCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
306 { 159 {
307 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 160 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
308 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 161 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
309 162
310 v8::Isolate* isolate = arguments.GetIsolate(); 163 v8::Isolate* isolate = arguments.GetIsolate();
311 if (converted.size() != 2) 164 if (converted.size() != 2)
312 return ThrowExceptionInJS(isolate, "_fileSystem.stat requires 2 parameters "); 165 return ThrowExceptionInJS(isolate, "_fileSystem.stat requires 2 parameters ");
313 if (!converted[1].IsFunction()) 166 if (!converted[1].IsFunction())
314 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.stat mu st be a function"); 167 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.stat mu st be a function");
315 StatThread* const statThread = new StatThread(jsEngine, converted[1], 168
316 converted[0].AsString()); 169 JsValueList values;
317 statThread->Start(); 170 values.push_back(converted[1]);
171 auto weakCallback = jsEngine->StoreJsValues(values);
172 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
173 jsEngine->GetAsyncFileSystem()->Stat(converted[0].AsString(),
174 [weakJsEngine, weakCallback]
175 (const IFileSystem::StatResult& statResult, const std::string& error)
176 {
177 auto jsEngine = weakJsEngine.lock();
178 if (!jsEngine)
179 return;
180
181 const JsContext context(*jsEngine);
182 auto result = jsEngine->NewObject();
183
184 result.SetProperty("exists", statResult.exists);
185 result.SetProperty("isFile", statResult.isFile);
186 result.SetProperty("isDirectory", statResult.isDirectory);
187 result.SetProperty("lastModified", statResult.lastModified);
188 if (!error.empty())
189 result.SetProperty("error", error);
190
191 JsValueList params;
192 params.push_back(result);
193 jsEngine->TakeJsValues(weakCallback)[0].Call(params);
194 });
318 } 195 }
319 196
320 void ResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 197 void ResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
321 { 198 {
322 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 199 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
323 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 200 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
324 201
325 v8::Isolate* isolate = arguments.GetIsolate(); 202 v8::Isolate* isolate = arguments.GetIsolate();
326 if (converted.size() != 1) 203 if (converted.size() != 1)
327 return ThrowExceptionInJS(isolate, "_fileSystem.resolve requires 1 paramet er"); 204 return ThrowExceptionInJS(isolate, "_fileSystem.resolve requires 1 paramet er");
328 205
329 std::string resolved = jsEngine->GetFileSystem()->Resolve(converted[0].AsStr ing()); 206 std::string resolved = jsEngine->GetAsyncFileSystem()->Resolve(converted[0]. AsString());
330 arguments.GetReturnValue().Set(Utils::ToV8String(isolate, resolved)); 207 arguments.GetReturnValue().Set(Utils::ToV8String(isolate, resolved));
331 } 208 }
332 } 209 }
333 210
334 211
335 JsValue& FileSystemJsObject::Setup(JsEngine& jsEngine, JsValue& obj) 212 JsValue& FileSystemJsObject::Setup(JsEngine& jsEngine, JsValue& obj)
336 { 213 {
337 obj.SetProperty("read", jsEngine.NewCallback(::ReadCallback)); 214 obj.SetProperty("read", jsEngine.NewCallback(::ReadCallback));
338 obj.SetProperty("write", jsEngine.NewCallback(::WriteCallback)); 215 obj.SetProperty("write", jsEngine.NewCallback(::WriteCallback));
339 obj.SetProperty("move", jsEngine.NewCallback(::MoveCallback)); 216 obj.SetProperty("move", jsEngine.NewCallback(::MoveCallback));
340 obj.SetProperty("remove", jsEngine.NewCallback(::RemoveCallback)); 217 obj.SetProperty("remove", jsEngine.NewCallback(::RemoveCallback));
341 obj.SetProperty("stat", jsEngine.NewCallback(::StatCallback)); 218 obj.SetProperty("stat", jsEngine.NewCallback(::StatCallback));
342 obj.SetProperty("resolve", jsEngine.NewCallback(::ResolveCallback)); 219 obj.SetProperty("resolve", jsEngine.NewCallback(::ResolveCallback));
343 return obj; 220 return obj;
344 } 221 }
OLDNEW

Powered by Google App Engine
This is Rietveld