| 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-present eyeo GmbH |    3  * Copyright (C) 2006-present 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 | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  101   private: |  101   private: | 
|  102     ScopedV8Isolate(const ScopedV8Isolate&); |  102     ScopedV8Isolate(const ScopedV8Isolate&); | 
|  103     ScopedV8Isolate& operator=(const ScopedV8Isolate&); |  103     ScopedV8Isolate& operator=(const ScopedV8Isolate&); | 
|  104  |  104  | 
|  105     v8::Isolate* isolate; |  105     v8::Isolate* isolate; | 
|  106   }; |  106   }; | 
|  107 } |  107 } | 
|  108  |  108  | 
|  109 using namespace AdblockPlus; |  109 using namespace AdblockPlus; | 
|  110  |  110  | 
|  111 JsEngine::JsWeakValuesList::~JsWeakValuesList() |  111 template <> JsWeakValuesList<v8::Global<v8::Value>>::~JsWeakValuesList() | 
|  112 { |  112 { | 
|  113 } |  113 } | 
|  114  |  114  | 
|  115 void JsEngine::NotifyLowMemory() |  115  | 
 |  116 template <> void AdblockPlus::JSENGINEV8::NotifyLowMemory() | 
|  116 { |  117 { | 
|  117   const JsContext context(*this); |  118   const JsContext context(*this); | 
|  118   GetIsolate()->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical); |  119   GetIsolate()->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical); | 
|  119 } |  120 } | 
|  120  |  121  | 
|  121 void JsEngine::ScheduleTimer(const v8::FunctionCallbackInfo<v8::Value>& argument
     s) |  122 template <> void AdblockPlus::JSENGINEV8::ScheduleTimer(const v8::FunctionCallba
     ckInfo<v8::Value>& arguments) | 
|  122 { |  123 { | 
|  123   auto jsEngine = FromArguments(arguments); |  124   auto jsEngine = FromArguments(arguments); | 
|  124   if (arguments.Length() < 2) |  125   if (arguments.Length() < 2) | 
|  125     throw std::runtime_error("setTimeout requires at least 2 parameters"); |  126     throw std::runtime_error("setTimeout requires at least 2 parameters"); | 
|  126  |  127  | 
|  127   if (!arguments[0]->IsFunction()) |  128   if (!arguments[0]->IsFunction()) | 
|  128     throw std::runtime_error("First argument to setTimeout must be a function"); |  129     throw std::runtime_error("First argument to setTimeout must be a function"); | 
|  129  |  130  | 
|  130   auto jsValueArguments = jsEngine->ConvertArguments(arguments); |  131   auto jsValueArguments = jsEngine->ConvertArguments(arguments); | 
|  131   auto timerParamsID = jsEngine->StoreJsValues(jsValueArguments); |  132   auto timerParamsID = jsEngine->StoreJsValues(jsValueArguments); | 
|  132  |  133  | 
|  133   std::weak_ptr<JsEngine> weakJsEngine = jsEngine; |  134   std::weak_ptr<JsEngine> weakJsEngine = jsEngine; | 
|  134   jsEngine->platform.WithTimer( |  135   jsEngine->platform.WithTimer( | 
|  135     [arguments, weakJsEngine, timerParamsID](ITimer& timer) |  136     [arguments, weakJsEngine, timerParamsID](ITimer& timer) | 
|  136     { |  137     { | 
|  137       timer.SetTimer( |  138       timer.SetTimer( | 
|  138         std::chrono::milliseconds( |  139         std::chrono::milliseconds( | 
|  139           arguments[1]->IntegerValue()), [weakJsEngine, timerParamsID] |  140           arguments[1]->IntegerValue()), [weakJsEngine, timerParamsID] | 
|  140           { |  141           { | 
|  141             if (auto jsEngine = weakJsEngine.lock()) |  142             if (auto jsEngine = weakJsEngine.lock()) | 
|  142               jsEngine->CallTimerTask(timerParamsID); |  143               jsEngine->CallTimerTask(timerParamsID); | 
|  143           }); |  144           }); | 
|  144     }); |  145     }); | 
|  145 } |  146 } | 
|  146  |  147  | 
|  147 void JsEngine::CallTimerTask(const JsWeakValuesID& timerParamsID) |  148 template <> void AdblockPlus::JSENGINEV8::CallTimerTask(const JsWeakValuesID& ti
     merParamsID) | 
