| OLD | NEW | 
|---|
| 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-2016 Eyeo GmbH | 3  * Copyright (C) 2006-2016 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 "JsEngineTransition.h" | 
| 26 #include "Scheduler.h" | 27 #include "Scheduler.h" | 
| 27 #include "Utils.h" | 28 #include "Utils.h" | 
|  | 29 #include "Value.h" | 
| 28 | 30 | 
| 29 using namespace AdblockPlus; | 31 using namespace AdblockPlus; | 
| 30 | 32 | 
| 31 namespace | 33 namespace | 
| 32 { | 34 { | 
| 33   class IoTask | 35   class ReadTask | 
| 34   { | 36   { | 
| 35   protected: | 37     /** | 
| 36     virtual void operator()() = 0; | 38      * Shared pointer keeps engine in existence for task thread. | 
|  | 39      */ | 
| 37     JsEnginePtr jsEngine; | 40     JsEnginePtr jsEngine; | 
| 38     FileSystemPtr fileSystem; | 41     std::string path; | 
| 39     JsValuePtr callback; | 42     V8PersistentNG<v8::Function> callbackFunction; | 
| 40 | 43 | 
| 41   public: | 44   public: | 
| 42     IoTask(JsEnginePtr jsEngine, JsValuePtr callback) | 45     ReadTask(JsEngineInternal* engine, const std::string& path, | 
| 43       : jsEngine(jsEngine), fileSystem(jsEngine->GetFileSystem()), | 46       V8PersistentNG<v8::Function> callbackFunction) | 
| 44         callback(callback) | 47       : jsEngine(engine->shared_from_this()), path(path), | 
| 45     { | 48       callbackFunction(callbackFunction) | 
| 46     } | 49     {} | 
| 47 |  | 
| 48     virtual ~IoTask() {} |  | 
| 49   }; |  | 
| 50 |  | 
| 51   class ReadTask : public IoTask |  | 
| 52   { |  | 
| 53   public: |  | 
| 54     ReadTask(JsEnginePtr jsEngine, JsValuePtr callback, |  | 
| 55                const std::string& path) |  | 
| 56       : IoTask(jsEngine, callback), path(path) |  | 
| 57     { |  | 
| 58     } |  | 
| 59 | 50 | 
| 60     void operator()() | 51     void operator()() | 
| 61     { | 52     { | 
|  | 53       JsEngineInternal* engine = ToInternal(jsEngine); | 
| 62       std::string content; | 54       std::string content; | 
| 63       std::string error; | 55       std::string error; | 
|  | 56       // Read operation is long-lived. Do not lock engine during it. | 
| 64       try | 57       try | 
| 65       { | 58       { | 
| 66         std::shared_ptr<std::istream> stream = fileSystem->Read(path); | 59         std::shared_ptr<std::istream> stream = engine->GetFileSystem()->Read(pat
     h); | 
| 67         content = Utils::Slurp(*stream); | 60         content = Utils::Slurp(*stream); | 
| 68       } | 61       } | 
| 69       catch (std::exception& e) | 62       catch (std::exception& e) | 
| 70       { | 63       { | 
| 71         error = e.what(); | 64         error = e.what(); | 
| 72       } | 65       } | 
| 73       catch (...) | 66       catch (...) | 
| 74       { | 67       { | 
| 75         error =  "Unknown error while reading from " + path; | 68         error = "Unknown error while reading from " + path; | 
| 76       } | 69       } | 
| 77 | 70       // Call back with the results of the read operation | 
| 78       const JsContext context(jsEngine); | 71       V8ExecutionScope scope(engine); | 
| 79       JsValuePtr result = jsEngine->NewObject(); | 72       auto callbackArguments = v8::Object::New(); | 
| 80       result->SetProperty("content", content); | 73       callbackArguments->Set(engine->ToV8String("content"), engine->ToV8String(c
     ontent)); | 
| 81       result->SetProperty("error", error); | 74       callbackArguments->Set(engine->ToV8String("error"), engine->ToV8String(err
     or)); | 
| 82       JsValueList params; | 75       auto args = AllocatedArray<v8::Local<v8::Value>>(1); | 
| 83       params.push_back(result); | 76       args[0] = callbackArguments; | 
| 84       callback->Call(params); | 77       engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
     e(args)); | 
| 85     } | 78     } | 
| 86 |  | 
| 87   private: |  | 
| 88     std::string path; |  | 
| 89   }; | 79   }; | 
| 90 | 80 | 
| 91   class WriteTask : public IoTask | 81   class WriteTask | 
| 92   { | 82   { | 
|  | 83     /** | 
|  | 84      * Shared pointer keeps engine in existence for task thread. | 
|  | 85      */ | 
|  | 86     JsEnginePtr jsEngine; | 
|  | 87     std::string path; | 
|  | 88     std::string content; | 
|  | 89     V8PersistentNG<v8::Function> callbackFunction; | 
| 93   public: | 90   public: | 
| 94     WriteTask(JsEnginePtr jsEngine, JsValuePtr callback, | 91     WriteTask(JsEngineInternal* engine, | 
| 95                 const std::string& path, const std::string& content) | 92       const std::string& path, const std::string& content, | 
| 96       : IoTask(jsEngine, callback), path(path), content(content) | 93       V8PersistentNG<v8::Function> callbackFunction) | 
| 97     { | 94       : jsEngine(engine->shared_from_this()), path(path), content(content), | 
| 98     } | 95       callbackFunction(callbackFunction) | 
|  | 96     {} | 
| 99 | 97 | 
| 100     void operator()() | 98     void operator()() | 
| 101     { | 99     { | 
|  | 100       JsEngineInternal* engine = ToInternal(jsEngine); | 
| 102       std::string error; | 101       std::string error; | 
|  | 102       // Write operation is long-lived. Do not lock engine during it. | 
| 103       try | 103       try | 
| 104       { | 104       { | 
| 105         std::shared_ptr<std::iostream> stream(new std::stringstream); | 105         std::shared_ptr<std::iostream> stream(new std::stringstream); | 
| 106         *stream << content; | 106         *stream << content; | 
| 107         fileSystem->Write(path, stream); | 107         engine->GetFileSystem()->Write(path, stream); | 
| 108       } | 108       } | 
| 109       catch (std::exception& e) | 109       catch (std::exception& e) | 
| 110       { | 110       { | 
| 111         error = e.what(); | 111         error = e.what(); | 
| 112       } | 112       } | 
| 113       catch (...) | 113       catch (...) | 
| 114       { | 114       { | 
| 115         error = "Unknown error while writing to " + path; | 115         error = "Unknown error while writing to " + path; | 
| 116       } | 116       } | 
| 117 | 117       // Apply the callback function | 
| 118       const JsContext context(jsEngine); | 118       V8ExecutionScope scope(engine); | 
| 119       JsValuePtr errorValue = jsEngine->NewValue(error); | 119       auto args = AllocatedArray<v8::Local<v8::Value>>(1); | 
| 120       JsValueList params; | 120       args[0] = engine->ToV8String(error); | 
| 121       params.push_back(errorValue); | 121       engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
     e(args)); | 
| 122       callback->Call(params); |  | 
| 123     } | 122     } | 
| 124 |  | 
| 125   private: |  | 
| 126     std::string path; |  | 
| 127     std::string content; |  | 
| 128   }; | 123   }; | 
| 129 | 124 | 
| 130   class MoveTask : public IoTask | 125   class MoveTask | 
| 131   { | 126   { | 
|  | 127     /** | 
|  | 128      * Shared pointer keeps engine in existence for task thread. | 
|  | 129      */ | 
|  | 130     JsEnginePtr jsEngine; | 
|  | 131     std::string fromPath; | 
|  | 132     std::string toPath; | 
|  | 133     V8PersistentNG<v8::Function> callbackFunction; | 
|  | 134 | 
| 132   public: | 135   public: | 
| 133     MoveTask(JsEnginePtr jsEngine, JsValuePtr callback, | 136     MoveTask(JsEngineInternal* engine, const std::string& fromPath, const std::s
     tring& toPath, | 
| 134                const std::string& fromPath, const std::string& toPath) | 137       V8PersistentNG<v8::Function> callbackFunction) | 
| 135       : IoTask(jsEngine, callback), fromPath(fromPath), toPath(toPath) | 138       : jsEngine(engine->shared_from_this()), fromPath(fromPath), toPath(toPath)
     , | 
| 136     { | 139       callbackFunction(callbackFunction) | 
| 137     } | 140     {} | 
| 138 | 141 | 
| 139     void operator()() | 142     void operator()() | 
| 140     { | 143     { | 
|  | 144       JsEngineInternal* engine(ToInternal(jsEngine)); | 
| 141       std::string error; | 145       std::string error; | 
| 142       try | 146       try | 
| 143       { | 147       { | 
| 144         fileSystem->Move(fromPath, toPath); | 148         engine->GetFileSystem()->Move(fromPath, toPath); | 
| 145       } | 149       } | 
| 146       catch (std::exception& e) | 150       catch (std::exception& e) | 
| 147       { | 151       { | 
| 148         error = e.what(); | 152         error = e.what(); | 
| 149       } | 153       } | 
| 150       catch (...) | 154       catch (...) | 
| 151       { | 155       { | 
| 152         error = "Unknown error while moving " + fromPath + " to " + toPath; | 156         error = "Unknown error while moving " + fromPath + " to " + toPath; | 
| 153       } | 157       } | 
| 154 | 158       V8ExecutionScope scope(engine); | 
| 155       const JsContext context(jsEngine); | 159       auto args = AllocatedArray<v8::Local<v8::Value>>(1); | 
| 156       JsValuePtr errorValue = jsEngine->NewValue(error); | 160       args[0] = engine->ToV8String(error); | 
| 157       JsValueList params; | 161       engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
     e(args)); | 
| 158       params.push_back(errorValue); |  | 
| 159       callback->Call(params); |  | 
| 160     } | 162     } | 
| 161 |  | 
| 162   private: |  | 
| 163     std::string fromPath; |  | 
| 164     std::string toPath; |  | 
| 165   }; | 163   }; | 
| 166 | 164 | 
| 167   class RemoveTask : public IoTask | 165   class RemoveTask | 
| 168   { | 166   { | 
|  | 167     /** | 
|  | 168      * Shared pointer keeps engine in existence for task thread. | 
|  | 169      */ | 
|  | 170     JsEnginePtr jsEngine; | 
|  | 171     std::string path; | 
|  | 172     V8PersistentNG<v8::Function> callbackFunction; | 
|  | 173 | 
| 169   public: | 174   public: | 
| 170     RemoveTask(JsEnginePtr jsEngine, JsValuePtr callback, | 175     RemoveTask(JsEngineInternal *engine, const std::string& path, | 
| 171                  const std::string& path) | 176       V8PersistentNG<v8::Function> callbackFunction) | 
| 172       : IoTask(jsEngine, callback), path(path) | 177       : jsEngine(engine->shared_from_this()), path(path), | 
| 173     { | 178       callbackFunction(callbackFunction) | 
| 174     } | 179     {} | 
| 175 | 180 | 
| 176     void operator()() | 181     void operator()() | 
| 177     { | 182     { | 
|  | 183       JsEngineInternal* engine(ToInternal(jsEngine)); | 
| 178       std::string error; | 184       std::string error; | 
| 179       try | 185       try | 
| 180       { | 186       { | 
| 181         fileSystem->Remove(path); | 187         engine->GetFileSystem()->Remove(path); | 
| 182       } | 188       } | 
| 183       catch (std::exception& e) | 189       catch (std::exception& e) | 
| 184       { | 190       { | 
| 185         error = e.what(); | 191         error = e.what(); | 
| 186       } | 192       } | 
| 187       catch (...) | 193       catch (...) | 
| 188       { | 194       { | 
| 189         error = "Unknown error while removing " + path; | 195         error = "Unknown error while removing " + path; | 
| 190       } | 196       } | 
| 191 | 197       V8ExecutionScope scope(engine); | 
| 192       const JsContext context(jsEngine); | 198       auto args = AllocatedArray<v8::Local<v8::Value>>(1); | 
| 193       JsValuePtr errorValue = jsEngine->NewValue(error); | 199       args[0] = engine->ToV8String(error); | 
| 194       JsValueList params; | 200       engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
     e(args)); | 
| 195       params.push_back(errorValue); |  | 
| 196       callback->Call(params); |  | 
| 197     } | 201     } | 
| 198 |  | 
| 199   private: |  | 
| 200     std::string path; |  | 
| 201   }; | 202   }; | 
| 202 | 203 | 
|  | 204   class StatTask | 
|  | 205   { | 
|  | 206     /** | 
|  | 207      * Shared pointer keeps engine in existence for task thread. | 
|  | 208      */ | 
|  | 209     JsEnginePtr jsEngine; | 
|  | 210     std::string path; | 
|  | 211     V8PersistentNG<v8::Function> callbackFunction; | 
| 203 | 212 | 
| 204   class StatTask : public IoTask |  | 
| 205   { |  | 
| 206   public: | 213   public: | 
| 207     StatTask(JsEnginePtr jsEngine, JsValuePtr callback, | 214     StatTask(JsEngineInternal* engine, const std::string& path, | 
| 208                const std::string& path) | 215       V8PersistentNG<v8::Function> callbackFunction) | 
| 209       : IoTask(jsEngine, callback), path(path) | 216       : jsEngine(engine->shared_from_this()), path(path), | 
| 210     { | 217       callbackFunction(callbackFunction) | 
| 211     } | 218     {} | 
| 212 | 219 | 
| 213     void operator()() | 220     void operator()() | 
| 214     { | 221     { | 
|  | 222       JsEngineInternal* engine(ToInternal(jsEngine)); | 
| 215       std::string error; | 223       std::string error; | 
| 216       FileSystem::StatResult statResult; | 224       FileSystem::StatResult statResult; | 
| 217       try | 225       try | 
| 218       { | 226       { | 
| 219         statResult = fileSystem->Stat(path); | 227         statResult = engine->GetFileSystem()->Stat(path); | 
| 220       } | 228       } | 
| 221       catch (std::exception& e) | 229       catch (std::exception& e) | 
| 222       { | 230       { | 
| 223         error = e.what(); | 231         error = e.what(); | 
| 224       } | 232       } | 
| 225       catch (...) | 233       catch (...) | 
| 226       { | 234       { | 
| 227         error = "Unknown error while calling stat on " + path; | 235         error = "Unknown error while calling stat on " + path; | 
| 228       } | 236       } | 
| 229 | 237       V8ExecutionScope scope(engine); | 
| 230       const JsContext context(jsEngine); | 238       auto callbackArgument(v8::Object::New()); | 
| 231       JsValuePtr result = jsEngine->NewObject(); | 239       callbackArgument->Set(engine->ToV8String("exists"), v8::Boolean::New(statR
     esult.exists)); | 
| 232       result->SetProperty("exists", statResult.exists); | 240       callbackArgument->Set(engine->ToV8String("isFile"), v8::Boolean::New(statR
     esult.isFile)); | 
| 233       result->SetProperty("isFile", statResult.isFile); | 241       callbackArgument->Set(engine->ToV8String("isDirectory"), v8::Boolean::New(
     statResult.isDirectory)); | 
| 234       result->SetProperty("isDirectory", statResult.isDirectory); | 242       callbackArgument->Set(engine->ToV8String("lastModified"), v8::Number::New(
     statResult.lastModified)); | 
| 235       result->SetProperty("lastModified", statResult.lastModified); | 243       callbackArgument->Set(engine->ToV8String("error"), engine->ToV8String(erro
     r)); | 
| 236       result->SetProperty("error", error); | 244       auto args = AllocatedArray<v8::Local<v8::Value>>(1); | 
| 237 | 245       args[0] = callbackArgument; | 
| 238       JsValueList params; | 246       engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
     e(args)); | 
| 239       params.push_back(result); | 247     } | 
| 240       callback->Call(params); |  | 
| 241     } |  | 
| 242 |  | 
| 243   private: |  | 
| 244     std::string path; |  | 
| 245   }; | 248   }; | 
| 246 | 249 } | 
| 247   v8::Handle<v8::Value> ReadCallback(const v8::Arguments& arguments) | 250 | 
| 248   { | 251 v8::Handle<v8::Value> ReadCallback(const v8::Arguments& arguments) | 
| 249     AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
     uments); | 252 { | 
| 250     AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 253   auto engine(JsEngineInternal::ExtractEngine(arguments)); | 
| 251 | 254   std::shared_ptr<ReadTask> readTask; | 
|  | 255   try | 
|  | 256   { | 
|  | 257     if (arguments.Length() != 2) | 
|  | 258     { | 
|  | 259       throw std::runtime_error("_fileSystem.read requires 2 parameters"); | 
|  | 260     } | 
|  | 261     bool argumentIsString; | 
|  | 262     std::string firstArgument; | 
|  | 263     std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); | 
|  | 264     if (!argumentIsString) | 
|  | 265     { | 
|  | 266       throw std::runtime_error("First argument to _fileSystem.read must be a str
     ing"); | 
|  | 267     } | 
|  | 268     if (!arguments[1]->IsFunction()) | 
|  | 269     { | 
|  | 270       throw std::runtime_error("Second argument to _fileSystem.read must be a fu
     nction"); | 
|  | 271     } | 
|  | 272     readTask = std::make_shared<ReadTask>(engine, firstArgument, | 
|  | 273       V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>
     ::Cast(arguments[1]))); | 
|  | 274   } | 
|  | 275   catch (const std::exception& e) | 
|  | 276   { | 
|  | 277     return v8::ThrowException(engine->ToV8String(e.what())); | 
|  | 278   } | 
|  | 279   // Run the task | 
|  | 280   engine->Schedule(AdblockPlus::MakeHeapFunction(readTask), AdblockPlus::Immedia
     teSingleUseThread); | 
|  | 281   return v8::Undefined(); | 
|  | 282 } | 
|  | 283 | 
|  | 284 v8::Handle<v8::Value> WriteCallback(const v8::Arguments& arguments) | 
|  | 285 { | 
|  | 286   auto engine(JsEngineInternal::ExtractEngine(arguments)); | 
|  | 287   std::shared_ptr<WriteTask> writeTask; | 
|  | 288   try | 
|  | 289   { | 
| 252     v8::Isolate* isolate = arguments.GetIsolate(); | 290     v8::Isolate* isolate = arguments.GetIsolate(); | 
| 253     if (converted.size() != 2) | 291 | 
| 254       return v8::ThrowException(Utils::ToV8String(isolate, | 292     if (arguments.Length() != 3) | 
| 255         "_fileSystem.read requires 2 parameters")); | 293     { | 
| 256     if (!converted[1]->IsFunction()) | 294       throw std::exception("_fileSystem.write requires 3 parameters"); | 
| 257       return v8::ThrowException(Utils::ToV8String(isolate, | 295     } | 
| 258         "Second argument to _fileSystem.read must be a function")); | 296     bool argumentIsString; | 
| 259     const auto readTask = std::make_shared<ReadTask>(jsEngine, converted[1], | 297     std::string firstArgument; | 
| 260         converted[0]->AsString()); | 298     std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); | 
| 261     jsEngine->Schedule(AdblockPlus::MakeHeapFunction(readTask), AdblockPlus::Imm
     ediateSingleUseThread); | 299     if (!argumentIsString) | 
| 262     return v8::Undefined(); | 300     { | 
| 263   } | 301       throw std::runtime_error("First argument to _fileSystem.write must be a st
     ring"); | 
| 264 | 302     } | 
| 265   v8::Handle<v8::Value> WriteCallback(const v8::Arguments& arguments) | 303     std::string secondArgument; | 
| 266   { | 304     std::tie(argumentIsString, secondArgument) = ConvertString(arguments[1]); | 
| 267     AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
     uments); | 305     if (!argumentIsString) | 
| 268     AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 306     { | 
| 269 | 307       throw std::runtime_error("Second argument to _fileSystem.write must be a s
     tring"); | 
| 270     v8::Isolate* isolate = arguments.GetIsolate(); | 308     } | 
| 271     if (converted.size() != 3) | 309     if (!arguments[2]->IsFunction()) | 
| 272       return v8::ThrowException(Utils::ToV8String(isolate, | 310     { | 
| 273         "_fileSystem.write requires 3 parameters")); | 311       throw std::runtime_error("Third argument to _fileSystem.write must be a fu
     nction"); | 
| 274     if (!converted[2]->IsFunction()) | 312     } | 
| 275       return v8::ThrowException(Utils::ToV8String(isolate, | 313     writeTask = std::make_shared<WriteTask>(engine, firstArgument, secondArgumen
     t, | 
| 276         "Third argument to _fileSystem.write must be a function")); | 314       V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>
     ::Cast(arguments[2]))); | 
| 277     const auto writeTask = std::make_shared<WriteTask>(jsEngine, converted[2], | 315   } | 
| 278         converted[0]->AsString(), converted[1]->AsString()); | 316   catch (const std::exception& e) | 
| 279     jsEngine->Schedule(AdblockPlus::MakeHeapFunction(writeTask), AdblockPlus::Im
     mediateSingleUseThread); | 317   { | 
| 280     return v8::Undefined(); | 318     return v8::ThrowException(engine->ToV8String(e.what())); | 
| 281   } | 319   } | 
| 282 | 320   engine->Schedule(AdblockPlus::MakeHeapFunction(writeTask), AdblockPlus::Immedi
     ateSingleUseThread); | 
