 Issue 6567422169448448:
  Issue 119 - Switch to injecting CSS for element hiding  (Closed)
    
  
    Issue 6567422169448448:
  Issue 119 - Switch to injecting CSS for element hiding  (Closed) 
  | Index: src/plugin/WebBrowserEventsListener.cpp | 
| diff --git a/src/plugin/WebBrowserEventsListener.cpp b/src/plugin/WebBrowserEventsListener.cpp | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..ac51387bdde8ed80ad038f64b23f4d76f9d550de | 
| --- /dev/null | 
| +++ b/src/plugin/WebBrowserEventsListener.cpp | 
| @@ -0,0 +1,164 @@ | 
| +/* | 
| + * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| + * Copyright (C) 2006-2016 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 "WebBrowserEventsListener.h" | 
| + | 
| +WebBrowserEventsListener::WebBrowserEventsListener() | 
| + : m_isDocumentEvents2Connected(false) | 
| + , m_state(State::FirstTimeLoading) | 
| +{ | 
| +} | 
| + | 
| +WebBrowserEventsListener::~WebBrowserEventsListener() | 
| +{ | 
| +} | 
| + | 
| +HRESULT STDMETHODCALLTYPE WebBrowserEventsListener::OnDocumentComplete(IDispatch* dispFrameBrowser, VARIANT* /*variantUrl*/) | 
| +{ | 
| + if (!dispFrameBrowser) | 
| + { | 
| + return E_POINTER; | 
| + } | 
| + | 
| + // if it's a signal from another browser (sub-frame for-example) then ignore it. | 
| + if (!m_browser.IsEqualObject(dispFrameBrowser)) | 
| + { | 
| + return S_OK; | 
| + } | 
| + | 
| + if (!m_isDocumentEvents2Connected) | 
| + { | 
| + ATL::CComPtr<IDispatch> dispDocument; | 
| + ATL::CComQIPtr<IHTMLDocument2> htmlDocument2; | 
| + bool isHtmlDocument2 = SUCCEEDED(m_browser->get_Document(&dispDocument)) && (htmlDocument2 = dispDocument); | 
| + isHtmlDocument2 && (m_isDocumentEvents2Connected = SUCCEEDED(HTMLDocumentEvents2Listener::DispEventAdvise(htmlDocument2))); | 
| + } | 
| + | 
| + // We can get here when readyStateChanged("complete") is already received, | 
| + // don't emit reloaded, because it's already emitted from OnReadyStateChange. | 
| + if (m_state == State::FirstTimeLoading) | 
| + { | 
| + m_state = State::Loaded; | 
| + emitReloaded(); | 
| + } | 
| + return S_OK; | 
| +} | 
| + | 
| +void STDMETHODCALLTYPE WebBrowserEventsListener::OnOnQuit() | 
| 
Oleksandr
2016/09/30 15:29:20
OnOnQuit sounds somewhat meta. How about just OnQu
 | 
| +{ | 
| + if (m_isDocumentEvents2Connected) | 
| + { | 
| + ATL::CComPtr<IDispatch> dispDocument; | 
| + ATL::CComQIPtr<IHTMLDocument2> htmlDocument2; | 
| + if (SUCCEEDED(m_browser->get_Document(&dispDocument)) && (htmlDocument2 = dispDocument)) | 
| + { | 
| + HTMLDocumentEvents2Listener::DispEventUnadvise(htmlDocument2); | 
| + } | 
| + } | 
| + WebBrowserEvents2Listener::DispEventUnadvise(m_browser); | 
| +} | 
| + | 
| +void STDMETHODCALLTYPE WebBrowserEventsListener::OnReadyStateChange(IHTMLEventObj* /*pEvtObj*/) | 
| +{ | 
| + auto documentReadyState = [this]()->std::wstring | 
| + { | 
| + std::wstring notAvailableReadyState; | 
| + ATL::CComPtr<IDispatch> pDocDispatch; | 
| + m_browser->get_Document(&pDocDispatch); | 
| + ATL::CComQIPtr<IHTMLDocument2> htmlDocument2 = pDocDispatch; | 
| + if (!htmlDocument2) | 
| + { | 
| + assert(false && "htmlDocument2 in OnReadyStateChange should not be nullptr"); | 
| + return notAvailableReadyState; | 
| + } | 
| + ATL::CComBSTR readyState; | 
| + if (FAILED(htmlDocument2->get_readyState(&readyState)) || !readyState) | 
| + { | 
| + assert(false && "cannot obtain document readyState in OnReadyStateChange"); | 
| + return notAvailableReadyState; | 
| + } | 
| + return std::wstring(readyState, readyState.Length()); | 
| + }(); | 
| + if (documentReadyState == L"loading") | 
| + { | 
| + m_state = State::Loading; | 
| + } | 
| + else if (documentReadyState == L"interactive") | 
| + { | 
| + } | 
| + else if (documentReadyState == L"complete") | 
| + { | 
| + if (m_state == State::Loading) | 
| + { | 
| + m_state = State::Loaded; | 
| + emitReloaded(); | 
| + } | 
| + else if (m_state == State::Loaded) | 
| + { | 
| + // It happens but very rearely, most often it appears on gmail. | 
| + // It seems IE prepares the 'browser' and then immediately says | 
| + // "complete" with the new URL. However all cases are related to | 
| + // some redirection technique and I could not reproduce it with local | 
| + // server which redirects, so let's wait for the user response on another | 
| + // web site when an advertisement is not blocked to better investigate | 
| + // when it happens. | 
| + } | 
| + else | 
| + { | 
| + assert(false); | 
| + } | 
| + } | 
| + else if (documentReadyState == L"uninitialized") | 
| + { | 
| + } | 
| + else | 
| + { | 
| + assert(false); | 
| + } | 
| +} | 
| + | 
| +void WebBrowserEventsListener::FinalRelease() | 
| +{ | 
| + if (!!m_onDestroy) | 
| + { | 
| + m_onDestroy(); | 
| + } | 
| +} | 
| + | 
| +HRESULT WebBrowserEventsListener::Init(IWebBrowser2* webBrowser, const OnDestroy& onDestroy, const OnReloaded& onReloaded) | 
| +{ | 
| + if (!(m_browser = webBrowser)) | 
| + { | 
| + return E_POINTER; | 
| + } | 
| + m_onDestroy = onDestroy; | 
| + m_onReloaded = onReloaded; | 
| + if (FAILED(WebBrowserEvents2Listener::DispEventAdvise(m_browser, &DIID_DWebBrowserEvents2))) | 
| + { | 
| + return E_FAIL; | 
| + } | 
| + return S_OK; | 
| +} | 
| + | 
| +void WebBrowserEventsListener::emitReloaded() | 
| +{ | 
| + if (m_onReloaded) | 
| + { | 
| + m_onReloaded(); | 
| + } | 
| +} |