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

Side by Side Diff: Shared/AdblockPlusClient.cpp

Issue 10580043: Run a single FilterEngine instance in a separate process (Closed)
Patch Set: Created May 16, 2013, 5:29 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 #include "PluginStdAfx.h" 1 #include "PluginStdAfx.h"
2 2
3 #include "PluginSettings.h" 3 #include "PluginSettings.h"
4 #include "PluginSystem.h" 4 #include "PluginSystem.h"
5 #include "PluginFilter.h" 5 #include "PluginFilter.h"
6 #include "PluginClientFactory.h" 6 #include "PluginClientFactory.h"
7 #include "PluginDictionary.h" 7 #include "PluginDictionary.h"
8 #include "PluginHttpRequest.h" 8 #include "PluginHttpRequest.h"
9 #include "PluginMutex.h" 9 #include "PluginMutex.h"
10 #include "PluginClass.h" 10 #include "PluginClass.h"
11 #include "PluginUtil.h"
11 12
12 #include "AdblockPlusClient.h" 13 #include "AdblockPlusClient.h"
13 14
15 namespace
16 {
17 // TODO: pipeName, bufferSize, AutoHandle, ReadMessage, WriteMessage, MarshalS trings and UnmarshalStrings are
18 // duplicated in AdblockPlusEngine. We should find a way to reuse them.
19
20 const std::wstring pipeName = L"\\\\.\\pipe\\adblockplusengine";
21 const int bufferSize = 1024;
22
23 class AutoHandle
24 {
25 public:
26 AutoHandle()
27 {
28 }
29
30 AutoHandle(HANDLE handle) : handle(handle)
31 {
32 }
33
34 ~AutoHandle()
35 {
36 CloseHandle(handle);
37 }
38
39 HANDLE get()
40 {
41 return handle;
42 }
43
44 private:
45 HANDLE handle;
46 static int references;
47
48 AutoHandle(const AutoHandle& autoHandle);
49 AutoHandle& operator=(const AutoHandle& autoHandle);
50 };
51
52 std::string MarshalStrings(const std::vector<std::string>& strings)
53 {
54 // TODO: This is some pretty hacky marshalling, replace it with something mo re robust
55 std::string marshalledStrings;
56 for (std::vector<std::string>::const_iterator it = strings.begin(); it != st rings.end(); it++)
57 marshalledStrings += *it + ';';
58 return marshalledStrings;
59 }
60
61 std::vector<std::string> UnmarshalStrings(const std::string& message)
62 {
63 std::stringstream stream(message);
64 std::vector<std::string> strings;
65 std::string string;
66 while (std::getline(stream, string, ';'))
67 strings.push_back(string);
68 return strings;
69 }
70
71 std::string ReadMessage(HANDLE pipe)
72 {
73 std::stringstream stream;
74 std::auto_ptr<char> buffer(new char[bufferSize]);
75 bool hasError;
76 do
77 {
78 DWORD bytesRead;
79 hasError = !ReadFile(pipe, buffer.get(), bufferSize * sizeof(char), &bytes Read, 0);
80 if (hasError && GetLastError() != ERROR_MORE_DATA)
81 {
82 std::stringstream stream;
83 stream << "Error reading from pipe: " << GetLastError();
84 throw std::runtime_error(stream.str());
85 }
86 stream << std::string(buffer.get(), bytesRead);
87 } while (hasError);
88 return stream.str();
89 }
90
91 void WriteMessage(HANDLE pipe, const std::string& message)
92 {
93 DWORD bytesWritten;
94 if (!WriteFile(pipe, message.c_str(), message.length(), &bytesWritten, 0))
95 throw std::runtime_error("Failed to write to pipe");
96 }
97
98 HANDLE OpenPipe(const std::wstring& name)
99 {
100 if (WaitNamedPipe(name.c_str(), 5000))
101 return CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_E XISTING, 0, 0);
102 return INVALID_HANDLE_VALUE;
103 }
104
105 void SpawnAdblockPlusEngine()
106 {
107 std::wstring engineExecutablePath = DllDir() + L"AdblockPlusEngine.exe";
108 STARTUPINFO startupInfo = {};
109 PROCESS_INFORMATION processInformation = {};
110
111 HANDLE token;
112 OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &token);
113 HANDLE newToken;
114 DuplicateTokenEx(token, 0, 0, SecurityImpersonation, TokenPrimary, &newToken );
115
116 if (!CreateProcessAsUser(newToken, 0, const_cast<wchar_t*>(engineExecutableP ath.c_str()), 0, 0, 0, 0, 0, 0,
Wladimir Palant 2013/05/16 11:52:16 You are leaking the handles created here: "Handles
Felix Dahlke 2013/05/23 12:31:20 Done.
117 &startupInfo, &processInformation))
118 {
119 DWORD error = GetLastError();
120 throw std::runtime_error("Failed to start Adblock Plus Engine");
121 }
122 }
123
124 HANDLE OpenAdblockPlusEnginePipe()
125 {
126 try
127 {
128 HANDLE pipe = OpenPipe(pipeName);
129 if (pipe == INVALID_HANDLE_VALUE)
130 {
131 SpawnAdblockPlusEngine();
Wladimir Palant 2013/05/16 11:52:16 I can't say that I like the logic here, timing ass
Oleksandr 2013/05/16 13:23:22 The documentation says "If no instances of the spe
Felix Dahlke 2013/05/17 09:11:36 Yes, Oleksandr is right. We are using WaitNamedPip
Wladimir Palant 2013/05/17 10:35:02 Ok, I wonder whether we can wait for pipe creation
132
133 int timeout = 5000;
134 while ((pipe = OpenPipe(pipeName)) == INVALID_HANDLE_VALUE)
135 {
136 const int step = 10;
137 Sleep(step);
138 timeout -= step;
139 if (timeout <= 0)
140 throw std::runtime_error("Unable to open Adblock Plus Engine pipe");
141 }
142 }
143
144 DWORD mode = PIPE_READMODE_MESSAGE;
145 if (!SetNamedPipeHandleState(pipe, &mode, 0, 0))
146 throw std::runtime_error("SetNamedPipeHandleState failed");
147
148 return pipe;
149 }
150 catch(std::exception e)
151 {
152 DEBUG_GENERAL(e.what());
153 return INVALID_HANDLE_VALUE;
154 }
155 }
156 }
14 157
15 CAdblockPlusClient* CAdblockPlusClient::s_instance = NULL; 158 CAdblockPlusClient* CAdblockPlusClient::s_instance = NULL;
16 159
17
18 CAdblockPlusClient::CAdblockPlusClient() : CPluginClientBase() 160 CAdblockPlusClient::CAdblockPlusClient() : CPluginClientBase()
19 { 161 {
20 try 162 m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter());
21 { 163 }
22 DEBUG_GENERAL("Building client");
23 m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter());
24 AdblockPlus::AppInfo appInfo;
25 appInfo.name = "adblockplusie";
26 appInfo.version = CT2CA(_T(IEPLUGIN_VERSION), CP_UTF8);
27 appInfo.platform = "msie";
28
29 DEBUG_GENERAL(L"Building engine");
30 164
31 JsEnginePtr jsEngine(AdblockPlus::JsEngine::New(appInfo));
32 filterEngine = std::auto_ptr<AdblockPlus::FilterEngine>(new AdblockPlus::Fil terEngine(jsEngine));
33
34 }
35 catch(std::exception ex)
36 {
37 DEBUG_GENERAL(ex.what());
38 }
39 }
40 CAdblockPlusClient::~CAdblockPlusClient() 165 CAdblockPlusClient::~CAdblockPlusClient()
41 { 166 {
42 s_instance = NULL; 167 s_instance = NULL;
43 } 168 }
44 169
45 170
46 CAdblockPlusClient* CAdblockPlusClient::GetInstance() 171 CAdblockPlusClient* CAdblockPlusClient::GetInstance()
47 { 172 {
48 CAdblockPlusClient* instance = NULL; 173 CAdblockPlusClient* instance = NULL;
49 174
50 s_criticalSectionLocal.Lock(); 175 s_criticalSectionLocal.Lock();
51 { 176 {
52 if (!s_instance) 177 if (!s_instance)
53 { 178 {
54 CAdblockPlusClient* client = new CAdblockPlusClient(); 179 CAdblockPlusClient* client = new CAdblockPlusClient();
55 180
56 s_instance = client; 181 s_instance = client;
57 } 182 }
58 183
59 instance = s_instance; 184 instance = s_instance;
60 } 185 }
61 s_criticalSectionLocal.Unlock(); 186 s_criticalSectionLocal.Unlock();
62 187
63 return instance; 188 return instance;
64 } 189 }
65 190
66 AdblockPlus::FilterEngine* CAdblockPlusClient::GetFilterEngine()
67 {
68 return filterEngine.get();
69 }
70 191
71 bool CAdblockPlusClient::ShouldBlock(CString src, int contentType, const CString & domain, bool addDebug) 192 bool CAdblockPlusClient::ShouldBlock(CString src, int contentType, const CString & domain, bool addDebug)
72 { 193 {
73 bool isBlocked = false; 194 bool isBlocked = false;
74 195
75 bool isCached = false; 196 bool isCached = false;
76 197
77 CPluginSettings* settings = CPluginSettings::GetInstance(); 198 CPluginSettings* settings = CPluginSettings::GetInstance();
78 199
79 m_criticalSectionCache.Lock(); 200 m_criticalSectionCache.Lock();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 BYTE version[50]; 277 BYTE version[50];
157 cbData = 50; 278 cbData = 50;
158 status = RegQueryValueEx(hKey, L"Version", NULL, &type, (BYTE*)version, &cbDat a); 279 status = RegQueryValueEx(hKey, L"Version", NULL, &type, (BYTE*)version, &cbDat a);
159 if (status != 0) 280 if (status != 0)
160 { 281 {
161 return 0; 282 return 0;
162 } 283 }
163 RegCloseKey(hKey); 284 RegCloseKey(hKey);
164 return (int)(version[0] - 48); 285 return (int)(version[0] - 48);
165 } 286 }
287
288 std::string CallAdblockPlusEngineProcedure(const std::string& name, const std::v ector<std::string>& args)
Wladimir Palant 2013/05/16 11:52:16 Why combine the parameters here? It's a private he
Wladimir Palant 2013/05/23 14:25:01 This comment doesn't seem to be addressed.
Felix Dahlke 2013/05/23 19:10:44 Oops, seems I missed this. Addressed now, you're r
289 {
290 AutoHandle pipe(OpenAdblockPlusEnginePipe());
291 std::vector<std::string> strings;
292 strings.push_back(name);
293 for (std::vector<std::string>::const_iterator it = args.begin(); it != args.en d(); it++)
294 strings.push_back(*it);
295 WriteMessage(pipe.get(), MarshalStrings(strings));
296 return ReadMessage(pipe.get());
297 }
298
299 bool CAdblockPlusClient::Matches(const std::string& url, const std::string& cont entType, const std::string& domain)
300 {
301 std::vector<std::string> args;
302 args.push_back(url);
303 args.push_back(contentType);
304 args.push_back(domain);
305
306 try
307 {
308 std::string response = CallAdblockPlusEngineProcedure("Matches", args);
309 return response == "1";
310 }
311 catch (const std::exception& e)
312 {
313 DEBUG_GENERAL(e.what());
314 return false;
315 }
316 }
317
318 std::vector<std::string> CAdblockPlusClient::GetElementHidingSelectors(std::stri ng domain)
319 {
320 std::vector<std::string> args;
321 args.push_back(domain);
322
323 try
324 {
325 std::string response = CallAdblockPlusEngineProcedure("GetElementHidingSelec tors", args);
326 return UnmarshalStrings(response);
327 }
328 catch (const std::exception& e)
329 {
330 DEBUG_GENERAL(e.what());
331 return std::vector<std::string>();
332 }
333 }
334
335 std::vector<AdblockPlus::SubscriptionPtr> CAdblockPlusClient::FetchAvailableSubs criptions()
336 {
337 //TODO: implement this
338 return std::vector<AdblockPlus::SubscriptionPtr>();
339 }
340
341 std::vector<AdblockPlus::FilterPtr> CAdblockPlusClient::GetListedFilters()
342 {
343 //TODO: implement this
344 return std::vector<AdblockPlus::FilterPtr>();
345 }
346
347 AdblockPlus::FilterPtr CAdblockPlusClient::GetFilter(std::string text)
348 {
349 //TODO: implement this
350 return AdblockPlus::FilterPtr();
351 }
352
353 std::vector<AdblockPlus::SubscriptionPtr> CAdblockPlusClient::GetListedSubscript ions()
354 {
355 //TODO: implement this
356 return std::vector<AdblockPlus::SubscriptionPtr>();
357 }
358
359 AdblockPlus::SubscriptionPtr CAdblockPlusClient::GetSubscription(std::string url )
360 {
361 //TODO: imlement this
362 return AdblockPlus::SubscriptionPtr();
363 }
OLDNEW

Powered by Google App Engine
This is Rietveld