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: Updated patch after review. Created June 16, 2017, 9:52 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 JsValue callback(converted[1]);
257 readThread->Start(); 45 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
46 jsEngine->GetAsyncFileSystem()->Read(converted[0].AsString(),
47 [weakJsEngine, callback]
sergei 2017/07/03 09:25:54 `JsValue callback` should not be captured by value
hub 2017/07/04 19:58:27 I'll fix that here and there.
48 (std::string&& content, const std::string& error)
49 {
50 auto jsEngine = weakJsEngine.lock();
51 if (!jsEngine)
52 return;
53
54 const JsContext context(*jsEngine);
55 auto result = jsEngine->NewObject();
56 result.SetProperty("content", std::move(content));
57 result.SetProperty("error", error);
58 callback.Call(result);
59 });
258 } 60 }
259 61
260 void WriteCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 62 void WriteCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
261 { 63 {
262 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 64 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
263 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 65 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
264 66
265 v8::Isolate* isolate = arguments.GetIsolate(); 67 v8::Isolate* isolate = arguments.GetIsolate();
266 if (converted.size() != 3) 68 if (converted.size() != 3)
267 return ThrowExceptionInJS(isolate, "_fileSystem.write requires 3 parameter s"); 69 return ThrowExceptionInJS(isolate, "_fileSystem.write requires 3 parameter s");
268 if (!converted[2].IsFunction()) 70 if (!converted[2].IsFunction())
269 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.write mu st be a function"); 71 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.write mu st be a function");
270 WriteThread* const writeThread = new WriteThread(jsEngine, converted[2], 72
271 converted[0].AsString(), converted[1].AsString()); 73 JsValue callback(converted[2]);
272 writeThread->Start(); 74 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
75 jsEngine->GetAsyncFileSystem()->Write(converted[0].AsString(),
76 converted[1].AsString(),
77 [weakJsEngine, callback](const std::string& error)
78 {
79 auto jsEngine = weakJsEngine.lock();
80 if (!jsEngine)
81 return;
82
83 const JsContext context(*jsEngine);
84 JsValueList params;
85 params.push_back(jsEngine->NewValue(error));
86 callback.Call(params);
87 });
273 } 88 }
274 89
275 void MoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 90 void MoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
276 { 91 {
277 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 92 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
278 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 93 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
279 94
280 v8::Isolate* isolate = arguments.GetIsolate(); 95 v8::Isolate* isolate = arguments.GetIsolate();
281 if (converted.size() != 3) 96 if (converted.size() != 3)
282 return ThrowExceptionInJS(isolate, "_fileSystem.move requires 3 parameters "); 97 return ThrowExceptionInJS(isolate, "_fileSystem.move requires 3 parameters ");
283 if (!converted[2].IsFunction()) 98 if (!converted[2].IsFunction())
284 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.move mus t be a function"); 99 return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.move mus t be a function");
285 MoveThread* const moveThread = new MoveThread(jsEngine, converted[2], 100
286 converted[0].AsString(), converted[1].AsString()); 101 JsValue callback(converted[2]);
287 moveThread->Start(); 102 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
103 jsEngine->GetAsyncFileSystem()->Move(converted[0].AsString(),
104 converted[1].AsString(),
105 [weakJsEngine, callback](const std::string& error)
106 {
107 auto jsEngine = weakJsEngine.lock();
108 if (!jsEngine)
109 return;
110
111 const JsContext context(*jsEngine);
112 auto errorValue = jsEngine->NewValue(error);
113 JsValueList params;
114 params.push_back(errorValue);
sergei 2017/07/03 09:25:54 But the problem is that the empty string will be c
hub 2017/07/04 19:58:27 This mean we are changing the semantics of the API
115 callback.Call(params);
116 });
288 } 117 }
289 118
290 void RemoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 119 void RemoveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
291 { 120 {
292 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 121 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
293 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 122 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
294 123
295 v8::Isolate* isolate = arguments.GetIsolate(); 124 v8::Isolate* isolate = arguments.GetIsolate();
296 if (converted.size() != 2) 125 if (converted.size() != 2)
297 return ThrowExceptionInJS(isolate, "_fileSystem.remove requires 2 paramete rs"); 126 return ThrowExceptionInJS(isolate, "_fileSystem.remove requires 2 paramete rs");
298 if (!converted[1].IsFunction()) 127 if (!converted[1].IsFunction())
299 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.remove must be a function"); 128 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.remove must be a function");
300 RemoveThread* const removeThread = new RemoveThread(jsEngine, converted[1], 129
301 converted[0].AsString()); 130 JsValue callback(converted[1]);
302 removeThread->Start(); 131 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
132 jsEngine->GetAsyncFileSystem()->Remove(converted[0].AsString(),
133 [weakJsEngine, callback](const std::string& error)
134 {
135 auto jsEngine = weakJsEngine.lock();
136 if (!jsEngine)
137 return;
138
139 const JsContext context(*jsEngine);
140 auto errorValue = jsEngine->NewValue(error);
141 JsValueList params;
142 params.push_back(errorValue);
143 callback.Call(params);
144 });
303 } 145 }
304 146
305 void StatCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 147 void StatCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
306 { 148 {
307 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 149 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
308 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 150 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
309 151
310 v8::Isolate* isolate = arguments.GetIsolate(); 152 v8::Isolate* isolate = arguments.GetIsolate();
311 if (converted.size() != 2) 153 if (converted.size() != 2)
312 return ThrowExceptionInJS(isolate, "_fileSystem.stat requires 2 parameters "); 154 return ThrowExceptionInJS(isolate, "_fileSystem.stat requires 2 parameters ");
313 if (!converted[1].IsFunction()) 155 if (!converted[1].IsFunction())
314 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.stat mu st be a function"); 156 return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.stat mu st be a function");
315 StatThread* const statThread = new StatThread(jsEngine, converted[1], 157
316 converted[0].AsString()); 158 JsValue callback(converted[1]);
317 statThread->Start(); 159 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
160 jsEngine->GetAsyncFileSystem()->Stat(converted[0].AsString(),
161 [weakJsEngine, callback]
162 (const IFileSystem::StatResult& statResult, const std::string& error)
163 {
164 auto jsEngine = weakJsEngine.lock();
165 if (!jsEngine)
166 return;
167
168 const JsContext context(*jsEngine);
169 auto result = jsEngine->NewObject();
170
171 result.SetProperty("exists", statResult.exists);
172 result.SetProperty("isFile", statResult.isFile);
173 result.SetProperty("isDirectory", statResult.isDirectory);
174 result.SetProperty("lastModified", statResult.lastModified);
175 result.SetProperty("error", error);
176
177 JsValueList params;
178 params.push_back(result);
179 callback.Call(params);
180 });
318 } 181 }
319 182
320 void ResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) 183 void ResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments)
321 { 184 {
322 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 185 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
323 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 186 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
324 187
325 v8::Isolate* isolate = arguments.GetIsolate(); 188 v8::Isolate* isolate = arguments.GetIsolate();
326 if (converted.size() != 1) 189 if (converted.size() != 1)
327 return ThrowExceptionInJS(isolate, "_fileSystem.resolve requires 1 paramet er"); 190 return ThrowExceptionInJS(isolate, "_fileSystem.resolve requires 1 paramet er");
328 191
329 std::string resolved = jsEngine->GetFileSystem()->Resolve(converted[0].AsStr ing()); 192 std::string resolved = jsEngine->GetAsyncFileSystem()->Resolve(converted[0]. AsString());
330 arguments.GetReturnValue().Set(Utils::ToV8String(isolate, resolved)); 193 arguments.GetReturnValue().Set(Utils::ToV8String(isolate, resolved));
331 } 194 }
332 } 195 }
333 196
334 197
335 JsValue& FileSystemJsObject::Setup(JsEngine& jsEngine, JsValue& obj) 198 JsValue& FileSystemJsObject::Setup(JsEngine& jsEngine, JsValue& obj)
336 { 199 {
337 obj.SetProperty("read", jsEngine.NewCallback(::ReadCallback)); 200 obj.SetProperty("read", jsEngine.NewCallback(::ReadCallback));
338 obj.SetProperty("write", jsEngine.NewCallback(::WriteCallback)); 201 obj.SetProperty("write", jsEngine.NewCallback(::WriteCallback));
339 obj.SetProperty("move", jsEngine.NewCallback(::MoveCallback)); 202 obj.SetProperty("move", jsEngine.NewCallback(::MoveCallback));
340 obj.SetProperty("remove", jsEngine.NewCallback(::RemoveCallback)); 203 obj.SetProperty("remove", jsEngine.NewCallback(::RemoveCallback));
341 obj.SetProperty("stat", jsEngine.NewCallback(::StatCallback)); 204 obj.SetProperty("stat", jsEngine.NewCallback(::StatCallback));
342 obj.SetProperty("resolve", jsEngine.NewCallback(::ResolveCallback)); 205 obj.SetProperty("resolve", jsEngine.NewCallback(::ResolveCallback));
343 return obj; 206 return obj;
344 } 207 }
OLDNEW

Powered by Google App Engine
This is Rietveld