Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1088 lines
31 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. Events.cpp
  5. Abstract:
  6. This file contains the implementation of the classes related to events.
  7. Revision History:
  8. Davide Massarenti (dmassare) 10/31/99
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. #include <mshtmdid.h>
  13. /////////////////////////////////////////////////////////////////////////////
  14. /////////////////////////////////////////////////////////////////////////////
  15. /////////////////////////////////////////////////////////////////////////////
  16. #ifdef DEBUG
  17. static void DEBUG_CheckReadyState()
  18. {
  19. CComPtr<IWebBrowser2> wb2; wb2.Attach( CPCHHelpCenterExternal::s_GLOBAL->Contents() );
  20. tagREADYSTATE ready;
  21. if(wb2 && SUCCEEDED(wb2->get_ReadyState( &ready )))
  22. {
  23. DebugLog( "#################### WEB %d\n", (int)ready );
  24. }
  25. }
  26. static HRESULT DEBUG_GetReadyStateFromBrowser( IDispatch* pDisp ,
  27. tagREADYSTATE *pVal )
  28. {
  29. __HCP_FUNC_ENTRY( "DEBUG_GetReadyStateFromBrowser" );
  30. HRESULT hr;
  31. CComPtr<IWebBrowser2> wb;
  32. *pVal = READYSTATE_UNINITIALIZED;
  33. __MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->QueryInterface( IID_IWebBrowser2, (LPVOID*)&wb ));
  34. __MPC_EXIT_IF_METHOD_FAILS(hr, wb ->get_ReadyState( pVal ));
  35. hr = S_OK;
  36. __HCP_FUNC_CLEANUP;
  37. __HCP_FUNC_EXIT(hr);
  38. }
  39. static HRESULT DEBUG_GetLocationFromBrowser( IDispatch* pDisp ,
  40. BSTR *pVal )
  41. {
  42. __HCP_FUNC_ENTRY( "DEBUG_GetLocationFromBrowser" );
  43. HRESULT hr;
  44. CComPtr<IWebBrowser2> wb;
  45. *pVal = NULL;
  46. __MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->QueryInterface ( IID_IWebBrowser2, (LPVOID*)&wb ));
  47. __MPC_EXIT_IF_METHOD_FAILS(hr, wb ->get_LocationURL( pVal ));
  48. hr = S_OK;
  49. __HCP_FUNC_CLEANUP;
  50. __HCP_FUNC_EXIT(hr);
  51. }
  52. static HRESULT DEBUG_GetLocationFromDocument2( IHTMLDocument2* pDoc ,
  53. BSTR *pVal )
  54. {
  55. __HCP_FUNC_ENTRY( "DEBUG_GetLocationFromDocument2" );
  56. HRESULT hr;
  57. CComPtr<IHTMLLocation> pLoc;
  58. *pVal = NULL;
  59. __MPC_EXIT_IF_METHOD_FAILS(hr, pDoc->get_location( &pLoc )); if(pLoc == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  60. __MPC_EXIT_IF_METHOD_FAILS(hr, pLoc->get_href ( pVal ));
  61. hr = S_OK;
  62. __HCP_FUNC_CLEANUP;
  63. __HCP_FUNC_EXIT(hr);
  64. }
  65. #else
  66. inline void DEBUG_CheckReadyState () {}
  67. inline HRESULT DEBUG_GetReadyStateFromBrowser() { return S_OK; }
  68. inline HRESULT DEBUG_GetLocationFromBrowser () { return S_OK; }
  69. inline HRESULT DEBUG_GetLocationFromDocument2() { return S_OK; }
  70. #endif
  71. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. static WCHAR s_eventNames_onBeforeNavigate [] = L"onBeforeNavigate" ;
  75. static WCHAR s_eventNames_onNavigateComplete [] = L"onNavigateComplete" ;
  76. static WCHAR s_eventNames_onBeforeTransition [] = L"onBeforeTransition" ;
  77. static WCHAR s_eventNames_onTransition [] = L"onTransition" ;
  78. static WCHAR s_eventNames_onBeforeContextSwitch[] = L"onBeforeContextSwitch";
  79. static WCHAR s_eventNames_onContextSwitch [] = L"onContextSwitch" ;
  80. static WCHAR s_eventNames_onPersistLoad [] = L"onPersistLoad" ;
  81. static WCHAR s_eventNames_onPersistSave [] = L"onPersistSave" ;
  82. static WCHAR s_eventNames_onTravelDone [] = L"onTravelDone" ;
  83. static WCHAR s_eventNames_onShutdown [] = L"onShutdown" ;
  84. static WCHAR s_eventNames_onPrint [] = L"onPrint" ;
  85. static WCHAR s_eventNames_onSwitchedHelpFiles [] = L"onSwitchedHelpFiles" ;
  86. static WCHAR s_eventNames_onFavoritesUpdate [] = L"onFavoritesUpdate" ;
  87. static WCHAR s_eventNames_onOptionsChanged [] = L"onOptionsChanged" ;
  88. static WCHAR s_eventNames_onCssChanged [] = L"onCssChanged" ;
  89. static struct
  90. {
  91. LPCWSTR szName;
  92. DISPID id;
  93. }
  94. s_lookup[] =
  95. {
  96. { s_eventNames_onBeforeNavigate , DISPID_PCH_E_BEFORENAVIGATE },
  97. { s_eventNames_onNavigateComplete , DISPID_PCH_E_NAVIGATECOMPLETE },
  98. { s_eventNames_onBeforeTransition , DISPID_PCH_E_BEFORETRANSITION },
  99. { s_eventNames_onTransition , DISPID_PCH_E_TRANSITION },
  100. { s_eventNames_onBeforeContextSwitch, DISPID_PCH_E_BEFORECONTEXTSWITCH },
  101. { s_eventNames_onContextSwitch , DISPID_PCH_E_CONTEXTSWITCH },
  102. { s_eventNames_onPersistLoad , DISPID_PCH_E_PERSISTLOAD },
  103. { s_eventNames_onPersistSave , DISPID_PCH_E_PERSISTSAVE },
  104. { s_eventNames_onTravelDone , DISPID_PCH_E_TRAVELDONE },
  105. { s_eventNames_onShutdown , DISPID_PCH_E_SHUTDOWN },
  106. { s_eventNames_onPrint , DISPID_PCH_E_PRINT },
  107. { s_eventNames_onSwitchedHelpFiles , DISPID_PCH_E_SWITCHEDHELPFILES },
  108. { s_eventNames_onFavoritesUpdate , DISPID_PCH_E_FAVORITESUPDATE },
  109. { s_eventNames_onOptionsChanged , DISPID_PCH_E_OPTIONSCHANGED },
  110. { s_eventNames_onCssChanged , DISPID_PCH_E_CSSCHANGED },
  111. };
  112. /////////////////////////////////////////////////////////////////////////////
  113. bool CPCHEvents::EventRegistration::operator==( /*[in]*/ const long lCookie ) const { return m_lCookie == lCookie ; }
  114. bool CPCHEvents::EventRegistration::operator< ( /*[in]*/ const long lPriority ) const { return m_lPriority < lPriority; }
  115. CPCHEvents::CPCHEvents()
  116. {
  117. m_parent = NULL; // CPCHHelpCenterExternal* m_parent;
  118. // List m_lstEvents;
  119. // List m_lstEvents_Staging;
  120. m_lLastCookie = 0; // long m_lLastCookie;
  121. }
  122. CPCHEvents::~CPCHEvents()
  123. {
  124. Passivate();
  125. }
  126. void CPCHEvents::Initialize( /*[in]*/ CPCHHelpCenterExternal* parent )
  127. {
  128. m_parent = parent;
  129. }
  130. void CPCHEvents::Passivate()
  131. {
  132. //
  133. // We don't remove the item from the main list, only FireEvent is allowed to change that list!
  134. //
  135. for(Iter it=m_lstEvents.begin(); it!=m_lstEvents.end(); it++)
  136. {
  137. it->m_fnCallback.Release();
  138. }
  139. m_lstEvents_Staging.clear();
  140. m_parent = NULL;
  141. }
  142. ////////////////////
  143. HRESULT CPCHEvents::RegisterEvents( /*[in]*/ long id ,
  144. /*[in]*/ long pri ,
  145. /*[in]*/ IDispatch* function ,
  146. /*[out,retval]*/ long *cookie )
  147. {
  148. __HCP_FUNC_ENTRY( "CPCHEvents::RegisterEvents" );
  149. HRESULT hr;
  150. Iter it;
  151. if(id != -1) // Special case, used only internally, to pass the ID of the event through the Invoke method call.
  152. {
  153. if(CPCHEvents::ReverseLookup( id ) == NULL)
  154. {
  155. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  156. }
  157. }
  158. it = m_lstEvents_Staging.insert( m_lstEvents_Staging.end() ); // This line creates a new item!!
  159. it->m_lCookie = ++m_lLastCookie; // long m_lCookie;
  160. it->m_id = id; // DISPID m_id;
  161. it->m_lPriority = pri; // long m_lPriority;
  162. it->m_fnCallback = function; // MPC::CComPtrThreadNeutral<IDispatch> m_fnCallback;
  163. if(cookie) *cookie = it->m_lCookie;
  164. hr = S_OK;
  165. __HCP_FUNC_CLEANUP;
  166. __HCP_FUNC_EXIT(hr);
  167. }
  168. HRESULT CPCHEvents::RegisterEvents( /*[in]*/ BSTR bstrID ,
  169. /*[in]*/ long pri ,
  170. /*[in]*/ IDispatch* function ,
  171. /*[out,retval]*/ long *cookie )
  172. {
  173. return RegisterEvents( bstrID ? CPCHEvents::Lookup( bstrID ) : -1, pri, function, cookie );
  174. }
  175. HRESULT CPCHEvents::UnregisterEvents( /*[in]*/ long cookie )
  176. {
  177. __HCP_FUNC_ENTRY( "CPCHEvents::UnregisterEvents" );
  178. HRESULT hr;
  179. Iter it;
  180. //
  181. // We don't remove the item from the main list, only FireEvent is allowed to change that list!
  182. //
  183. it = std::find( m_lstEvents.begin(), m_lstEvents.end(), cookie );
  184. if(it != m_lstEvents.end())
  185. {
  186. it->m_fnCallback.Release();
  187. }
  188. it = std::find( m_lstEvents_Staging.begin(), m_lstEvents_Staging.end(), cookie );
  189. if(it != m_lstEvents_Staging.end())
  190. {
  191. m_lstEvents_Staging.erase( it );
  192. }
  193. hr = S_OK;
  194. __HCP_FUNC_EXIT(hr);
  195. }
  196. ////////////////////
  197. HRESULT CPCHEvents::FireEvent( /*[in]*/ CPCHEvent* eventObj )
  198. {
  199. __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent" );
  200. HRESULT hr;
  201. if(m_parent)
  202. {
  203. Iter it;
  204. Iter itStaging;
  205. DISPID id = eventObj->m_idAction;
  206. CComVariant vEvent = eventObj;
  207. CPCHHelpSession* hs = m_parent->HelpSession();
  208. eventObj->m_hsiCurrentContext = hs->Current();
  209. if(eventObj->m_hsiCurrentContext)
  210. {
  211. eventObj->m_hsiPreviousContext = eventObj->m_hsiCurrentContext->Previous();
  212. }
  213. DEBUG_AppendPerf( DEBUG_PERF_EVENTS_OUT, L"CPCHHelpCenterExternal::FireEvent: %s - URL: %s - Frame: %s - Panel: %s",
  214. CPCHEvents::ReverseLookup( id ),
  215. SAFEBSTR( eventObj->m_bstrURL ),
  216. SAFEBSTR( eventObj->m_bstrFrame ),
  217. SAFEBSTR( eventObj->m_bstrPanel ) );
  218. DebugLog( L"%%%%%%%%%%%%%%%%%%%% EVENT %s - URL: %s - Frame: %s - Panel: %s\n",
  219. CPCHEvents::ReverseLookup( id ),
  220. SAFEBSTR( eventObj->m_bstrURL ),
  221. SAFEBSTR( eventObj->m_bstrFrame ),
  222. SAFEBSTR( eventObj->m_bstrPanel ) );
  223. //
  224. // Merge staging list into main list.
  225. //
  226. for(itStaging=m_lstEvents_Staging.begin(); itStaging!=m_lstEvents_Staging.end(); itStaging++)
  227. {
  228. //
  229. // Insert in priority order.
  230. //
  231. for(it=m_lstEvents.begin(); it!=m_lstEvents.end(); it++)
  232. {
  233. if(*it < itStaging->m_lPriority) break;
  234. }
  235. m_lstEvents.insert( it, *itStaging );
  236. }
  237. m_lstEvents_Staging.clear();
  238. //
  239. // Dispatch the event to all the sinks registered for it.
  240. //
  241. for(it=m_lstEvents.begin(); it!=m_lstEvents.end(); )
  242. {
  243. if(it->m_id == -1 || // Listen to all the events...
  244. it->m_id == id )
  245. {
  246. CComPtr<IDispatch> pPtr = it->m_fnCallback;
  247. CComDispatchDriver pDisp = pPtr;
  248. if(pDisp)
  249. {
  250. if(SUCCEEDED(pDisp.Invoke1( it->m_id == -1 ? id : (DISPID)0, &vEvent )))
  251. {
  252. VARIANT_BOOL fCancel;
  253. __MPC_EXIT_IF_METHOD_FAILS(hr, eventObj->get_Cancel( &fCancel ));
  254. if(fCancel == VARIANT_TRUE) break;
  255. }
  256. else
  257. {
  258. //
  259. // The script is no more valid, prepare to release it.
  260. //
  261. it->m_fnCallback.Release();
  262. }
  263. }
  264. }
  265. if(!m_parent) break; // We have been passivated...
  266. if(!it->m_fnCallback)
  267. {
  268. m_lstEvents.erase( it++ );
  269. }
  270. else
  271. {
  272. it++;
  273. }
  274. }
  275. }
  276. if(!m_parent) // We have been passivated...
  277. {
  278. m_lstEvents .clear();
  279. m_lstEvents_Staging.clear();
  280. }
  281. hr = S_OK;
  282. __HCP_FUNC_CLEANUP;
  283. __HCP_FUNC_EXIT(hr);
  284. }
  285. /////////////////////////////////////////////////////////////////////////////
  286. HRESULT CPCHEvents::FireEvent_Generic( /*[in]*/ DISPID id ,
  287. /*[out]*/ VARIANT_BOOL *Cancel )
  288. {
  289. __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_Generic" );
  290. HRESULT hr;
  291. CComPtr<CPCHEvent> obj;
  292. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  293. obj->m_idAction = id;
  294. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
  295. if(Cancel) *Cancel = obj->m_fCancel;
  296. hr = S_OK;
  297. __HCP_FUNC_CLEANUP;
  298. __HCP_FUNC_EXIT(hr);
  299. }
  300. HRESULT CPCHEvents::FireEvent_BeforeNavigate( /*[in]*/ BSTR bstrURL ,
  301. /*[in]*/ BSTR bstrFrame ,
  302. /*[in]*/ HscPanel idPanel ,
  303. /*[out]*/ VARIANT_BOOL *Cancel )
  304. {
  305. __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_BeforeNavigate" );
  306. HRESULT hr;
  307. CComPtr<CPCHEvent> obj;
  308. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  309. obj->m_idAction = DISPID_PCH_E_BEFORENAVIGATE;
  310. obj->m_bstrURL = bstrURL;
  311. obj->m_bstrFrame = bstrFrame;
  312. obj->m_bstrPanel = m_parent->PanelName( idPanel );
  313. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
  314. if(Cancel) *Cancel = obj->m_fCancel;
  315. hr = S_OK;
  316. __HCP_FUNC_CLEANUP;
  317. __HCP_FUNC_EXIT(hr);
  318. }
  319. HRESULT CPCHEvents::FireEvent_NavigateComplete( /*[in]*/ BSTR bstrURL ,
  320. /*[in]*/ HscPanel idPanel ,
  321. /*[out]*/ VARIANT_BOOL *Cancel )
  322. {
  323. __HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_NavigateComplete" );
  324. HRESULT hr;
  325. CComPtr<CPCHEvent> obj;
  326. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  327. obj->m_idAction = DISPID_PCH_E_NAVIGATECOMPLETE;
  328. obj->m_bstrURL = bstrURL;
  329. obj->m_bstrPanel = m_parent->PanelName( idPanel );
  330. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
  331. if(Cancel) *Cancel = obj->m_fCancel;
  332. hr = S_OK;
  333. __HCP_FUNC_CLEANUP;
  334. __HCP_FUNC_EXIT(hr);
  335. }
  336. HRESULT CPCHEvents::FireEvent_BeforeTransition( /*[in]*/ BSTR bstrPlace ,
  337. /*[out]*/ VARIANT_BOOL *Cancel )
  338. {
  339. __HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_BeforeTransition" );
  340. HRESULT hr;
  341. CComPtr<CPCHEvent> obj;
  342. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  343. obj->m_idAction = DISPID_PCH_E_BEFORETRANSITION;
  344. obj->m_bstrPlace = bstrPlace;
  345. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
  346. if(Cancel) *Cancel = obj->m_fCancel;
  347. hr = S_OK;
  348. __HCP_FUNC_CLEANUP;
  349. __HCP_FUNC_EXIT(hr);
  350. }
  351. HRESULT CPCHEvents::FireEvent_Transition( /*[in]*/ BSTR bstrPlace )
  352. {
  353. __HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_Transition" );
  354. HRESULT hr;
  355. CComPtr<CPCHEvent> obj;
  356. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  357. obj->m_idAction = DISPID_PCH_E_TRANSITION;
  358. obj->m_bstrPlace = bstrPlace;
  359. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
  360. hr = S_OK;
  361. __HCP_FUNC_CLEANUP;
  362. __HCP_FUNC_EXIT(hr);
  363. }
  364. HRESULT CPCHEvents::FireEvent_BeforeContextSwitch( /*[in ]*/ HscContext iVal ,
  365. /*[in ]*/ BSTR bstrInfo ,
  366. /*[in ]*/ BSTR bstrURL ,
  367. /*[out]*/ VARIANT_BOOL *Cancel )
  368. {
  369. __HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_BeforeContextSwitch" );
  370. HRESULT hr;
  371. CComPtr<CPCHEvent> obj;
  372. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  373. obj->m_idAction = DISPID_PCH_E_BEFORECONTEXTSWITCH;
  374. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->HelpSession()->RegisterContextSwitch( iVal, bstrInfo, bstrURL, &obj->m_hsiNextContext ));
  375. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
  376. if(Cancel) *Cancel = obj->m_fCancel;
  377. hr = S_OK;
  378. __HCP_FUNC_CLEANUP;
  379. __HCP_FUNC_EXIT(hr);
  380. }
  381. HRESULT CPCHEvents::FireEvent_ContextSwitch ( ) { return FireEvent_Generic( DISPID_PCH_E_CONTEXTSWITCH ); }
  382. HRESULT CPCHEvents::FireEvent_PersistLoad ( ) { return FireEvent_Generic( DISPID_PCH_E_PERSISTLOAD ); }
  383. HRESULT CPCHEvents::FireEvent_PersistSave ( ) { return FireEvent_Generic( DISPID_PCH_E_PERSISTSAVE ); }
  384. HRESULT CPCHEvents::FireEvent_TravelDone ( ) { return FireEvent_Generic( DISPID_PCH_E_TRAVELDONE ); }
  385. HRESULT CPCHEvents::FireEvent_Shutdown ( VARIANT_BOOL *Cancel ) { return FireEvent_Generic( DISPID_PCH_E_SHUTDOWN , Cancel ); }
  386. HRESULT CPCHEvents::FireEvent_Print ( VARIANT_BOOL *Cancel ) { return FireEvent_Generic( DISPID_PCH_E_PRINT , Cancel ); }
  387. HRESULT CPCHEvents::FireEvent_SwitchedHelpFiles( ) { return FireEvent_Generic( DISPID_PCH_E_SWITCHEDHELPFILES ); }
  388. HRESULT CPCHEvents::FireEvent_FavoritesUpdate ( ) { return FireEvent_Generic( DISPID_PCH_E_FAVORITESUPDATE ); }
  389. HRESULT CPCHEvents::FireEvent_OptionsChanged ( ) { return FireEvent_Generic( DISPID_PCH_E_OPTIONSCHANGED ); }
  390. HRESULT CPCHEvents::FireEvent_CssChanged ( ) { return FireEvent_Generic( DISPID_PCH_E_CSSCHANGED ); }
  391. DISPID CPCHEvents::Lookup( LPCWSTR szName )
  392. {
  393. if(szName)
  394. {
  395. for(int i = 0; i<ARRAYSIZE(s_lookup); i++)
  396. {
  397. if(!_wcsicmp( s_lookup[i].szName, szName )) return s_lookup[i].id;
  398. }
  399. }
  400. return 0;
  401. }
  402. LPCWSTR CPCHEvents::ReverseLookup( DISPID idEvent )
  403. {
  404. for(int i = 0; i<ARRAYSIZE(s_lookup); i++)
  405. {
  406. if(s_lookup[i].id == idEvent) return s_lookup[i].szName;
  407. }
  408. return NULL;
  409. }
  410. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  411. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  412. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  413. CPCHEvent::CPCHEvent()
  414. {
  415. // DISPID m_idAction;
  416. m_fCancel = VARIANT_FALSE; // VARIANT_BOOL m_fCancel;
  417. //
  418. // CComBSTR m_bstrURL;
  419. // CComBSTR m_bstrFrame;
  420. // CComBSTR m_bstrPanel;
  421. // CComBSTR m_bstrPlace;
  422. // CComBSTR m_bstrContextData;
  423. //
  424. // CComPtr<CPCHHelpSessionItem> m_hsiCurrentContext;
  425. // CComPtr<CPCHHelpSessionItem> m_hsiPreviousContext;
  426. }
  427. CPCHEvent::~CPCHEvent()
  428. {
  429. }
  430. ////////////////////////////////////////
  431. STDMETHODIMP CPCHEvent::get_Action( /*[out, retval]*/ BSTR *pVal )
  432. {
  433. return MPC::GetBSTR( CPCHEvents::ReverseLookup( m_idAction ), pVal );
  434. }
  435. ////////////////////
  436. STDMETHODIMP CPCHEvent::put_Cancel( /*[in]*/ VARIANT_BOOL newVal )
  437. {
  438. m_fCancel = newVal;
  439. return S_OK;
  440. }
  441. STDMETHODIMP CPCHEvent::get_Cancel( /*[out, retval]*/ VARIANT_BOOL *pVal )
  442. {
  443. if(pVal == NULL) return E_POINTER;
  444. *pVal = m_fCancel;
  445. return S_OK;
  446. }
  447. ////////////////////
  448. HRESULT CPCHEvent::put_URL( /*[in]*/ BSTR newVal )
  449. {
  450. return MPC::PutBSTR( m_bstrURL, newVal );
  451. }
  452. STDMETHODIMP CPCHEvent::get_URL( /*[out, retval]*/ BSTR *pVal )
  453. {
  454. return MPC::GetBSTR( m_bstrURL, pVal );
  455. }
  456. ////////////////////
  457. HRESULT CPCHEvent::put_Frame( /*[in]*/ BSTR newVal )
  458. {
  459. return MPC::PutBSTR( m_bstrFrame, newVal );
  460. }
  461. STDMETHODIMP CPCHEvent::get_Frame( /*[out, retval]*/ BSTR *pVal )
  462. {
  463. return MPC::GetBSTR( m_bstrFrame, pVal );
  464. }
  465. ////////////////////
  466. HRESULT CPCHEvent::put_Panel( /*[in]*/ BSTR newVal )
  467. {
  468. return MPC::PutBSTR( m_bstrPanel, newVal );
  469. }
  470. STDMETHODIMP CPCHEvent::get_Panel( /*[out, retval]*/ BSTR *pVal )
  471. {
  472. return MPC::GetBSTR( m_bstrPanel, pVal );
  473. }
  474. ////////////////////
  475. HRESULT CPCHEvent::put_Place( /*[in]*/ BSTR newVal )
  476. {
  477. return MPC::PutBSTR( m_bstrPlace, newVal );
  478. }
  479. STDMETHODIMP CPCHEvent::get_Place( /*[out, retval]*/ BSTR *pVal )
  480. {
  481. return MPC::GetBSTR( m_bstrPlace, pVal );
  482. }
  483. ////////////////////
  484. STDMETHODIMP CPCHEvent::get_CurrentContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal )
  485. {
  486. return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiCurrentContext, pVal );
  487. }
  488. STDMETHODIMP CPCHEvent::get_PreviousContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal )
  489. {
  490. return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiPreviousContext, pVal );
  491. }
  492. STDMETHODIMP CPCHEvent::get_NextContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal )
  493. {
  494. return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiNextContext, pVal );
  495. }
  496. ////////////////////////////////////////////////////////////////////////////////
  497. ////////////////////////////////////////////////////////////////////////////////
  498. ////////////////////////////////////////////////////////////////////////////////
  499. CPCHTimerHandle::CallbackBase::CallbackBase()
  500. {
  501. m_lRef = 1; // long m_lRef;
  502. }
  503. STDMETHODIMP_(ULONG) CPCHTimerHandle::CallbackBase::AddRef()
  504. {
  505. return ::InterlockedIncrement( &m_lRef );
  506. }
  507. STDMETHODIMP_(ULONG) CPCHTimerHandle::CallbackBase::Release()
  508. {
  509. ULONG l = ::InterlockedDecrement( &m_lRef );
  510. if(l == 0) delete this;
  511. return l;
  512. }
  513. STDMETHODIMP CPCHTimerHandle::CallbackBase::QueryInterface( REFIID iid, void ** ppvObject )
  514. {
  515. if(ppvObject == NULL) return E_POINTER;
  516. if(InlineIsEqualUnknown( iid ) ||
  517. InlineIsEqualGUID ( iid, IID_ITimerSink ) )
  518. {
  519. *ppvObject = this; AddRef();
  520. return S_OK;
  521. }
  522. *ppvObject = NULL;
  523. return E_NOINTERFACE;
  524. }
  525. ////////////////////////////////////////
  526. CPCHTimerHandle::CPCHTimerHandle()
  527. {
  528. // CComPtr<ITimer> m_timer;
  529. m_dwCookie = 0; // DWORD m_dwCookie;
  530. m_callback = NULL; // CallbackBase* m_callback;
  531. }
  532. CPCHTimerHandle::~CPCHTimerHandle()
  533. {
  534. Unadvise();
  535. }
  536. void CPCHTimerHandle::Initialize( /*[in]*/ ITimer* timer )
  537. {
  538. Unadvise();
  539. m_timer = timer;
  540. }
  541. HRESULT CPCHTimerHandle::Advise( /*[in]*/ CallbackBase* callback, /*[in]*/ DWORD dwWait )
  542. {
  543. if(!callback) return E_OUTOFMEMORY;
  544. Unadvise();
  545. m_callback = callback;
  546. if(!m_timer) return E_INVALIDARG;
  547. CComVariant vTime = (long)(dwWait + ::GetTickCount());
  548. CComVariant vZero = 0;
  549. return m_timer->Advise( vTime, vZero, vZero, 0, callback, &m_dwCookie );
  550. }
  551. void CPCHTimerHandle::Unadvise()
  552. {
  553. if(m_timer)
  554. {
  555. if(m_dwCookie)
  556. {
  557. m_timer->Unadvise( m_dwCookie );
  558. m_dwCookie = 0;
  559. }
  560. }
  561. if(m_callback)
  562. {
  563. m_callback->Detach ();
  564. m_callback->Release();
  565. m_callback = NULL;
  566. }
  567. }
  568. /////////////////////////////////////////////////////////////////////////////
  569. /////////////////////////////////////////////////////////////////////////////
  570. /////////////////////////////////////////////////////////////////////////////
  571. CPCHWebBrowserEvents::CPCHWebBrowserEvents()
  572. {
  573. __HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::CPCHWebBrowserEvents" );
  574. m_parent = NULL; // CPCHHelpCenterExternal* m_parent;
  575. m_idPanel = HSCPANEL_INVALID; // HscPanel m_idPanel;
  576. //
  577. // CComPtr<IWebBrowser2> m_pWB2;
  578. m_fLoading = false; // bool m_fLoading;
  579. //
  580. // CPCHTimerHandle m_TimerDelay;
  581. // CPCHTimerHandle m_TimerExpire;
  582. }
  583. CPCHWebBrowserEvents::~CPCHWebBrowserEvents()
  584. {
  585. Passivate();
  586. }
  587. ////////////////////////////////////////////////////////////////////////////////
  588. void CPCHWebBrowserEvents::NotifyStartOfNavigation( /*[in]*/ BSTR url )
  589. {
  590. CPCHHelpSession* hs = m_parent->HelpSession();
  591. if(hs)
  592. {
  593. m_fLoading = true;
  594. (void)hs->StartNavigation( url, m_idPanel );
  595. }
  596. }
  597. void CPCHWebBrowserEvents::NotifyEndOfNavigation()
  598. {
  599. CPCHHelpSession* hs = m_parent->HelpSession();
  600. m_fLoading = false;
  601. if(hs)
  602. {
  603. (void)hs->CompleteNavigation( m_idPanel );
  604. }
  605. }
  606. void CPCHWebBrowserEvents::NotifyStop()
  607. {
  608. TimerControl( TIMERMODE_STOP );
  609. }
  610. ////////////////////////////////////////////////////////////////////////////////
  611. void CPCHWebBrowserEvents::Initialize( /*[in]*/ CPCHHelpCenterExternal* parent, /*[in]*/ HscPanel idPanel )
  612. {
  613. m_parent = parent;
  614. m_idPanel = idPanel;
  615. }
  616. void CPCHWebBrowserEvents::Passivate()
  617. {
  618. Detach();
  619. m_parent = NULL;
  620. }
  621. void CPCHWebBrowserEvents::Attach( /*[in]*/ IWebBrowser2* pWB )
  622. {
  623. __HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::Attach" );
  624. Detach();
  625. m_pWB2 = pWB;
  626. if(m_pWB2)
  627. {
  628. CPCHWebBrowserEvents_DWebBrowserEvents2::DispEventAdvise( m_pWB2 );
  629. }
  630. m_TimerDelay .Initialize( m_parent->Timer() );
  631. m_TimerExpire.Initialize( m_parent->Timer() );
  632. }
  633. void CPCHWebBrowserEvents::Detach()
  634. {
  635. __HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::Detach" );
  636. TimerControl( TIMERMODE_STOP );
  637. if(m_pWB2)
  638. {
  639. CPCHWebBrowserEvents_DWebBrowserEvents2::DispEventUnadvise( m_pWB2 );
  640. m_pWB2.Release();
  641. }
  642. }
  643. /////////////////////////////////////////////////////////////////////////////
  644. void CPCHWebBrowserEvents::TimerControl( /*[in]*/ TimerMode mode )
  645. {
  646. switch(mode)
  647. {
  648. case TIMERMODE_STOP:
  649. m_TimerDelay .Stop();
  650. m_TimerExpire.Stop();
  651. break;
  652. case TIMERMODE_RESTART:
  653. m_TimerDelay .Stop ( );
  654. m_TimerExpire.Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 2000 );
  655. break;
  656. case TIMERMODE_MORETIME:
  657. m_TimerExpire.Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 100 );
  658. break;
  659. case TIMERMODE_COMPLETE:
  660. m_TimerDelay .Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 20 );
  661. m_TimerExpire.Stop ( );
  662. break;
  663. }
  664. }
  665. HRESULT CPCHWebBrowserEvents::OnTimer( VARIANT vtimeAdvise )
  666. {
  667. TimerControl( TIMERMODE_STOP );
  668. NotifyEndOfNavigation();
  669. return S_OK;
  670. }
  671. /////////////////////////////////////////////////////////////////////////////
  672. void __stdcall CPCHWebBrowserEvents::BeforeNavigate2( IDispatch* pDisp ,
  673. VARIANT* URL ,
  674. VARIANT* Flags ,
  675. VARIANT* TargetFrameName,
  676. VARIANT* PostData ,
  677. VARIANT* Headers ,
  678. VARIANT_BOOL *Cancel )
  679. {
  680. if(!m_parent) return; // Called before init or after passivate.
  681. #ifdef DEBUG
  682. DebugLog( L"#################### BeforeNavigate2 %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( V_BSTR( URL ) ) );
  683. DEBUG_CheckReadyState();
  684. #endif
  685. DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::BeforeNavigate2 : %s", SAFEBSTR( V_BSTR( URL ) ) );
  686. CComBSTR bstrFrame;
  687. BSTR bstrURL = V_BSTR( URL );
  688. if(FAILED(MPC::HTML::GetFramePath( bstrFrame, pDisp )) || !bstrFrame)
  689. {
  690. if(V_VT(TargetFrameName) == VT_BSTR)
  691. {
  692. bstrFrame = V_BSTR(TargetFrameName);
  693. }
  694. }
  695. {
  696. bool fProceed = m_parent->ProcessNavigation( m_idPanel, bstrURL, bstrFrame, m_fLoading, *Cancel );
  697. DebugLog( L"#################### ProcessNavigation %s%s%s\n", m_fLoading ? L"loading " : L"", fProceed ? L"proceed " : L"", *Cancel ? L"cancelled " : L"" );
  698. if(fProceed)
  699. {
  700. if(m_fLoading)
  701. {
  702. TimerControl( TIMERMODE_MORETIME );
  703. }
  704. else
  705. {
  706. TimerControl( TIMERMODE_RESTART );
  707. NotifyStartOfNavigation( bstrURL );
  708. }
  709. }
  710. }
  711. }
  712. void __stdcall CPCHWebBrowserEvents::NewWindow2( IDispatch* *ppDisp ,
  713. VARIANT_BOOL *Cancel )
  714. {
  715. // Not disabled in Whistler.
  716. // *Cancel = VARIANT_TRUE;
  717. }
  718. void __stdcall CPCHWebBrowserEvents::NavigateComplete2( IDispatch* pDisp ,
  719. VARIANT* URL )
  720. {
  721. if(!m_parent) return; // Called before init or after passivate.
  722. #ifdef DEBUG
  723. DebugLog( L"#################### NavigateComplete2 %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( V_BSTR( URL ) ) );
  724. DEBUG_CheckReadyState();
  725. #endif
  726. DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::NavigateComplete2 : %s", SAFEBSTR( V_BSTR( URL ) ) );
  727. TimerControl( TIMERMODE_MORETIME );
  728. }
  729. void __stdcall CPCHWebBrowserEvents::DocumentComplete( IDispatch* pDisp ,
  730. VARIANT* URL )
  731. {
  732. if(!m_parent) return; // Called before init or after passivate.
  733. BSTR bstrURL = V_BSTR( URL );
  734. #ifdef DEBUG
  735. DebugLog( L"#################### DocumentComplete %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( bstrURL ) );
  736. DEBUG_CheckReadyState();
  737. #endif
  738. DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::DocumentComplete : %s", SAFEBSTR( bstrURL ) );
  739. TimerControl( TIMERMODE_MORETIME );
  740. //
  741. // If it's one of the URL in the ignore list, don't queue the complete notification.
  742. //
  743. {
  744. CPCHHelpSession* hs = m_parent->HelpSession();
  745. if(hs && hs->IsUrlToIgnore( bstrURL, /*fRemove*/true ))
  746. {
  747. m_fLoading = false;
  748. return;
  749. }
  750. }
  751. //
  752. // Get to the document and extract its title.
  753. //
  754. {
  755. CComPtr<IHTMLDocument2> pDoc;
  756. if(SUCCEEDED(MPC::HTML::IDispatch_To_IHTMLDocument2( pDoc, pDisp )))
  757. {
  758. CComBSTR bstrTitle;
  759. if(SUCCEEDED(pDoc->get_title( &bstrTitle )))
  760. {
  761. (void)m_parent->HelpSession()->RecordTitle( URL->bstrVal, bstrTitle, false );
  762. }
  763. }
  764. }
  765. if(m_fLoading)
  766. {
  767. if(m_pWB2)
  768. {
  769. tagREADYSTATE readystate;
  770. if(SUCCEEDED(m_pWB2->get_ReadyState( &readystate )) && readystate == READYSTATE_COMPLETE)
  771. {
  772. bool fDone;
  773. if(SUCCEEDED(MPC::HTML::AreAllTheFramesInTheCompleteState( fDone, m_pWB2 )) && fDone)
  774. {
  775. TimerControl( TIMERMODE_COMPLETE );
  776. }
  777. }
  778. }
  779. }
  780. }