|  148 { |  149 { | 
|  149   auto timerParams = TakeJsValues(timerParamsID); |  150   auto timerParams = TakeJsValues(timerParamsID); | 
|  150   JsValue callback = std::move(timerParams[0]); |  151   JsValue callback = std::move(timerParams[0]); | 
|  151  |  152  | 
|  152   timerParams.erase(timerParams.begin()); // remove callback placeholder |  153   timerParams.erase(timerParams.begin()); // remove callback placeholder | 
|  153   timerParams.erase(timerParams.begin()); // remove timeout param |  154   timerParams.erase(timerParams.begin()); // remove timeout param | 
|  154   callback.Call(timerParams); |  155   callback.Call(timerParams); | 
|  155 } |  156 } | 
|  156  |  157  | 
|  157 AdblockPlus::JsEngine::JsEngine(Platform& platform, std::unique_ptr<IV8IsolatePr
     ovider> isolate) |  158 template <> AdblockPlus::JSENGINEV8::JsEngineTemplate(Platform& platform, std::u
     nique_ptr<IV8IsolateProvider> isolate) | 
|  158   : platform(platform) |  159   : platform(platform) | 
|  159   , isolate(std::move(isolate)) |  160   , isolate(std::move(isolate)) | 
|  160 { |  161 { | 
|  161 } |  162 } | 
|  162  |  163  | 
|  163 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::New(const AppInfo& appInfo, |  164  | 
 |  165 template <> AdblockPlus::JsEnginePtr AdblockPlus::JSENGINEV8::New(const AppInfo&
      appInfo, | 
|  164   Platform& platform, std::unique_ptr<IV8IsolateProvider> isolate) |  166   Platform& platform, std::unique_ptr<IV8IsolateProvider> isolate) | 
|  165 { |  167 { | 
|  166   if (!isolate) |  168   if (!isolate) | 
|  167   { |  169   { | 
|  168     isolate.reset(new ScopedV8Isolate()); |  170     isolate.reset(new ScopedV8Isolate()); | 
|  169   } |  171   } | 
|  170   JsEnginePtr result(new JsEngine(platform, std::move(isolate))); |  172   JsEnginePtr result(new JsEngine(platform, std::move(isolate))); | 
|  171  |  173  | 
|  172   const v8::Locker locker(result->GetIsolate()); |  174   const v8::Locker locker(result->GetIsolate()); | 
|  173   const v8::Isolate::Scope isolateScope(result->GetIsolate()); |  175   const v8::Isolate::Scope isolateScope(result->GetIsolate()); | 
|  174   const v8::HandleScope handleScope(result->GetIsolate()); |  176   const v8::HandleScope handleScope(result->GetIsolate()); | 
|  175  |  177  | 
|  176   result->context.reset(new v8::Global<v8::Context>(result->GetIsolate(), |  178   result->context.reset(new v8::Global<v8::Context>(result->GetIsolate(), | 
|  177     v8::Context::New(result->GetIsolate()))); |  179     v8::Context::New(result->GetIsolate()))); | 
|  178   auto global = result->GetGlobalObject(); |  180   auto global = result->GetGlobalObject(); | 
|  179   AdblockPlus::GlobalJsObject::Setup(*result, appInfo, global); |  181   AdblockPlus::GlobalJsObject::Setup(*result, appInfo, global); | 
|  180   return result; |  182   return result; | 
|  181 } |  183 } | 
|  182  |  184  | 
|  183 AdblockPlus::JsValue AdblockPlus::JsEngine::GetGlobalObject() |  185 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::GetGlobalObject() | 
|  184 { |  186 { | 
|  185   JsContext context(*this); |  187   JsContext context(*this); | 
|  186   return JsValue(shared_from_this(), context.GetV8Context()->Global()); |  188   return JsValue(shared_from_this(), context.GetJSEngineContext()->Global()); | 
|  187 } |  189 } | 
|  188  |  190  | 
|  189 AdblockPlus::JsValue AdblockPlus::JsEngine::Evaluate(const std::string& source, |  191 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::Evaluate(const std::st
     ring& source, | 
|  190     const std::string& filename) |  192     const std::string& filename) | 
|  191 { |  193 { | 
|  192   const JsContext context(*this); |  194   const JsContext context(*this); | 
|  193   const v8::TryCatch tryCatch; |  195   const v8::TryCatch tryCatch; | 
|  194   const v8::Handle<v8::Script> script = CompileScript(GetIsolate(), source, |  196   const v8::Handle<v8::Script> script = CompileScript(GetIsolate(), source, | 
|  195     filename); |  197     filename); | 
|  196   CheckTryCatch(tryCatch); |  198   CheckTryCatch(tryCatch); | 
|  197   v8::Local<v8::Value> result = script->Run(); |  199   v8::Local<v8::Value> result = script->Run(); | 
|  198   CheckTryCatch(tryCatch); |  200   CheckTryCatch(tryCatch); | 
|  199   return JsValue(shared_from_this(), result); |  201   return JsValue(shared_from_this(), result); | 
|  200 } |  202 } | 
|  201  |  203  | 
|  202 void AdblockPlus::JsEngine::SetEventCallback(const std::string& eventName, |  204 template <> void AdblockPlus::JSENGINEV8::SetEventCallback(const std::string& ev
     entName, | 
|  203     const AdblockPlus::JsEngine::EventCallback& callback) |  205     const AdblockPlus::JSENGINEV8::EventCallback& callback) | 
|  204 { |  206 { | 
|  205   if (!callback) |  207   if (!callback) | 
|  206   { |  208   { | 
|  207     RemoveEventCallback(eventName); |  209     RemoveEventCallback(eventName); | 
|  208     return; |  210     return; | 
|  209   } |  211   } | 
|  210   std::lock_guard<std::mutex> lock(eventCallbacksMutex); |  212   std::lock_guard<std::mutex> lock(eventCallbacksMutex); | 
|  211   eventCallbacks[eventName] = callback; |  213   eventCallbacks[eventName] = callback; | 
|  212 } |  214 } | 
|  213  |  215  | 
|  214 void AdblockPlus::JsEngine::RemoveEventCallback(const std::string& eventName) |  216 template <> void AdblockPlus::JSENGINEV8::RemoveEventCallback(const std::string&
      eventName) | 