| 283   v8::Handle<v8::Value> MoveCallback(const v8::Arguments& arguments) | 321   return v8::Undefined(); | 
| 284   { | 322 } | 
| 285     AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
     uments); | 323 | 
| 286     AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 324 v8::Handle<v8::Value> MoveCallback(const v8::Arguments& arguments) | 
| 287 | 325 { | 
| 288     v8::Isolate* isolate = arguments.GetIsolate(); | 326   auto engine(JsEngineInternal::ExtractEngine(arguments)); | 
| 289     if (converted.size() != 3) | 327   std::shared_ptr<MoveTask> moveTask; | 
| 290       return v8::ThrowException(Utils::ToV8String(isolate, | 328   std::string firstArgument, secondArgument; | 
| 291         "_fileSystem.move requires 3 parameters")); | 329   try | 
| 292     if (!converted[2]->IsFunction()) | 330   { | 
| 293       return v8::ThrowException(Utils::ToV8String(isolate, | 331     if (arguments.Length() != 3) | 
| 294         "Third argument to _fileSystem.move must be a function")); | 332     { | 
| 295     const auto moveTask = std::make_shared<MoveTask>(jsEngine, converted[2], | 333       throw std::runtime_error("_fileSystem.move requires 3 parameters"); | 
| 296         converted[0]->AsString(), converted[1]->AsString()); | 334     } | 
| 297     jsEngine->Schedule(AdblockPlus::MakeHeapFunction(moveTask), AdblockPlus::Imm
     ediateSingleUseThread); | 335     bool argumentIsString; | 
| 298     return v8::Undefined(); | 336     std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); | 
| 299   } | 337     if (!argumentIsString) | 
| 300 | 338     { | 
| 301   v8::Handle<v8::Value> RemoveCallback(const v8::Arguments& arguments) | 339       throw std::runtime_error("First argument to _fileSystem.write must be a st
     ring"); | 
| 302   { | 340     } | 
| 303     AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
     uments); | 341     std::tie(argumentIsString, secondArgument) = ConvertString(arguments[1]); | 
| 304     AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 342     if (!argumentIsString) | 
| 305 | 343     { | 
| 306     v8::Isolate* isolate = arguments.GetIsolate(); | 344       throw std::runtime_error("Second argument to _fileSystem.write must be a s
     tring"); | 
| 307     if (converted.size() != 2) | 345     } | 
| 308       return v8::ThrowException(Utils::ToV8String(isolate, | 346     if (!arguments[2]->IsFunction()) | 
| 309         "_fileSystem.remove requires 2 parameters")); | 347     { | 
| 310     if (!converted[1]->IsFunction()) | 348       throw std::runtime_error("Third argument to _fileSystem.move must be a fun
     ction"); | 
| 311       return v8::ThrowException(Utils::ToV8String(isolate, | 349     } | 
| 312         "Second argument to _fileSystem.remove must be a function")); | 350   } | 
| 313     const auto removeTask = std::make_shared<RemoveTask>(jsEngine, converted[1], | 351   catch (const std::exception& e) | 
| 314         converted[0]->AsString()); | 352   { | 
| 315     jsEngine->Schedule(AdblockPlus::MakeHeapFunction(removeTask), AdblockPlus::I
     mmediateSingleUseThread); | 353     return v8::ThrowException(engine->ToV8String(e.what())); | 
| 316     return v8::Undefined(); | 354   } | 
| 317   } | 355   // Run the task | 
| 318 | 356   moveTask = std::make_shared<MoveTask>(engine, firstArgument, secondArgument, | 
| 319   v8::Handle<v8::Value> StatCallback(const v8::Arguments& arguments) | 357     V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::
     Cast(arguments[2]))); | 
