| Index: Shared/AdblockPlusClient.cpp | 
| =================================================================== | 
| --- a/Shared/AdblockPlusClient.cpp | 
| +++ b/Shared/AdblockPlusClient.cpp | 
| @@ -8,35 +8,177 @@ | 
| #include "PluginHttpRequest.h" | 
| #include "PluginMutex.h" | 
| #include "PluginClass.h" | 
| +#include "PluginUtil.h" | 
| #include "AdblockPlusClient.h" | 
| +namespace | 
| +{ | 
| + // TODO: GetUserName, pipeName, bufferSize, AutoHandle, ReadMessage, WriteMessage, MarshalStrings and UnmarshalStrings are | 
| + // duplicated in AdblockPlusEngine. We should find a way to reuse them. | 
| + | 
| + std::wstring GetUserName() | 
| + { | 
| + const DWORD maxLength = UNLEN + 1; | 
| + std::auto_ptr<wchar_t> buffer(new wchar_t[maxLength]); | 
| + DWORD length = maxLength; | 
| + if (!::GetUserName(buffer.get(), &length)) | 
| + { | 
| + std::stringstream stream; | 
| + stream << "Failed to get the current user's name (Error code: " << GetLastError() << ")"; | 
| + throw std::runtime_error("Failed to get the current user's name"); | 
| + } | 
| + return std::wstring(buffer.get(), length); | 
| + } | 
| + | 
| + const std::wstring pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); | 
| + const int bufferSize = 1024; | 
| + | 
| + class AutoHandle | 
| + { | 
| + public: | 
| + AutoHandle() | 
| + { | 
| + } | 
| + | 
| + AutoHandle(HANDLE handle) : handle(handle) | 
| + { | 
| + } | 
| + | 
| + ~AutoHandle() | 
| + { | 
| + CloseHandle(handle); | 
| + } | 
| + | 
| + HANDLE get() | 
| + { | 
| + return handle; | 
| + } | 
| + | 
| + private: | 
| + HANDLE handle; | 
| + | 
| + AutoHandle(const AutoHandle& autoHandle); | 
| + AutoHandle& operator=(const AutoHandle& autoHandle); | 
| + }; | 
| + | 
| + std::string MarshalStrings(const std::vector<std::string>& strings) | 
| + { | 
| + // TODO: This is some pretty hacky marshalling, replace it with something more robust | 
| + std::string marshalledStrings; | 
| + for (std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); it++) | 
| + marshalledStrings += *it + ';'; | 
| + return marshalledStrings; | 
| + } | 
| + | 
| + std::vector<std::string> UnmarshalStrings(const std::string& message) | 
| + { | 
| + std::stringstream stream(message); | 
| + std::vector<std::string> strings; | 
| + std::string string; | 
| + while (std::getline(stream, string, ';')) | 
| + strings.push_back(string); | 
| + return strings; | 
| + } | 
| + | 
| + std::string ReadMessage(HANDLE pipe) | 
| + { | 
| + std::stringstream stream; | 
| + std::auto_ptr<char> buffer(new char[bufferSize]); | 
| + bool doneReading = false; | 
| + while (!doneReading) | 
| + { | 
| + DWORD bytesRead; | 
| + if (ReadFile(pipe, buffer.get(), bufferSize * sizeof(char), &bytesRead, 0)) | 
| + doneReading = true; | 
| + else if (GetLastError() != ERROR_MORE_DATA) | 
| + { | 
| + std::stringstream stream; | 
| + stream << "Error reading from pipe: " << GetLastError(); | 
| + throw std::runtime_error(stream.str()); | 
| + } | 
| + stream << std::string(buffer.get(), bytesRead); | 
| + } | 
| + return stream.str(); | 
| + } | 
| + | 
| + void WriteMessage(HANDLE pipe, const std::string& message) | 
| + { | 
| + DWORD bytesWritten; | 
| + if (!WriteFile(pipe, message.c_str(), message.length(), &bytesWritten, 0)) | 
| + throw std::runtime_error("Failed to write to pipe"); | 
| + } | 
| + | 
| + HANDLE OpenPipe(const std::wstring& name) | 
| + { | 
| + if (WaitNamedPipe(name.c_str(), 5000)) | 
| + return CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); | 
| + return INVALID_HANDLE_VALUE; | 
| + } | 
| + | 
| + void SpawnAdblockPlusEngine() | 
| + { | 
| + std::wstring engineExecutablePath = DllDir() + L"AdblockPlusEngine.exe"; | 
| + STARTUPINFO startupInfo = {}; | 
| + PROCESS_INFORMATION processInformation = {}; | 
| + | 
| + HANDLE token; | 
| + OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &token); | 
| + HANDLE newToken; | 
| + DuplicateTokenEx(token, 0, 0, SecurityImpersonation, TokenPrimary, &newToken); | 
| + | 
| + if (!CreateProcessAsUser(newToken, 0, const_cast<wchar_t*>(engineExecutablePath.c_str()), 0, 0, 0, 0, 0, 0, | 
| + &startupInfo, &processInformation)) | 
| + { | 
| + DWORD error = GetLastError(); | 
| + throw std::runtime_error("Failed to start Adblock Plus Engine"); | 
| + } | 
| + | 
| + CloseHandle(processInformation.hProcess); | 
| + CloseHandle(processInformation.hThread); | 
| + } | 
| + | 
| + HANDLE OpenAdblockPlusEnginePipe() | 
| + { | 
| + try | 
| + { | 
| + HANDLE pipe = OpenPipe(pipeName); | 
| + if (pipe == INVALID_HANDLE_VALUE) | 
| + { | 
| + SpawnAdblockPlusEngine(); | 
| + | 
| + int timeout = 10000; | 
| + while ((pipe = OpenPipe(pipeName)) == INVALID_HANDLE_VALUE) | 
| + { | 
| + const int step = 10; | 
| + Sleep(step); | 
| + timeout -= step; | 
| + if (timeout <= 0) | 
| + throw std::runtime_error("Unable to open Adblock Plus Engine pipe"); | 
| + } | 
| + } | 
| + | 
| + DWORD mode = PIPE_READMODE_MESSAGE; | 
| + if (!SetNamedPipeHandleState(pipe, &mode, 0, 0)) | 
| + throw std::runtime_error("SetNamedPipeHandleState failed"); | 
| + | 
| + return pipe; | 
| + } | 
| + catch(std::exception e) | 
| + { | 
| + DEBUG_GENERAL(e.what()); | 
| + return INVALID_HANDLE_VALUE; | 
| + } | 
| + } | 
| +} | 
| CAdblockPlusClient* CAdblockPlusClient::s_instance = NULL; | 
| - | 
| CAdblockPlusClient::CAdblockPlusClient() : CPluginClientBase() | 
| { | 
| - try | 
| - { | 
| - DEBUG_GENERAL("Building client"); | 
| - m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter()); | 
| - AdblockPlus::AppInfo appInfo; | 
| - appInfo.name = "adblockplusie"; | 
| - appInfo.version = CT2CA(_T(IEPLUGIN_VERSION), CP_UTF8); | 
| - appInfo.platform = "msie"; | 
| - | 
| - DEBUG_GENERAL(L"Building engine"); | 
| + m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter()); | 
| +} | 
| - JsEnginePtr jsEngine(AdblockPlus::JsEngine::New(appInfo)); | 
| - filterEngine = std::auto_ptr<AdblockPlus::FilterEngine>(new AdblockPlus::FilterEngine(jsEngine)); | 
| - | 
| - } | 
| - catch(std::exception ex) | 
| - { | 
| - DEBUG_GENERAL(ex.what()); | 
| - } | 
| -} | 
| CAdblockPlusClient::~CAdblockPlusClient() | 
| { | 
| s_instance = NULL; | 
| @@ -63,10 +205,6 @@ | 
| return instance; | 
| } | 
| -AdblockPlus::FilterEngine* CAdblockPlusClient::GetFilterEngine() | 
| -{ | 
| - return filterEngine.get(); | 
| -} | 
| bool CAdblockPlusClient::ShouldBlock(CString src, int contentType, const CString& domain, bool addDebug) | 
| { | 
| @@ -163,3 +301,78 @@ | 
| RegCloseKey(hKey); | 
| return (int)(version[0] - 48); | 
| } | 
| + | 
| +std::string CallAdblockPlusEngineProcedure(const std::vector<std::string>& args) | 
| +{ | 
| + AutoHandle pipe(OpenAdblockPlusEnginePipe()); | 
| + WriteMessage(pipe.get(), MarshalStrings(args)); | 
| + return ReadMessage(pipe.get()); | 
| +} | 
| + | 
| +bool CAdblockPlusClient::Matches(const std::string& url, const std::string& contentType, const std::string& domain) | 
| +{ | 
| + std::vector<std::string> args; | 
| + args.push_back("Matches"); | 
| + args.push_back(url); | 
| + args.push_back(contentType); | 
| + args.push_back(domain); | 
| + | 
| + try | 
| + { | 
| + std::string response = CallAdblockPlusEngineProcedure(args); | 
| + return response == "1"; | 
| + } | 
| + catch (const std::exception& e) | 
| + { | 
| + DEBUG_GENERAL(e.what()); | 
| + return false; | 
| + } | 
| +} | 
| + | 
| +std::vector<std::string> CAdblockPlusClient::GetElementHidingSelectors(std::string domain) | 
| +{ | 
| + std::vector<std::string> args; | 
| + args.push_back("GetElementHidingSelectors"); | 
| + args.push_back(domain); | 
| + | 
| + try | 
| + { | 
| + std::string response = CallAdblockPlusEngineProcedure(args); | 
| + return UnmarshalStrings(response); | 
| + } | 
| + catch (const std::exception& e) | 
| + { | 
| + DEBUG_GENERAL(e.what()); | 
| + return std::vector<std::string>(); | 
| + } | 
| +} | 
| + | 
| +std::vector<AdblockPlus::SubscriptionPtr> CAdblockPlusClient::FetchAvailableSubscriptions() | 
| +{ | 
| + //TODO: implement this | 
| + return std::vector<AdblockPlus::SubscriptionPtr>(); | 
| +} | 
| + | 
| +std::vector<AdblockPlus::FilterPtr> CAdblockPlusClient::GetListedFilters() | 
| +{ | 
| + //TODO: implement this | 
| + return std::vector<AdblockPlus::FilterPtr>(); | 
| +} | 
| + | 
| +AdblockPlus::FilterPtr CAdblockPlusClient::GetFilter(std::string text) | 
| +{ | 
| + //TODO: implement this | 
| + return AdblockPlus::FilterPtr(); | 
| +} | 
| + | 
| +std::vector<AdblockPlus::SubscriptionPtr> CAdblockPlusClient::GetListedSubscriptions() | 
| +{ | 
| + //TODO: implement this | 
| + return std::vector<AdblockPlus::SubscriptionPtr>(); | 
| +} | 
| + | 
| +AdblockPlus::SubscriptionPtr CAdblockPlusClient::GetSubscription(std::string url) | 
| +{ | 
| + //TODO: imlement this | 
| + return AdblockPlus::SubscriptionPtr(); | 
| +} |