// Purpose: wxMSW wxWebViewIE class implementation for web view component
// Author: Marianne Gagnon
// Id: $Id$
-// Copyright: (c) 2010 Marianne Gagnon
+// Copyright: (c) 2010 Marianne Gagnon, Steven Lamerton
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/msw/webview_ie.h"
-#if wxHAVE_WEB_BACKEND_IE
+#if wxUSE_WEBVIEW_IE
#include <olectl.h>
#include <oleidl.h>
#include <exdisp.h>
#include <mshtml.h>
+// Various definitions are missing from mingw
#ifdef __MINGW32__
-// FIXME: Seems like MINGW does not have these, how to handle cleanly?
-#define DISPID_COMMANDSTATECHANGE 105
typedef enum CommandStateChangeConstants {
CSC_UPDATECOMMANDS = (int) 0xFFFFFFFF,
CSC_NAVIGATEFORWARD = 0x1,
CSC_NAVIGATEBACK = 0x2
} CommandStateChangeConstants;
-
-// FIXME: Seems like MINGW does not have these, how to handle cleanly?
-#define DISPID_NAVIGATECOMPLETE2 252
-#define DISPID_NAVIGATEERROR 271
-#define OLECMDID_OPTICAL_ZOOM 63
+#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_CODE_INSTALL_BLOCKED_BY_HASH_POLICY 0x800C0500L
#define INET_E_CODE_INSTALL_SUPPRESSED 0x800C0400L
+#define REFRESH_NORMAL 0
#define REFRESH_COMPLETELY 3
#endif
m_canNavigateBack = false;
m_canNavigateForward = false;
m_isBusy = false;
+ m_historyLoadingFromList = false;
+ m_historyEnabled = true;
+ m_historyPosition = -1;
if (::CoCreateInstance(CLSID_WebBrowser, NULL,
CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
SetBackgroundStyle(wxBG_STYLE_PAINT);
SetDoubleBuffered(true);
+ LoadUrl(url);
return true;
}
void wxWebViewIE::LoadUrl(const wxString& url)
{
- wxVariant out = m_ie.CallMethod("Navigate", (BSTR) url.wc_str(),
- NULL, NULL, NULL, NULL);
-
- // FIXME: why is out value null??
- //(HRESULT)(out.GetLong()) == S_OK;
+ m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), NULL, NULL, NULL, NULL);
}
-void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl)
+void wxWebViewIE::SetPage(const wxString& html, const wxString&)
{
LoadUrl("about:blank");
// FIXME: calling wxYield is not elegant nor very reliable probably
wxYield();
- wxVariant documentVariant = m_ie.GetProperty("Document");
- void* documentPtr = documentVariant.GetVoidPtr();
-
- wxASSERT (documentPtr != NULL);
-
// TODO: consider the "baseUrl" parameter if possible
// TODO: consider encoding
BSTR bstr = SysAllocString(html.wc_str());
param->bstrVal = bstr;
hr = SafeArrayUnaccessData(psaStrings);
-
- IHTMLDocument2* document = (IHTMLDocument2*)documentPtr;
+ IHTMLDocument2* document = GetDocument();
document->write(psaStrings);
// SafeArrayDestroy calls SysFreeString for each BSTR
wxString wxWebViewIE::GetPageSource()
{
- wxVariant documentVariant = m_ie.GetProperty("Document");
- void* documentPtr = documentVariant.GetVoidPtr();
-
- if (documentPtr == NULL)
- {
- return wxEmptyString;
- }
-
- IHTMLDocument2* document = (IHTMLDocument2*)documentPtr;
-
+ IHTMLDocument2* document = GetDocument();
IHTMLElement *bodyTag = NULL;
IHTMLElement *htmlTag = NULL;
- document->get_body(&bodyTag);
- wxASSERT(bodyTag != NULL);
+ BSTR bstr;
+ HRESULT hr = document->get_body(&bodyTag);
+ if(SUCCEEDED(hr))
+ {
+ hr = bodyTag->get_parentElement(&htmlTag);
+ if(SUCCEEDED(hr))
+ {
+ htmlTag->get_outerHTML(&bstr);
+ htmlTag->Release();
+ }
+ bodyTag->Release();
+ }
document->Release();
- bodyTag->get_parentElement(&htmlTag);
- wxASSERT(htmlTag != NULL);
-
- BSTR bstr;
- htmlTag->get_outerHTML(&bstr);
-
- bodyTag->Release();
- htmlTag->Release();
-
- //wxMessageBox(wxString(bstr));
-
- // TODO: check encoding
return wxString(bstr);
}
wxASSERT (result == S_OK);
int zoom = V_I4(&zoomVariant);
- // wxMessageBox(wxString::Format("Zoom : %i", zoom));
VariantClear (&zoomVariant);
return zoom;
OLECMDEXECOPT_DODEFAULT, NULL, NULL);
}
-void wxWebViewIE::GoBack()
+bool wxWebViewIE::CanGoBack()
{
- wxVariant out = m_ie.CallMethod("GoBack");
+ if(m_historyEnabled)
+ return m_historyPosition > 0;
+ else
+ return false;
+}
- // FIXME: why is out value null??
- //return (HRESULT)(out.GetLong()) == S_OK;
+bool wxWebViewIE::CanGoForward()
+{
+ if(m_historyEnabled)
+ return m_historyPosition != static_cast<int>(m_historyList.size()) - 1;
+ else
+ return false;
}
-void wxWebViewIE::GoForward()
+void wxWebViewIE::LoadHistoryItem(wxSharedPtr<wxWebHistoryItem> item)
{
- wxVariant out = m_ie.CallMethod("GoForward");
+ int pos = -1;
+ for(unsigned int i = 0; i < m_historyList.size(); i++)
+ {
+ //We compare the actual pointers to find the correct item
+ if(m_historyList[i].get() == item.get())
+ pos = i;
+ }
+ wxASSERT_MSG(pos != static_cast<int>(m_historyList.size()),
+ "invalid history item");
+ m_historyLoadingFromList = true;
+ LoadUrl(item->GetUrl());
+ m_historyPosition = pos;
+}
- // FIXME: why is out value null??
- //return (HRESULT)(out.GetLong()) == S_OK;
+wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetBackwardHistory()
+{
+ wxVector<wxSharedPtr<wxWebHistoryItem> > 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++)
+ {
+ backhist.push_back(m_historyList[i]);
+ }
+ return backhist;
+}
+
+wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetForwardHistory()
+{
+ wxVector<wxSharedPtr<wxWebHistoryItem> > 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<int>(m_historyList.size()); i++)
+ {
+ forwardhist.push_back(m_historyList[i]);
+ }
+ return forwardhist;
+}
+
+void wxWebViewIE::GoBack()
+{
+ LoadHistoryItem(m_historyList[m_historyPosition - 1]);
+}
+
+void wxWebViewIE::GoForward()
+{
+ LoadHistoryItem(m_historyList[m_historyPosition + 1]);
}
void wxWebViewIE::Stop()
{
- wxVariant out = m_ie.CallMethod("Stop");
+ m_ie.CallMethod("Stop");
+}
- // FIXME: why is out value null??
- //return (HRESULT)(out.GetLong()) == S_OK;
+void wxWebViewIE::ClearHistory()
+{
+ m_historyList.clear();
+ m_historyPosition = -1;
}
+void wxWebViewIE::EnableHistory(bool enable)
+{
+ m_historyEnabled = enable;
+ m_historyList.clear();
+ m_historyPosition = -1;
+}
void wxWebViewIE::Reload(wxWebViewReloadFlags flags)
{
wxString wxWebViewIE::GetCurrentTitle()
{
- wxVariant out = m_ie.GetProperty("LocationName");
+ IHTMLDocument2* document = GetDocument();
+ BSTR title;
- wxASSERT(out.GetType() == "string");
- return out.GetString();
+ document->get_nameProp(&title);
+ document->Release();
+ return wxString(title);
+}
+
+bool wxWebViewIE::CanCut()
+{
+ return CanExecCommand("Cut");
+}
+
+bool wxWebViewIE::CanCopy()
+{
+ return CanExecCommand("Copy");
+}
+bool wxWebViewIE::CanPaste()
+{
+ return CanExecCommand("Paste");
+}
+
+void wxWebViewIE::Cut()
+{
+ ExecCommand("Cut");
+}
+
+void wxWebViewIE::Copy()
+{
+ ExecCommand("Copy");
+}
+
+void wxWebViewIE::Paste()
+{
+ ExecCommand("Paste");
+}
+
+bool wxWebViewIE::CanUndo()
+{
+ return CanExecCommand("Undo");
+}
+bool wxWebViewIE::CanRedo()
+{
+ return CanExecCommand("Redo");
+}
+
+void wxWebViewIE::Undo()
+{
+ ExecCommand("Undo");
+}
+
+void wxWebViewIE::Redo()
+{
+ ExecCommand("Redo");
+}
+
+void wxWebViewIE::SetEditable(bool enable)
+{
+ IHTMLDocument2* document = GetDocument();
+ if( enable )
+ document->put_designMode(SysAllocString(L"On"));
+ else
+ document->put_designMode(SysAllocString(L"Off"));
+
+ document->Release();
+}
+
+bool wxWebViewIE::IsEditable()
+{
+ IHTMLDocument2* document = GetDocument();
+ BSTR mode;
+ document->get_designMode(&mode);
+ if(wxString(mode) == "On")
+ return true;
+ else
+ return false;
+
+ document->Release();
+}
+
+void wxWebViewIE::SelectAll()
+{
+ ExecCommand("SelectAll");
+}
+
+bool wxWebViewIE::HasSelection()
+{
+ IHTMLDocument2* document = GetDocument();
+ IHTMLSelectionObject* selection;
+ BSTR type;
+ HRESULT hr = document->get_selection(&selection);
+ if(SUCCEEDED(hr))
+ {
+ selection->get_type(&type);
+ selection->Release();
+ }
+ document->Release();
+ return wxString(type) != "None";
+}
+
+void wxWebViewIE::DeleteSelection()
+{
+ ExecCommand("Delete");
+}
+
+wxString wxWebViewIE::GetSelectedText()
+{
+ IHTMLDocument2* document = GetDocument();
+ IHTMLSelectionObject* selection;
+ wxString selected;
+ HRESULT hr = document->get_selection(&selection);
+ if(SUCCEEDED(hr))
+ {
+ IDispatch* disrange;
+ hr = selection->createRange(&disrange);
+ if(SUCCEEDED(hr))
+ {
+ IHTMLTxtRange* range;
+ hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
+ if(SUCCEEDED(hr))
+ {
+ BSTR text;
+ range->get_text(&text);
+ selected = wxString(text);
+ range->Release();
+ }
+ disrange->Release();
+ }
+ selection->Release();
+ }
+ document->Release();
+ return selected;
+}
+
+bool wxWebViewIE::CanExecCommand(wxString command)
+{
+ IHTMLDocument2* document = GetDocument();
+ VARIANT_BOOL enabled;
+
+ document->queryCommandEnabled(SysAllocString(command.wc_str()), &enabled);
+ document->Release();
+
+ return (enabled == VARIANT_TRUE);
+}
+
+void wxWebViewIE::ExecCommand(wxString command)
+{
+ IHTMLDocument2* document = GetDocument();
+ document->execCommand(SysAllocString(command.wc_str()), VARIANT_FALSE, VARIANT(), NULL);
+ document->Release();
+}
+
+IHTMLDocument2* wxWebViewIE::GetDocument()
+{
+ wxVariant variant = m_ie.GetProperty("Document");
+ IHTMLDocument2* document = (IHTMLDocument2*)variant.GetVoidPtr();
+
+ wxASSERT(document);
+
+ return document;
}
void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
case DISPID_DOCUMENTCOMPLETE:
{
+ //Only send a complete even if we are actually finished, this brings
+ //the event in to line with webkit
+ READYSTATE rs;
+ m_webBrowser->get_ReadyState( &rs );
+ if(rs != READYSTATE_COMPLETE)
+ break;
+
wxString url = evt[1].GetString();
+
+ //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())
+ {
+ //If we are not at the end of the list, then erase everything
+ //between us and the end before adding the new page
+ if(m_historyPosition != static_cast<int>(m_historyList.size()) - 1)
+ {
+ m_historyList.erase(m_historyList.begin() + m_historyPosition + 1,
+ m_historyList.end());
+ }
+ wxSharedPtr<wxWebHistoryItem> item(new wxWebHistoryItem(url, GetCurrentTitle()));
+ m_historyList.push_back(item);
+ m_historyPosition++;
+ }
+ //Reset as we are done now
+ m_historyLoadingFromList = false;
// TODO: set target parameter if possible
wxString target = wxEmptyString;
wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),
}
break;
}
- case DISPID_NEWWINDOW2:
+ case DISPID_NEWWINDOW3:
{
- wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters();
- // Cancel the attempt to open a new window
- *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE;
+ wxString url = evt[4].GetString();
+
+ wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
+ GetId(), url, wxEmptyString, true);
+ 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;
+ }
break;
}
}