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(); |
+} |