| Index: src/engine/Main.cpp | 
| diff --git a/src/engine/Main.cpp b/src/engine/Main.cpp | 
| index 1f5f17c4dc72f8faa3281f40635b5f644f8178a2..705d700095cdb97eaf44a940b6bae64ccfcbddce 100644 | 
| --- a/src/engine/Main.cpp | 
| +++ b/src/engine/Main.cpp | 
| @@ -15,497 +15,505 @@ | 
| * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| */ | 
|  | 
| -#include <AdblockPlus.h> | 
| -#include <functional> | 
| -#include <vector> | 
| -#include <thread> | 
| -#include <Windows.h> | 
| - | 
| -#include "../shared/AutoHandle.h" | 
| -#include "../shared/Communication.h" | 
| -#include "../shared/Dictionary.h" | 
| -#include "../shared/Utils.h" | 
| -#include "../shared/Version.h" | 
| -#include "../shared/CriticalSection.h" | 
| -#include "../shared/IE_version.h" | 
| -#include "AdblockPlus.h" | 
| -#include "Debug.h" | 
| -#include "Updater.h" | 
| - | 
| -namespace | 
| -{ | 
| -  std::auto_ptr<AdblockPlus::FilterEngine> filterEngine; | 
| -  std::auto_ptr<Updater> updater; | 
| -  int activeConnections = 0; | 
| -  CriticalSection activeConnectionsLock; | 
| -  HWND callbackWindow; | 
| - | 
| -  void WriteStrings(Communication::OutputBuffer& response, | 
| -      const std::vector<std::string>& strings) | 
| -  { | 
| -    int32_t count = static_cast<int32_t>(strings.size()); | 
| -    response << count; | 
| -    for (int32_t i = 0; i < count; i++) | 
| -      response << strings[i]; | 
| -  } | 
| - | 
| -  void WriteSubscriptions(Communication::OutputBuffer& response, | 
| -      const std::vector<AdblockPlus::SubscriptionPtr>& subscriptions) | 
| -  { | 
| -    int32_t count = static_cast<int32_t>(subscriptions.size()); | 
| -    response << count; | 
| -    for (int32_t i = 0; i < count; i++) | 
| -    { | 
| -      AdblockPlus::SubscriptionPtr subscription = subscriptions[i]; | 
| -      response << subscription->GetProperty("url")->AsString() | 
| -               << subscription->GetProperty("title")->AsString() | 
| -               << subscription->GetProperty("specialization")->AsString() | 
| -               << subscription->IsListed(); | 
| -    } | 
| -  } | 
| - | 
| -  bool updateAvailable; | 
| -  bool checkingForUpdate = false; | 
| -  void UpdateCallback(const std::string res) | 
| -  { | 
| -    UINT message; | 
| -    if (updateAvailable) | 
| -    { | 
| -      message = WM_DOWNLOADING_UPDATE; | 
| -    } | 
| -    else if (res.length() == 0) | 
| -    { | 
| -      message = WM_ALREADY_UP_TO_DATE; | 
| -    } | 
| -    else | 
| -    { | 
| -      message = WM_UPDATE_CHECK_ERROR; | 
| -    } | 
| -    if (callbackWindow) | 
| -    { | 
| -      SendMessage(callbackWindow, message, 0, 0); | 
| -      checkingForUpdate = false; | 
| -      callbackWindow = 0; | 
| -    } | 
| -    return; | 
| -  } | 
| - | 
| - | 
| -  CriticalSection firstRunLock; | 
| -  CriticalSection updateCheckLock; | 
| -  bool firstRunActionExecuted = false; | 
| -  AdblockPlus::ReferrerMapping referrerMapping; | 
| -  Communication::OutputBuffer HandleRequest(Communication::InputBuffer& request) | 
| -  { | 
| -    Communication::OutputBuffer response; | 
| - | 
| -    Communication::ProcType procedure; | 
| -    request >> procedure; | 
| -    switch (procedure) | 
| -    { | 
| -      case Communication::PROC_MATCHES: | 
| -      { | 
| -        std::string url; | 
| -        std::string type; | 
| -        std::string documentUrl; | 
| -        request >> url >> type >> documentUrl; | 
| -        referrerMapping.Add(url, documentUrl); | 
| -        AdblockPlus::FilterPtr filter = filterEngine->Matches(url, type, referrerMapping.BuildReferrerChain(documentUrl)); | 
| -        response << (filter && filter->GetType() != AdblockPlus::Filter::TYPE_EXCEPTION); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_GET_ELEMHIDE_SELECTORS: | 
| -      { | 
| -        std::string domain; | 
| -        request >> domain; | 
| -        WriteStrings(response, filterEngine->GetElementHidingSelectors(domain)); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_AVAILABLE_SUBSCRIPTIONS: | 
| -      { | 
| -        WriteSubscriptions(response, filterEngine->FetchAvailableSubscriptions()); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_LISTED_SUBSCRIPTIONS: | 
| -      { | 
| -        WriteSubscriptions(response, filterEngine->GetListedSubscriptions()); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_SET_SUBSCRIPTION: | 
| -      { | 
| -        std::string url; | 
| -        request >> url; | 
| - | 
| -        AdblockPlus::JsValuePtr valuePtr = filterEngine->GetPref("subscriptions_exceptionsurl"); | 
| -        std::string aaUrl = ""; | 
| -        if (!valuePtr->IsNull()) | 
| -        { | 
| -          aaUrl = valuePtr->AsString(); | 
| -        } | 
| -        std::vector<AdblockPlus::SubscriptionPtr> subscriptions = filterEngine->GetListedSubscriptions(); | 
| - | 
| -        // Remove all subscriptions, besides the Acceptable Ads | 
| -        for (size_t i = 0, count = subscriptions.size(); i < count; i++) | 
| -        { | 
| -          if (subscriptions[i]->GetProperty("url")->AsString() != aaUrl) | 
| -          { | 
| -            subscriptions[i]->RemoveFromList(); | 
| -          } | 
| -        } | 
| - | 
| -        filterEngine->GetSubscription(url)->AddToList(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_ADD_SUBSCRIPTION: | 
| -      { | 
| -        std::string url; | 
| -        request >> url; | 
| - | 
| -        filterEngine->GetSubscription(url)->AddToList(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_REMOVE_SUBSCRIPTION: | 
| -      { | 
| -        std::string url; | 
| -        request >> url; | 
| - | 
| -        filterEngine->GetSubscription(url)->RemoveFromList(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_UPDATE_ALL_SUBSCRIPTIONS: | 
| -      { | 
| -        std::vector<AdblockPlus::SubscriptionPtr> subscriptions = filterEngine->GetListedSubscriptions(); | 
| -        for (size_t i = 0, count = subscriptions.size(); i < count; i++) | 
| -          subscriptions[i]->UpdateFilters(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_GET_EXCEPTION_DOMAINS: | 
| -      { | 
| -        std::vector<AdblockPlus::FilterPtr> filters = filterEngine->GetListedFilters(); | 
| -        std::vector<std::string> domains; | 
| -        for (size_t i = 0, count = filters.size(); i < count; i++) | 
| -        { | 
| -          AdblockPlus::FilterPtr filter = filters[i]; | 
| -          if (filter->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION) | 
| -          { | 
| -            std::string text = filter->GetProperty("text")->AsString(); | 
| - | 
| -            //@@||example.com^$document | 
| -            const char prefix[] = "@@||"; | 
| -            const char suffix[] = "^$document"; | 
| -            const size_t prefixLen = strlen(prefix); | 
| -            const size_t suffixLen = strlen(suffix); | 
| -            if (!text.compare(0, prefixLen, prefix) && | 
| -                !text.compare(text.size() - suffixLen, suffixLen, suffix)) | 
| -            { | 
| -              domains.push_back(text.substr(prefixLen, text.size() - prefixLen - suffixLen)); | 
| -            } | 
| -          } | 
| -        } | 
| - | 
| -        WriteStrings(response, domains); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_IS_WHITELISTED_URL: | 
| -      { | 
| -        std::string url; | 
| -        request >> url; | 
| -        AdblockPlus::FilterPtr match = filterEngine->Matches(url, "DOCUMENT", url); | 
| -        response << (match && match->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_IS_ELEMHIDE_WHITELISTED_ON_URL: | 
| -      { | 
| -        std::string url; | 
| -        request >> url; | 
| -        AdblockPlus::FilterPtr match = filterEngine->Matches(url, "ELEMHIDE", url); | 
| -        response << (match && match->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_ADD_FILTER: | 
| -      { | 
| -        std::string text; | 
| -        request >> text; | 
| - | 
| -        filterEngine->GetFilter(text)->AddToList(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_REMOVE_FILTER: | 
| -      { | 
| -        std::string text; | 
| -        request >> text; | 
| -        filterEngine->GetFilter(text)->RemoveFromList(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_SET_PREF: | 
| -      { | 
| -        std::string prefName; | 
| -        request >> prefName; | 
| - | 
| -        Communication::ValueType valueType = request.GetType(); | 
| -        switch (valueType) | 
| -        { | 
| -        case Communication::TYPE_STRING: | 
| -          { | 
| -            std::string prefValue; | 
| -            request >> prefValue; | 
| -            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| -            break; | 
| -          } | 
| -        case Communication::TYPE_INT64: | 
| -          { | 
| -            int64_t prefValue; | 
| -            request >> prefValue; | 
| -            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| -            break; | 
| -          } | 
| -        case Communication::TYPE_INT32: | 
| -          { | 
| -            int prefValue; | 
| -            request >> prefValue; | 
| -            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| -            break; | 
| -          } | 
| -        case Communication::TYPE_BOOL: | 
| -          { | 
| -            bool prefValue; | 
| -            request >> prefValue; | 
| -            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| -            break; | 
| -          } | 
| -        default: | 
| -          break; | 
| -        } | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_GET_PREF: | 
| -      { | 
| -        std::string name; | 
| -        request >> name; | 
| - | 
| -        AdblockPlus::JsValuePtr valuePtr = filterEngine->GetPref(name); | 
| -        if (valuePtr->IsBool()) | 
| -        { | 
| -          response << true; | 
| -          response << valuePtr->AsBool(); | 
| -        } | 
| -        else if (valuePtr->IsNumber()) | 
| -        { | 
| -          response << true; | 
| -          response << valuePtr->AsInt(); | 
| -        } | 
| -        else if (valuePtr->IsString()) | 
| -        { | 
| -          response << true; | 
| -          response << valuePtr->AsString(); | 
| -        } | 
| -        else | 
| -        { | 
| -          // Report failure | 
| -          response << false; | 
| -        } | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_CHECK_FOR_UPDATES: | 
| -      { | 
| -        request >> (int32_t&)callbackWindow; | 
| -        CriticalSection::Lock lock(updateCheckLock); | 
| -        if (!checkingForUpdate) | 
| -        { | 
| -          updateAvailable = false; | 
| -          checkingForUpdate = true; | 
| -          filterEngine->ForceUpdateCheck(UpdateCallback); | 
| -        } | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_IS_FIRST_RUN_ACTION_NEEDED: | 
| -      { | 
| -        CriticalSection::Lock lock(firstRunLock); | 
| -        if (!firstRunActionExecuted && filterEngine->IsFirstRun()) | 
| -        { | 
| -          response << true; | 
| -          firstRunActionExecuted = true; | 
| -        } | 
| -        else | 
| -        { | 
| -          response << false; | 
| -        } | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_COMPARE_VERSIONS: | 
| -      { | 
| -        std::string v1, v2; | 
| -        request >> v1 >> v2; | 
| - | 
| -        response << filterEngine->CompareVersions(v1, v2); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_GET_DOCUMENTATION_LINK: | 
| -      { | 
| -        response << filterEngine->GetPref("documentation_link")->AsString(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_TOGGLE_PLUGIN_ENABLED: | 
| -      { | 
| -        filterEngine->SetPref("enabled", filterEngine->GetJsEngine()->NewValue(!filterEngine->GetPref("enabled")->AsBool())); | 
| -        response << filterEngine->GetPref("enabled")->AsBool(); | 
| -        break; | 
| -      } | 
| -      case Communication::PROC_GET_HOST: | 
| -      { | 
| -        std::string url; | 
| -        request >> url; | 
| -        std::string host = filterEngine->GetHostFromURL(url); | 
| -        if (host.empty()) | 
| -        { | 
| -          response << url; | 
| -        } | 
| -        else | 
| -        { | 
| -          response << host; | 
| -        } | 
| -        break; | 
| -      } | 
| -    } | 
| -    return response; | 
| -  } | 
| - | 
| -  void ClientThread(Communication::Pipe* pipe) | 
| -  { | 
| -    std::stringstream stream; | 
| -    stream << GetCurrentThreadId(); | 
| -    std::string threadId = stream.str(); | 
| -    std::string threadString = "(Thread ID: " + threadId + ")"; | 
| -    Debug("Client connected " + threadString); | 
| - | 
| -    { | 
| -      CriticalSection::Lock lock(activeConnectionsLock); | 
| -      activeConnections++; | 
| -    } | 
| - | 
| -    for (;;) | 
| -    { | 
| -      try | 
| -      { | 
| -        Communication::InputBuffer message = pipe->ReadMessage(); | 
| -        Communication::OutputBuffer response = HandleRequest(message); | 
| -        pipe->WriteMessage(response); | 
| -      } | 
| -      catch (const Communication::PipeDisconnectedError&) | 
| -      { | 
| -        break; | 
| -      } | 
| -      catch (const std::exception& e) | 
| -      { | 
| -        DebugException(e); | 
| -        break; | 
| -      } | 
| -    } | 
| - | 
| -    Debug("Client disconnected " + threadString); | 
| - | 
| -    { | 
| -      CriticalSection::Lock lock(activeConnectionsLock); | 
| -      activeConnections--; | 
| -      if (activeConnections < 1) | 
| -      { | 
| -        Debug("No connections left, shutting down the engine"); | 
| -        activeConnections = 0; | 
| -        exit(0); | 
| -      } | 
| -    } | 
| - | 
| -  } | 
| - | 
| -  void OnUpdateAvailable(AdblockPlus::JsValueList& params) | 
| -  { | 
| -    if (params.size() < 1) | 
| -    { | 
| -      Debug("updateAvailable event missing URL"); | 
| -      return; | 
| -    } | 
| -    updateAvailable = true; | 
| - | 
| -    updater->Update(params[0]->AsString()); | 
| -  } | 
| -} | 
| - | 
| -std::auto_ptr<AdblockPlus::FilterEngine> CreateFilterEngine(const std::wstring& locale) | 
| -{ | 
| -  AdblockPlus::AppInfo appInfo; | 
| -  appInfo.version = ToUtf8String(IEPLUGIN_VERSION); | 
| -  appInfo.name = "adblockplusie"; | 
| -#ifdef _WIN64 | 
| -  appInfo.application = "msie64"; | 
| -#else | 
| -  appInfo.application = "msie32"; | 
| -#endif | 
| -  appInfo.applicationVersion = ToUtf8String(AdblockPlus::IE::InstalledVersionString()); | 
| -  appInfo.locale = ToUtf8String(locale); | 
| -#ifdef ADBLOCK_PLUS_TEST_MODE | 
| -  appInfo.developmentBuild = true; | 
| -#else | 
| -  appInfo.developmentBuild = false; | 
| -#endif | 
| - | 
| -  AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::New(appInfo); | 
| -  jsEngine->SetEventCallback("updateAvailable", &OnUpdateAvailable); | 
| - | 
| -  std::string dataPath = ToUtf8String(GetAppDataPath()); | 
| -  dynamic_cast<AdblockPlus::DefaultFileSystem*>(jsEngine->GetFileSystem().get())->SetBasePath(dataPath); | 
| -  std::auto_ptr<AdblockPlus::FilterEngine> filterEngine(new AdblockPlus::FilterEngine(jsEngine)); | 
| -  return filterEngine; | 
| -} | 
| - | 
| -int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) | 
| -{ | 
| -  AutoHandle mutex(CreateMutexW(0, false, L"AdblockPlusEngine")); | 
| -  if (!mutex) | 
| -  { | 
| -    DebugLastError("CreateMutex failed"); | 
| -    return 1; | 
| -  } | 
| - | 
| -  if (GetLastError() == ERROR_ALREADY_EXISTS) | 
| -  { | 
| -    DebugLastError("Named pipe exists, another engine instance appears to be running"); | 
| -    return 1; | 
| -  } | 
| - | 
| -  int argc; | 
| -  LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); | 
| -  std::wstring locale(argc >= 2 ? argv[1] : L""); | 
| -  LocalFree(argv); | 
| -  Dictionary::Create(locale); | 
| -  filterEngine = CreateFilterEngine(locale); | 
| -  updater.reset(new Updater(filterEngine->GetJsEngine())); | 
| - | 
| -  for (;;) | 
| -  { | 
| -    try | 
| -    { | 
| -      auto pipe = std::make_shared<Communication::Pipe>(Communication::pipeName, Communication::Pipe::MODE_CREATE); | 
| - | 
| -      // TODO: we should wait for the finishing of the thread before exiting from this function. | 
| -      // It works now in most cases because the browser waits for the response in the pipe, and the | 
| -      // thread has time to finish while this response is being processed and the browser is | 
| -      // disposing all its stuff. | 
| -      std::thread([pipe]() | 
| -      { | 
| -        ClientThread(pipe.get()); | 
| -      }).detach(); | 
| -    } | 
| -    catch(const std::system_error& ex) | 
| -    { | 
| -      DebugException(ex); | 
| -      return 1; | 
| -    } | 
| -    catch (const std::runtime_error& e) | 
| -    { | 
| -      DebugException(e); | 
| -      return 1; | 
| -    } | 
| -  } | 
| - | 
| -  return 0; | 
| -} | 
| +#include <AdblockPlus.h> | 
| +#include <functional> | 
| +#include <vector> | 
| +#include <thread> | 
| +#include <Windows.h> | 
| + | 
| +#include "../shared/AutoHandle.h" | 
| +#include "../shared/Communication.h" | 
| +#include "../shared/Dictionary.h" | 
| +#include "../shared/Utils.h" | 
| +#include "../shared/Version.h" | 
| +#include "../shared/CriticalSection.h" | 
| +#include "../shared/IE_version.h" | 
| +#include "../shared/ContentType.h" | 
| +#include "AdblockPlus.h" | 
| +#include "Debug.h" | 
| +#include "Updater.h" | 
| + | 
| +namespace | 
| +{ | 
| +  std::auto_ptr<AdblockPlus::FilterEngine> filterEngine; | 
| +  std::auto_ptr<Updater> updater; | 
| +  int activeConnections = 0; | 
| +  CriticalSection activeConnectionsLock; | 
| +  HWND callbackWindow; | 
| + | 
| +  void WriteStrings(Communication::OutputBuffer& response, | 
| +      const std::vector<std::string>& strings) | 
| +  { | 
| +    int32_t count = static_cast<int32_t>(strings.size()); | 
| +    response << count; | 
| +    for (int32_t i = 0; i < count; i++) | 
| +      response << strings[i]; | 
| +  } | 
| + | 
| +  void WriteSubscriptions(Communication::OutputBuffer& response, | 
| +      const std::vector<AdblockPlus::SubscriptionPtr>& subscriptions) | 
| +  { | 
| +    int32_t count = static_cast<int32_t>(subscriptions.size()); | 
| +    response << count; | 
| +    for (int32_t i = 0; i < count; i++) | 
| +    { | 
| +      AdblockPlus::SubscriptionPtr subscription = subscriptions[i]; | 
| +      response << subscription->GetProperty("url")->AsString() | 
| +               << subscription->GetProperty("title")->AsString() | 
| +               << subscription->GetProperty("specialization")->AsString() | 
| +               << subscription->IsListed(); | 
| +    } | 
| +  } | 
| + | 
| +  bool updateAvailable; | 
| +  bool checkingForUpdate = false; | 
| +  void UpdateCallback(const std::string res) | 
| +  { | 
| +    UINT message; | 
| +    if (updateAvailable) | 
| +    { | 
| +      message = WM_DOWNLOADING_UPDATE; | 
| +    } | 
| +    else if (res.length() == 0) | 
| +    { | 
| +      message = WM_ALREADY_UP_TO_DATE; | 
| +    } | 
| +    else | 
| +    { | 
| +      message = WM_UPDATE_CHECK_ERROR; | 
| +    } | 
| +    if (callbackWindow) | 
| +    { | 
| +      SendMessage(callbackWindow, message, 0, 0); | 
| +      checkingForUpdate = false; | 
| +      callbackWindow = 0; | 
| +    } | 
| +    return; | 
| +  } | 
| + | 
| + | 
| +  CriticalSection firstRunLock; | 
| +  CriticalSection updateCheckLock; | 
| +  bool firstRunActionExecuted = false; | 
| +  AdblockPlus::ReferrerMapping referrerMapping; | 
| +  Communication::OutputBuffer HandleRequest(Communication::InputBuffer& request) | 
| +  { | 
| +    Communication::OutputBuffer response; | 
| + | 
| +    Communication::ProcType procedure; | 
| +    request >> procedure; | 
| +    switch (procedure) | 
| +    { | 
| +      case Communication::PROC_MATCHES: | 
| +      { | 
| +        std::string url; | 
| +        using namespace AdblockPlus; | 
| +        FilterEngine::ContentType contentType; | 
| +        std::string documentUrl; | 
| +        request >> url >> contentType >> documentUrl; | 
| +        auto isFrame = contentType == FilterEngine::ContentType::CONTENT_TYPE_SUBDOCUMENT ? | 
| +          ReferrerMapping::FrameIndicator::FRAME_INDICATOR_FRAME: | 
| +          ReferrerMapping::FrameIndicator::FRAME_INDICATOR_NOT_FRAME; | 
| + | 
| +        referrerMapping.Add(url, documentUrl, isFrame); | 
| +        AdblockPlus::FilterPtr filter = filterEngine->Matches(url, contentType, referrerMapping.BuildFrameStructure(documentUrl)); | 
| +        response << (filter && filter->GetType() != AdblockPlus::Filter::TYPE_EXCEPTION); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_GET_ELEMHIDE_SELECTORS: | 
| +      { | 
| +        std::string domain; | 
| +        request >> domain; | 
| +        WriteStrings(response, filterEngine->GetElementHidingSelectors(domain)); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_AVAILABLE_SUBSCRIPTIONS: | 
| +      { | 
| +        WriteSubscriptions(response, filterEngine->FetchAvailableSubscriptions()); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_LISTED_SUBSCRIPTIONS: | 
| +      { | 
| +        WriteSubscriptions(response, filterEngine->GetListedSubscriptions()); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_SET_SUBSCRIPTION: | 
| +      { | 
| +        std::string url; | 
| +        request >> url; | 
| + | 
| +        AdblockPlus::JsValuePtr valuePtr = filterEngine->GetPref("subscriptions_exceptionsurl"); | 
| +        std::string aaUrl = ""; | 
| +        if (!valuePtr->IsNull()) | 
| +        { | 
| +          aaUrl = valuePtr->AsString(); | 
| +        } | 
| +        std::vector<AdblockPlus::SubscriptionPtr> subscriptions = filterEngine->GetListedSubscriptions(); | 
| + | 
| +        // Remove all subscriptions, besides the Acceptable Ads | 
| +        for (size_t i = 0, count = subscriptions.size(); i < count; i++) | 
| +        { | 
| +          if (subscriptions[i]->GetProperty("url")->AsString() != aaUrl) | 
| +          { | 
| +            subscriptions[i]->RemoveFromList(); | 
| +          } | 
| +        } | 
| + | 
| +        filterEngine->GetSubscription(url)->AddToList(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_ADD_SUBSCRIPTION: | 
| +      { | 
| +        std::string url; | 
| +        request >> url; | 
| + | 
| +        filterEngine->GetSubscription(url)->AddToList(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_REMOVE_SUBSCRIPTION: | 
| +      { | 
| +        std::string url; | 
| +        request >> url; | 
| + | 
| +        filterEngine->GetSubscription(url)->RemoveFromList(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_UPDATE_ALL_SUBSCRIPTIONS: | 
| +      { | 
| +        std::vector<AdblockPlus::SubscriptionPtr> subscriptions = filterEngine->GetListedSubscriptions(); | 
| +        for (size_t i = 0, count = subscriptions.size(); i < count; i++) | 
| +          subscriptions[i]->UpdateFilters(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_GET_EXCEPTION_DOMAINS: | 
| +      { | 
| +        std::vector<AdblockPlus::FilterPtr> filters = filterEngine->GetListedFilters(); | 
| +        std::vector<std::string> domains; | 
| +        for (size_t i = 0, count = filters.size(); i < count; i++) | 
| +        { | 
| +          AdblockPlus::FilterPtr filter = filters[i]; | 
| +          if (filter->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION) | 
| +          { | 
| +            std::string text = filter->GetProperty("text")->AsString(); | 
| + | 
| +            //@@||example.com^$document | 
| +            const char prefix[] = "@@||"; | 
| +            const char suffix[] = "^$document"; | 
| +            const size_t prefixLen = strlen(prefix); | 
| +            const size_t suffixLen = strlen(suffix); | 
| +            if (!text.compare(0, prefixLen, prefix) && | 
| +                !text.compare(text.size() - suffixLen, suffixLen, suffix)) | 
| +            { | 
| +              domains.push_back(text.substr(prefixLen, text.size() - prefixLen - suffixLen)); | 
| +            } | 
| +          } | 
| +        } | 
| + | 
| +        WriteStrings(response, domains); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_IS_WHITELISTED_URL: | 
| +      { | 
| +        std::string url; | 
| +        request >> url; | 
| +        AdblockPlus::FilterPtr match = filterEngine->Matches(url, | 
| +          AdblockPlus::FilterEngine::ContentType::CONTENT_TYPE_DOCUMENT, url); | 
| +        response << (match && match->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_IS_ELEMHIDE_WHITELISTED_ON_URL: | 
| +      { | 
| +        std::string url; | 
| +        request >> url; | 
| +        AdblockPlus::FilterPtr match = filterEngine->Matches(url, | 
| +          AdblockPlus::FilterEngine::ContentType::CONTENT_TYPE_ELEMHIDE, url); | 
| +        response << (match && match->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_ADD_FILTER: | 
| +      { | 
| +        std::string text; | 
| +        request >> text; | 
| + | 
| +        filterEngine->GetFilter(text)->AddToList(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_REMOVE_FILTER: | 
| +      { | 
| +        std::string text; | 
| +        request >> text; | 
| +        filterEngine->GetFilter(text)->RemoveFromList(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_SET_PREF: | 
| +      { | 
| +        std::string prefName; | 
| +        request >> prefName; | 
| + | 
| +        Communication::ValueType valueType = request.GetType(); | 
| +        switch (valueType) | 
| +        { | 
| +        case Communication::TYPE_STRING: | 
| +          { | 
| +            std::string prefValue; | 
| +            request >> prefValue; | 
| +            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| +            break; | 
| +          } | 
| +        case Communication::TYPE_INT64: | 
| +          { | 
| +            int64_t prefValue; | 
| +            request >> prefValue; | 
| +            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| +            break; | 
| +          } | 
| +        case Communication::TYPE_INT32: | 
| +          { | 
| +            int prefValue; | 
| +            request >> prefValue; | 
| +            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| +            break; | 
| +          } | 
| +        case Communication::TYPE_BOOL: | 
| +          { | 
| +            bool prefValue; | 
| +            request >> prefValue; | 
| +            filterEngine->SetPref(prefName, filterEngine->GetJsEngine()->NewValue(prefValue)); | 
| +            break; | 
| +          } | 
| +        default: | 
| +          break; | 
| +        } | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_GET_PREF: | 
| +      { | 
| +        std::string name; | 
| +        request >> name; | 
| + | 
| +        AdblockPlus::JsValuePtr valuePtr = filterEngine->GetPref(name); | 
| +        if (valuePtr->IsBool()) | 
| +        { | 
| +          response << true; | 
| +          response << valuePtr->AsBool(); | 
| +        } | 
| +        else if (valuePtr->IsNumber()) | 
| +        { | 
| +          response << true; | 
| +          response << valuePtr->AsInt(); | 
| +        } | 
| +        else if (valuePtr->IsString()) | 
| +        { | 
| +          response << true; | 
| +          response << valuePtr->AsString(); | 
| +        } | 
| +        else | 
| +        { | 
| +          // Report failure | 
| +          response << false; | 
| +        } | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_CHECK_FOR_UPDATES: | 
| +      { | 
| +        request >> (int32_t&)callbackWindow; | 
| +        CriticalSection::Lock lock(updateCheckLock); | 
| +        if (!checkingForUpdate) | 
| +        { | 
| +          updateAvailable = false; | 
| +          checkingForUpdate = true; | 
| +          filterEngine->ForceUpdateCheck(UpdateCallback); | 
| +        } | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_IS_FIRST_RUN_ACTION_NEEDED: | 
| +      { | 
| +        CriticalSection::Lock lock(firstRunLock); | 
| +        if (!firstRunActionExecuted && filterEngine->IsFirstRun()) | 
| +        { | 
| +          response << true; | 
| +          firstRunActionExecuted = true; | 
| +        } | 
| +        else | 
| +        { | 
| +          response << false; | 
| +        } | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_COMPARE_VERSIONS: | 
| +      { | 
| +        std::string v1, v2; | 
| +        request >> v1 >> v2; | 
| + | 
| +        response << filterEngine->CompareVersions(v1, v2); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_GET_DOCUMENTATION_LINK: | 
| +      { | 
| +        response << filterEngine->GetPref("documentation_link")->AsString(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_TOGGLE_PLUGIN_ENABLED: | 
| +      { | 
| +        filterEngine->SetPref("enabled", filterEngine->GetJsEngine()->NewValue(!filterEngine->GetPref("enabled")->AsBool())); | 
| +        response << filterEngine->GetPref("enabled")->AsBool(); | 
| +        break; | 
| +      } | 
| +      case Communication::PROC_GET_HOST: | 
| +      { | 
| +        std::string url; | 
| +        request >> url; | 
| +        std::string host = filterEngine->GetHostFromURL(url); | 
| +        if (host.empty()) | 
| +        { | 
| +          response << url; | 
| +        } | 
| +        else | 
| +        { | 
| +          response << host; | 
| +        } | 
| +        break; | 
| +      } | 
| +    } | 
| +    return response; | 
| +  } | 
| + | 
| +  void ClientThread(Communication::Pipe* pipe) | 
| +  { | 
| +    std::stringstream stream; | 
| +    stream << GetCurrentThreadId(); | 
| +    std::string threadId = stream.str(); | 
| +    std::string threadString = "(Thread ID: " + threadId + ")"; | 
| +    Debug("Client connected " + threadString); | 
| + | 
| +    { | 
| +      CriticalSection::Lock lock(activeConnectionsLock); | 
| +      activeConnections++; | 
| +    } | 
| + | 
| +    for (;;) | 
| +    { | 
| +      try | 
| +      { | 
| +        Communication::InputBuffer message = pipe->ReadMessage(); | 
| +        Communication::OutputBuffer response = HandleRequest(message); | 
| +        pipe->WriteMessage(response); | 
| +      } | 
| +      catch (const Communication::PipeDisconnectedError&) | 
| +      { | 
| +        break; | 
| +      } | 
| +      catch (const std::exception& e) | 
| +      { | 
| +        DebugException(e); | 
| +        break; | 
| +      } | 
| +    } | 
| + | 
| +    Debug("Client disconnected " + threadString); | 
| + | 
| +    { | 
| +      CriticalSection::Lock lock(activeConnectionsLock); | 
| +      activeConnections--; | 
| +      if (activeConnections < 1) | 
| +      { | 
| +        Debug("No connections left, shutting down the engine"); | 
| +        activeConnections = 0; | 
| +        exit(0); | 
| +      } | 
| +    } | 
| + | 
| +  } | 
| + | 
| +  void OnUpdateAvailable(AdblockPlus::JsValueList& params) | 
| +  { | 
| +    if (params.size() < 1) | 
| +    { | 
| +      Debug("updateAvailable event missing URL"); | 
| +      return; | 
| +    } | 
| +    updateAvailable = true; | 
| + | 
| +    updater->Update(params[0]->AsString()); | 
| +  } | 
| +} | 
| + | 
| +std::auto_ptr<AdblockPlus::FilterEngine> CreateFilterEngine(const std::wstring& locale) | 
| +{ | 
| +  AdblockPlus::AppInfo appInfo; | 
| +  appInfo.version = ToUtf8String(IEPLUGIN_VERSION); | 
| +  appInfo.name = "adblockplusie"; | 
| +#ifdef _WIN64 | 
| +  appInfo.application = "msie64"; | 
| +#else | 
| +  appInfo.application = "msie32"; | 
| +#endif | 
| +  appInfo.applicationVersion = ToUtf8String(AdblockPlus::IE::InstalledVersionString()); | 
| +  appInfo.locale = ToUtf8String(locale); | 
| +#ifdef ADBLOCK_PLUS_TEST_MODE | 
| +  appInfo.developmentBuild = true; | 
| +#else | 
| +  appInfo.developmentBuild = false; | 
| +#endif | 
| + | 
| +  AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::New(appInfo); | 
| +  jsEngine->SetEventCallback("updateAvailable", &OnUpdateAvailable); | 
| + | 
| +  std::string dataPath = ToUtf8String(GetAppDataPath()); | 
| +  dynamic_cast<AdblockPlus::DefaultFileSystem*>(jsEngine->GetFileSystem().get())->SetBasePath(dataPath); | 
| +  std::auto_ptr<AdblockPlus::FilterEngine> filterEngine(new AdblockPlus::FilterEngine(jsEngine)); | 
| +  return filterEngine; | 
| +} | 
| + | 
| +int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) | 
| +{ | 
| +  AutoHandle mutex(CreateMutexW(0, false, L"AdblockPlusEngine")); | 
| +  if (!mutex) | 
| +  { | 
| +    DebugLastError("CreateMutex failed"); | 
| +    return 1; | 
| +  } | 
| + | 
| +  if (GetLastError() == ERROR_ALREADY_EXISTS) | 
| +  { | 
| +    DebugLastError("Named pipe exists, another engine instance appears to be running"); | 
| +    return 1; | 
| +  } | 
| + | 
| +  int argc; | 
| +  LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); | 
| +  std::wstring locale(argc >= 2 ? argv[1] : L""); | 
| +  LocalFree(argv); | 
| +  Dictionary::Create(locale); | 
| +  filterEngine = CreateFilterEngine(locale); | 
| +  updater.reset(new Updater(filterEngine->GetJsEngine())); | 
| + | 
| +  for (;;) | 
| +  { | 
| +    try | 
| +    { | 
| +      auto pipe = std::make_shared<Communication::Pipe>(Communication::pipeName, Communication::Pipe::MODE_CREATE); | 
| + | 
| +      // TODO: we should wait for the finishing of the thread before exiting from this function. | 
| +      // It works now in most cases because the browser waits for the response in the pipe, and the | 
| +      // thread has time to finish while this response is being processed and the browser is | 
| +      // disposing all its stuff. | 
| +      std::thread([pipe]() | 
| +      { | 
| +        ClientThread(pipe.get()); | 
| +      }).detach(); | 
| +    } | 
| +    catch(const std::system_error& ex) | 
| +    { | 
| +      DebugException(ex); | 
| +      return 1; | 
| +    } | 
| +    catch (const std::runtime_error& e) | 
| +    { | 
| +      DebugException(e); | 
| +      return 1; | 
| +    } | 
| +  } | 
| + | 
| +  return 0; | 
| +} | 
|  |