diff --git a/src/msw/webview_ie.cpp b/src/msw/webview_ie.cpp index 74d1236cb3..658bc12224 100644 --- a/src/msw/webview_ie.cpp +++ b/src/msw/webview_ie.cpp @@ -26,6 +26,8 @@ #include "wx/msw/missing.h" #include "wx/filesys.h" #include "wx/dynlib.h" +#include "wx/scopeguard.h" + #include #include @@ -141,18 +143,89 @@ void wxWebViewIE::LoadURL(const wxString& url) m_ie.CallMethod("Navigate", wxConvertStringToOle(url)); } -void wxWebViewIE::DoSetPage(const wxString& html, const wxString& baseUrl) +namespace { - BSTR bstr = SysAllocString(OLESTR("")); - SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); - if (psaStrings != NULL) + +// Simple RAII wrapper for accessing SAFEARRAY. This class is not specific +// to wxWebView at all and could be extended to work for any type and extracted +// into a header later if it is ever needed elsewhere, but for now keep it here +// as it is only used in MakeOneElementVariantSafeArray() which, itself, is +// only used by DoSetPage() below. +class wxSafeArrayVariantAccessor +{ +public: + explicit wxSafeArrayVariantAccessor(SAFEARRAY* sa) + : m_sa(sa), + m_data(DoAccessData(sa)) + { + } + + VARIANT* GetData() const + { + return m_data; + } + + ~wxSafeArrayVariantAccessor() + { + if ( m_data ) + SafeArrayUnaccessData(m_sa); + } + +private: + static VARIANT* DoAccessData(SAFEARRAY* sa) { VARIANT *param; - HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m); - param->vt = VT_BSTR; - param->bstrVal = bstr; + HRESULT hr = SafeArrayAccessData(sa, (LPVOID*)¶m); + if ( FAILED(hr) ) + { + wxLogLastError(wxT("SafeArrayAccessData")); + return NULL; + } - hr = SafeArrayUnaccessData(psaStrings); + return param; + } + + SAFEARRAY* const m_sa; + VARIANT* const m_data; + + wxDECLARE_NO_COPY_CLASS(wxSafeArrayVariantAccessor); +}; + +// Helper function: wrap the given string in a SAFEARRAY of size 1. +SAFEARRAY* MakeOneElementVariantSafeArray(const wxString& str) +{ + SAFEARRAY* const sa = SafeArrayCreateVector(VT_VARIANT, 0, 1); + if ( !sa ) + { + wxLogLastError(wxT("SafeArrayCreateVector")); + return NULL; + } + + wxSafeArrayVariantAccessor access(sa); + + VARIANT* const param = access.GetData(); + if ( !param ) + { + SafeArrayDestroy(sa); + return NULL; + } + + param->vt = VT_BSTR; + param->bstrVal = SysAllocString(str.wc_str()); + + return sa; +} + +} // anonymous namespace + +void wxWebViewIE::DoSetPage(const wxString& html, const wxString& baseUrl) +{ + { + SAFEARRAY* const psaStrings = MakeOneElementVariantSafeArray(wxString()); + if ( !psaStrings ) + return; + + wxON_BLOCK_EXIT1(SafeArrayDestroy, psaStrings); wxCOMPtr document(GetDocument()); @@ -161,50 +234,34 @@ void wxWebViewIE::DoSetPage(const wxString& html, const wxString& baseUrl) document->write(psaStrings); document->close(); - - SafeArrayDestroy(psaStrings); - - bstr = SysAllocString(html.wc_str()); - - // Creates a new one-dimensional array - psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); - if (psaStrings != NULL) - { - hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m); - param->vt = VT_BSTR; - param->bstrVal = bstr; - hr = SafeArrayUnaccessData(psaStrings); - - document = GetDocument(); - - if(!document) - return; - - document->write(psaStrings); - - // SafeArrayDestroy calls SysFreeString for each BSTR - SafeArrayDestroy(psaStrings); - - //We send the events when we are done to mimic webkit - //Navigated event - wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATED, - GetId(), baseUrl, ""); - event.SetEventObject(this); - HandleWindowEvent(event); - - //Document complete event - event.SetEventType(wxEVT_WEBVIEW_LOADED); - event.SetEventObject(this); - HandleWindowEvent(event); - } - else - { - wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL"); - } } - else + { - wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL during clear"); + SAFEARRAY* const psaStrings = MakeOneElementVariantSafeArray(html); + + if ( !psaStrings ) + return; + + wxON_BLOCK_EXIT1(SafeArrayDestroy, psaStrings); + + wxCOMPtr document(GetDocument()); + + if(!document) + return; + + document->write(psaStrings); + + //We send the events when we are done to mimic webkit + //Navigated event + wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATED, + GetId(), baseUrl, ""); + event.SetEventObject(this); + HandleWindowEvent(event); + + //Document complete event + event.SetEventType(wxEVT_WEBVIEW_LOADED); + event.SetEventObject(this); + HandleWindowEvent(event); } }