X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/442262d47ae64e33697ee344eedbaba144de91a0..74a8f67d96591cec101def2a7d47c64072aff7fd:/src/msw/webview_ie.cpp diff --git a/src/msw/webview_ie.cpp b/src/msw/webview_ie.cpp index 0c8c88609f..92edb4ecd5 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,13 @@ #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" + +wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewIE, wxWebView); + +//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 +52,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,18 +70,17 @@ 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); SetBackgroundStyle(wxBG_STYLE_PAINT); SetDoubleBuffered(true); - LoadUrl(url); + LoadURL(url); return true; } -void wxWebViewIE::LoadUrl(const wxString& url) +void wxWebViewIE::LoadURL(const wxString& url) { m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), NULL, NULL, NULL, NULL); } @@ -151,8 +109,8 @@ void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl) //We send the events when we are done to mimic webkit //Navigated event - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - GetId(), baseUrl, "", false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + GetId(), baseUrl, ""); event.SetEventObject(this); HandleWindowEvent(event); @@ -168,7 +126,7 @@ void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl) } -wxString wxWebViewIE::GetPageSource() +wxString wxWebViewIE::GetPageSource() const { IHTMLDocument2* document = GetDocument(); IHTMLElement *bodyTag = NULL; @@ -192,7 +150,7 @@ wxString wxWebViewIE::GetPageSource() return source; } -wxWebViewZoom wxWebViewIE::GetZoom() +wxWebViewZoom wxWebViewIE::GetZoom() const { if(m_zoomType == wxWEB_VIEW_ZOOM_TYPE_LAYOUT) return GetIEOpticalZoom(); @@ -203,7 +161,7 @@ wxWebViewZoom wxWebViewIE::GetZoom() //Dummy return to stop compiler warnings return wxWEB_VIEW_ZOOM_MEDIUM; - + } void wxWebViewIE::SetZoom(wxWebViewZoom zoom) @@ -218,7 +176,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; @@ -232,7 +190,7 @@ void wxWebViewIE::SetIETextZoom(wxWebViewZoom level) wxASSERT(result == S_OK); } -wxWebViewZoom wxWebViewIE::GetIETextZoom() +wxWebViewZoom wxWebViewIE::GetIETextZoom() const { VARIANT zoomVariant; VariantInit (&zoomVariant); @@ -249,7 +207,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); @@ -284,7 +242,7 @@ void wxWebViewIE::SetIEOpticalZoom(wxWebViewZoom level) wxASSERT(result == S_OK); } -wxWebViewZoom wxWebViewIE::GetIEOpticalZoom() +wxWebViewZoom wxWebViewIE::GetIEOpticalZoom() const { VARIANT zoomVariant; VariantInit (&zoomVariant); @@ -351,7 +309,7 @@ void wxWebViewIE::Print() OLECMDEXECOPT_DODEFAULT, NULL, NULL); } -bool wxWebViewIE::CanGoBack() +bool wxWebViewIE::CanGoBack() const { if(m_historyEnabled) return m_historyPosition > 0; @@ -359,7 +317,7 @@ bool wxWebViewIE::CanGoBack() return false; } -bool wxWebViewIE::CanGoForward() +bool wxWebViewIE::CanGoForward() const { if(m_historyEnabled) return m_historyPosition != static_cast(m_historyList.size()) - 1; @@ -367,7 +325,7 @@ bool wxWebViewIE::CanGoForward() return false; } -void wxWebViewIE::LoadHistoryItem(wxSharedPtr item) +void wxWebViewIE::LoadHistoryItem(wxSharedPtr item) { int pos = -1; for(unsigned int i = 0; i < m_historyList.size(); i++) @@ -376,16 +334,16 @@ 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()); + LoadURL(item->GetUrl()); m_historyPosition = pos; } -wxVector > wxWebViewIE::GetBackwardHistory() +wxVector > wxWebViewIE::GetBackwardHistory() { - wxVector > backhist; + wxVector > backhist; //As we don't have std::copy or an iterator constructor in the wxwidgets //native vector we construct it by hand for(int i = 0; i < m_historyPosition; i++) @@ -395,9 +353,9 @@ wxVector > wxWebViewIE::GetBackwardHistory() return backhist; } -wxVector > wxWebViewIE::GetForwardHistory() +wxVector > wxWebViewIE::GetForwardHistory() { - wxVector > forwardhist; + wxVector > forwardhist; //As we don't have std::copy or an iterator constructor in the wxwidgets //native vector we construct it by hand for(int i = m_historyPosition + 1; i < static_cast(m_historyList.size()); i++) @@ -475,8 +433,8 @@ void wxWebViewIE::SetOfflineMode(bool offline) wxASSERT(success); } -bool wxWebViewIE::IsBusy() -{ +bool wxWebViewIE::IsBusy() const +{ if (m_isBusy) return true; wxVariant out = m_ie.GetProperty("Busy"); @@ -486,7 +444,7 @@ bool wxWebViewIE::IsBusy() return out.GetBool(); } -wxString wxWebViewIE::GetCurrentURL() +wxString wxWebViewIE::GetCurrentURL() const { wxVariant out = m_ie.GetProperty("LocationURL"); @@ -494,7 +452,7 @@ wxString wxWebViewIE::GetCurrentURL() return out.GetString(); } -wxString wxWebViewIE::GetCurrentTitle() +wxString wxWebViewIE::GetCurrentTitle() const { IHTMLDocument2* document = GetDocument(); BSTR title; @@ -504,16 +462,16 @@ wxString wxWebViewIE::GetCurrentTitle() return wxString(title); } -bool wxWebViewIE::CanCut() +bool wxWebViewIE::CanCut() const { return CanExecCommand("Cut"); } -bool wxWebViewIE::CanCopy() +bool wxWebViewIE::CanCopy() const { return CanExecCommand("Copy"); } -bool wxWebViewIE::CanPaste() +bool wxWebViewIE::CanPaste() const { return CanExecCommand("Paste"); } @@ -533,11 +491,11 @@ void wxWebViewIE::Paste() ExecCommand("Paste"); } -bool wxWebViewIE::CanUndo() +bool wxWebViewIE::CanUndo() const { return CanExecCommand("Undo"); } -bool wxWebViewIE::CanRedo() +bool wxWebViewIE::CanRedo() const { return CanExecCommand("Redo"); } @@ -563,7 +521,7 @@ void wxWebViewIE::SetEditable(bool enable) document->Release(); } -bool wxWebViewIE::IsEditable() +bool wxWebViewIE::IsEditable() const { IHTMLDocument2* document = GetDocument(); BSTR mode; @@ -580,7 +538,7 @@ void wxWebViewIE::SelectAll() ExecCommand("SelectAll"); } -bool wxWebViewIE::HasSelection() +bool wxWebViewIE::HasSelection() const { IHTMLDocument2* document = GetDocument(); IHTMLSelectionObject* selection; @@ -602,7 +560,7 @@ void wxWebViewIE::DeleteSelection() ExecCommand("Delete"); } -wxString wxWebViewIE::GetSelectedText() +wxString wxWebViewIE::GetSelectedText() const { IHTMLDocument2* document = GetDocument(); IHTMLSelectionObject* selection; @@ -631,7 +589,7 @@ wxString wxWebViewIE::GetSelectedText() return selected; } -wxString wxWebViewIE::GetSelectedSource() +wxString wxWebViewIE::GetSelectedSource() const { IHTMLDocument2* document = GetDocument(); IHTMLSelectionObject* selection; @@ -674,7 +632,7 @@ void wxWebViewIE::ClearSelection() document->Release(); } -wxString wxWebViewIE::GetPageText() +wxString wxWebViewIE::GetPageText() const { IHTMLDocument2* document = GetDocument(); wxString text; @@ -707,7 +665,23 @@ void wxWebViewIE::RunScript(const wxString& javascript) document->Release(); } -bool wxWebViewIE::CanExecCommand(wxString command) +void wxWebViewIE::RegisterHandler(wxSharedPtr 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) const { IHTMLDocument2* document = GetDocument(); VARIANT_BOOL enabled; @@ -725,7 +699,7 @@ void wxWebViewIE::ExecCommand(wxString command) document->Release(); } -IHTMLDocument2* wxWebViewIE::GetDocument() +IHTMLDocument2* wxWebViewIE::GetDocument() const { wxVariant variant = m_ie.GetProperty("Document"); IHTMLDocument2* document = (IHTMLDocument2*)variant.GetVoidPtr(); @@ -748,12 +722,12 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) wxString url = evt[1].GetString(); wxString target = evt[3].GetString(); - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, - GetId(), url, target, true); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, + GetId(), url, target); event.SetEventObject(this); HandleWindowEvent(event); - if (event.IsVetoed()) + if (!event.IsAllowed()) { wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters(); @@ -774,8 +748,8 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) wxString url = evt[1].GetString(); // TODO: set target parameter if possible wxString target = wxEmptyString; - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - GetId(), url, target, false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + GetId(), url, target); event.SetEventObject(this); HandleWindowEvent(event); break; @@ -800,7 +774,13 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) //As we are complete we also add to the history list, but not if the //page is not the main page, ie it is a subframe - if(m_historyEnabled && !m_historyLoadingFromList && url == GetCurrentURL()) + //We also have to check if we are loading a file:// url, if so we + //need to change the comparison as ie passes back a different style + //of url + if(m_historyEnabled && !m_historyLoadingFromList && + (url == GetCurrentURL() || + (GetCurrentURL().substr(0, 4) == "file" && + wxFileSystem::URLToFileName(GetCurrentURL()).GetFullPath() == url))) { //If we are not at the end of the list, then erase everything //between us and the end before adding the new page @@ -809,7 +789,7 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) m_historyList.erase(m_historyList.begin() + m_historyPosition + 1, m_historyList.end()); } - wxSharedPtr item(new wxWebHistoryItem(url, GetCurrentTitle())); + wxSharedPtr item(new wxWebViewHistoryItem(url, GetCurrentTitle())); m_historyList.push_back(item); m_historyPosition++; } @@ -817,8 +797,8 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) m_historyLoadingFromList = false; // TODO: set target parameter if possible wxString target = wxEmptyString; - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(), - url, target, false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(), + url, target); event.SetEventObject(this); HandleWindowEvent(event); break; @@ -831,12 +811,19 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) case DISPID_TITLECHANGE: { + wxString title = evt[0].GetString(); + + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED, + GetId(), GetCurrentURL(), ""); + event.SetString(title); + event.SetEventObject(this); + HandleWindowEvent(event); break; } case DISPID_NAVIGATEERROR: { - wxWebNavigationError errorType = wxWEB_NAV_ERR_OTHER; + wxWebViewNavigationError errorType = wxWEB_NAV_ERR_OTHER; wxString errorCode = "?"; switch (evt[3].GetLong()) { @@ -950,44 +937,27 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) wxString url = evt[1].GetString(); wxString target = evt[2].GetString(); - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(), - url, target, false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(), + url, target); event.SetEventObject(this); event.SetInt(errorType); event.SetString(errorCode); 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(); - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW, - GetId(), url, wxEmptyString, true); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW, + GetId(), url, wxEmptyString); 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; } } @@ -995,4 +965,173 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) evt.Skip(); } +VirtualProtocol::VirtualProtocol(wxSharedPtr 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 + { + *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 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