Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: Shared/AdblockPlusClient.cpp

Issue 10580043: Run a single FilterEngine instance in a separate process (Closed)
Patch Set: Addressed all issues Created May 23, 2013, 12:29 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Shared/AdblockPlusClient.cpp
===================================================================
--- a/Shared/AdblockPlusClient.cpp
+++ b/Shared/AdblockPlusClient.cpp
@@ -8,35 +8,163 @@
#include "PluginHttpRequest.h"
#include "PluginMutex.h"
#include "PluginClass.h"
+#include "PluginUtil.h"
#include "AdblockPlusClient.h"
+namespace
+{
+ // TODO: pipeName, bufferSize, AutoHandle, ReadMessage, WriteMessage, MarshalStrings and UnmarshalStrings are
+ // duplicated in AdblockPlusEngine. We should find a way to reuse them.
+
+ const std::wstring pipeName = L"\\\\.\\pipe\\adblockplusengine";
+ 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 +191,6 @@
return instance;
}
-AdblockPlus::FilterEngine* CAdblockPlusClient::GetFilterEngine()
-{
- return filterEngine.get();
-}
bool CAdblockPlusClient::ShouldBlock(CString src, int contentType, const CString& domain, bool addDebug)
{
@@ -163,3 +287,80 @@
RegCloseKey(hKey);
return (int)(version[0] - 48);
}
+
+std::string CallAdblockPlusEngineProcedure(const std::string& name, const std::vector<std::string>& args)
+{
+ AutoHandle pipe(OpenAdblockPlusEnginePipe());
+ std::vector<std::string> strings;
+ strings.push_back(name);
+ for (std::vector<std::string>::const_iterator it = args.begin(); it != args.end(); it++)
+ strings.push_back(*it);
+ WriteMessage(pipe.get(), MarshalStrings(strings));
+ 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(url);
+ args.push_back(contentType);
+ args.push_back(domain);
+
+ try
+ {
+ std::string response = CallAdblockPlusEngineProcedure("Matches", 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(domain);
+
+ try
+ {
+ std::string response = CallAdblockPlusEngineProcedure("GetElementHidingSelectors", 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();
+}

Powered by Google App Engine
This is Rietveld