| 320   { | 358   engine->Schedule(AdblockPlus::MakeHeapFunction(moveTask), AdblockPlus::Immedia
     teSingleUseThread); | 
| 321     AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
     uments); | 359   return v8::Undefined(); | 
| 322     AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 360 } | 
| 323 | 361 | 
| 324     v8::Isolate* isolate = arguments.GetIsolate(); | 362 v8::Handle<v8::Value> RemoveCallback(const v8::Arguments& arguments) | 
| 325     if (converted.size() != 2) | 363 { | 
| 326       return v8::ThrowException(Utils::ToV8String(isolate, | 364   auto engine(JsEngineInternal::ExtractEngine(arguments)); | 
| 327         "_fileSystem.stat requires 2 parameters")); | 365   std::shared_ptr<RemoveTask> removeTask; | 
| 328     if (!converted[1]->IsFunction()) | 366   std::string firstArgument; | 
| 329       return v8::ThrowException(Utils::ToV8String(isolate, | 367   try | 
| 330         "Second argument to _fileSystem.stat must be a function")); | 368   { | 
| 331     const auto statTask = std::make_shared<StatTask>(jsEngine, converted[1], | 369     if (arguments.Length() != 2) | 
| 332         converted[0]->AsString()); | 370     { | 
| 333     jsEngine->Schedule(AdblockPlus::MakeHeapFunction(statTask), AdblockPlus::Imm
     ediateSingleUseThread); | 371       throw std::runtime_error("_fileSystem.remove requires 2 parameters"); | 
| 334     return v8::Undefined(); | 372     } | 
| 335   } | 373     bool argumentIsString; | 
| 336 | 374     std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); | 
| 337   v8::Handle<v8::Value> ResolveCallback(const v8::Arguments& arguments) | 375     if (!argumentIsString) | 
| 338   { | 376     { | 
| 339     AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
     uments); | 377       throw std::runtime_error("First argument to _fileSystem.remove must be a s
     tring"); | 
| 340     AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 378     } | 
| 341 | 379     if (!arguments[1]->IsFunction()) | 
| 342     v8::Isolate* isolate = arguments.GetIsolate(); | 380     { | 
| 343     if (converted.size() != 1) | 381       throw std::runtime_error("Second argument to _fileSystem.remove must be a 
     function"); | 
| 344       return v8::ThrowException(Utils::ToV8String(isolate, | 382     } | 
| 345         "_fileSystem.resolve requires 1 parameter")); | 383   } | 
| 346 | 384   catch (const std::exception& e) | 
| 347     std::string resolved = jsEngine->GetFileSystem()->Resolve(converted[0]->AsSt
     ring()); | 385   { | 
| 348 | 386     return v8::ThrowException(engine->ToV8String(e.what())); | 
| 349     return Utils::ToV8String(isolate, resolved); | 387   } | 
| 350   } | 388   // Run the task | 
| 351 | 389   removeTask = std::make_shared<RemoveTask>(engine, firstArgument, | 
| 352 } | 390     V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::
     Cast(arguments[1]))); | 
