FilterEngine::FilterEngine(JsEnginePtr jsEngine,
                           const FilterEngine::Prefs& preconfiguredPrefs)
    : jsEngine(jsEngine), initialized(false), firstRun(false), updateCheckId(0)
{
  jsEngine->SetEventCallback("_init", std::bind(&FilterEngine::InitDone,
      this, std::placeholders::_1));

  {
    // Lock the JS engine while we are loading scripts, no timeouts should fire
    // until we are done.
    const JsContext context(jsEngine);

    // Set the preconfigured prefs
    JsValuePtr preconfiguredPrefsObject = jsEngine->NewObject();
    for (FilterEngine::Prefs::const_iterator it = preconfiguredPrefs.begin();
         it != preconfiguredPrefs.end(); it++)
    {
      preconfiguredPrefsObject->SetProperty(it->first, it->second);
    }
    jsEngine->SetGlobalProperty("_preconfiguredPrefs", preconfiguredPrefsObject);
    // Load adblockplus scripts
    for (int i = 0; !jsSources[i].empty(); i += 2)
      jsEngine->Evaluate(jsSources[i + 1], jsSources[i]);
  }

  // TODO: This should really be implemented via a conditional variable
  while (!initialized)
    ::Sleep(10);
}
FilterEngine::FilterEngine(JsEnginePtr jsEngine)
    : jsEngine(jsEngine), initialized(false), firstRun(false), updateCheckId(0)
{
  jsEngine->SetEventCallback("init", std::tr1::bind(&FilterEngine::InitDone,
      this, std::tr1::placeholders::_1));

  {
    // Lock the JS engine while we are loading scripts, no timeouts should fire
    // until we are done.
    const JsContext context(jsEngine);
    for (int i = 0; !jsSources[i].empty(); i += 2)
      jsEngine->Evaluate(jsSources[i + 1], jsSources[i]);
  }

  // TODO: This should really be implemented via a conditional variable
  while (!initialized)
    ::Sleep(10);
}
JsValuePtr FileSystemJsObject::Setup(JsEnginePtr jsEngine, JsValuePtr obj)
{
  obj->SetProperty("read", jsEngine->NewCallback(::ReadCallback));
  obj->SetProperty("write", jsEngine->NewCallback(::WriteCallback));
  obj->SetProperty("move", jsEngine->NewCallback(::MoveCallback));
  obj->SetProperty("remove", jsEngine->NewCallback(::RemoveCallback));
  obj->SetProperty("stat", jsEngine->NewCallback(::StatCallback));
  obj->SetProperty("resolve", jsEngine->NewCallback(::ResolveCallback));
  return obj;
}
JsValuePtr GlobalJsObject::Setup(JsEnginePtr jsEngine, const AppInfo& appInfo,
    JsValuePtr obj)
{
  obj->SetProperty("setTimeout", jsEngine->NewCallback(::SetTimeoutCallback));
  obj->SetProperty("_triggerEvent", jsEngine->NewCallback(::TriggerEventCallback));
  obj->SetProperty("_fileSystem",
      FileSystemJsObject::Setup(jsEngine, jsEngine->NewObject()));
  obj->SetProperty("_webRequest",
      WebRequestJsObject::Setup(jsEngine, jsEngine->NewObject()));
  obj->SetProperty("console",
      ConsoleJsObject::Setup(jsEngine, jsEngine->NewObject()));
  obj->SetProperty("_appInfo",
      AppInfoJsObject::Setup(jsEngine, appInfo, jsEngine->NewObject()));
  return obj;
}