/****************************************************************************** Copyright (c) 1999 Microsoft Corporation Module Name: Events.cpp Abstract: This file contains the implementation of the classes related to events. Revision History: Davide Massarenti (dmassare) 10/31/99 created ******************************************************************************/ #include "stdafx.h" #include ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// #ifdef DEBUG static void DEBUG_CheckReadyState() { CComPtr wb2; wb2.Attach( CPCHHelpCenterExternal::s_GLOBAL->Contents() ); tagREADYSTATE ready; if(wb2 && SUCCEEDED(wb2->get_ReadyState( &ready ))) { DebugLog( "#################### WEB %d\n", (int)ready ); } } static HRESULT DEBUG_GetReadyStateFromBrowser( IDispatch* pDisp , tagREADYSTATE *pVal ) { __HCP_FUNC_ENTRY( "DEBUG_GetReadyStateFromBrowser" ); HRESULT hr; CComPtr wb; *pVal = READYSTATE_UNINITIALIZED; __MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->QueryInterface( IID_IWebBrowser2, (LPVOID*)&wb )); __MPC_EXIT_IF_METHOD_FAILS(hr, wb ->get_ReadyState( pVal )); hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } static HRESULT DEBUG_GetLocationFromBrowser( IDispatch* pDisp , BSTR *pVal ) { __HCP_FUNC_ENTRY( "DEBUG_GetLocationFromBrowser" ); HRESULT hr; CComPtr wb; *pVal = NULL; __MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->QueryInterface ( IID_IWebBrowser2, (LPVOID*)&wb )); __MPC_EXIT_IF_METHOD_FAILS(hr, wb ->get_LocationURL( pVal )); hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } static HRESULT DEBUG_GetLocationFromDocument2( IHTMLDocument2* pDoc , BSTR *pVal ) { __HCP_FUNC_ENTRY( "DEBUG_GetLocationFromDocument2" ); HRESULT hr; CComPtr pLoc; *pVal = NULL; __MPC_EXIT_IF_METHOD_FAILS(hr, pDoc->get_location( &pLoc )); if(pLoc == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL); __MPC_EXIT_IF_METHOD_FAILS(hr, pLoc->get_href ( pVal )); hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } #else inline void DEBUG_CheckReadyState () {} inline HRESULT DEBUG_GetReadyStateFromBrowser() { return S_OK; } inline HRESULT DEBUG_GetLocationFromBrowser () { return S_OK; } inline HRESULT DEBUG_GetLocationFromDocument2() { return S_OK; } #endif ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static WCHAR s_eventNames_onBeforeNavigate [] = L"onBeforeNavigate" ; static WCHAR s_eventNames_onNavigateComplete [] = L"onNavigateComplete" ; static WCHAR s_eventNames_onBeforeTransition [] = L"onBeforeTransition" ; static WCHAR s_eventNames_onTransition [] = L"onTransition" ; static WCHAR s_eventNames_onBeforeContextSwitch[] = L"onBeforeContextSwitch"; static WCHAR s_eventNames_onContextSwitch [] = L"onContextSwitch" ; static WCHAR s_eventNames_onPersistLoad [] = L"onPersistLoad" ; static WCHAR s_eventNames_onPersistSave [] = L"onPersistSave" ; static WCHAR s_eventNames_onTravelDone [] = L"onTravelDone" ; static WCHAR s_eventNames_onShutdown [] = L"onShutdown" ; static WCHAR s_eventNames_onPrint [] = L"onPrint" ; static WCHAR s_eventNames_onSwitchedHelpFiles [] = L"onSwitchedHelpFiles" ; static WCHAR s_eventNames_onFavoritesUpdate [] = L"onFavoritesUpdate" ; static WCHAR s_eventNames_onOptionsChanged [] = L"onOptionsChanged" ; static WCHAR s_eventNames_onCssChanged [] = L"onCssChanged" ; static struct { LPCWSTR szName; DISPID id; } s_lookup[] = { { s_eventNames_onBeforeNavigate , DISPID_PCH_E_BEFORENAVIGATE }, { s_eventNames_onNavigateComplete , DISPID_PCH_E_NAVIGATECOMPLETE }, { s_eventNames_onBeforeTransition , DISPID_PCH_E_BEFORETRANSITION }, { s_eventNames_onTransition , DISPID_PCH_E_TRANSITION }, { s_eventNames_onBeforeContextSwitch, DISPID_PCH_E_BEFORECONTEXTSWITCH }, { s_eventNames_onContextSwitch , DISPID_PCH_E_CONTEXTSWITCH }, { s_eventNames_onPersistLoad , DISPID_PCH_E_PERSISTLOAD }, { s_eventNames_onPersistSave , DISPID_PCH_E_PERSISTSAVE }, { s_eventNames_onTravelDone , DISPID_PCH_E_TRAVELDONE }, { s_eventNames_onShutdown , DISPID_PCH_E_SHUTDOWN }, { s_eventNames_onPrint , DISPID_PCH_E_PRINT }, { s_eventNames_onSwitchedHelpFiles , DISPID_PCH_E_SWITCHEDHELPFILES }, { s_eventNames_onFavoritesUpdate , DISPID_PCH_E_FAVORITESUPDATE }, { s_eventNames_onOptionsChanged , DISPID_PCH_E_OPTIONSCHANGED }, { s_eventNames_onCssChanged , DISPID_PCH_E_CSSCHANGED }, }; ///////////////////////////////////////////////////////////////////////////// bool CPCHEvents::EventRegistration::operator==( /*[in]*/ const long lCookie ) const { return m_lCookie == lCookie ; } bool CPCHEvents::EventRegistration::operator< ( /*[in]*/ const long lPriority ) const { return m_lPriority < lPriority; } CPCHEvents::CPCHEvents() { m_parent = NULL; // CPCHHelpCenterExternal* m_parent; // List m_lstEvents; // List m_lstEvents_Staging; m_lLastCookie = 0; // long m_lLastCookie; } CPCHEvents::~CPCHEvents() { Passivate(); } void CPCHEvents::Initialize( /*[in]*/ CPCHHelpCenterExternal* parent ) { m_parent = parent; } void CPCHEvents::Passivate() { // // We don't remove the item from the main list, only FireEvent is allowed to change that list! // for(Iter it=m_lstEvents.begin(); it!=m_lstEvents.end(); it++) { it->m_fnCallback.Release(); } m_lstEvents_Staging.clear(); m_parent = NULL; } //////////////////// HRESULT CPCHEvents::RegisterEvents( /*[in]*/ long id , /*[in]*/ long pri , /*[in]*/ IDispatch* function , /*[out,retval]*/ long *cookie ) { __HCP_FUNC_ENTRY( "CPCHEvents::RegisterEvents" ); HRESULT hr; Iter it; if(id != -1) // Special case, used only internally, to pass the ID of the event through the Invoke method call. { if(CPCHEvents::ReverseLookup( id ) == NULL) { __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); } } it = m_lstEvents_Staging.insert( m_lstEvents_Staging.end() ); // This line creates a new item!! it->m_lCookie = ++m_lLastCookie; // long m_lCookie; it->m_id = id; // DISPID m_id; it->m_lPriority = pri; // long m_lPriority; it->m_fnCallback = function; // MPC::CComPtrThreadNeutral m_fnCallback; if(cookie) *cookie = it->m_lCookie; hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT CPCHEvents::RegisterEvents( /*[in]*/ BSTR bstrID , /*[in]*/ long pri , /*[in]*/ IDispatch* function , /*[out,retval]*/ long *cookie ) { return RegisterEvents( bstrID ? CPCHEvents::Lookup( bstrID ) : -1, pri, function, cookie ); } HRESULT CPCHEvents::UnregisterEvents( /*[in]*/ long cookie ) { __HCP_FUNC_ENTRY( "CPCHEvents::UnregisterEvents" ); HRESULT hr; Iter it; // // We don't remove the item from the main list, only FireEvent is allowed to change that list! // it = std::find( m_lstEvents.begin(), m_lstEvents.end(), cookie ); if(it != m_lstEvents.end()) { it->m_fnCallback.Release(); } it = std::find( m_lstEvents_Staging.begin(), m_lstEvents_Staging.end(), cookie ); if(it != m_lstEvents_Staging.end()) { m_lstEvents_Staging.erase( it ); } hr = S_OK; __HCP_FUNC_EXIT(hr); } //////////////////// HRESULT CPCHEvents::FireEvent( /*[in]*/ CPCHEvent* eventObj ) { __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent" ); HRESULT hr; if(m_parent) { Iter it; Iter itStaging; DISPID id = eventObj->m_idAction; CComVariant vEvent = eventObj; CPCHHelpSession* hs = m_parent->HelpSession(); eventObj->m_hsiCurrentContext = hs->Current(); if(eventObj->m_hsiCurrentContext) { eventObj->m_hsiPreviousContext = eventObj->m_hsiCurrentContext->Previous(); } DEBUG_AppendPerf( DEBUG_PERF_EVENTS_OUT, L"CPCHHelpCenterExternal::FireEvent: %s - URL: %s - Frame: %s - Panel: %s", CPCHEvents::ReverseLookup( id ), SAFEBSTR( eventObj->m_bstrURL ), SAFEBSTR( eventObj->m_bstrFrame ), SAFEBSTR( eventObj->m_bstrPanel ) ); DebugLog( L"%%%%%%%%%%%%%%%%%%%% EVENT %s - URL: %s - Frame: %s - Panel: %s\n", CPCHEvents::ReverseLookup( id ), SAFEBSTR( eventObj->m_bstrURL ), SAFEBSTR( eventObj->m_bstrFrame ), SAFEBSTR( eventObj->m_bstrPanel ) ); // // Merge staging list into main list. // for(itStaging=m_lstEvents_Staging.begin(); itStaging!=m_lstEvents_Staging.end(); itStaging++) { // // Insert in priority order. // for(it=m_lstEvents.begin(); it!=m_lstEvents.end(); it++) { if(*it < itStaging->m_lPriority) break; } m_lstEvents.insert( it, *itStaging ); } m_lstEvents_Staging.clear(); // // Dispatch the event to all the sinks registered for it. // for(it=m_lstEvents.begin(); it!=m_lstEvents.end(); ) { if(it->m_id == -1 || // Listen to all the events... it->m_id == id ) { CComPtr pPtr = it->m_fnCallback; CComDispatchDriver pDisp = pPtr; if(pDisp) { if(SUCCEEDED(pDisp.Invoke1( it->m_id == -1 ? id : (DISPID)0, &vEvent ))) { VARIANT_BOOL fCancel; __MPC_EXIT_IF_METHOD_FAILS(hr, eventObj->get_Cancel( &fCancel )); if(fCancel == VARIANT_TRUE) break; } else { // // The script is no more valid, prepare to release it. // it->m_fnCallback.Release(); } } } if(!m_parent) break; // We have been passivated... if(!it->m_fnCallback) { m_lstEvents.erase( it++ ); } else { it++; } } } if(!m_parent) // We have been passivated... { m_lstEvents .clear(); m_lstEvents_Staging.clear(); } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } ///////////////////////////////////////////////////////////////////////////// HRESULT CPCHEvents::FireEvent_Generic( /*[in]*/ DISPID id , /*[out]*/ VARIANT_BOOL *Cancel ) { __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_Generic" ); HRESULT hr; CComPtr obj; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj )); obj->m_idAction = id; __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj )); if(Cancel) *Cancel = obj->m_fCancel; hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT CPCHEvents::FireEvent_BeforeNavigate( /*[in]*/ BSTR bstrURL , /*[in]*/ BSTR bstrFrame , /*[in]*/ HscPanel idPanel , /*[out]*/ VARIANT_BOOL *Cancel ) { __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_BeforeNavigate" ); HRESULT hr; CComPtr obj; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj )); obj->m_idAction = DISPID_PCH_E_BEFORENAVIGATE; obj->m_bstrURL = bstrURL; obj->m_bstrFrame = bstrFrame; obj->m_bstrPanel = m_parent->PanelName( idPanel ); __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj )); if(Cancel) *Cancel = obj->m_fCancel; hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT CPCHEvents::FireEvent_NavigateComplete( /*[in]*/ BSTR bstrURL , /*[in]*/ HscPanel idPanel , /*[out]*/ VARIANT_BOOL *Cancel ) { __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_NavigateComplete" ); HRESULT hr; CComPtr obj; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj )); obj->m_idAction = DISPID_PCH_E_NAVIGATECOMPLETE; obj->m_bstrURL = bstrURL; obj->m_bstrPanel = m_parent->PanelName( idPanel ); __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj )); if(Cancel) *Cancel = obj->m_fCancel; hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT CPCHEvents::FireEvent_BeforeTransition( /*[in]*/ BSTR bstrPlace , /*[out]*/ VARIANT_BOOL *Cancel ) { __HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_BeforeTransition" ); HRESULT hr; CComPtr obj; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj )); obj->m_idAction = DISPID_PCH_E_BEFORETRANSITION; obj->m_bstrPlace = bstrPlace; __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj )); if(Cancel) *Cancel = obj->m_fCancel; hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT CPCHEvents::FireEvent_Transition( /*[in]*/ BSTR bstrPlace ) { __HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_Transition" ); HRESULT hr; CComPtr obj; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj )); obj->m_idAction = DISPID_PCH_E_TRANSITION; obj->m_bstrPlace = bstrPlace; __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj )); hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT CPCHEvents::FireEvent_BeforeContextSwitch( /*[in ]*/ HscContext iVal , /*[in ]*/ BSTR bstrInfo , /*[in ]*/ BSTR bstrURL , /*[out]*/ VARIANT_BOOL *Cancel ) { __HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_BeforeContextSwitch" ); HRESULT hr; CComPtr obj; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj )); obj->m_idAction = DISPID_PCH_E_BEFORECONTEXTSWITCH; __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->HelpSession()->RegisterContextSwitch( iVal, bstrInfo, bstrURL, &obj->m_hsiNextContext )); __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj )); if(Cancel) *Cancel = obj->m_fCancel; hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT CPCHEvents::FireEvent_ContextSwitch ( ) { return FireEvent_Generic( DISPID_PCH_E_CONTEXTSWITCH ); } HRESULT CPCHEvents::FireEvent_PersistLoad ( ) { return FireEvent_Generic( DISPID_PCH_E_PERSISTLOAD ); } HRESULT CPCHEvents::FireEvent_PersistSave ( ) { return FireEvent_Generic( DISPID_PCH_E_PERSISTSAVE ); } HRESULT CPCHEvents::FireEvent_TravelDone ( ) { return FireEvent_Generic( DISPID_PCH_E_TRAVELDONE ); } HRESULT CPCHEvents::FireEvent_Shutdown ( VARIANT_BOOL *Cancel ) { return FireEvent_Generic( DISPID_PCH_E_SHUTDOWN , Cancel ); } HRESULT CPCHEvents::FireEvent_Print ( VARIANT_BOOL *Cancel ) { return FireEvent_Generic( DISPID_PCH_E_PRINT , Cancel ); } HRESULT CPCHEvents::FireEvent_SwitchedHelpFiles( ) { return FireEvent_Generic( DISPID_PCH_E_SWITCHEDHELPFILES ); } HRESULT CPCHEvents::FireEvent_FavoritesUpdate ( ) { return FireEvent_Generic( DISPID_PCH_E_FAVORITESUPDATE ); } HRESULT CPCHEvents::FireEvent_OptionsChanged ( ) { return FireEvent_Generic( DISPID_PCH_E_OPTIONSCHANGED ); } HRESULT CPCHEvents::FireEvent_CssChanged ( ) { return FireEvent_Generic( DISPID_PCH_E_CSSCHANGED ); } DISPID CPCHEvents::Lookup( LPCWSTR szName ) { if(szName) { for(int i = 0; i m_hsiCurrentContext; // CComPtr m_hsiPreviousContext; } CPCHEvent::~CPCHEvent() { } //////////////////////////////////////// STDMETHODIMP CPCHEvent::get_Action( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( CPCHEvents::ReverseLookup( m_idAction ), pVal ); } //////////////////// STDMETHODIMP CPCHEvent::put_Cancel( /*[in]*/ VARIANT_BOOL newVal ) { m_fCancel = newVal; return S_OK; } STDMETHODIMP CPCHEvent::get_Cancel( /*[out, retval]*/ VARIANT_BOOL *pVal ) { if(pVal == NULL) return E_POINTER; *pVal = m_fCancel; return S_OK; } //////////////////// HRESULT CPCHEvent::put_URL( /*[in]*/ BSTR newVal ) { return MPC::PutBSTR( m_bstrURL, newVal ); } STDMETHODIMP CPCHEvent::get_URL( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_bstrURL, pVal ); } //////////////////// HRESULT CPCHEvent::put_Frame( /*[in]*/ BSTR newVal ) { return MPC::PutBSTR( m_bstrFrame, newVal ); } STDMETHODIMP CPCHEvent::get_Frame( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_bstrFrame, pVal ); } //////////////////// HRESULT CPCHEvent::put_Panel( /*[in]*/ BSTR newVal ) { return MPC::PutBSTR( m_bstrPanel, newVal ); } STDMETHODIMP CPCHEvent::get_Panel( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_bstrPanel, pVal ); } //////////////////// HRESULT CPCHEvent::put_Place( /*[in]*/ BSTR newVal ) { return MPC::PutBSTR( m_bstrPlace, newVal ); } STDMETHODIMP CPCHEvent::get_Place( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_bstrPlace, pVal ); } //////////////////// STDMETHODIMP CPCHEvent::get_CurrentContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal ) { return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiCurrentContext, pVal ); } STDMETHODIMP CPCHEvent::get_PreviousContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal ) { return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiPreviousContext, pVal ); } STDMETHODIMP CPCHEvent::get_NextContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal ) { return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiNextContext, pVal ); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// CPCHTimerHandle::CallbackBase::CallbackBase() { m_lRef = 1; // long m_lRef; } STDMETHODIMP_(ULONG) CPCHTimerHandle::CallbackBase::AddRef() { return ::InterlockedIncrement( &m_lRef ); } STDMETHODIMP_(ULONG) CPCHTimerHandle::CallbackBase::Release() { ULONG l = ::InterlockedDecrement( &m_lRef ); if(l == 0) delete this; return l; } STDMETHODIMP CPCHTimerHandle::CallbackBase::QueryInterface( REFIID iid, void ** ppvObject ) { if(ppvObject == NULL) return E_POINTER; if(InlineIsEqualUnknown( iid ) || InlineIsEqualGUID ( iid, IID_ITimerSink ) ) { *ppvObject = this; AddRef(); return S_OK; } *ppvObject = NULL; return E_NOINTERFACE; } //////////////////////////////////////// CPCHTimerHandle::CPCHTimerHandle() { // CComPtr m_timer; m_dwCookie = 0; // DWORD m_dwCookie; m_callback = NULL; // CallbackBase* m_callback; } CPCHTimerHandle::~CPCHTimerHandle() { Unadvise(); } void CPCHTimerHandle::Initialize( /*[in]*/ ITimer* timer ) { Unadvise(); m_timer = timer; } HRESULT CPCHTimerHandle::Advise( /*[in]*/ CallbackBase* callback, /*[in]*/ DWORD dwWait ) { if(!callback) return E_OUTOFMEMORY; Unadvise(); m_callback = callback; if(!m_timer) return E_INVALIDARG; CComVariant vTime = (long)(dwWait + ::GetTickCount()); CComVariant vZero = 0; return m_timer->Advise( vTime, vZero, vZero, 0, callback, &m_dwCookie ); } void CPCHTimerHandle::Unadvise() { if(m_timer) { if(m_dwCookie) { m_timer->Unadvise( m_dwCookie ); m_dwCookie = 0; } } if(m_callback) { m_callback->Detach (); m_callback->Release(); m_callback = NULL; } } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// CPCHWebBrowserEvents::CPCHWebBrowserEvents() { __HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::CPCHWebBrowserEvents" ); m_parent = NULL; // CPCHHelpCenterExternal* m_parent; m_idPanel = HSCPANEL_INVALID; // HscPanel m_idPanel; // // CComPtr m_pWB2; m_fLoading = false; // bool m_fLoading; // // CPCHTimerHandle m_TimerDelay; // CPCHTimerHandle m_TimerExpire; } CPCHWebBrowserEvents::~CPCHWebBrowserEvents() { Passivate(); } //////////////////////////////////////////////////////////////////////////////// void CPCHWebBrowserEvents::NotifyStartOfNavigation( /*[in]*/ BSTR url ) { CPCHHelpSession* hs = m_parent->HelpSession(); if(hs) { m_fLoading = true; (void)hs->StartNavigation( url, m_idPanel ); } } void CPCHWebBrowserEvents::NotifyEndOfNavigation() { CPCHHelpSession* hs = m_parent->HelpSession(); m_fLoading = false; if(hs) { (void)hs->CompleteNavigation( m_idPanel ); } } void CPCHWebBrowserEvents::NotifyStop() { TimerControl( TIMERMODE_STOP ); } //////////////////////////////////////////////////////////////////////////////// void CPCHWebBrowserEvents::Initialize( /*[in]*/ CPCHHelpCenterExternal* parent, /*[in]*/ HscPanel idPanel ) { m_parent = parent; m_idPanel = idPanel; } void CPCHWebBrowserEvents::Passivate() { Detach(); m_parent = NULL; } void CPCHWebBrowserEvents::Attach( /*[in]*/ IWebBrowser2* pWB ) { __HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::Attach" ); Detach(); m_pWB2 = pWB; if(m_pWB2) { CPCHWebBrowserEvents_DWebBrowserEvents2::DispEventAdvise( m_pWB2 ); } m_TimerDelay .Initialize( m_parent->Timer() ); m_TimerExpire.Initialize( m_parent->Timer() ); } void CPCHWebBrowserEvents::Detach() { __HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::Detach" ); TimerControl( TIMERMODE_STOP ); if(m_pWB2) { CPCHWebBrowserEvents_DWebBrowserEvents2::DispEventUnadvise( m_pWB2 ); m_pWB2.Release(); } } ///////////////////////////////////////////////////////////////////////////// void CPCHWebBrowserEvents::TimerControl( /*[in]*/ TimerMode mode ) { switch(mode) { case TIMERMODE_STOP: m_TimerDelay .Stop(); m_TimerExpire.Stop(); break; case TIMERMODE_RESTART: m_TimerDelay .Stop ( ); m_TimerExpire.Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 2000 ); break; case TIMERMODE_MORETIME: m_TimerExpire.Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 100 ); break; case TIMERMODE_COMPLETE: m_TimerDelay .Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 20 ); m_TimerExpire.Stop ( ); break; } } HRESULT CPCHWebBrowserEvents::OnTimer( VARIANT vtimeAdvise ) { TimerControl( TIMERMODE_STOP ); NotifyEndOfNavigation(); return S_OK; } ///////////////////////////////////////////////////////////////////////////// void __stdcall CPCHWebBrowserEvents::BeforeNavigate2( IDispatch* pDisp , VARIANT* URL , VARIANT* Flags , VARIANT* TargetFrameName, VARIANT* PostData , VARIANT* Headers , VARIANT_BOOL *Cancel ) { if(!m_parent) return; // Called before init or after passivate. #ifdef DEBUG DebugLog( L"#################### BeforeNavigate2 %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( V_BSTR( URL ) ) ); DEBUG_CheckReadyState(); #endif DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::BeforeNavigate2 : %s", SAFEBSTR( V_BSTR( URL ) ) ); CComBSTR bstrFrame; BSTR bstrURL = V_BSTR( URL ); if(FAILED(MPC::HTML::GetFramePath( bstrFrame, pDisp )) || !bstrFrame) { if(V_VT(TargetFrameName) == VT_BSTR) { bstrFrame = V_BSTR(TargetFrameName); } } { bool fProceed = m_parent->ProcessNavigation( m_idPanel, bstrURL, bstrFrame, m_fLoading, *Cancel ); DebugLog( L"#################### ProcessNavigation %s%s%s\n", m_fLoading ? L"loading " : L"", fProceed ? L"proceed " : L"", *Cancel ? L"cancelled " : L"" ); if(fProceed) { if(m_fLoading) { TimerControl( TIMERMODE_MORETIME ); } else { TimerControl( TIMERMODE_RESTART ); NotifyStartOfNavigation( bstrURL ); } } } } void __stdcall CPCHWebBrowserEvents::NewWindow2( IDispatch* *ppDisp , VARIANT_BOOL *Cancel ) { // Not disabled in Whistler. // *Cancel = VARIANT_TRUE; } void __stdcall CPCHWebBrowserEvents::NavigateComplete2( IDispatch* pDisp , VARIANT* URL ) { if(!m_parent) return; // Called before init or after passivate. #ifdef DEBUG DebugLog( L"#################### NavigateComplete2 %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( V_BSTR( URL ) ) ); DEBUG_CheckReadyState(); #endif DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::NavigateComplete2 : %s", SAFEBSTR( V_BSTR( URL ) ) ); TimerControl( TIMERMODE_MORETIME ); } void __stdcall CPCHWebBrowserEvents::DocumentComplete( IDispatch* pDisp , VARIANT* URL ) { if(!m_parent) return; // Called before init or after passivate. BSTR bstrURL = V_BSTR( URL ); #ifdef DEBUG DebugLog( L"#################### DocumentComplete %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( bstrURL ) ); DEBUG_CheckReadyState(); #endif DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::DocumentComplete : %s", SAFEBSTR( bstrURL ) ); TimerControl( TIMERMODE_MORETIME ); // // If it's one of the URL in the ignore list, don't queue the complete notification. // { CPCHHelpSession* hs = m_parent->HelpSession(); if(hs && hs->IsUrlToIgnore( bstrURL, /*fRemove*/true )) { m_fLoading = false; return; } } // // Get to the document and extract its title. // { CComPtr pDoc; if(SUCCEEDED(MPC::HTML::IDispatch_To_IHTMLDocument2( pDoc, pDisp ))) { CComBSTR bstrTitle; if(SUCCEEDED(pDoc->get_title( &bstrTitle ))) { (void)m_parent->HelpSession()->RecordTitle( URL->bstrVal, bstrTitle, false ); } } } if(m_fLoading) { if(m_pWB2) { tagREADYSTATE readystate; if(SUCCEEDED(m_pWB2->get_ReadyState( &readystate )) && readystate == READYSTATE_COMPLETE) { bool fDone; if(SUCCEEDED(MPC::HTML::AreAllTheFramesInTheCompleteState( fDone, m_pWB2 )) && fDone) { TimerControl( TIMERMODE_COMPLETE ); } } } } }