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

Delta Between Two Patch Sets: src/plugin/PluginTabBase.cpp

Issue 6567422169448448: Issue 119 - Switch to injecting CSS for element hiding (Closed)
Left Patch Set: Created Dec. 10, 2014, 5:12 p.m.
Right Patch Set: rename OnQuit Created Sept. 30, 2016, 3:25 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/plugin/PluginTabBase.h ('k') | src/plugin/WebBrowserEventsListener.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2016 Eyeo GmbH
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
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/>.
16 */
17
1 #include "PluginStdAfx.h" 18 #include "PluginStdAfx.h"
2 19 #include "AdblockPlusClient.h"
3 #include "PluginClient.h" 20 #include "PluginClientBase.h"
4 #include "PluginSettings.h" 21 #include "PluginSettings.h"
5 #include "PluginTab.h"
6 #include "AdblockPlusDomTraverser.h" 22 #include "AdblockPlusDomTraverser.h"
7 #include "PluginClass.h"
8 #include "PluginTabBase.h" 23 #include "PluginTabBase.h"
9 #include "PluginUtil.h" 24 #include "IeVersion.h"
10 #include <dispex.h> 25 #include "../shared/Utils.h"
26 #include "../shared/EventWithSetter.h"
11 #include <Mshtmhst.h> 27 #include <Mshtmhst.h>
12 #include "../shared/Utils.h" 28 #include <mutex>
13 29
14 int CPluginTabBase::s_dictionaryVersion = 0; 30 class CPluginTab::AsyncPluginFilter
15 int CPluginTabBase::s_settingsVersion = 1; 31 {
16 int CPluginTabBase::s_filterVersion = 0; 32 public:
17 int CPluginTabBase::s_whitelistVersion = 0; 33 static std::shared_ptr<AsyncPluginFilter> CreateAsync(const std::wstring& doma in)
18 34 {
19 CPluginTabBase::CPluginTabBase(CPluginClass* plugin) 35 std::shared_ptr<AsyncPluginFilter> asyncFilter = std::make_shared<AsyncPlugi nFilter>();
20 : m_plugin(plugin) 36 std::weak_ptr<AsyncPluginFilter> weakAsyncData = asyncFilter;
21 , m_isActivated(false) 37 auto eventSetter = asyncFilter->event.CreateSetter();
38 try
39 {
40 std::thread([domain, weakAsyncData, eventSetter]
41 {
42 try
43 {
44 CreateAsyncImpl(domain, weakAsyncData, eventSetter);
45 }
46 » catch (...)
47 {
48 // As a thread-main function, we truncate any C++ exception.
49 }
50 }).detach();
51 // TODO: we should do something with that `detach` above.
52 }
53 catch (const std::system_error& ex)
54 {
55 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD_C REATE_PROCESS,
56 "Class::Thread - Failed to start filter loader thread");
57 }
58 return asyncFilter;
59 }
60 PluginFilterPtr GetFilter()
61 {
62 if (!event.Wait())
63 return PluginFilterPtr();
64 std::lock_guard<std::mutex> lock(mutex);
65 return filter;
66 }
67 private:
68 static void CreateAsyncImpl(const std::wstring& domain, std::weak_ptr<AsyncPlu ginFilter> weakAsyncData, const std::shared_ptr<EventWithSetter::Setter>& setter )
69 {
70 std::unique_ptr<CPluginFilter> pluginFilter(new CPluginFilter(CPluginClient: :GetInstance()->GetElementHidingSelectors(domain)));
71 if (auto asyncData = weakAsyncData.lock())
72 {
73 {
74 std::lock_guard<std::mutex> lock(asyncData->mutex);
75 asyncData->filter = move(pluginFilter);
76 }
77 setter->Set();
78 }
79 }
80 EventWithSetter event;
81 std::mutex mutex;
82 PluginFilterPtr filter;
83 };
84
85 CPluginTab::CPluginTab()
86 : m_isActivated(false)
22 , m_continueThreadRunning(true) 87 , m_continueThreadRunning(true)
23 { 88 {
24 m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter());
25 m_filter->hideFiltersLoadedEvent = CreateEvent(NULL, true, false, NULL);
26
27 CPluginClient* client = CPluginClient::GetInstance(); 89 CPluginClient* client = CPluginClient::GetInstance();
28 if (client->GetIEVersion() < 10) 90 if (AdblockPlus::IE::InstalledMajorVersion() < 10)
29 { 91 {
30 m_isActivated = true; 92 m_isActivated = true;
31 } 93 }
32 94
33 try 95 try
34 { 96 {
35 m_thread = std::thread(&CPluginTabBase::ThreadProc, this); 97 m_thread = std::thread(&CPluginTab::ThreadProc, this);
36 } 98 }
37 catch (const std::system_error& ex) 99 catch (const std::system_error& ex)
38 { 100 {
39 auto errDescription = std::string("Tab::Thread - Failed to create tab thread ") + 101 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_TAB_THREAD_CREA TE_PROCESS,
40 ex.code().message() + ex.what(); 102 "Tab::Thread - Failed to create tab thread");
41 DEBUG_ERROR_LOG(ex.code().value(), PLUGIN_ERROR_THREAD, PLUGIN_ERROR_TAB_THR EAD_CREATE_PROCESS, errDescription.c_str()); 103 }
42 } 104 }
43 m_traverser = new CPluginDomTraverser(static_cast<CPluginTab*>(this)); 105
44 } 106
45 107 CPluginTab::~CPluginTab()
46 108 {
47 CPluginTabBase::~CPluginTabBase()
48 {
49 delete m_traverser;
50 m_traverser = NULL;
51 m_continueThreadRunning = false; 109 m_continueThreadRunning = false;
52 if (m_thread.joinable()) { 110 if (m_thread.joinable()) {
53 m_thread.join(); 111 m_thread.join();
54 } 112 }
55 } 113 }
56 114
57 void CPluginTabBase::OnActivate() 115 /**
116 * ABP only intercepts protocols "http:" and "https:".
117 * We can disable any domain used in those protocol with an appropriate whitelis t filter.
118 * Thus, the possibility to disable on a particular site depends only on the pro tocol.
119 */
120 bool CPluginTab::IsPossibleToDisableOnSite()
121 {
122 auto url = GetDocumentUrl();
123 return BeginsWith(url, L"http:") || BeginsWith(url, L"https:");
124 }
125
126 void CPluginTab::OnActivate()
58 { 127 {
59 m_isActivated = true; 128 m_isActivated = true;
60 } 129 }
61 130
62 131
63 void CPluginTabBase::OnUpdate() 132 void CPluginTab::OnUpdate()
64 { 133 {
65 m_isActivated = true; 134 m_isActivated = true;
66 } 135 }
67 136
137 void CPluginTab::OnNavigate(const std::wstring& url)
138 {
139 SetDocumentUrl(url);
140 std::wstring domain = GetDocumentDomain();
141 ClearFrameCache(domain);
142 m_asyncPluginFilter = AsyncPluginFilter::CreateAsync(domain);
143 m_traverser.reset();
144 }
145
68 namespace 146 namespace
69 { 147 {
70 void FilterLoader(CPluginTabBase* tabBase) 148 /**
71 { 149 * Determine if the HTML file is one of ours.
72 tabBase->m_filter->LoadHideFilters(CPluginClient::GetInstance()->GetElementH idingSelectors(tabBase->GetDocumentDomain())); 150 * The criterion is that it appear in the "html/templates" folder within our i nstallation.
73 SetEvent(tabBase->m_filter->hideFiltersLoadedEvent); 151 *
74 } 152 * Warning: This function may fail if the argument is not a "file://" URL.
75 } 153 * This is occasionally the case in circumstances yet to be characterized.
76 154 */
77 void CPluginTabBase::OnNavigate(const CString& url) 155 bool IsOurHtmlFile(const std::wstring& url)
78 { 156 {
79 SetDocumentUrl(url); 157 // Declared static because the value is derived from an installation directo ry, which won't change during run-time.
80 ClearFrameCache(GetDocumentDomain()); 158 static auto dir = FileUrl(HtmlFolderPath());
81 std::wstring domainString = GetDocumentDomain(); 159
82 ResetEvent(m_filter->hideFiltersLoadedEvent); 160 DEBUG_GENERAL([&]() -> std::wstring {
83 try 161 std::wstring log = L"InjectABP. Current URL: ";
84 { 162 log += url;
85 std::thread filterLoaderThread(&FilterLoader, this); 163 log += L", template directory URL: ";
86 filterLoaderThread.detach(); // TODO: but actually we should wait for the th read in the dtr. 164 log += dir;
87 } 165 return log;
88 catch (const std::system_error& ex) 166 }());
89 { 167
90 auto errDescription = std::string("Class::Thread - Failed to start filter lo ader thread, ") + 168 /*
91 ex.code().message() + ex.what(); 169 * The length check here is defensive, in case the document URL is truncated for some reason.
92 DEBUG_ERROR_LOG(ex.code().value(), PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_TH READ_CREATE_PROCESS, errDescription.c_str()); 170 */
93 } 171 if (url.length() < 5)
94 m_traverser->ClearCache(); 172 {
95 } 173 // We can't match ".html" at the end of the URL if it's too short.
96 174 return false;
97 void CPluginTabBase::InjectABP(IWebBrowser2* browser) 175 }
176 auto urlCstr = url.c_str();
177 // Check the prefix to match our directory
178 // Check the suffix to be an HTML file
179 return (_wcsnicmp(urlCstr, dir.c_str(), dir.length()) == 0) &&
180 (_wcsnicmp(urlCstr + url.length() - 5, L".html", 5) == 0);
181 }
182 }
183
184 void CPluginTab::InjectABP(IWebBrowser2* browser)
98 { 185 {
99 CriticalSection::Lock lock(m_csInject); 186 CriticalSection::Lock lock(m_csInject);
100 CString url = GetDocumentUrl(); 187 auto url = GetDocumentUrl();
101 CString log; 188 if (!IsOurHtmlFile(url))
102 log.Format(L"InjectABP. Current URL: %s, settings URL: %s", url, UserSettingsF ileUrl().c_str()); 189 {
103 DEBUG_GENERAL(log); 190 DEBUG_GENERAL(L"InjectABP. Not injecting");
104 if (!(0 == url.CompareNoCase(CString(UserSettingsFileUrl().c_str())) || 191 return;
105 0 == url.CompareNoCase(CString(FirstRunPageFileUrl().c_str())))) 192 }
106 { 193 DEBUG_GENERAL(L"InjectABP. Injecting");
107 DEBUG_GENERAL(L"Not injecting");
108 return;
109 }
110 DEBUG_GENERAL(L"Going to inject");
111 CComPtr<IDispatch> pDocDispatch; 194 CComPtr<IDispatch> pDocDispatch;
112 browser->get_Document(&pDocDispatch); 195 browser->get_Document(&pDocDispatch);
113 CComQIPtr<IHTMLDocument2> pDoc2 = pDocDispatch; 196 CComQIPtr<IHTMLDocument2> pDoc2(pDocDispatch);
114 if (!pDoc2) 197 if (!pDoc2)
115 { 198 {
116 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI docume nt"); 199 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTab::InjectABP - Failed to QI document") ;
117 return; 200 return;
118 } 201 }
119
120 CComPtr<IHTMLWindow2> pWnd2; 202 CComPtr<IHTMLWindow2> pWnd2;
121 pDoc2->get_parentWindow(&pWnd2); 203 pDoc2->get_parentWindow(&pWnd2);
122 if (!pWnd2) 204 if (!pWnd2)
123 { 205 {
124 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get paren t window"); 206 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTab::InjectABP - Failed to get parent wi ndow");
125 return; 207 return;
126 } 208 }
127 CComQIPtr<IDispatchEx> pWndEx = pWnd2; 209 CComQIPtr<IDispatchEx> pWndEx(pWnd2);
128 if (!pWndEx) 210 if (!pWndEx)
129 { 211 {
130 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI dispat ch"); 212 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CRE ATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTab::InjectABP - Failed to QI dispatch") ;
131 return; 213 return;
132 } 214 }
133 // Create "Settings" object in JavaScript. 215 // Create "Settings" object in JavaScript.
134 // A method call of "Settings" in JavaScript, transfered to "Invoke" of m_plug inUserSettings 216 // A method call of "Settings" in JavaScript, transfered to "Invoke" of m_plug inUserSettings
135 DISPID dispid; 217 DISPID dispid;
136 HRESULT hr = pWndEx->GetDispID(L"Settings", fdexNameEnsure, &dispid); 218 HRESULT hr = pWndEx->GetDispID(L"Settings", fdexNameEnsure, &dispid);
137 if (FAILED(hr)) 219 if (FAILED(hr))
138 { 220 {
139 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CR EATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get disp atch"); 221 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CR EATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTab::InjectABP - Failed to get dispatch ");
140 return; 222 return;
141 } 223 }
142 CComVariant var((IDispatch*)&m_pluginUserSettings); 224 CComVariant var((IDispatch*)&m_pluginUserSettings);
143 225
144 DEBUG_GENERAL("Injecting"); 226 DEBUG_GENERAL("Injecting");
145 227
146 DISPPARAMS params; 228 DISPPARAMS params;
147 params.cArgs = 1; 229 params.cArgs = 1;
148 params.cNamedArgs = 0; 230 params.cNamedArgs = 0;
149 params.rgvarg = &var; 231 params.rgvarg = &var;
150 params.rgdispidNamedArgs = 0; 232 params.rgdispidNamedArgs = 0;
151 hr = pWndEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPU T | DISPATCH_PROPERTYPUTREF, &params, 0, 0, 0); 233 hr = pWndEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPU T | DISPATCH_PROPERTYPUTREF, &params, 0, 0, 0);
152 DEBUG_GENERAL("Invoke"); 234 DEBUG_GENERAL("Invoke");
153 if (FAILED(hr)) 235 if (FAILED(hr))
154 { 236 {
155 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"); 237 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CR EATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTab::InjectABP - Failed to create Setti ngs in JavaScript");
156 } 238 }
157 } 239 }
158 240
159 bool CPluginTabBase::IsTraverserEnabled() 241 bool CPluginTab::IsTraverserEnabled()
160 { 242 {
161 return !IsCSSInjectionEnabled(); 243 return !IsCSSInjectionEnabled();
162 } 244 }
163 245
164 bool CPluginTabBase::IsCSSInjectionEnabled() 246 bool CPluginTab::IsCSSInjectionEnabled()
165 { 247 {
166 return IsWindowsVistaOrLater() && CPluginClient::GetInstance()->GetIEVersion() >= 10; 248 return IsWindowsVistaOrLater() && AdblockPlus::IE::InstalledMajorVersion() >= 10;
167 } 249 }
168 250
169 namespace 251 namespace
170 { 252 {
171 void InjectABPCSS(IHTMLDocument2& htmlDocument2, const std::vector<std::wstrin g>& hideFilters) 253 void InjectABPCSS(IHTMLDocument2& htmlDocument2, const std::vector<std::wstrin g>& hideFilters)
172 { 254 {
173 ATL::CComPtr<IHTMLElement> stylePureHtmlElement; 255 // pseudocode: styleHtmlElement = htmlDocument2.createElement("style");
174 ATL::CComQIPtr<IHTMLStyleElement> styleHtmlElement; 256 ATL::CComQIPtr<IHTMLStyleElement> styleHtmlElement;
175 if (FAILED(htmlDocument2.createElement(ATL::CComBSTR(L"style"), &stylePureHt mlElement))) 257 {
176 { 258 ATL::CComPtr<IHTMLElement> stylePureHtmlElement;
177 DEBUG_GENERAL(L"Cannot create style element"); 259 if (FAILED(htmlDocument2.createElement(ATL::CComBSTR(L"style"), &stylePure HtmlElement)))
178 return; 260 {
179 } 261 DEBUG_GENERAL(L"Cannot create style element");
180 if (!(styleHtmlElement = stylePureHtmlElement)) 262 return;
181 { 263 }
182 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleElement from IHTMLElement"); 264 if (!(styleHtmlElement = stylePureHtmlElement))
183 return; 265 {
184 } 266 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleElement from IHTMLElement");
267 return;
268 }
269 }
270 // pseudocode: styleHtmlElement.type = "text/css";
185 if (FAILED(styleHtmlElement->put_type(ATL::CComBSTR("text/css")))) 271 if (FAILED(styleHtmlElement->put_type(ATL::CComBSTR("text/css"))))
186 { 272 {
187 DEBUG_GENERAL(L"Cannot set type text/css"); 273 DEBUG_GENERAL(L"Cannot set type text/css");
188 return; 274 return;
189 } 275 }
190 ATL::CComQIPtr<IHTMLStyleSheet> styleSheet; 276 // pseudocode: styleSheet4 = styleHtmlElement.sheet;
191 // IHTMLStyleElement2 is availabe starting from IE9, Vista 277 ATL::CComQIPtr<IHTMLStyleSheet4> styleSheet4;
192 ATL::CComQIPtr<IHTMLStyleElement2> styleHtmlElement2 = styleHtmlElement; 278 {
193 if (!styleHtmlElement2) 279 // IHTMLStyleElement2 is availabe starting from IE9, Vista
194 { 280 ATL::CComQIPtr<IHTMLStyleElement2> styleHtmlElement2 = styleHtmlElement;
195 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleElement2 from IHTMLStyleElement"); 281 if (!styleHtmlElement2)
196 return; 282 {
197 } 283 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleElement2 from IHTMLStyleElement" );
198 if (FAILED(styleHtmlElement2->get_sheet(&styleSheet)) || !styleSheet) 284 return;
199 { 285 }
200 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleSheet"); 286 ATL::CComQIPtr<IHTMLStyleSheet> styleSheet;
201 return; 287 if (FAILED(styleHtmlElement2->get_sheet(&styleSheet)) || !styleSheet)
202 } 288 {
203 // IHTMLStyleSheet4 is availabe starting from IE9, Vista 289 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleSheet");
204 ATL::CComQIPtr<IHTMLStyleSheet4> styleSheet4 = styleSheet; 290 return;
205 if (!styleSheet4) 291 }
206 { 292 // IHTMLStyleSheet4 is availabe starting from IE9, Vista
207 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleSheet4"); 293 styleSheet4 = styleSheet;
208 return; 294 if (!styleSheet4)
209 } 295 {
296 DEBUG_GENERAL(L"Cannot obtain IHTMLStyleSheet4");
297 return;
298 }
299 }
300 // pseudocode: for (auto i = 0; i < hideFilters.length; ++i) {
301 // pseudocode: i = styleSheet4.insertRule(hideFilters + cssValue, i);
302 // pseudocode: }
210 long newIndex = 0; 303 long newIndex = 0;
211 std::wstring cssValue = L"{ display: none !important; }"; 304 std::wstring cssValue = L"{ display: none !important; }";
212 for (const auto& selector : hideFilters) 305 for (const auto& selector : hideFilters)
213 { 306 {
214 auto cssRule = selector + cssValue; 307 auto cssRule = selector + cssValue;
215 ATL::CComBSTR selector(cssRule.size(), cssRule.c_str()); 308 ATL::CComBSTR selector(cssRule.size(), cssRule.c_str());
216 if (SUCCEEDED(styleSheet4->insertRule(selector, newIndex, &newIndex))) 309 if (SUCCEEDED(styleSheet4->insertRule(selector, newIndex, &newIndex)))
217 { 310 {
218 ++newIndex; 311 ++newIndex;
219 } 312 }
220 else 313 else
221 { 314 {
222 DEBUG_GENERAL(ToCString(L"Cannot add rule for selector " + cssRule)); 315 DEBUG_GENERAL(L"Cannot add rule for selector " + cssRule);
223 } 316 }
224 } 317 }
225 318
226 ATL::CComQIPtr<IHTMLDOMNode> styleNode = stylePureHtmlElement; 319 // pseudocode: htmlDocument2.head.appendChild(styleHtmlElement);
227 if (!styleNode) 320 {
228 { 321 // IHTMLDocument7 is availabe starting from IE9, Vista
229 DEBUG_GENERAL(L"Cannot obtain IHTMLDOMNode from stylePureHtmlElement"); 322 ATL::CComQIPtr<IHTMLDocument7> htmlDocument7 = &htmlDocument2;
230 return; 323 if (!htmlDocument7)
231 } 324 {
232 ATL::CComPtr<IHTMLElement> headHtmlElement; 325 DEBUG_GENERAL(L"Cannot obtain IHTMLDocument7 from htmlDocument2");
233 // IHTMLDocument7 is availabe starting from IE9, Vista 326 return;
234 ATL::CComQIPtr<IHTMLDocument7> htmlDocument7 = &htmlDocument2; 327 }
235 if (!htmlDocument7) 328 ATL::CComPtr<IHTMLElement> headHtmlElement;
236 { 329 if (FAILED(htmlDocument7->get_head(&headHtmlElement)))
237 DEBUG_GENERAL(L"Cannot obtain IHTMLDocument7 from htmlDocument2"); 330 {
238 return; 331 DEBUG_GENERAL(L"Cannot obtain head from pDoc7");
239 } 332 return;
240 if (FAILED(htmlDocument7->get_head(&headHtmlElement))) 333 }
241 { 334 ATL::CComQIPtr<IHTMLDOMNode> headNode = headHtmlElement;
242 DEBUG_GENERAL(L"Cannot obtain head from pDoc7"); 335 if (!headNode)
243 return; 336 {
244 } 337 DEBUG_GENERAL(L"Cannot obtain headNode from headHtmlElement");
245 ATL::CComQIPtr<IHTMLDOMNode> headNode = headHtmlElement; 338 return;
246 if (!headNode) 339 }
247 { 340 ATL::CComQIPtr<IHTMLDOMNode> styleNode = styleHtmlElement;
248 DEBUG_GENERAL(L"Cannot obtain headNode from headHtmlElement"); 341 if (!styleNode)
249 return; 342 {
250 } 343 DEBUG_GENERAL(L"Cannot obtain IHTMLDOMNode from stylePureHtmlElement");
251 if (FAILED(headNode->appendChild(styleNode, nullptr))) 344 return;
252 { 345 }
253 DEBUG_GENERAL(L"Cannot append blocking style"); 346 if (FAILED(headNode->appendChild(styleNode, nullptr)))
254 } 347 {
255 } 348 DEBUG_GENERAL(L"Cannot append blocking style");
256 } 349 }
257 350 }
258 void CPluginTabBase::OnDownloadComplete(IWebBrowser2* browser) 351 }
352 }
353
354 namespace
355 {
356 ATL::CComPtr<IWebBrowser2> GetParent(IWebBrowser2& browser)
357 {
358 ATL::CComPtr<IDispatch> parentDispatch;
359 if (FAILED(browser.get_Parent(&parentDispatch)) || !parentDispatch)
360 {
361 return nullptr;
362 }
363 // The InternetExplorer application always returns a pointer to itself.
364 // https://msdn.microsoft.com/en-us/library/aa752136(v=vs.85).aspx
365 if (parentDispatch.IsEqualObject(&browser))
366 {
367 return nullptr;
368 }
369 ATL::CComQIPtr<IServiceProvider> parentDocumentServiceProvider = parentDispa tch;
370 if (!parentDocumentServiceProvider)
371 {
372 return nullptr;
373 }
374 ATL::CComPtr<IWebBrowser2> parentBrowser;
375 if (FAILED(parentDocumentServiceProvider->QueryService(SID_SWebBrowserApp, & parentBrowser)))
376 {
377 return nullptr;
378 }
379 return parentBrowser;
380 }
381
382 bool IsFrameWhiteListed(ATL::CComPtr<IWebBrowser2> frame)
383 {
384 if (!frame)
385 {
386 return false;
387 }
388 auto url = GetLocationUrl(*frame);
389 std::vector<std::string> frameHierarchy;
390 while(frame = GetParent(*frame))
391 {
392 frameHierarchy.push_back(ToUtf8String(GetLocationUrl(*frame)));
393 }
394 CPluginClient* client = CPluginClient::GetInstance();
395 return client->IsWhitelistedUrl(url, frameHierarchy)
396 || client->IsElemhideWhitelistedOnDomain(url, frameHierarchy);
397 }
398 }
399
400 void CPluginTab::OnDownloadComplete(IWebBrowser2* browser)
259 { 401 {
260 if (IsTraverserEnabled()) 402 if (IsTraverserEnabled())
261 { 403 {
262 CPluginClient* client = CPluginClient::GetInstance(); 404 CPluginClient* client = CPluginClient::GetInstance();
263 std::wstring url = to_wstring(GetDocumentUrl()); 405 std::wstring url = GetDocumentUrl();
264 if (!client->IsWhitelistedUrl(url) && !client->IsElemhideWhitelistedOnDomain (url)) 406 if (!client->IsWhitelistedUrl(url) && !client->IsElemhideWhitelistedOnDomain (url))
265 { 407 {
266 m_traverser->TraverseDocument(browser, GetDocumentDomain(), GetDocumentUrl ()); 408 if (!m_traverser)
409 {
410 assert(m_asyncPluginFilter && "Filter initialization should be already a t least started");
411 if (m_asyncPluginFilter)
412 {
413 auto pluginFilter = m_asyncPluginFilter->GetFilter();
414 assert(pluginFilter && "Plugin filter should be a valid object");
415 if (pluginFilter)
416 m_traverser.reset(new CPluginDomTraverser(pluginFilter));
417 }
418 }
419 assert(m_traverser && "Traverser should be a valid object");
420 if (m_traverser)
421 m_traverser->TraverseDocument(browser, GetDocumentDomain(), GetDocumentU rl());
267 } 422 }
268 } 423 }
269 InjectABP(browser); 424 InjectABP(browser);
270 } 425 }
271 426
272 void CPluginTabBase::OnDocumentComplete(IWebBrowser2* browser, const CString& ur l, bool isDocumentBrowser) 427 void CPluginTab::OnDocumentComplete(IWebBrowser2* browser, const std::wstring& u rl, bool isDocumentBrowser)
273 { 428 {
274 CString documentUrl = GetDocumentUrl(); 429 std::wstring documentUrl = GetDocumentUrl();
275 430
276 if (isDocumentBrowser) 431 if (isDocumentBrowser)
277 { 432 {
278 if (url != documentUrl) 433 if (url != documentUrl)
279 { 434 {
280 SetDocumentUrl(url); 435 SetDocumentUrl(url);
281 } 436 }
282 InjectABP(browser); 437 InjectABP(browser);
283 } 438 }
284 if (url.Left(6) == "res://") 439 if (BeginsWith(url, L"res://"))
285 { 440 {
286 return; 441 return;
287 } 442 }
288 // Get document 443 // Get document
289 ATL::CComPtr<IDispatch> pDocDispatch; 444 CComPtr<IDispatch> pDocDispatch;
290 HRESULT hr = browser->get_Document(&pDocDispatch); 445 HRESULT hr = browser->get_Document(&pDocDispatch);
291 if (FAILED(hr) || !pDocDispatch) 446 if (FAILED(hr) || !pDocDispatch)
292 { 447 {
293 return; 448 return;
294 } 449 }
295 450
296 ATL::CComQIPtr<IHTMLDocument2> pDoc = pDocDispatch; 451 CComQIPtr<IHTMLDocument2> pDoc(pDocDispatch);
297 if (!pDoc) 452 if (!pDoc)
298 { 453 {
299 return; 454 return;
300 } 455 }
301 456
302 if (IsCSSInjectionEnabled()) 457 if (IsCSSInjectionEnabled() && CPluginSettings::GetInstance()->GetPluginEnable d())
303 { 458 {
304 DEBUG_GENERAL(ToCString(L"Inject CSS into ") + url); 459 if (!IsFrameWhiteListed(browser))
305 InjectABPCSS(*pDoc, m_filter->getHideFilters()); 460 {
306 } 461 DEBUG_GENERAL(L"Inject CSS into " + url);
307 462 assert(m_asyncPluginFilter && "Filter initialization should be already at least started");
308 ATL::CComPtr<IOleObject> pOleObj; 463 if (m_asyncPluginFilter)
309 pDocDispatch->QueryInterface(IID_IOleObject, (void**)&pOleObj); 464 {
310 465 auto pluginFilter = m_asyncPluginFilter->GetFilter();
466 assert(pluginFilter && "Plugin filter should be a valid object");
467 if (pluginFilter)
468 {
469 InjectABPCSS(*pDoc, pluginFilter->GetHideFilters());
470 }
471 }
472 }
473 }
474
475 CComPtr<IOleObject> pOleObj;
476 pDocDispatch->QueryInterface(&pOleObj);
477 if (!pOleObj)
478 {
479 return;
480 }
311 CComPtr<IOleClientSite> pClientSite; 481 CComPtr<IOleClientSite> pClientSite;
312 pOleObj->GetClientSite(&pClientSite); 482 pOleObj->GetClientSite(&pClientSite);
313 if (pClientSite != NULL) 483 if (pClientSite != NULL)
314 { 484 {
315 CComPtr<IDocHostUIHandler> docHostUIHandler; 485 CComPtr<IDocHostUIHandler> docHostUIHandler;
316 pClientSite->QueryInterface(IID_IDocHostUIHandler, (void**)&docHostUIHandler ); 486 pClientSite->QueryInterface(&docHostUIHandler);
317 if (docHostUIHandler != NULL) 487 if (docHostUIHandler != NULL)
318 { 488 {
319 docHostUIHandler->UpdateUI(); 489 docHostUIHandler->UpdateUI();
320 } 490 }
321 } 491 }
322 } 492 }
323 493
324 std::wstring CPluginTabBase::GetDocumentDomain() 494 std::wstring CPluginTab::GetDocumentDomain()
325 { 495 {
326 std::wstring domain; 496 std::wstring domain;
327 497
328 m_criticalSection.Lock(); 498 m_criticalSection.Lock();
329 { 499 {
330 domain = m_documentDomain; 500 domain = m_documentDomain;
331 } 501 }
332 m_criticalSection.Unlock(); 502 m_criticalSection.Unlock();
333 503
334 return domain; 504 return domain;
335 } 505 }
336 506
337 void CPluginTabBase::SetDocumentUrl(const CString& url) 507 void CPluginTab::SetDocumentUrl(const std::wstring& url)
338 { 508 {
339 m_criticalSection.Lock(); 509 m_criticalSection.Lock();
340 { 510 {
341 m_documentUrl = url; 511 m_documentUrl = url;
342 m_documentDomain = CAdblockPlusClient::GetInstance()->GetHostFromUrl(to_wstr ing(url)); 512 m_documentDomain = CAdblockPlusClient::GetInstance()->GetHostFromUrl(url);
343 } 513 }
344 m_criticalSection.Unlock(); 514 m_criticalSection.Unlock();
345 } 515 }
346 516
347 CString CPluginTabBase::GetDocumentUrl() 517 std::wstring CPluginTab::GetDocumentUrl()
348 { 518 {
349 CString url; 519 std::wstring url;
350 520
351 m_criticalSection.Lock(); 521 m_criticalSection.Lock();
352 { 522 {
353 url = m_documentUrl; 523 url = m_documentUrl;
354 } 524 }
355 m_criticalSection.Unlock(); 525 m_criticalSection.Unlock();
356 526
357 return url; 527 return url;
358 } 528 }
359 529
360 530
361 // ============================================================================ 531 // ============================================================================
362 // Frame caching 532 // Frame caching
363 // ============================================================================ 533 // ============================================================================
364 bool CPluginTabBase::IsFrameCached(const CString& url) 534 bool CPluginTab::IsFrameCached(const std::wstring& url)
365 { 535 {
366 bool isFrame; 536 bool isFrame;
367 537
368 m_criticalSectionCache.Lock(); 538 m_criticalSectionCache.Lock();
369 { 539 {
370 isFrame = m_cacheFrames.find(url) != m_cacheFrames.end(); 540 isFrame = m_cacheFrames.find(url) != m_cacheFrames.end();
371 } 541 }
372 m_criticalSectionCache.Unlock(); 542 m_criticalSectionCache.Unlock();
373 543
374 return isFrame; 544 return isFrame;
375 } 545 }
376 546
377 void CPluginTabBase::CacheFrame(const CString& url) 547 void CPluginTab::CacheFrame(const std::wstring& url)
378 { 548 {
379 m_criticalSectionCache.Lock(); 549 m_criticalSectionCache.Lock();
380 { 550 {
381 m_cacheFrames.insert(url); 551 m_cacheFrames.insert(url);
382 } 552 }
383 m_criticalSectionCache.Unlock(); 553 m_criticalSectionCache.Unlock();
384 } 554 }
385 555
386 void CPluginTabBase::ClearFrameCache(const std::wstring& domain) 556 void CPluginTab::ClearFrameCache(const std::wstring& domain)
387 { 557 {
388 m_criticalSectionCache.Lock(); 558 m_criticalSectionCache.Lock();
389 { 559 {
390 if (domain.empty() || domain != m_cacheDomain) 560 if (domain.empty() || domain != m_cacheDomain)
391 { 561 {
392 m_cacheFrames.clear(); 562 m_cacheFrames.clear();
393 m_cacheDomain = domain; 563 m_cacheDomain = domain;
394 } 564 }
395 } 565 }
396 m_criticalSectionCache.Unlock(); 566 m_criticalSectionCache.Unlock();
397 } 567 }
398 568
399 void CPluginTabBase::ThreadProc() 569 void CPluginTab::ThreadProc()
400 { 570 {
401 // Force loading/creation of settings 571 // Force loading/creation of settings
402 CPluginSettings* settings = CPluginSettings::GetInstance(); 572 CPluginSettings::GetInstance();
403 573
404 settings->SetWorkingThreadId(); 574 std::string message =
405 575 "=========================================================================== =====\n"
406 CString threadInfo; 576 "TAB THREAD process=";
407 threadInfo.Format(L"%d.%d", ::GetCurrentProcessId(), ::GetCurrentThreadId()); 577 message += std::to_string(::GetCurrentProcessId());
408 578 message + " thread=";
409 CString debugText; 579 message += std::to_string(::GetCurrentThreadId());
410 580 message +=
411 debugText += L"=============================================================== ================="; 581 "\n"
412 debugText += L"\nTAB THREAD " + threadInfo; 582 "=========================================================================== =====";
413 debugText += L"\n============================================================= ==================="; 583 DEBUG_GENERAL(message);
414
415 DEBUG_GENERAL(debugText)
416 584
417 // -------------------------------------------------------------------- 585 // --------------------------------------------------------------------
418 // Tab loop 586 // Tab loop
419 // -------------------------------------------------------------------- 587 // --------------------------------------------------------------------
420 588
421 DWORD loopCount = 0; 589 DWORD loopCount = 0;
422 DWORD tabLoopIteration = 1; 590 DWORD tabLoopIteration = 1;
423 591
424 while (this->m_continueThreadRunning) 592 while (this->m_continueThreadRunning)
425 { 593 {
426 #ifdef ENABLE_DEBUG_THREAD 594 #ifdef ENABLE_DEBUG_THREAD
427 CStringA sTabLoopIteration; 595 CStringA sTabLoopIteration;
428 sTabLoopIteration.Format("%u", tabLoopIteration); 596 sTabLoopIteration.Format("%u", tabLoopIteration);
429 597
430 DEBUG_THREAD("-------------------------------------------------------------- ------------------") 598 DEBUG_THREAD("-------------------------------------------------------------- ------------------")
431 DEBUG_THREAD("Loop iteration " + sTabLoopIteration); 599 DEBUG_THREAD("Loop iteration " + sTabLoopIteration);
432 DEBUG_THREAD("-------------------------------------------------------------- ------------------") 600 DEBUG_THREAD("-------------------------------------------------------------- ------------------")
433 #endif 601 #endif
434 if (this->m_isActivated) 602 this->m_isActivated = false;
435 {
436 bool isChanged = false;
437
438 if (isChanged)
439 {
440 this->m_plugin->UpdateStatusBar();
441 }
442
443 this->m_isActivated = false;
444 }
445 603
446 // -------------------------------------------------------------------- 604 // --------------------------------------------------------------------
447 // End loop 605 // End loop
448 // -------------------------------------------------------------------- 606 // --------------------------------------------------------------------
449 607
450 // Sleep loop 608 // Sleep loop
451 while (this->m_continueThreadRunning && !this->m_isActivated && (++loopCou nt % (TIMER_THREAD_SLEEP_TAB_LOOP / 50)) != 0) 609 while (this->m_continueThreadRunning && !this->m_isActivated && (++loopCou nt % (TIMER_THREAD_SLEEP_TAB_LOOP / 50)) != 0)
452 { 610 {
453 // Post async plugin error 611 // Post async plugin error
454 CPluginError pluginError; 612 CPluginError pluginError;
455 if (CPluginClient::PopFirstPluginError(pluginError)) 613 if (LogQueue::PopFirstPluginError(pluginError))
456 { 614 {
457 CPluginClient::LogPluginError(pluginError.GetErrorCode(), pluginError. GetErrorId(), pluginError.GetErrorSubid(), pluginError.GetErrorDescription(), tr ue, pluginError.GetProcessId(), pluginError.GetThreadId()); 615 LogQueue::LogPluginError(pluginError.GetErrorCode(), pluginError.GetEr rorId(), pluginError.GetErrorSubid(), pluginError.GetErrorDescription(), true, p luginError.GetProcessId(), pluginError.GetThreadId());
458 } 616 }
459 617
460 // Non-hanging sleep 618 // Non-hanging sleep
461 Sleep(50); 619 Sleep(50);
462 } 620 }
463 621
464 tabLoopIteration++; 622 tabLoopIteration++;
465 } 623 }
466 } 624 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld