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

Side by Side Diff: src/plugin/PluginTabBase.cpp

Issue 6567422169448448: Issue 119 - Switch to injecting CSS for element hiding (Closed)
Patch Set: rebase Created Dec. 1, 2015, 3:45 p.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 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include "PluginStdAfx.h" 18 #include "PluginStdAfx.h"
19 #include "AdblockPlusClient.h" 19 #include "AdblockPlusClient.h"
20 #include "PluginClientBase.h" 20 #include "PluginClientBase.h"
21 #include "PluginSettings.h" 21 #include "PluginSettings.h"
22 #include "AdblockPlusDomTraverser.h" 22 #include "AdblockPlusDomTraverser.h"
23 #include "PluginTabBase.h" 23 #include "PluginTabBase.h"
24 #include "IeVersion.h" 24 #include "IeVersion.h"
25 #include "../shared/Utils.h" 25 #include "../shared/Utils.h"
26 #include <Mshtmhst.h> 26 #include <Mshtmhst.h>
27 #include "../shared/Utils.h"
27 28
28 CPluginTabBase::CPluginTabBase(CPluginClass* plugin) 29 CPluginTabBase::CPluginTabBase(CPluginClass* plugin)
29 : m_plugin(plugin) 30 : m_plugin(plugin)
30 , m_isActivated(false) 31 , m_isActivated(false)
31 , m_continueThreadRunning(true) 32 , m_continueThreadRunning(true)
32 { 33 {
33 m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter()); 34 m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter());
34 m_filter->hideFiltersLoadedEvent = CreateEvent(NULL, true, false, NULL); 35 m_filter->hideFiltersLoadedEvent = CreateEvent(NULL, true, false, NULL);
35 36
36 CPluginClient* client = CPluginClient::GetInstance(); 37 CPluginClient* client = CPluginClient::GetInstance();
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 } 159 }
159 DEBUG_GENERAL(L"InjectABP. Injecting"); 160 DEBUG_GENERAL(L"InjectABP. Injecting");
160 CComPtr<IDispatch> pDocDispatch; 161 CComPtr<IDispatch> pDocDispatch;
161 browser->get_Document(&pDocDispatch); 162 browser->get_Document(&pDocDispatch);
162 CComQIPtr<IHTMLDocument2> pDoc2(pDocDispatch); 163 CComQIPtr<IHTMLDocument2> pDoc2(pDocDispatch);
163 if (!pDoc2) 164 if (!pDoc2)
164 { 165 {
165 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI docume nt"); 166 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI docume nt");
166 return; 167 return;
167 } 168 }
169
168 CComPtr<IHTMLWindow2> pWnd2; 170 CComPtr<IHTMLWindow2> pWnd2;
169 pDoc2->get_parentWindow(&pWnd2); 171 pDoc2->get_parentWindow(&pWnd2);
170 if (!pWnd2) 172 if (!pWnd2)
171 { 173 {
172 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get paren t window"); 174 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get paren t window");
173 return; 175 return;
174 } 176 }
175 CComQIPtr<IDispatchEx> pWndEx(pWnd2); 177 CComQIPtr<IDispatchEx> pWndEx(pWnd2);
176 if (!pWndEx) 178 if (!pWndEx)
177 { 179 {
(...skipping 19 matching lines...) Expand all
197 params.rgvarg = &var; 199 params.rgvarg = &var;
198 params.rgdispidNamedArgs = 0; 200 params.rgdispidNamedArgs = 0;
199 hr = pWndEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPU T | DISPATCH_PROPERTYPUTREF, &params, 0, 0, 0); 201 hr = pWndEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPU T | DISPATCH_PROPERTYPUTREF, &params, 0, 0, 0);
200 DEBUG_GENERAL("Invoke"); 202 DEBUG_GENERAL("Invoke");
201 if (FAILED(hr)) 203 if (FAILED(hr))
202 { 204 {
203 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CR EATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to create S ettings in JavaScript"); 205 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CR EATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to create S ettings in JavaScript");
204 } 206 }
205 } 207 }
206 208
209 bool CPluginTabBase::IsTraverserEnabled()
210 {
211 return !IsCSSInjectionEnabled();
212 }
213
214 bool CPluginTabBase::IsCSSInjectionEnabled()
215 {
216 return IsWindowsVistaOrLater() && AdblockPlus::IE::InstalledMajorVersion() >= 10;
217 }
Eric 2015/12/02 17:00:15 I'd like to see a user setting for these predicate
sergei 2016/02/25 17:48:28 I have created those methods exactly for that reas
218
219 namespace
220 {
221 void InjectABPCSS(IHTMLDocument2& htmlDocument2, const std::vector<std::wstrin g>& hideFilters)
222 {
223 // pseudocode: styleHtmlElement = htmlDocument2.createElement("style");
224 ATL::CComQIPtr<IHTMLStyleElement> styleHtmlElement;
225 {
226 ATL::CComPtr<IHTMLElement> stylePureHtmlElement;
227 if (FAILED(htmlDocument2.createElement(ATL::CComBSTR(L"style"), &stylePure HtmlElement)))
228 {
229 DEBUG_GENERAL(L"Cannot create style element");
230 return;
231 }
232 if (!(styleHtmlElement = stylePureHtmlElement))
233 {
234 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleElement from IHTMLElement");
235 return;
236 }
237 }
238 // pseudocode: styleHtmlElement.type = "text/css";
239 if (FAILED(styleHtmlElement->put_type(ATL::CComBSTR("text/css"))))
240 {
241 DEBUG_GENERAL(L"Cannot set type text/css");
242 return;
243 }
244 // pseudocode: styleSheet4 = styleHtmlElement.sheet;
245 ATL::CComQIPtr<IHTMLStyleSheet4> styleSheet4;
246 {
247 // IHTMLStyleElement2 is availabe starting from IE9, Vista
248 ATL::CComQIPtr<IHTMLStyleElement2> styleHtmlElement2 = styleHtmlElement;
249 if (!styleHtmlElement2)
250 {
251 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleElement2 from IHTMLStyleElement" );
252 return;
253 }
254 ATL::CComQIPtr<IHTMLStyleSheet> styleSheet;
255 if (FAILED(styleHtmlElement2->get_sheet(&styleSheet)) || !styleSheet)
256 {
257 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleSheet");
258 return;
259 }
260 // IHTMLStyleSheet4 is availabe starting from IE9, Vista
261 styleSheet4 = styleSheet;
262 if (!styleSheet4)
263 {
264 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleSheet4");
265 return;
266 }
267 }
268 // pseudocode: for (auto i = 0; i < hideFilters.length; ++i) {
269 // pseudocode: i = styleSheet4.insertRule(hideFilters + cssValue, i);
270 // pseudocode: }
271 long newIndex = 0;
272 std::wstring cssValue = L"{ display: none !important; }";
273 for (const auto& selector : hideFilters)
274 {
275 auto cssRule = selector + cssValue;
276 ATL::CComBSTR selector(cssRule.size(), cssRule.c_str());
277 if (SUCCEEDED(styleSheet4->insertRule(selector, newIndex, &newIndex)))
278 {
279 ++newIndex;
280 }
281 else
282 {
283 DEBUG_GENERAL(L"Cannot add rule for selector " + cssRule);
284 }
285 }
286
287 // pseudocode: htmlDocument2.head.appendChild(styleHtmlElement);
288 {
289 // IHTMLDocument7 is availabe starting from IE9, Vista
290 ATL::CComQIPtr<IHTMLDocument7> htmlDocument7 = &htmlDocument2;
291 if (!htmlDocument7)
292 {
293 DEBUG_GENERAL(L"Cannot obtain IHTMLDocument7 from htmlDocument2");
294 return;
295 }
296 ATL::CComPtr<IHTMLElement> headHtmlElement;
297 if (FAILED(htmlDocument7->get_head(&headHtmlElement)))
298 {
299 DEBUG_GENERAL(L"Cannot obtain head from pDoc7");
300 return;
301 }
302 ATL::CComQIPtr<IHTMLDOMNode> headNode = headHtmlElement;
303 if (!headNode)
304 {
305 DEBUG_GENERAL(L"Cannot obtain headNode from headHtmlElement");
306 return;
307 }
308 ATL::CComQIPtr<IHTMLDOMNode> styleNode = styleHtmlElement;
309 if (!styleNode)
310 {
311 DEBUG_GENERAL(L"Cannot obtain IHTMLDOMNode from stylePureHtmlElement");
312 return;
313 }
314 if (FAILED(headNode->appendChild(styleNode, nullptr)))
315 {
316 DEBUG_GENERAL(L"Cannot append blocking style");
317 }
318 }
319 }
320 }
321
207 namespace 322 namespace
208 { 323 {
209 ATL::CComPtr<IWebBrowser2> GetParent(IWebBrowser2& browser) 324 ATL::CComPtr<IWebBrowser2> GetParent(IWebBrowser2& browser)
210 { 325 {
211 ATL::CComPtr<IDispatch> parentDispatch; 326 ATL::CComPtr<IDispatch> parentDispatch;
212 if (FAILED(browser.get_Parent(&parentDispatch)) || !parentDispatch) 327 if (FAILED(browser.get_Parent(&parentDispatch)) || !parentDispatch)
213 { 328 {
214 return nullptr; 329 return nullptr;
215 } 330 }
216 // The InternetExplorer application always returns a pointer to itself. 331 // The InternetExplorer application always returns a pointer to itself.
(...skipping 28 matching lines...) Expand all
245 frameHierarchy.push_back(ToUtf8String(GetLocationUrl(*frame))); 360 frameHierarchy.push_back(ToUtf8String(GetLocationUrl(*frame)));
246 } 361 }
247 CPluginClient* client = CPluginClient::GetInstance(); 362 CPluginClient* client = CPluginClient::GetInstance();
248 return client->IsWhitelistedUrl(url, frameHierarchy) 363 return client->IsWhitelistedUrl(url, frameHierarchy)
249 || client->IsElemhideWhitelistedOnDomain(url, frameHierarchy); 364 || client->IsElemhideWhitelistedOnDomain(url, frameHierarchy);
250 } 365 }
251 } 366 }
252 367
253 void CPluginTabBase::OnDownloadComplete(IWebBrowser2* browser) 368 void CPluginTabBase::OnDownloadComplete(IWebBrowser2* browser)
254 { 369 {
255 CPluginClient* client = CPluginClient::GetInstance(); 370 if (IsTraverserEnabled())
256 std::wstring url = GetDocumentUrl();
257 if (!client->IsWhitelistedUrl(url) && !client->IsElemhideWhitelistedOnDomain(u rl))
258 { 371 {
259 m_traverser->TraverseDocument(browser, GetDocumentDomain(), GetDocumentUrl() ); 372 CPluginClient* client = CPluginClient::GetInstance();
373 std::wstring url = GetDocumentUrl();
374 if (!client->IsWhitelistedUrl(url) && !client->IsElemhideWhitelistedOnDomain (url))
375 {
376 m_traverser->TraverseDocument(browser, GetDocumentDomain(), GetDocumentUrl ());
377 }
260 } 378 }
261 InjectABP(browser); 379 InjectABP(browser);
262 } 380 }
263 381
264 void CPluginTabBase::OnDocumentComplete(IWebBrowser2* browser, const std::wstrin g& url, bool isDocumentBrowser) 382 void CPluginTabBase::OnDocumentComplete(IWebBrowser2* browser, const std::wstrin g& url, bool isDocumentBrowser)
265 { 383 {
266 std::wstring documentUrl = GetDocumentUrl(); 384 std::wstring documentUrl = GetDocumentUrl();
267 385
268 if (isDocumentBrowser) 386 if (isDocumentBrowser)
269 { 387 {
270 if (url != documentUrl) 388 if (url != documentUrl)
271 { 389 {
272 SetDocumentUrl(url); 390 SetDocumentUrl(url);
273 } 391 }
274 InjectABP(browser); 392 InjectABP(browser);
275 } 393 }
276 CString urlLegacy = ToCString(url); 394 CString urlLegacy = ToCString(url);
277 if (urlLegacy.Left(6) != "res://") 395 if (urlLegacy.Left(6) == "res://")
278 { 396 {
279 // Get document 397 return;
280 CComPtr<IDispatch> pDocDispatch; 398 }
Eric 2015/12/02 17:00:15 This optimization, for early return on a "res://"
sergei 2016/02/25 17:48:28 Done. It's already not relevant.
281 HRESULT hr = browser->get_Document(&pDocDispatch); 399 // Get document
282 if (FAILED(hr) || !pDocDispatch) 400 CComPtr<IDispatch> pDocDispatch;
401 HRESULT hr = browser->get_Document(&pDocDispatch);
402 if (FAILED(hr) || !pDocDispatch)
403 {
404 return;
405 }
406
407 CComQIPtr<IHTMLDocument2> pDoc(pDocDispatch);
408 if (!pDoc)
409 {
410 return;
411 }
412
413 if (IsCSSInjectionEnabled() && CPluginSettings::GetInstance()->GetPluginEnable d())
414 {
415 if (!IsFrameWhiteListed(browser))
283 { 416 {
284 return; 417 DEBUG_GENERAL(L"Inject CSS into " + url);
418 InjectABPCSS(*pDoc, m_filter->GetHideFilters());
285 } 419 }
420 }
286 421
287 CComQIPtr<IHTMLDocument2> pDoc(pDocDispatch); 422 ATL::CComQIPtr<IOleObject> pOleObj(pDocDispatch);
288 if (!pDoc) 423 if (!pOleObj)
424 return;
425
426 ATL::CComQIPtr<IOleClientSite> pClientSite;
427 pOleObj->GetClientSite(&pClientSite);
428 if (pClientSite != NULL)
429 {
430 ATL::CComQIPtr<IDocHostUIHandler> docHostUIHandler(pClientSite);
431 if (docHostUIHandler != NULL)
289 { 432 {
290 return; 433 docHostUIHandler->UpdateUI();
291 }
292
293 CComPtr<IOleObject> pOleObj;
294 pDocDispatch->QueryInterface(&pOleObj);
295 if (!pOleObj)
296 {
297 return;
298 }
299 CComPtr<IOleClientSite> pClientSite;
300 pOleObj->GetClientSite(&pClientSite);
301 if (pClientSite != NULL)
302 {
303 CComPtr<IDocHostUIHandler> docHostUIHandler;
304 pClientSite->QueryInterface(&docHostUIHandler);
305 if (docHostUIHandler != NULL)
306 {
307 docHostUIHandler->UpdateUI();
308 }
309 } 434 }
310 } 435 }
311 } 436 }
312 437
313 std::wstring CPluginTabBase::GetDocumentDomain() 438 std::wstring CPluginTabBase::GetDocumentDomain()
314 { 439 {
315 std::wstring domain; 440 std::wstring domain;
316 441
317 m_criticalSection.Lock(); 442 m_criticalSection.Lock();
318 { 443 {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 LogQueue::LogPluginError(pluginError.GetErrorCode(), pluginError.GetEr rorId(), pluginError.GetErrorSubid(), pluginError.GetErrorDescription(), true, p luginError.GetProcessId(), pluginError.GetThreadId()); 559 LogQueue::LogPluginError(pluginError.GetErrorCode(), pluginError.GetEr rorId(), pluginError.GetErrorSubid(), pluginError.GetErrorDescription(), true, p luginError.GetProcessId(), pluginError.GetThreadId());
435 } 560 }
436 561
437 // Non-hanging sleep 562 // Non-hanging sleep
438 Sleep(50); 563 Sleep(50);
439 } 564 }
440 565
441 tabLoopIteration++; 566 tabLoopIteration++;
442 } 567 }
443 } 568 }
OLDNEW

Powered by Google App Engine
This is Rietveld