Index: src/plugin/PluginClass.h |
=================================================================== |
--- a/src/plugin/PluginClass.h |
+++ b/src/plugin/PluginClass.h |
@@ -41,6 +41,95 @@ |
class CPluginMimeFilterClient; |
+/** |
+ * Resource class for COM events. |
+ * If an instance exists, there's an active connection behind it. |
+ * |
+ * \tparam Sink |
+ * subclass of ATL::IDispEventImpl. |
+ * \tparam Source |
+ * Type of event source. Implements IConnectionPoint |
+ */ |
+template<class Sink, class Source> |
+class AtlEventRegistration |
+{ |
+ CComPtr<Sink> consumer; |
+ CComPtr<Source> producer; |
+public: |
+ /** |
+ * \throw std::runtime_error |
+ * If connection is not established |
+ * |
+ * \par Precondition |
+ * - consumer is not nullptr (not checked) |
+ * - producer is not nullptr (not checked) |
+ */ |
+ AtlEventRegistration(Sink* consumer, Source* producer) |
+ : consumer(consumer), producer(producer) |
+ { |
+ auto hr = consumer->DispEventAdvise(producer); |
+ if (FAILED(hr)) |
+ { |
+ DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVICE, "AtlEventRegistrationImpl::<constructor> - Advise"); |
+ throw std::runtime_error("DispEventAdvise() failed"); |
+ } |
+ } |
+ |
+ ~AtlEventRegistration() // noexcept |
+ { |
+ try |
+ { |
+ // Smart pointer members ensure that this statement does not fail because of life span |
+ auto hr = consumer->DispEventUnadvise(producer); |
+ if (FAILED(hr)) |
+ { |
+ DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_UNADVISE, "AtlEventRegistrationImpl::<destructor> - Unadvise"); |
+ } |
+ } |
+ catch (...) |
+ { |
+ // Suppress exceptions |
+ } |
+ } |
+}; |
+ |
+/** |
+ * Resource holder for COM events. |
+ * |
+ * Manages the life time of an 'AtlEventRegistration' instance. |
+ * Allows events to be started and stopped at some time other than construction/destruction. |
+ * |
+ * \tparam Sink |
+ * subclass of ATL::IDispEventImpl. |
+ * \tparam Source |
+ * Type of event source. Implements IConnectionPoint |
+ */ |
+template<class Sink, class Source> |
+class AtlEventRegistrationHolder |
+{ |
+ typedef AtlEventRegistration<Sink, Source> ImplType; |
+ std::unique_ptr<ImplType> impl; |
+ |
+public: |
+ bool Start(Sink* consumer, Source* producer) // noexcept |
+ { |
+ try |
+ { |
+ impl.reset(new ImplType(consumer, producer)); |
+ } |
+ catch (...) |
+ { |
+ impl.reset(); |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ void Stop() // noexcept |
+ { |
+ impl.reset(); |
+ } |
+}; |
class ATL_NO_VTABLE CPluginClass : |
public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>, |
public ATL::CComCoClass<CPluginClass, &CLSID_PluginClass>, |
@@ -72,7 +161,6 @@ |
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) |
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_WINDOWSTATECHANGED, OnWindowStateChanged) |
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_COMMANDSTATECHANGE, OnCommandStateChange) |
- SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_ONQUIT, OnOnQuit) |
END_SINK_MAP() |
CPluginClass(); |
@@ -131,9 +219,7 @@ |
void STDMETHODCALLTYPE OnDocumentComplete(IDispatch* frameBrowserDisp, VARIANT* /*urlOrPidl*/); |
void STDMETHODCALLTYPE OnWindowStateChanged(unsigned long flags, unsigned long validFlagsMask); |
void STDMETHODCALLTYPE OnCommandStateChange(long command, VARIANT_BOOL enable); |
- void STDMETHODCALLTYPE OnOnQuit(); |
- void Unadvise(); |
- |
+ |
void ShowStatusBar(); |
bool IsStatusBarEnabled(); |
@@ -143,6 +229,12 @@ |
* It's values are set and reset solely in SetSite(). |
*/ |
CComPtr<IWebBrowser2> m_webBrowser2; |
+ /** |
+ * Event manager for events coming from our site object. |
+ */ |
+ AtlEventRegistrationHolder<CPluginClass, IWebBrowser2> browserEvents; |
+ bool detachedInitializationFailed; |
+ |
HWND m_hBrowserWnd; |
HWND m_hTabWnd; |
HWND m_hStatusBarWnd; |
@@ -156,7 +248,6 @@ |
NotificationMessage notificationMessage; |
- bool m_isAdvised; |
bool m_isInitializedOk; |
// Atom pane class |