| Index: src/plugin/PluginClass.h |
| =================================================================== |
| --- a/src/plugin/PluginClass.h |
| +++ b/src/plugin/PluginClass.h |
| @@ -41,6 +41,102 @@ |
| 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: |
| + AtlEventRegistrationHolder() |
| + : impl(nullptr) |
| + {} |
| + |
| + ~AtlEventRegistrationHolder() // = default; |
| + {} |
| + |
| + bool Start(Sink* consumer, Source* producer) // noexcept |
| + { |
| + try |
| + { |
| + impl = new ImplType(consumer, producer); |
| + } |
| + catch (...) |
| + { |
| + impl = nullptr; |
| + return false; |
| + } |
| + return true; |
| + } |
| + |
| + Stop() // noexcept |
| + { |
| + impl = nullptr; |
| + } |
| +}; |
| class ATL_NO_VTABLE CPluginClass : |
| public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>, |
| @@ -73,7 +169,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(); |
| @@ -132,9 +227,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(); |
| @@ -144,6 +237,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; |
| @@ -157,7 +256,6 @@ |
| NotificationMessage notificationMessage; |
| - bool m_isAdvised; |
| bool m_isInitializedOk; |
| // Atom pane class |