|  215 { |  217 { | 
|  216   std::lock_guard<std::mutex> lock(eventCallbacksMutex); |  218   std::lock_guard<std::mutex> lock(eventCallbacksMutex); | 
|  217   eventCallbacks.erase(eventName); |  219   eventCallbacks.erase(eventName); | 
|  218 } |  220 } | 
|  219  |  221  | 
|  220 void AdblockPlus::JsEngine::TriggerEvent(const std::string& eventName, AdblockPl
     us::JsValueList&& params) |  222 template <> void AdblockPlus::JSENGINEV8::TriggerEvent(const std::string& eventN
     ame, AdblockPlus::JsValueList&& params) | 
|  221 { |  223 { | 
|  222   EventCallback callback; |  224   EventCallback callback; | 
|  223   { |  225   { | 
|  224     std::lock_guard<std::mutex> lock(eventCallbacksMutex); |  226     std::lock_guard<std::mutex> lock(eventCallbacksMutex); | 
|  225     auto it = eventCallbacks.find(eventName); |  227     auto it = eventCallbacks.find(eventName); | 
|  226     if (it == eventCallbacks.end()) |  228     if (it == eventCallbacks.end()) | 
|  227       return; |  229       return; | 
|  228     callback = it->second; |  230     callback = it->second; | 
|  229   } |  231   } | 
|  230   callback(move(params)); |  232   callback(move(params)); | 
|  231 } |  233 } | 
|  232  |  234  | 
|  233 void AdblockPlus::JsEngine::Gc() |  235 template <> void AdblockPlus::JSENGINEV8::Gc() | 
|  234 { |  236 { | 
|  235   while (!GetIsolate()->IdleNotification(1000)); |  237   while (!GetIsolate()->IdleNotification(1000)); | 
|  236 } |  238 } | 
|  237  |  239  | 
|  238 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(const std::string& val) |  240 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewValue(const std::st
     ring& val) | 
