diff options
Diffstat (limited to 'chrome_frame/chrome_frame_activex_base.h')
-rw-r--r-- | chrome_frame/chrome_frame_activex_base.h | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/chrome_frame/chrome_frame_activex_base.h b/chrome_frame/chrome_frame_activex_base.h index 2b9d60d..ebb57b0 100644 --- a/chrome_frame/chrome_frame_activex_base.h +++ b/chrome_frame/chrome_frame_activex_base.h @@ -14,6 +14,7 @@ #include <set> #include <string> +#include <vector> #include "base/histogram.h" #include "base/scoped_bstr_win.h" @@ -46,14 +47,19 @@ class ATL_NO_VTABLE ProxyDIChromeFrameEvents void FireMethodWithParams(ChromeFrameEventDispId dispid, const VARIANT* params, size_t num_params) { T* me = static_cast<T*>(this); - int connections = m_vec.GetSize(); - - for (int connection = 0; connection < connections; ++connection) { - me->Lock(); - CComPtr<IUnknown> sink(m_vec.GetAt(connection)); - me->Unlock(); - - DIChromeFrameEvents* events = static_cast<DIChromeFrameEvents*>(sink.p); + // We need to copy the whole vector and AddRef the sinks in case + // some would get disconnected as we fire methods. Note that this is not + // a threading issue, but a re-entrance issue, because the connection + // can be affected by the implementation of the sinks receiving the event. + me->Lock(); + std::vector< ScopedComPtr<IUnknown> > sink_array(m_vec.GetSize()); + for (int connection = 0; connection < m_vec.GetSize(); ++connection) + sink_array[connection] = m_vec.GetAt(connection); + me->Unlock(); + + for (size_t sink = 0; sink < sink_array.size(); ++sink) { + DIChromeFrameEvents* events = + static_cast<DIChromeFrameEvents*>(sink_array[sink].get()); if (events) { DISPPARAMS disp_params = { const_cast<VARIANT*>(params), @@ -123,13 +129,17 @@ class ATL_NO_VTABLE ProxyDIChromeFrameEvents arraysize(args)); } - void Fire_ongetenabledextensionscomplete(SAFEARRAY* extension_dirs) { // NOLINT + void Fire_ongetenabledextensionscomplete(SAFEARRAY* extension_dirs) { VARIANT args[1] = { { VT_ARRAY | VT_BSTR } }; args[0].parray = extension_dirs; FireMethodWithParams(CF_EVENT_DISPID_ONGETENABLEDEXTENSIONSCOMPLETE, args, arraysize(args)); } + + void Fire_onchannelerror() { // NOLINT + FireMethodWithParams(CF_EVENT_DISPID_ONCHANNELERROR, NULL, 0); + } }; extern bool g_first_launch_by_process_; |