| 353 | 391   engine->Schedule(AdblockPlus::MakeHeapFunction(removeTask), AdblockPlus::Immed
     iateSingleUseThread); | 
| 354 | 392   return v8::Undefined(); | 
| 355 JsValuePtr FileSystemJsObject::Setup(JsEnginePtr jsEngine, JsValuePtr obj) | 393 } | 
| 356 { | 394 | 
| 357   obj->SetProperty("read", jsEngine->NewCallback(::ReadCallback)); | 395 v8::Handle<v8::Value> StatCallback(const v8::Arguments& arguments) | 
| 358   obj->SetProperty("write", jsEngine->NewCallback(::WriteCallback)); | 396 { | 
| 359   obj->SetProperty("move", jsEngine->NewCallback(::MoveCallback)); | 397   auto engine(JsEngineInternal::ExtractEngine(arguments)); | 
| 360   obj->SetProperty("remove", jsEngine->NewCallback(::RemoveCallback)); | 398   std::shared_ptr<StatTask> statTask; | 
| 361   obj->SetProperty("stat", jsEngine->NewCallback(::StatCallback)); | 399   std::string firstArgument; | 
| 362   obj->SetProperty("resolve", jsEngine->NewCallback(::ResolveCallback)); | 400   try | 
| 363   return obj; | 401   { | 
| 364 } | 402     if (arguments.Length() != 2) | 
|  | 403     { | 
|  | 404       throw std::runtime_error("_fileSystem.stat requires 2 parameters"); | 
|  | 405     } | 
|  | 406     bool argumentIsString; | 
|  | 407     std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); | 
|  | 408     if (!argumentIsString) | 
|  | 409     { | 
|  | 410       throw std::runtime_error("First argument to _fileSystem.stat must be a str
     ing"); | 
|  | 411     } | 
|  | 412     if (!arguments[1]->IsFunction()) | 
|  | 413     { | 
|  | 414       throw std::runtime_error("Second argument to _fileSystem.stat must be a fu
     nction"); | 
|  | 415     } | 
|  | 416   } | 
|  | 417   catch (const std::exception& e) | 
|  | 418   { | 
|  | 419     return v8::ThrowException(engine->ToV8String(e.what())); | 
|  | 420   } | 
|  | 421   // Run the task | 
|  | 422   statTask = std::make_shared<StatTask>(engine, firstArgument, | 
|  | 423     V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::
     Cast(arguments[1]))); | 
|  | 424   engine->Schedule(AdblockPlus::MakeHeapFunction(statTask), AdblockPlus::Immedia
     teSingleUseThread); | 
|  | 425   return v8::Undefined(); | 
|  | 426 } | 
|  | 427 | 
|  | 428 v8::Handle<v8::Value> ResolveCallback(const v8::Arguments& arguments) | 
|  | 429 { | 
|  | 430   auto engine(JsEngineInternal::ExtractEngine(arguments)); | 
|  | 431   std::string firstArgument; | 
|  | 432   try | 
|  | 433   { | 
|  | 434     if (arguments.Length() != 1) | 
|  | 435     { | 
|  | 436       throw std::runtime_error("_fileSystem.resolve requires 1 parameter"); | 
|  | 437     } | 
|  | 438     bool argumentIsString; | 
|  | 439     std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); | 
|  | 440     if (!argumentIsString) | 
|  | 441     { | 
|  | 442       throw std::runtime_error("First argument to _fileSystem.write must be a st
     ring"); | 
|  | 443     } | 
|  | 444   } | 
|  | 445   catch (const std::exception& e) | 
|  | 446   { | 
|  | 447     return v8::ThrowException(engine->ToV8String(e.what())); | 
|  | 448   } | 
|  | 449   /* | 
|  | 450    * Make sure to perform long-lived file system operation with engine unlocked. | 
|  | 451    */ | 
|  | 452   std::string resolved = engine->GetFileSystem()->Resolve(firstArgument); | 
|  | 453   return engine->ToV8String(resolved); | 
|  | 454 } | 
| OLD | NEW | 
|---|