| 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"; |
| +} |