Index: src/plugin/PluginTabBase.cpp |
diff --git a/src/plugin/PluginTabBase.cpp b/src/plugin/PluginTabBase.cpp |
index 3ac26f23bfca300ac710654ca2b406b6bd1be5c1..4acc8242924fc788481bdf495a08dc707300fdfc 100644 |
--- a/src/plugin/PluginTabBase.cpp |
+++ b/src/plugin/PluginTabBase.cpp |
@@ -1,394 +1,441 @@ |
-/* |
- * This file is part of Adblock Plus <https://adblockplus.org/>, |
- * Copyright (C) 2006-2015 Eyeo GmbH |
- * |
- * Adblock Plus is free software: you can redistribute it and/or modify |
- * it under the terms of the GNU General Public License version 3 as |
- * published by the Free Software Foundation. |
- * |
- * Adblock Plus is distributed in the hope that it will be useful, |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
- * GNU General Public License for more details. |
- * |
- * You should have received a copy of the GNU General Public License |
- * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
- */ |
- |
-#include "PluginStdAfx.h" |
-#include "AdblockPlusClient.h" |
-#include "PluginClientBase.h" |
-#include "PluginSettings.h" |
-#include "AdblockPlusDomTraverser.h" |
-#include "PluginTabBase.h" |
-#include "IeVersion.h" |
-#include <Mshtmhst.h> |
- |
-CPluginTabBase::CPluginTabBase(CPluginClass* plugin) |
- : m_plugin(plugin) |
- , m_isActivated(false) |
- , m_continueThreadRunning(true) |
-{ |
- m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter()); |
- m_filter->hideFiltersLoadedEvent = CreateEvent(NULL, true, false, NULL); |
- |
- CPluginClient* client = CPluginClient::GetInstance(); |
- if (AdblockPlus::IE::InstalledMajorVersion() < 10) |
- { |
- m_isActivated = true; |
- } |
- |
- try |
- { |
- m_thread = std::thread(&CPluginTabBase::ThreadProc, this); |
- } |
- catch (const std::system_error& ex) |
- { |
- DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_TAB_THREAD_CREATE_PROCESS, |
- "Tab::Thread - Failed to create tab thread"); |
- } |
- m_traverser = new CPluginDomTraverser(static_cast<CPluginTab*>(this)); |
-} |
- |
- |
-CPluginTabBase::~CPluginTabBase() |
-{ |
- delete m_traverser; |
- m_traverser = NULL; |
- m_continueThreadRunning = false; |
- if (m_thread.joinable()) { |
- m_thread.join(); |
- } |
-} |
- |
-void CPluginTabBase::OnActivate() |
-{ |
- m_isActivated = true; |
-} |
- |
- |
-void CPluginTabBase::OnUpdate() |
-{ |
- m_isActivated = true; |
-} |
- |
-namespace |
-{ |
- // Entry Point |
- void FilterLoader(CPluginTabBase* tabBase) |
- { |
- try |
- { |
- tabBase->m_filter->LoadHideFilters(CPluginClient::GetInstance()->GetElementHidingSelectors(tabBase->GetDocumentDomain())); |
- SetEvent(tabBase->m_filter->hideFiltersLoadedEvent); |
- } |
- catch (...) |
- { |
- // As a thread-main function, we truncate any C++ exception. |
- } |
- } |
-} |
- |
-void CPluginTabBase::OnNavigate(const std::wstring& url) |
-{ |
- SetDocumentUrl(url); |
- ClearFrameCache(GetDocumentDomain()); |
- std::wstring domainString = GetDocumentDomain(); |
- ResetEvent(m_filter->hideFiltersLoadedEvent); |
- try |
- { |
- std::thread filterLoaderThread(&FilterLoader, this); |
- filterLoaderThread.detach(); // TODO: but actually we should wait for the thread in the dtr. |
- } |
- catch (const std::system_error& ex) |
- { |
- DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS, |
- "Class::Thread - Failed to start filter loader thread"); |
- } |
- m_traverser->ClearCache(); |
-} |
- |
-namespace |
-{ |
- /** |
- * Determine if the HTML file is one of ours. |
- * The criterion is that it appear in the "html/templates" folder within our installation. |
- * |
- * Warning: This function may fail if the argument is not a "file://" URL. |
- * This is occasionally the case in circumstances yet to be characterized. |
- */ |
- bool IsOurHtmlFile(const std::wstring& url) |
- { |
- // Declared static because the value is derived from an installation directory, which won't change during run-time. |
- static auto dir = FileUrl(HtmlFolderPath()); |
- |
- DEBUG_GENERAL([&]() -> std::wstring { |
- std::wstring log = L"InjectABP. Current URL: "; |
- log += url; |
- log += L", template directory URL: "; |
- log += dir; |
- return log; |
- }()); |
- |
- /* |
- * The length check here is defensive, in case the document URL is truncated for some reason. |
- */ |
- if (url.length() < 5) |
- { |
- // We can't match ".html" at the end of the URL if it's too short. |
- return false; |
- } |
- auto urlCstr = url.c_str(); |
- // Check the prefix to match our directory |
- // Check the suffix to be an HTML file |
- return (_wcsnicmp(urlCstr, dir.c_str(), dir.length()) == 0) && |
- (_wcsnicmp(urlCstr + url.length() - 5, L".html", 5) == 0); |
- } |
-} |
- |
-void CPluginTabBase::InjectABP(IWebBrowser2* browser) |
-{ |
- CriticalSection::Lock lock(m_csInject); |
- auto url = GetDocumentUrl(); |
- if (!IsOurHtmlFile(url)) |
- { |
- DEBUG_GENERAL(L"InjectABP. Not injecting"); |
- return; |
- } |
- DEBUG_GENERAL(L"InjectABP. Injecting"); |
- CComPtr<IDispatch> pDocDispatch; |
- browser->get_Document(&pDocDispatch); |
- CComQIPtr<IHTMLDocument2> pDoc2 = pDocDispatch; |
- if (!pDoc2) |
- { |
- DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI document"); |
- return; |
- } |
- CComPtr<IHTMLWindow2> pWnd2; |
- pDoc2->get_parentWindow(&pWnd2); |
- if (!pWnd2) |
- { |
- DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get parent window"); |
- return; |
- } |
- CComQIPtr<IDispatchEx> pWndEx = pWnd2; |
- if (!pWndEx) |
- { |
- DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI dispatch"); |
- return; |
- } |
- // Create "Settings" object in JavaScript. |
- // A method call of "Settings" in JavaScript, transfered to "Invoke" of m_pluginUserSettings |
- DISPID dispid; |
- HRESULT hr = pWndEx->GetDispID(L"Settings", fdexNameEnsure, &dispid); |
- if (FAILED(hr)) |
- { |
- DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get dispatch"); |
- return; |
- } |
- CComVariant var((IDispatch*)&m_pluginUserSettings); |
- |
- DEBUG_GENERAL("Injecting"); |
- |
- DISPPARAMS params; |
- params.cArgs = 1; |
- params.cNamedArgs = 0; |
- params.rgvarg = &var; |
- params.rgdispidNamedArgs = 0; |
- hr = pWndEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF, ¶ms, 0, 0, 0); |
- DEBUG_GENERAL("Invoke"); |
- if (FAILED(hr)) |
- { |
- DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to create Settings in JavaScript"); |
- } |
-} |
- |
-void CPluginTabBase::OnDownloadComplete(IWebBrowser2* browser) |
-{ |
- CPluginClient* client = CPluginClient::GetInstance(); |
- std::wstring url = GetDocumentUrl(); |
- if (!client->IsWhitelistedUrl(url) && !client->IsElemhideWhitelistedOnDomain(url)) |
- { |
- m_traverser->TraverseDocument(browser, GetDocumentDomain(), GetDocumentUrl()); |
- } |
- InjectABP(browser); |
-} |
- |
-void CPluginTabBase::OnDocumentComplete(IWebBrowser2* browser, const std::wstring& url, bool isDocumentBrowser) |
-{ |
- std::wstring documentUrl = GetDocumentUrl(); |
- |
- if (isDocumentBrowser) |
- { |
- if (url != documentUrl) |
- { |
- SetDocumentUrl(url); |
- } |
- InjectABP(browser); |
- } |
- CString urlLegacy = ToCString(url); |
- if (urlLegacy.Left(6) != "res://") |
- { |
- // Get document |
- CComPtr<IDispatch> pDocDispatch; |
- HRESULT hr = browser->get_Document(&pDocDispatch); |
- if (FAILED(hr) || !pDocDispatch) |
- { |
- return; |
- } |
- |
- CComQIPtr<IHTMLDocument2> pDoc = pDocDispatch; |
- if (!pDoc) |
- { |
- return; |
- } |
- CComPtr<IOleObject> pOleObj; |
- |
- pDocDispatch->QueryInterface(IID_IOleObject, (void**)&pOleObj); |
- |
- |
- CComPtr<IOleClientSite> pClientSite; |
- pOleObj->GetClientSite(&pClientSite); |
- if (pClientSite != NULL) |
- { |
- CComPtr<IDocHostUIHandler> docHostUIHandler; |
- pClientSite->QueryInterface(IID_IDocHostUIHandler, (void**)&docHostUIHandler); |
- if (docHostUIHandler != NULL) |
- { |
- docHostUIHandler->UpdateUI(); |
- } |
- } |
- } |
-} |
- |
-std::wstring CPluginTabBase::GetDocumentDomain() |
-{ |
- std::wstring domain; |
- |
- m_criticalSection.Lock(); |
- { |
- domain = m_documentDomain; |
- } |
- m_criticalSection.Unlock(); |
- |
- return domain; |
-} |
- |
-void CPluginTabBase::SetDocumentUrl(const std::wstring& url) |
-{ |
- m_criticalSection.Lock(); |
- { |
- m_documentUrl = url; |
- m_documentDomain = CAdblockPlusClient::GetInstance()->GetHostFromUrl(url); |
- } |
- m_criticalSection.Unlock(); |
-} |
- |
-std::wstring CPluginTabBase::GetDocumentUrl() |
-{ |
- std::wstring url; |
- |
- m_criticalSection.Lock(); |
- { |
- url = m_documentUrl; |
- } |
- m_criticalSection.Unlock(); |
- |
- return url; |
-} |
- |
- |
-// ============================================================================ |
-// Frame caching |
-// ============================================================================ |
-bool CPluginTabBase::IsFrameCached(const std::wstring& url) |
-{ |
- bool isFrame; |
- |
- m_criticalSectionCache.Lock(); |
- { |
- isFrame = m_cacheFrames.find(url) != m_cacheFrames.end(); |
- } |
- m_criticalSectionCache.Unlock(); |
- |
- return isFrame; |
-} |
- |
-void CPluginTabBase::CacheFrame(const std::wstring& url) |
-{ |
- m_criticalSectionCache.Lock(); |
- { |
- m_cacheFrames.insert(url); |
- } |
- m_criticalSectionCache.Unlock(); |
-} |
- |
-void CPluginTabBase::ClearFrameCache(const std::wstring& domain) |
-{ |
- m_criticalSectionCache.Lock(); |
- { |
- if (domain.empty() || domain != m_cacheDomain) |
- { |
- m_cacheFrames.clear(); |
- m_cacheDomain = domain; |
- } |
- } |
- m_criticalSectionCache.Unlock(); |
-} |
- |
-void CPluginTabBase::ThreadProc() |
-{ |
- // Force loading/creation of settings |
- CPluginSettings::GetInstance()->SetWorkingThreadId(); |
- |
- std::string message = |
- "================================================================================\n" |
- "TAB THREAD process="; |
- message += std::to_string(::GetCurrentProcessId()); |
- message + " thread="; |
- message += std::to_string(::GetCurrentThreadId()); |
- message += |
- "\n" |
- "================================================================================"; |
- DEBUG_GENERAL(message); |
- |
- // -------------------------------------------------------------------- |
- // Tab loop |
- // -------------------------------------------------------------------- |
- |
- DWORD loopCount = 0; |
- DWORD tabLoopIteration = 1; |
- |
- while (this->m_continueThreadRunning) |
- { |
-#ifdef ENABLE_DEBUG_THREAD |
- CStringA sTabLoopIteration; |
- sTabLoopIteration.Format("%u", tabLoopIteration); |
- |
- DEBUG_THREAD("--------------------------------------------------------------------------------") |
- DEBUG_THREAD("Loop iteration " + sTabLoopIteration); |
- DEBUG_THREAD("--------------------------------------------------------------------------------") |
-#endif |
- this->m_isActivated = false; |
- |
- // -------------------------------------------------------------------- |
- // End loop |
- // -------------------------------------------------------------------- |
- |
- // Sleep loop |
- while (this->m_continueThreadRunning && !this->m_isActivated && (++loopCount % (TIMER_THREAD_SLEEP_TAB_LOOP / 50)) != 0) |
- { |
- // Post async plugin error |
- CPluginError pluginError; |
- if (LogQueue::PopFirstPluginError(pluginError)) |
- { |
- LogQueue::LogPluginError(pluginError.GetErrorCode(), pluginError.GetErrorId(), pluginError.GetErrorSubid(), pluginError.GetErrorDescription(), true, pluginError.GetProcessId(), pluginError.GetThreadId()); |
- } |
- |
- // Non-hanging sleep |
- Sleep(50); |
- } |
- |
- tabLoopIteration++; |
- } |
-} |
+/* |
+ * This file is part of Adblock Plus <https://adblockplus.org/>, |
+ * Copyright (C) 2006-2015 Eyeo GmbH |
+ * |
+ * Adblock Plus is free software: you can redistribute it and/or modify |
+ * it under the terms of the GNU General Public License version 3 as |
+ * published by the Free Software Foundation. |
+ * |
+ * Adblock Plus is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ * GNU General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU General Public License |
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
+ */ |
+ |
+#include "PluginStdAfx.h" |
+#include "AdblockPlusClient.h" |
+#include "PluginClientBase.h" |
+#include "PluginSettings.h" |
+#include "AdblockPlusDomTraverser.h" |
+#include "PluginTabBase.h" |
+#include "IeVersion.h" |
+#include "../shared/Utils.h" |
+#include <Mshtmhst.h> |
+ |
+CPluginTabBase::CPluginTabBase(CPluginClass* plugin) |
+ : m_plugin(plugin) |
+ , m_isActivated(false) |
+ , m_continueThreadRunning(true) |
+{ |
+ m_filter = std::auto_ptr<CPluginFilter>(new CPluginFilter()); |
+ m_filter->hideFiltersLoadedEvent = CreateEvent(NULL, true, false, NULL); |
+ |
+ CPluginClient* client = CPluginClient::GetInstance(); |
+ if (AdblockPlus::IE::InstalledMajorVersion() < 10) |
+ { |
+ m_isActivated = true; |
+ } |
+ |
+ try |
+ { |
+ m_thread = std::thread(&CPluginTabBase::ThreadProc, this); |
+ } |
+ catch (const std::system_error& ex) |
+ { |
+ DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_TAB_THREAD_CREATE_PROCESS, |
+ "Tab::Thread - Failed to create tab thread"); |
+ } |
+ m_traverser = new CPluginDomTraverser(static_cast<CPluginTab*>(this)); |
+} |
+ |
+ |
+CPluginTabBase::~CPluginTabBase() |
+{ |
+ delete m_traverser; |
+ m_traverser = NULL; |
+ m_continueThreadRunning = false; |
+ if (m_thread.joinable()) { |
+ m_thread.join(); |
+ } |
+} |
+ |
+void CPluginTabBase::OnActivate() |
+{ |
+ m_isActivated = true; |
+} |
+ |
+ |
+void CPluginTabBase::OnUpdate() |
+{ |
+ m_isActivated = true; |
+} |
+ |
+namespace |
+{ |
+ // Entry Point |
+ void FilterLoader(CPluginTabBase* tabBase) |
+ { |
+ try |
+ { |
+ tabBase->m_filter->LoadHideFilters(CPluginClient::GetInstance()->GetElementHidingSelectors(tabBase->GetDocumentDomain())); |
+ SetEvent(tabBase->m_filter->hideFiltersLoadedEvent); |
+ } |
+ catch (...) |
+ { |
+ // As a thread-main function, we truncate any C++ exception. |
+ } |
+ } |
+} |
+ |
+void CPluginTabBase::OnNavigate(const std::wstring& url) |
+{ |
+ SetDocumentUrl(url); |
+ ClearFrameCache(GetDocumentDomain()); |
+ std::wstring domainString = GetDocumentDomain(); |
+ ResetEvent(m_filter->hideFiltersLoadedEvent); |
+ try |
+ { |
+ std::thread filterLoaderThread(&FilterLoader, this); |
+ filterLoaderThread.detach(); // TODO: but actually we should wait for the thread in the dtr. |
+ } |
+ catch (const std::system_error& ex) |
+ { |
+ DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS, |
+ "Class::Thread - Failed to start filter loader thread"); |
+ } |
+ m_traverser->ClearCache(); |
+} |
+ |
+namespace |
+{ |
+ /** |
+ * Determine if the HTML file is one of ours. |
+ * The criterion is that it appear in the "html/templates" folder within our installation. |
+ * |
+ * Warning: This function may fail if the argument is not a "file://" URL. |
+ * This is occasionally the case in circumstances yet to be characterized. |
+ */ |
+ bool IsOurHtmlFile(const std::wstring& url) |
+ { |
+ // Declared static because the value is derived from an installation directory, which won't change during run-time. |
+ static auto dir = FileUrl(HtmlFolderPath()); |
+ |
+ DEBUG_GENERAL([&]() -> std::wstring { |
+ std::wstring log = L"InjectABP. Current URL: "; |
+ log += url; |
+ log += L", template directory URL: "; |
+ log += dir; |
+ return log; |
+ }()); |
+ |
+ /* |
+ * The length check here is defensive, in case the document URL is truncated for some reason. |
+ */ |
+ if (url.length() < 5) |
+ { |
+ // We can't match ".html" at the end of the URL if it's too short. |
+ return false; |
+ } |
+ auto urlCstr = url.c_str(); |
+ // Check the prefix to match our directory |
+ // Check the suffix to be an HTML file |
+ return (_wcsnicmp(urlCstr, dir.c_str(), dir.length()) == 0) && |
+ (_wcsnicmp(urlCstr + url.length() - 5, L".html", 5) == 0); |
+ } |
+} |
+ |
+void CPluginTabBase::InjectABP(IWebBrowser2* browser) |
+{ |
+ CriticalSection::Lock lock(m_csInject); |
+ auto url = GetDocumentUrl(); |
+ if (!IsOurHtmlFile(url)) |
+ { |
+ DEBUG_GENERAL(L"InjectABP. Not injecting"); |
+ return; |
+ } |
+ DEBUG_GENERAL(L"InjectABP. Injecting"); |
+ CComPtr<IDispatch> pDocDispatch; |
+ browser->get_Document(&pDocDispatch); |
+ CComQIPtr<IHTMLDocument2> pDoc2 = pDocDispatch; |
+ if (!pDoc2) |
+ { |
+ DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI document"); |
+ return; |
+ } |
+ CComPtr<IHTMLWindow2> pWnd2; |
+ pDoc2->get_parentWindow(&pWnd2); |
+ if (!pWnd2) |
+ { |
+ DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get parent window"); |
+ return; |
+ } |
+ CComQIPtr<IDispatchEx> pWndEx = pWnd2; |
+ if (!pWndEx) |
+ { |
+ DEBUG_ERROR_LOG(0, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to QI dispatch"); |
+ return; |
+ } |
+ // Create "Settings" object in JavaScript. |
+ // A method call of "Settings" in JavaScript, transfered to "Invoke" of m_pluginUserSettings |
+ DISPID dispid; |
+ HRESULT hr = pWndEx->GetDispID(L"Settings", fdexNameEnsure, &dispid); |
+ if (FAILED(hr)) |
+ { |
+ DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to get dispatch"); |
+ return; |
+ } |
+ CComVariant var((IDispatch*)&m_pluginUserSettings); |
+ |
+ DEBUG_GENERAL("Injecting"); |
+ |
+ DISPPARAMS params; |
+ params.cArgs = 1; |
+ params.cNamedArgs = 0; |
+ params.rgvarg = &var; |
+ params.rgdispidNamedArgs = 0; |
+ hr = pWndEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF, ¶ms, 0, 0, 0); |
+ DEBUG_GENERAL("Invoke"); |
+ if (FAILED(hr)) |
+ { |
+ DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT, PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE, "CPluginTabBase::InjectABP - Failed to create Settings in JavaScript"); |
+ } |
+} |
+ |
+namespace |
+{ |
Eric
2015/11/14 20:28:13
I don't believe that any of the pointers in the fu
|
+ ATL::CComPtr<IWebBrowser2> GetParent(IWebBrowser2& browser) |
+ { |
+ ATL::CComPtr<IDispatch> parentDispatch; |
+ if (FAILED(browser.get_Parent(&parentDispatch)) || !parentDispatch) |
+ { |
+ return nullptr; |
+ } |
+ // The InternetExplorer application always returns a pointer to itself. |
+ // https://msdn.microsoft.com/en-us/library/aa752136(v=vs.85).aspx |
+ if (parentDispatch.IsEqualObject(&browser)) |
+ { |
+ return nullptr; |
+ } |
Eric
2015/11/14 20:28:13
I don't see the need for any of the code in the fu
sergei
2015/11/17 20:16:00
Smart pointers are used to avoid manual calls of R
Eric
2015/11/17 21:00:16
I know what smart pointers for COM objects do.
My
sergei
2015/11/17 21:05:23
We should call Release on pointers obtained either
Eric
2015/11/17 22:30:22
This is the real reason. We don't need to manage t
sergei
2015/11/18 10:07:50
I see the point.
You are talking that the lifetime
Eric
2015/11/18 15:25:22
I'll concede the point that this is purely defensi
|
+ ATL::CComQIPtr<IServiceProvider> parentDocumentServiceProvider = parentDispatch; |
+ if (!parentDocumentServiceProvider) |
+ { |
+ return nullptr; |
+ } |
+ ATL::CComPtr<IWebBrowserApp> webBrowserApp; |
+ if (FAILED(parentDocumentServiceProvider->QueryService(IID_IWebBrowserApp, &webBrowserApp)) || !webBrowserApp) |
+ { |
+ return nullptr; |
+ } |
+ return ATL::CComQIPtr<IWebBrowser2>(webBrowserApp); |
+ } |
+ |
+ bool IsFrameWhiteListed(ATL::CComPtr<IWebBrowser2> frame) |
+ { |
+ if (!frame) |
+ { |
+ return false; |
+ } |
+ auto url = GetLocationUrl(*frame); |
+ std::vector<std::string> frameHierarchy; |
+ while(frame = GetParent(*frame)) |
+ { |
+ frameHierarchy.push_back(ToUtf8String(GetLocationUrl(*frame))); |
+ } |
+ CPluginClient* client = CPluginClient::GetInstance(); |
+ return client->IsWhitelistedUrl(url, frameHierarchy) |
+ || client->IsElemhideWhitelistedOnDomain(url, frameHierarchy); |
+ } |
+} |
+ |
+void CPluginTabBase::OnDownloadComplete(IWebBrowser2* browser) |
+{ |
+ CPluginClient* client = CPluginClient::GetInstance(); |
+ std::wstring url = GetDocumentUrl(); |
+ if (!client->IsWhitelistedUrl(url) && !client->IsElemhideWhitelistedOnDomain(url)) |
+ { |
+ m_traverser->TraverseDocument(browser, GetDocumentDomain(), GetDocumentUrl()); |
+ } |
+ InjectABP(browser); |
+} |
+ |
+void CPluginTabBase::OnDocumentComplete(IWebBrowser2* browser, const std::wstring& url, bool isDocumentBrowser) |
+{ |
+ std::wstring documentUrl = GetDocumentUrl(); |
+ |
+ if (isDocumentBrowser) |
+ { |
+ if (url != documentUrl) |
+ { |
+ SetDocumentUrl(url); |
+ } |
+ InjectABP(browser); |
+ } |
+ CString urlLegacy = ToCString(url); |
+ if (urlLegacy.Left(6) != "res://") |
+ { |
+ // Get document |
+ CComPtr<IDispatch> pDocDispatch; |
+ HRESULT hr = browser->get_Document(&pDocDispatch); |
+ if (FAILED(hr) || !pDocDispatch) |
+ { |
+ return; |
+ } |
+ |
+ CComQIPtr<IHTMLDocument2> pDoc = pDocDispatch; |
+ if (!pDoc) |
+ { |
+ return; |
+ } |
+ CComPtr<IOleObject> pOleObj; |
+ |
+ pDocDispatch->QueryInterface(IID_IOleObject, (void**)&pOleObj); |
+ |
+ |
+ CComPtr<IOleClientSite> pClientSite; |
+ pOleObj->GetClientSite(&pClientSite); |
+ if (pClientSite != NULL) |
+ { |
+ CComPtr<IDocHostUIHandler> docHostUIHandler; |
+ pClientSite->QueryInterface(IID_IDocHostUIHandler, (void**)&docHostUIHandler); |
+ if (docHostUIHandler != NULL) |
+ { |
+ docHostUIHandler->UpdateUI(); |
+ } |
+ } |
+ } |
+} |
+ |
+std::wstring CPluginTabBase::GetDocumentDomain() |
+{ |
+ std::wstring domain; |
+ |
+ m_criticalSection.Lock(); |
+ { |
+ domain = m_documentDomain; |
+ } |
+ m_criticalSection.Unlock(); |
+ |
+ return domain; |
+} |
+ |
+void CPluginTabBase::SetDocumentUrl(const std::wstring& url) |
+{ |
+ m_criticalSection.Lock(); |
+ { |
+ m_documentUrl = url; |
+ m_documentDomain = CAdblockPlusClient::GetInstance()->GetHostFromUrl(url); |
+ } |
+ m_criticalSection.Unlock(); |
+} |
+ |
+std::wstring CPluginTabBase::GetDocumentUrl() |
+{ |
+ std::wstring url; |
+ |
+ m_criticalSection.Lock(); |
+ { |
+ url = m_documentUrl; |
+ } |
+ m_criticalSection.Unlock(); |
+ |
+ return url; |
+} |
+ |
+ |
+// ============================================================================ |
+// Frame caching |
+// ============================================================================ |
+bool CPluginTabBase::IsFrameCached(const std::wstring& url) |
+{ |
+ bool isFrame; |
+ |
+ m_criticalSectionCache.Lock(); |
+ { |
+ isFrame = m_cacheFrames.find(url) != m_cacheFrames.end(); |
+ } |
+ m_criticalSectionCache.Unlock(); |
+ |
+ return isFrame; |
+} |
+ |
+void CPluginTabBase::CacheFrame(const std::wstring& url) |
+{ |
+ m_criticalSectionCache.Lock(); |
+ { |
+ m_cacheFrames.insert(url); |
+ } |
+ m_criticalSectionCache.Unlock(); |
+} |
+ |
+void CPluginTabBase::ClearFrameCache(const std::wstring& domain) |
+{ |
+ m_criticalSectionCache.Lock(); |
+ { |
+ if (domain.empty() || domain != m_cacheDomain) |
+ { |
+ m_cacheFrames.clear(); |
+ m_cacheDomain = domain; |
+ } |
+ } |
+ m_criticalSectionCache.Unlock(); |
+} |
+ |
+void CPluginTabBase::ThreadProc() |
+{ |
+ // Force loading/creation of settings |
+ CPluginSettings::GetInstance()->SetWorkingThreadId(); |
+ |
+ std::string message = |
+ "================================================================================\n" |
+ "TAB THREAD process="; |
+ message += std::to_string(::GetCurrentProcessId()); |
+ message + " thread="; |
+ message += std::to_string(::GetCurrentThreadId()); |
+ message += |
+ "\n" |
+ "================================================================================"; |
+ DEBUG_GENERAL(message); |
+ |
+ // -------------------------------------------------------------------- |
+ // Tab loop |
+ // -------------------------------------------------------------------- |
+ |
+ DWORD loopCount = 0; |
+ DWORD tabLoopIteration = 1; |
+ |
+ while (this->m_continueThreadRunning) |
+ { |
+#ifdef ENABLE_DEBUG_THREAD |
+ CStringA sTabLoopIteration; |
+ sTabLoopIteration.Format("%u", tabLoopIteration); |
+ |
+ DEBUG_THREAD("--------------------------------------------------------------------------------") |
+ DEBUG_THREAD("Loop iteration " + sTabLoopIteration); |
+ DEBUG_THREAD("--------------------------------------------------------------------------------") |
+#endif |
+ this->m_isActivated = false; |
+ |
+ // -------------------------------------------------------------------- |
+ // End loop |
+ // -------------------------------------------------------------------- |
+ |
+ // Sleep loop |
+ while (this->m_continueThreadRunning && !this->m_isActivated && (++loopCount % (TIMER_THREAD_SLEEP_TAB_LOOP / 50)) != 0) |
+ { |
+ // Post async plugin error |
+ CPluginError pluginError; |
+ if (LogQueue::PopFirstPluginError(pluginError)) |
+ { |
+ LogQueue::LogPluginError(pluginError.GetErrorCode(), pluginError.GetErrorId(), pluginError.GetErrorSubid(), pluginError.GetErrorDescription(), true, pluginError.GetProcessId(), pluginError.GetThreadId()); |
+ } |
+ |
+ // Non-hanging sleep |
+ Sleep(50); |
+ } |
+ |
+ tabLoopIteration++; |
+ } |
+} |