|  239 { |  241 { | 
|  240   const JsContext context(*this); |  242   const JsContext context(*this); | 
|  241   return JsValue(shared_from_this(), Utils::ToV8String(GetIsolate(), val)); |  243   return JsValue(shared_from_this(), Utils::ToV8String(GetIsolate(), val)); | 
|  242 } |  244 } | 
|  243  |  245  | 
|  244 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(int64_t val) |  246 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewValue(int64_t val) | 
|  245 { |  247 { | 
|  246   const JsContext context(*this); |  248   const JsContext context(*this); | 
|  247   return JsValue(shared_from_this(), v8::Number::New(GetIsolate(), val)); |  249   return JsValue(shared_from_this(), v8::Number::New(GetIsolate(), val)); | 
|  248 } |  250 } | 
|  249  |  251  | 
|  250 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(bool val) |  252 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewValue(bool val) | 
|  251 { |  253 { | 
|  252   const JsContext context(*this); |  254   const JsContext context(*this); | 
|  253   return JsValue(shared_from_this(), v8::Boolean::New(GetIsolate(), val)); |  255   return JsValue(shared_from_this(), v8::Boolean::New(GetIsolate(), val)); | 
|  254 } |  256 } | 
|  255  |  257  | 
|  256 AdblockPlus::JsValue AdblockPlus::JsEngine::NewObject() |  258 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewObject() | 
|  257 { |  259 { | 
|  258   const JsContext context(*this); |  260   const JsContext context(*this); | 
|  259   return JsValue(shared_from_this(), v8::Object::New(GetIsolate())); |  261   return JsValue(shared_from_this(), v8::Object::New(GetIsolate())); | 
|  260 } |  262 } | 
|  261  |  263  | 
|  262 AdblockPlus::JsValue AdblockPlus::JsEngine::NewCallback( |  264 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewCallback( | 
|  263     const v8::FunctionCallback& callback) |  265     const v8::FunctionCallback& callback) | 
|  264 { |  266 { | 
|  265   const JsContext context(*this); |  267   const JsContext context(*this); | 
|  266  |  268  | 
|  267   // Note: we are leaking this weak pointer, no obvious way to destroy it when |  269   // Note: we are leaking this weak pointer, no obvious way to destroy it when | 
|  268   // it's no longer used |  270   // it's no longer used | 
|  269   std::weak_ptr<JsEngine>* data = |  271   std::weak_ptr<JsEngine>* data = | 
|  270       new std::weak_ptr<JsEngine>(shared_from_this()); |  272       new std::weak_ptr<JsEngine>(shared_from_this()); | 
|  271   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(GetIsolate()
     , callback, |  273   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(GetIsolate()
     , callback, | 
|  272       v8::External::New(GetIsolate(), data)); |  274       v8::External::New(GetIsolate(), data)); | 
|  273   return JsValue(shared_from_this(), templ->GetFunction()); |  275   return JsValue(shared_from_this(), templ->GetFunction()); | 
|  274 } |  276 } | 
|  275  |  277  | 
|  276 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::FromArguments(const v8::Function
     CallbackInfo<v8::Value>& arguments) |  278 template <> AdblockPlus::JsEnginePtr AdblockPlus::JSENGINEV8::FromArguments(cons
     t v8::FunctionCallbackInfo<v8::Value>& arguments) | 
|  277 { |  279 { | 
|  278   const v8::Local<const v8::External> external = |  280   const v8::Local<const v8::External> external = | 
|  279       v8::Local<const v8::External>::Cast(arguments.Data()); |  281       v8::Local<const v8::External>::Cast(arguments.Data()); | 
|  280   std::weak_ptr<JsEngine>* data = |  282   std::weak_ptr<JsEngine>* data = | 
|  281       static_cast<std::weak_ptr<JsEngine>*>(external->Value()); |  283       static_cast<std::weak_ptr<JsEngine>*>(external->Value()); | 
|  282   JsEnginePtr result = data->lock(); |  284   JsEnginePtr result = data->lock(); | 
|  283   if (!result) |  285   if (!result) | 
|  284     throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?")
     ; |  286     throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?")
     ; | 
|  285   return result; |  287   return result; | 
|  286 } |  288 } | 
|  287  |  289  | 
|  288 JsEngine::JsWeakValuesID JsEngine::StoreJsValues(const JsValueList& values) |  290 template <> AdblockPlus::JsWeakValuesID AdblockPlus::JSENGINEV8::StoreJsValues(c
     onst JsValueList& values) | 
