X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c9ccc09c64f4c29d4667796bef7b507d9e8d25ed..75b0b0bcae2198a53e093cbaaaa09ec10b62b839:/src/msw/webview_ie.cpp diff --git a/src/msw/webview_ie.cpp b/src/msw/webview_ie.cpp index dbb35fdc3a..9f0c1168b4 100644 --- a/src/msw/webview_ie.cpp +++ b/src/msw/webview_ie.cpp @@ -3,7 +3,7 @@ // Purpose: wxMSW wxWebViewIE class implementation for web view component // Author: Marianne Gagnon // Id: $Id$ -// Copyright: (c) 2010 Marianne Gagnon, Steven Lamerton +// Copyright: (c) 2010 Marianne Gagnon, 2011 Steven Lamerton // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -16,7 +16,6 @@ #include "wx/msw/webview_ie.h" - #if wxUSE_WEBVIEW_IE #include @@ -25,51 +24,11 @@ #include #include #include "wx/msw/registry.h" -// Various definitions are missing from mingw -#ifdef __MINGW32__ -typedef enum CommandStateChangeConstants { - CSC_UPDATECOMMANDS = (int) 0xFFFFFFFF, - CSC_NAVIGATEFORWARD = 0x1, - CSC_NAVIGATEBACK = 0x2 -} CommandStateChangeConstants; - -#define DISPID_COMMANDSTATECHANGE 105 -#define DISPID_NAVIGATECOMPLETE2 252 -#define DISPID_NAVIGATEERROR 271 -#define DISPID_NEWWINDOW3 273 -#define OLECMDID_OPTICAL_ZOOM 63 -#define INET_E_ERROR_FIRST 0x800C0002L -#define INET_E_INVALID_URL 0x800C0002L -#define INET_E_NO_SESSION 0x800C0003L -#define INET_E_CANNOT_CONNECT 0x800C0004L -#define INET_E_RESOURCE_NOT_FOUND 0x800C0005L -#define INET_E_OBJECT_NOT_FOUND 0x800C0006L -#define INET_E_DATA_NOT_AVAILABLE 0x800C0007L -#define INET_E_DOWNLOAD_FAILURE 0x800C0008L -#define INET_E_AUTHENTICATION_REQUIRED 0x800C0009L -#define INET_E_NO_VALID_MEDIA 0x800C000AL -#define INET_E_CONNECTION_TIMEOUT 0x800C000BL -#define INET_E_INVALID_REQUEST 0x800C000CL -#define INET_E_UNKNOWN_PROTOCOL 0x800C000DL -#define INET_E_SECURITY_PROBLEM 0x800C000EL -#define INET_E_CANNOT_LOAD_DATA 0x800C000FL -#define INET_E_CANNOT_INSTANTIATE_OBJECT 0x800C0010L -#define INET_E_QUERYOPTION_UNKNOWN 0x800C0013L -#define INET_E_REDIRECT_FAILED 0x800C0014L -#define INET_E_REDIRECT_TO_DIR 0x800C0015L -#define INET_E_CANNOT_LOCK_REQUEST 0x800C0016L -#define INET_E_USE_EXTEND_BINDING 0x800C0017L -#define INET_E_TERMINATED_BIND 0x800C0018L -#define INET_E_INVALID_CERTIFICATE 0x800C0019L -#define INET_E_CODE_DOWNLOAD_DECLINED 0x800C0100L -#define INET_E_RESULT_DISPATCHED 0x800C0200L -#define INET_E_CANNOT_REPLACE_SFP_FILE 0x800C0300L -#define INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY 0x800C0500L -#define INET_E_CODE_INSTALL_SUPPRESSED 0x800C0400L - -#define REFRESH_NORMAL 0 -#define REFRESH_COMPLETELY 3 -#endif +#include "wx/msw/missing.h" +#include "wx/filesys.h" + +//We link to urlmon as it is required for CoInternetGetSession +#pragma comment(lib, "urlmon") BEGIN_EVENT_TABLE(wxWebViewIE, wxControl) EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent) @@ -91,8 +50,6 @@ bool wxWebViewIE::Create(wxWindow* parent, } m_webBrowser = NULL; - m_canNavigateBack = false; - m_canNavigateForward = false; m_isBusy = false; m_historyLoadingFromList = false; m_historyEnabled = true; @@ -111,7 +68,6 @@ bool wxWebViewIE::Create(wxWindow* parent, m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE); m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE); - //m_webBrowser->put_Silent(VARIANT_FALSE); m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser); @@ -127,17 +83,8 @@ void wxWebViewIE::LoadUrl(const wxString& url) m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), NULL, NULL, NULL, NULL); } -void wxWebViewIE::SetPage(const wxString& html, const wxString&) +void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl) { - LoadUrl("about:blank"); - - // Let the wx events generated for navigation events be processed, so - // that the underlying IE component completes its Document object. - // FIXME: calling wxYield is not elegant nor very reliable probably - wxYield(); - - // TODO: consider the "baseUrl" parameter if possible - // TODO: consider encoding BSTR bstr = SysAllocString(html.wc_str()); // Creates a new one-dimensional array @@ -145,16 +92,30 @@ void wxWebViewIE::SetPage(const wxString& html, const wxString&) if (psaStrings != NULL) { VARIANT *param; + HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m); param->vt = VT_BSTR; param->bstrVal = bstr; - hr = SafeArrayUnaccessData(psaStrings); + IHTMLDocument2* document = GetDocument(); document->write(psaStrings); + document->Release(); // SafeArrayDestroy calls SysFreeString for each BSTR SafeArrayDestroy(psaStrings); + + //We send the events when we are done to mimic webkit + //Navigated event + wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + GetId(), baseUrl, "", false); + event.SetEventObject(this); + HandleWindowEvent(event); + + //Document complete event + event.SetEventType(wxEVT_COMMAND_WEB_VIEW_LOADED); + event.SetEventObject(this); + HandleWindowEvent(event); } else { @@ -198,7 +159,7 @@ wxWebViewZoom wxWebViewIE::GetZoom() //Dummy return to stop compiler warnings return wxWEB_VIEW_ZOOM_MEDIUM; - + } void wxWebViewIE::SetZoom(wxWebViewZoom zoom) @@ -213,7 +174,7 @@ void wxWebViewIE::SetZoom(wxWebViewZoom zoom) void wxWebViewIE::SetIETextZoom(wxWebViewZoom level) { - //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range + //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range //is 0 to 4 so the check is unnecessary, these match exactly with the //enum values VARIANT zoomVariant; @@ -244,7 +205,7 @@ wxWebViewZoom wxWebViewIE::GetIETextZoom() void wxWebViewIE::SetIEOpticalZoom(wxWebViewZoom level) { - //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range + //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range //is 10 to 1000 so the check is unnecessary VARIANT zoomVariant; VariantInit (&zoomVariant); @@ -371,7 +332,7 @@ void wxWebViewIE::LoadHistoryItem(wxSharedPtr item) if(m_historyList[i].get() == item.get()) pos = i; } - wxASSERT_MSG(pos != static_cast(m_historyList.size()), + wxASSERT_MSG(pos != static_cast(m_historyList.size()), "invalid history item"); m_historyLoadingFromList = true; LoadUrl(item->GetUrl()); @@ -702,6 +663,22 @@ void wxWebViewIE::RunScript(const wxString& javascript) document->Release(); } +void wxWebViewIE::RegisterHandler(wxWebHandler* handler) +{ + ClassFactory* cf = new ClassFactory(handler); + IInternetSession* session; + if(FAILED(CoInternetGetSession(0, &session, 0))) + { + wxFAIL_MSG("Could not retrive internet session"); + } + + HRESULT hr = session->RegisterNameSpace(cf, CLSID_FileProtocol, handler->GetName(), 0, NULL, 0); + if(FAILED(hr)) + { + wxFAIL_MSG("Could not register protocol"); + } +} + bool wxWebViewIE::CanExecCommand(wxString command) { IHTMLDocument2* document = GetDocument(); @@ -826,6 +803,13 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) case DISPID_TITLECHANGE: { + wxString title = evt[0].GetString(); + + wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED, + GetId(), GetCurrentURL(), wxEmptyString, true); + event.SetString(title); + event.SetEventObject(this); + HandleWindowEvent(event); break; } @@ -953,21 +937,6 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) HandleWindowEvent(event); break; } - - case DISPID_COMMANDSTATECHANGE: - { - long commandId = evt[0].GetLong(); - bool enable = evt[1].GetBool(); - if (commandId == CSC_NAVIGATEBACK) - { - m_canNavigateBack = enable; - } - else if (commandId == CSC_NAVIGATEFORWARD) - { - m_canNavigateForward = enable; - } - break; - } case DISPID_NEWWINDOW3: { wxString url = evt[4].GetString(); @@ -977,12 +946,10 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) event.SetEventObject(this); HandleWindowEvent(event); - //If we veto the event then we cancel the new window - if (event.IsVetoed()) - { - wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters(); - *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE; - } + //We always cancel this event otherwise an Internet Exporer window + //is opened for the url + wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters(); + *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE; break; } } @@ -990,4 +957,223 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) evt.Skip(); } +VirtualProtocol::VirtualProtocol(wxWebHandler *handler) +{ + m_refCount = 0; + m_file = NULL; + m_handler = handler; +} + +VirtualProtocol::~VirtualProtocol() +{ +} + +ULONG VirtualProtocol::AddRef() +{ + m_refCount++; + return m_refCount; +} + +HRESULT VirtualProtocol::QueryInterface(REFIID riid, void **ppvObject) +{ + if(riid == IID_IUnknown || riid == IID_IInternetProtocolRoot || + riid == IID_IInternetProtocol) + { + *ppvObject = (IInternetProtocol*)this; + AddRef(); + return S_OK; + } + else if(riid == IID_IInternetProtocolInfo) + { + *ppvObject = (IInternetProtocolInfo*)this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_POINTER; + } +} + +ULONG VirtualProtocol::Release() +{ + m_refCount--; + if (m_refCount > 0) + { + return m_refCount; + } + else + { + delete this; + return 0; + } +} + +HRESULT VirtualProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, + IInternetBindInfo *pOIBindInfo, DWORD grfPI, + HANDLE_PTR dwReserved) +{ + wxUnusedVar(szUrl); + wxUnusedVar(pOIBindInfo); + wxUnusedVar(grfPI); + wxUnusedVar(dwReserved); + m_protocolSink = pOIProtSink; + + //We get the file itself from the protocol handler + m_file = m_handler->GetFile(szUrl); + + + if(!m_file) + return INET_E_RESOURCE_NOT_FOUND; + + //We return the stream length for current and total size as we can always + //read the whole file from the stream + wxFileOffset length = m_file->GetStream()->GetLength(); + m_protocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION | + BSCF_DATAFULLYAVAILABLE | + BSCF_LASTDATANOTIFICATION, + length, length); + return S_OK; +} + +HRESULT VirtualProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead) +{ + //If the file is null we return false to indicte it is finished + if(!m_file) + return S_FALSE; + + wxStreamError err = m_file->GetStream()->Read(pv, cb).GetLastError(); + *pcbRead = m_file->GetStream()->LastRead(); + + if(err == wxSTREAM_NO_ERROR) + { + if(*pcbRead < cb) + { + wxDELETE(m_file); + m_protocolSink->ReportResult(S_OK, 0, NULL); + } + //As we are not eof there is more data + return S_OK; + } + else if(err == wxSTREAM_EOF) + { + wxDELETE(m_file); + m_protocolSink->ReportResult(S_OK, 0, NULL); + //We are eof and so finished + return S_OK; + } + else if(err == wxSTREAM_READ_ERROR) + { + wxDELETE(m_file); + return INET_E_DOWNLOAD_FAILURE; + } + else + { + //Dummy return to surpress a compiler warning + wxFAIL; + return INET_E_DOWNLOAD_FAILURE; + } +} + +HRESULT VirtualProtocol::CombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, + DWORD WXUNUSED(dwCombineFlags), + LPWSTR pwzResult, + DWORD cchResult, DWORD *pcchResult, + DWORD WXUNUSED(dwReserved)) +{ + + wxString newuri = m_handler->CombineURIs(pwzBaseUrl, pwzRelativeUrl); + //Check the buffer we are given can hold the new url + if(wxStrlen(newuri) > cchResult) + return S_FALSE; + + wxStrcpy(pwzResult, newuri.c_str()); + *pcchResult = wxStrlen(newuri); + return S_OK; +} + +HRESULT VirtualProtocol::ParseUrl(LPCWSTR pwzUrl, + PARSEACTION WXUNUSED(ParseAction), + DWORD WXUNUSED(dwParseFlags), + LPWSTR pwzResult, + DWORD cchResult, DWORD *pcchResult, + DWORD WXUNUSED(dwReserved)) +{ + //Check the buffer we are given can hold the new url + if(wxStrlen(pwzUrl) > cchResult) + return S_FALSE; + + wxStrcpy(pwzResult, pwzUrl); + *pcchResult = wxStrlen(pwzResult); + return S_OK; +} + +HRESULT VirtualProtocol::QueryInfo(LPCWSTR WXUNUSED(pwzUrl), + QUERYOPTION WXUNUSED(OueryOption), + DWORD WXUNUSED(dwQueryFlags), + LPVOID WXUNUSED(pBuffer), + DWORD WXUNUSED(cbBuffer), + DWORD* WXUNUSED(pcbBuf), + DWORD WXUNUSED(dwReserved)) +{ + return INET_E_DEFAULT_ACTION; +} + +HRESULT ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid, + void ** ppvObject) +{ + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + VirtualProtocol* vp = new VirtualProtocol(m_handler); + vp->AddRef(); + HRESULT hr = vp->QueryInterface(riid, ppvObject); + vp->Release(); + return hr; + +} + +STDMETHODIMP ClassFactory::LockServer(BOOL fLock) +{ + wxUnusedVar(fLock); + return S_OK; +} + +ULONG ClassFactory::AddRef(void) +{ + m_refCount++; + return m_refCount; +} + +HRESULT ClassFactory::QueryInterface(REFIID riid, void **ppvObject) +{ + if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_POINTER; + } + +} + +ULONG ClassFactory::Release(void) +{ + m_refCount--; + if (m_refCount > 0) + { + return m_refCount; + } + else + { + delete this; + return 0; + } + +} + #endif