Index: Shared/AdblockPlusClient.cpp |
=================================================================== |
--- a/Shared/AdblockPlusClient.cpp |
+++ b/Shared/AdblockPlusClient.cpp |
@@ -11,32 +11,185 @@ |
#include "AdblockPlusClient.h" |
+namespace |
+{ |
+ const LPCWSTR responseClassName = L"FilterEngineResponse"; |
+ std::string response; |
+ bool responseReady; |
+ |
+ std::auto_ptr<AdblockPlus::FilterEngine> CreateFilterEngine() |
+ { |
+ try |
+ { |
+ DEBUG_GENERAL("Building client"); |
+ AdblockPlus::AppInfo appInfo; |
+ appInfo.name = "adblockplusie"; |
+ appInfo.version = CT2CA(_T(IEPLUGIN_VERSION), CP_UTF8); |
+ appInfo.platform = "msie"; |
+ |
+ DEBUG_GENERAL(L"Building engine"); |
+ |
+ JsEnginePtr jsEngine(AdblockPlus::JsEngine::New(appInfo)); |
+ return std::auto_ptr<AdblockPlus::FilterEngine>(new AdblockPlus::FilterEngine(jsEngine)); |
+ } |
+ catch(std::exception ex) |
+ { |
+ DEBUG_GENERAL(ex.what()); |
+ } |
+ } |
+ |
+ template<typename T> |
+ std::wstring ToWString(const T& value) |
+ { |
+ std::wstringstream stream; |
+ stream << value; |
+ return stream.str(); |
+ } |
+ |
+ std::wstring ToWString(LPCSTR value) |
+ { |
+ USES_CONVERSION; |
+ return ToWString(A2W(value)); |
+ } |
+ |
+ template<> |
+ std::wstring ToWString(const std::string& value) |
+ { |
+ return ToWString(value.c_str()); |
+ } |
+ |
+ template<typename T> |
+ std::string ToString(const T& value) |
+ { |
+ std::stringstream stream; |
+ stream << value; |
+ return stream.str(); |
+ } |
+ |
+ std::string ToString(LPCWSTR value) |
+ { |
+ USES_CONVERSION; |
+ return ToString(W2A(value)); |
+ } |
+ |
+ template<> |
+ std::string ToString(const std::wstring& value) |
+ { |
+ return ToString(value.c_str()); |
+ } |
+ |
+ std::string MarshalStrings(const std::vector<std::string>& strings) |
+ { |
+ std::string marshalledStrings; |
+ for (std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); it++) |
+ marshalledStrings += *it + '\0'; |
+ return marshalledStrings; |
+ } |
+ |
+ std::vector<std::string> UnmarshalStrings(std::string::value_type* message, int count) |
+ { |
+ std::vector<std::string> strings; |
+ for (int i = 0; i < count; i++) |
+ { |
+ std::string::value_type* part = message; |
+ strings.push_back(message); |
+ message += strlen(part) + 1; |
+ } |
+ return strings; |
+ } |
+ |
+ void SendStringMessage(HWND messageWindow, const std::string& message) |
+ { |
+ COPYDATASTRUCT data; |
+ data.cbData = message.length() * sizeof(std::string::value_type); |
+ data.lpData = (PVOID) message.c_str(); |
+ SendMessage(messageWindow, WM_COPYDATA, (WPARAM) messageWindow, (LPARAM)(LPVOID) &data); |
+ } |
+ |
+ LRESULT CALLBACK RequestWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
+ { |
+ if (uMsg == WM_COPYDATA) |
+ { |
+ COPYDATASTRUCT* data = (COPYDATASTRUCT*) lParam; |
+ std::vector<std::string> args = UnmarshalStrings((std::string::value_type*) data->lpData, 4); |
+ |
+ FilterEngine* filterEngine = (FilterEngine*) GetWindowLongPtr(hWnd, GWLP_USERDATA); |
+ bool matches = filterEngine->Matches(args[1], args[2], args[3]); |
+ |
+ std::wstring responseWindowName = ToWString(args[0]); |
+ HWND responseWindow = FindWindowEx(HWND_MESSAGE, 0, responseClassName, responseWindowName.c_str()); |
+ if (!responseWindow) |
+ { |
+ DEBUG_GENERAL(L"Failed to find the filter engine response window"); |
+ } |
+ else |
+ { |
+ SendStringMessage(responseWindow, ToString(matches)); |
+ } |
+ } |
+ return DefWindowProc(hWnd, uMsg, wParam, lParam); |
+ } |
+ |
+ LRESULT CALLBACK ResponseWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
+ { |
+ if (uMsg == WM_COPYDATA) |
+ { |
+ COPYDATASTRUCT* data = (COPYDATASTRUCT*) lParam; |
+ response = (std::string::value_type*) data->lpData; |
+ responseReady = true; |
+ } |
+ return DefWindowProc(hWnd, uMsg, wParam, lParam); |
+ } |
+} |
CAdblockPlusClient* CAdblockPlusClient::s_instance = NULL; |
- |
CAdblockPlusClient::CAdblockPlusClient() : CPluginClientBase() |
{ |
- try |
+ m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter()); |
+ |
+ // TODO: Only create a single filter engine instance, share them across all |
+ // processes. For this we need to invoke all filter engine methods via |
+ // IPC. This is already done for FilterEngine::Matches(). |
+ filterEngine = CreateFilterEngine(); |
+ |
+ const LPCWSTR requestClassName = L"FilterEngineRequest"; |
+ WNDCLASS requestClass = {}; |
+ requestClass.lpfnWndProc = (WNDPROC) RequestWindowProcedure; |
+ requestClass.lpszClassName = requestClassName; |
+ if (!RegisterClass(&requestClass)) |
{ |
- 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"); |
+ DEBUG_GENERAL(L"Failed to register FilterEngineRequest class"); |
+ return; |
+ } |
- JsEnginePtr jsEngine(AdblockPlus::JsEngine::New(appInfo)); |
- filterEngine = std::auto_ptr<AdblockPlus::FilterEngine>(new AdblockPlus::FilterEngine(jsEngine)); |
+ filterEngineRequestWindow = FindWindowEx(HWND_MESSAGE, 0, requestClassName, 0); |
+ if (!filterEngineRequestWindow) |
+ { |
+ filterEngineRequestWindow = CreateWindow(requestClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0); |
+ if (!filterEngineRequestWindow) |
+ { |
+ DEBUG_GENERAL(L"Failed to create filter engine request window"); |
+ return; |
+ } |
+ SetWindowLongPtr(filterEngineRequestWindow, GWLP_USERDATA, (LONG_PTR) filterEngine.get()); |
+ } |
+ WNDCLASS responseClass = {}; |
+ responseClass.lpfnWndProc = (WNDPROC) ResponseWindowProcedure; |
+ responseClass.lpszClassName = responseClassName; |
+ if (!RegisterClass(&responseClass)) |
+ { |
+ DEBUG_GENERAL(L"Failed to register FilterEngineRequest class"); |
+ return; |
} |
- catch(std::exception ex) |
- { |
- DEBUG_GENERAL(ex.what()); |
- } |
+ |
+ filterEngineResponseWindowName = ToWString(GetCurrentThreadId()); |
+ filterEngineResponseWindow = CreateWindow(responseClassName, filterEngineResponseWindowName.c_str(), 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0); |
+ if (!filterEngineResponseWindow) |
+ DEBUG_GENERAL(L"Failed to create filter engine response window"); |
} |
+ |
CAdblockPlusClient::~CAdblockPlusClient() |
{ |
s_instance = NULL; |
@@ -163,3 +316,17 @@ |
RegCloseKey(hKey); |
return (int)(version[0] - 48); |
} |
+ |
+bool CAdblockPlusClient::Matches(const std::string& url, const std::string& contentType, const std::string& domain) |
+{ |
+ std::vector<std::string> args; |
+ args.push_back(ToString(filterEngineResponseWindowName)); |
+ args.push_back(url); |
+ args.push_back(contentType); |
+ args.push_back(domain); |
+ responseReady = false; |
+ SendStringMessage(filterEngineRequestWindow, MarshalStrings(args)); |
+ while (!responseReady) |
+ Sleep(10); |
+ return response == "1"; |
+} |