|  289 { |  291 { | 
|  290   JsWeakValuesLists::iterator it; |  292   JsWeakValuesLists::iterator it; | 
|  291   { |  293   { | 
|  292     std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); |  294     std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); | 
|  293     it = jsWeakValuesLists.emplace(jsWeakValuesLists.end()); |  295     it = jsWeakValuesLists.emplace(jsWeakValuesLists.end()); | 
|  294   } |  296   } | 
|  295   { |  297   { | 
|  296     JsContext context(*this); |  298     JsContext context(*this); | 
|  297     for (const auto& value : values) |  299     for (const auto& value : values) | 
|  298     { |  300     { | 
|  299       it->values.emplace_back(GetIsolate(), value.UnwrapValue()); |  301       it->values.emplace_back(GetIsolate(), value.UnwrapValue()); | 
|  300     } |  302     } | 
|  301   } |  303   } | 
|  302   JsWeakValuesID retValue; |  304   JsWeakValuesID retValue; | 
|  303   retValue.iterator = it; |  305   retValue.iterator = it; | 
|  304   return retValue; |  306   return retValue; | 
|  305 } |  307 } | 
|  306  |  308  | 
|  307 JsValueList JsEngine::TakeJsValues(const JsWeakValuesID& id) |  309 template <> JsValueList JSENGINEV8::TakeJsValues(const JsWeakValuesID& id) | 
|  308 { |  310 { | 
|  309   JsValueList retValue; |  311   JsValueList retValue; | 
|  310   { |  312   { | 
|  311     JsContext context(*this); |  313     JsContext context(*this); | 
|  312     for (const auto& v8Value : id.iterator->values) |  314     for (const auto& v8Value : id.iterator->values) | 
|  313     { |  315     { | 
|  314       retValue.emplace_back(JsValue(shared_from_this(), v8::Local<v8::Value>::Ne
     w(GetIsolate(), v8Value))); |  316       retValue.emplace_back(JsValue(shared_from_this(), v8::Local<v8::Value>::Ne
     w(GetIsolate(), v8Value))); | 
|  315     } |  317     } | 
|  316   } |  318   } | 
|  317   { |  319   { | 
|  318     std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); |  320     std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); | 
|  319     jsWeakValuesLists.erase(id.iterator); |  321     jsWeakValuesLists.erase(id.iterator); | 
|  320   } |  322   } | 
|  321   return retValue; |  323   return retValue; | 
|  322 } |  324 } | 
|  323  |  325  | 
|  324 AdblockPlus::JsValueList AdblockPlus::JsEngine::ConvertArguments(const v8::Funct
     ionCallbackInfo<v8::Value>& arguments) |  326 template <> AdblockPlus::JsValueList AdblockPlus::JSENGINEV8::ConvertArguments(c
     onst v8::FunctionCallbackInfo<v8::Value>& arguments) | 
|  325 { |  327 { | 
|  326   const JsContext context(*this); |  328   const JsContext context(*this); | 
|  327   JsValueList list; |  329   JsValueList list; | 
|  328   for (int i = 0; i < arguments.Length(); i++) |  330   for (int i = 0; i < arguments.Length(); i++) | 
|  329     list.push_back(JsValue(shared_from_this(), arguments[i])); |  331     list.push_back(JsValue(shared_from_this(), arguments[i])); | 
|  330   return list; |  332   return list; | 
|  331 } |  333 } | 
|  332  |  334  | 
|  333 void AdblockPlus::JsEngine::SetGlobalProperty(const std::string& name, |  335 void AdblockPlus::JSENGINEV8::SetGlobalProperty(const std::string& name, | 
|  334                                               const AdblockPlus::JsValue& value) |  336                                               const AdblockPlus::JsValue& value) | 
|  335 { |  337 { | 
|  336   auto global = GetGlobalObject(); |  338   auto global = GetGlobalObject(); | 
|  337   global.SetProperty(name, value); |  339   global.SetProperty(name, value); | 
|  338 } |  340 } | 
| OLD | NEW |