Initial implementation of wxWebProtocolHandler and wxWebFileProtocolHandler for the IE backend. This allows browsing of local files and files in zip archives when using a query string which specifies the protocol and path.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/SOC2011_WEBVIEW@68445 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -26,6 +26,20 @@ struct IHTMLDocument2;
|
|||||||
class wxFSFile;
|
class wxFSFile;
|
||||||
class wxFileSystem;
|
class wxFileSystem;
|
||||||
|
|
||||||
|
//Loads from uris such as file:///C:/example/example.html or archives such as
|
||||||
|
//file:///C:/example/example.zip?protocol=zip;path=example.html
|
||||||
|
class WXDLLIMPEXP_WEB wxWebFileProtocolHandler : public wxWebProtocolHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxWebFileProtocolHandler();
|
||||||
|
virtual wxString GetProtocol() { return m_protocol; }
|
||||||
|
virtual wxFSFile* GetFile(const wxString &uri);
|
||||||
|
virtual wxString CombineURIs(const wxString &baseuri, const wxString &newuri);
|
||||||
|
private:
|
||||||
|
wxString m_protocol;
|
||||||
|
wxFileSystem* m_fileSystem;
|
||||||
|
};
|
||||||
|
|
||||||
class WXDLLIMPEXP_WEB wxWebViewIE : public wxWebView
|
class WXDLLIMPEXP_WEB wxWebViewIE : public wxWebView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -111,6 +125,9 @@ public:
|
|||||||
|
|
||||||
virtual void RunScript(const wxString& javascript);
|
virtual void RunScript(const wxString& javascript);
|
||||||
|
|
||||||
|
//Virtual Filesystem Support
|
||||||
|
virtual void RegisterProtocol(wxWebProtocolHandler* hanlder);
|
||||||
|
|
||||||
// ---- IE-specific methods
|
// ---- IE-specific methods
|
||||||
|
|
||||||
// FIXME: I seem to be able to access remote webpages even in offline mode...
|
// FIXME: I seem to be able to access remote webpages even in offline mode...
|
||||||
@@ -167,10 +184,10 @@ protected:
|
|||||||
VOID * fileP;
|
VOID * fileP;
|
||||||
|
|
||||||
wxFSFile* m_file;
|
wxFSFile* m_file;
|
||||||
wxFileSystem* m_fileSys;
|
wxWebProtocolHandler* m_handler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VirtualProtocol();
|
VirtualProtocol(wxWebProtocolHandler *handler);
|
||||||
~VirtualProtocol();
|
~VirtualProtocol();
|
||||||
|
|
||||||
//IUnknown
|
//IUnknown
|
||||||
@@ -228,6 +245,7 @@ class ClassFactory : public IClassFactory
|
|||||||
private:
|
private:
|
||||||
ULONG m_refCount;
|
ULONG m_refCount;
|
||||||
public:
|
public:
|
||||||
|
ClassFactory(wxWebProtocolHandler* handler) : m_handler(handler) {}
|
||||||
//IUnknown
|
//IUnknown
|
||||||
ULONG STDMETHODCALLTYPE AddRef();
|
ULONG STDMETHODCALLTYPE AddRef();
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
|
||||||
@@ -237,6 +255,8 @@ public:
|
|||||||
HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown* pUnkOuter,
|
HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown* pUnkOuter,
|
||||||
REFIID riid, void** ppvObject);
|
REFIID riid, void** ppvObject);
|
||||||
HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);
|
HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);
|
||||||
|
private:
|
||||||
|
wxWebProtocolHandler* m_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // wxUSE_WEBVIEW_IE
|
#endif // wxUSE_WEBVIEW_IE
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
#include "wx/sharedptr.h"
|
#include "wx/sharedptr.h"
|
||||||
#include "wx/vector.h"
|
#include "wx/vector.h"
|
||||||
|
|
||||||
|
class wxFSFile;
|
||||||
|
|
||||||
class WXDLLIMPEXP_WEB wxWebHistoryItem
|
class WXDLLIMPEXP_WEB wxWebHistoryItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -104,6 +106,14 @@ enum wxWebViewBackend
|
|||||||
wxWEB_VIEW_BACKEND_IE
|
wxWEB_VIEW_BACKEND_IE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_WEB wxWebProtocolHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual wxString GetProtocol() = 0;
|
||||||
|
virtual wxFSFile* GetFile(const wxString &uri) = 0;
|
||||||
|
virtual wxString CombineURIs(const wxString &baseuri, const wxString &newuri) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewNameStr[];
|
extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewNameStr[];
|
||||||
extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewDefaultURLStr[];
|
extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewDefaultURLStr[];
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include "wx/msw/registry.h"
|
#include "wx/msw/registry.h"
|
||||||
#include "wx/msw/missing.h"
|
#include "wx/msw/missing.h"
|
||||||
#include "wx/filesys.h"
|
#include "wx/filesys.h"
|
||||||
|
#include "wx/tokenzr.h"
|
||||||
|
|
||||||
//We link to urlmon as it is required for CoInternetGetSession
|
//We link to urlmon as it is required for CoInternetGetSession
|
||||||
#pragma comment(lib, "urlmon")
|
#pragma comment(lib, "urlmon")
|
||||||
@@ -55,6 +56,71 @@ static wxString EscapeFileNameCharsInURL(const char *in)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxWebFileProtocolHandler::wxWebFileProtocolHandler()
|
||||||
|
{
|
||||||
|
m_protocol = "test";
|
||||||
|
m_fileSystem = new wxFileSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxFSFile* wxWebFileProtocolHandler::GetFile(const wxString &uri)
|
||||||
|
{
|
||||||
|
size_t pos = uri.find('?');
|
||||||
|
//There is no query string so we can load the file directly
|
||||||
|
if(pos == wxString::npos)
|
||||||
|
{
|
||||||
|
size_t doubleslash = uri.find("//");
|
||||||
|
//The path is incorrectly formed without // after the first protocol
|
||||||
|
if(doubleslash == wxString::npos)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wxString fspath = "file:" +
|
||||||
|
EscapeFileNameCharsInURL(uri.substr(doubleslash + 2));
|
||||||
|
return m_fileSystem->OpenFile(fspath);
|
||||||
|
}
|
||||||
|
//Otherwise we have a query string of some kind that we need to extract
|
||||||
|
else{
|
||||||
|
//First we extract the query string, this should have two parameters,
|
||||||
|
//protocol=type and path=path
|
||||||
|
wxString query = uri.substr(pos + 1), protocol, path;
|
||||||
|
//We also trim the query off the end as we handle it alone
|
||||||
|
wxString lefturi = uri.substr(0, pos);
|
||||||
|
wxStringTokenizer tokenizer(query, ";");
|
||||||
|
while(tokenizer.HasMoreTokens() && (protocol == "" || path == ""))
|
||||||
|
{
|
||||||
|
wxString token = tokenizer.GetNextToken();
|
||||||
|
if(token.substr(0, 9) == "protocol=")
|
||||||
|
{
|
||||||
|
protocol = token.substr(9);
|
||||||
|
}
|
||||||
|
else if(token.substr(0, 5) == "path=")
|
||||||
|
{
|
||||||
|
path = token.substr(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(protocol == "" || path == "")
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
//We now have the path and the protocol and so can format a correct uri
|
||||||
|
//to pass to wxFileSystem to get a wxFSFile
|
||||||
|
size_t doubleslash = uri.find("//");
|
||||||
|
//The path is incorrectly formed without // after the first protocol
|
||||||
|
if(doubleslash == wxString::npos)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wxString fspath = "file:" +
|
||||||
|
EscapeFileNameCharsInURL(lefturi.substr(doubleslash + 2))
|
||||||
|
+ "#" + protocol +":" + path;
|
||||||
|
return m_fileSystem->OpenFile(fspath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString wxWebFileProtocolHandler::CombineURIs(const wxString &baseuri,
|
||||||
|
const wxString &newuri)
|
||||||
|
{
|
||||||
|
//Still need to be implemented correctly
|
||||||
|
return newuri;
|
||||||
|
}
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(wxWebViewIE, wxControl)
|
BEGIN_EVENT_TABLE(wxWebViewIE, wxControl)
|
||||||
EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent)
|
EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent)
|
||||||
EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg)
|
EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg)
|
||||||
@@ -93,17 +159,9 @@ bool wxWebViewIE::Create(wxWindow* parent,
|
|||||||
|
|
||||||
m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
|
m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
|
||||||
m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
|
m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
|
||||||
//m_webBrowser->put_Silent(VARIANT_FALSE);
|
|
||||||
|
|
||||||
//We register a custom handler for the file protocol so we can handle
|
//For testing purposes
|
||||||
//Virtual file systems
|
RegisterProtocol(new wxWebFileProtocolHandler());
|
||||||
ClassFactory* cf = new ClassFactory;
|
|
||||||
IInternetSession* session;
|
|
||||||
if(CoInternetGetSession(0, &session, 0) != S_OK)
|
|
||||||
return false;
|
|
||||||
HRESULT hr = session->RegisterNameSpace(cf, CLSID_FileProtocol, L"test", 0, NULL, 0);
|
|
||||||
if(FAILED(hr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser);
|
m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser);
|
||||||
|
|
||||||
@@ -699,6 +757,22 @@ void wxWebViewIE::RunScript(const wxString& javascript)
|
|||||||
document->Release();
|
document->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxWebViewIE::RegisterProtocol(wxWebProtocolHandler* 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->GetProtocol(), 0, NULL, 0);
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
wxFAIL_MSG("Could not register protocol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool wxWebViewIE::CanExecCommand(wxString command)
|
bool wxWebViewIE::CanExecCommand(wxString command)
|
||||||
{
|
{
|
||||||
IHTMLDocument2* document = GetDocument();
|
IHTMLDocument2* document = GetDocument();
|
||||||
@@ -970,16 +1044,15 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
|
|||||||
evt.Skip();
|
evt.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualProtocol::VirtualProtocol()
|
VirtualProtocol::VirtualProtocol(wxWebProtocolHandler *handler)
|
||||||
{
|
{
|
||||||
m_refCount = 0;
|
m_refCount = 0;
|
||||||
m_file = NULL;
|
m_file = NULL;
|
||||||
m_fileSys = new wxFileSystem;
|
m_handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualProtocol::~VirtualProtocol()
|
VirtualProtocol::~VirtualProtocol()
|
||||||
{
|
{
|
||||||
wxDELETE(m_fileSys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG VirtualProtocol::AddRef()
|
ULONG VirtualProtocol::AddRef()
|
||||||
@@ -990,8 +1063,8 @@ ULONG VirtualProtocol::AddRef()
|
|||||||
|
|
||||||
HRESULT VirtualProtocol::QueryInterface(REFIID riid, void **ppvObject)
|
HRESULT VirtualProtocol::QueryInterface(REFIID riid, void **ppvObject)
|
||||||
{
|
{
|
||||||
if(riid == IID_IUnknown || riid == IID_IInternetProtocol
|
if(riid == IID_IUnknown || riid == IID_IInternetProtocolRoot ||
|
||||||
|| riid == IID_IInternetProtocolRoot)
|
riid == IID_IInternetProtocol)
|
||||||
{
|
{
|
||||||
*ppvObject = (IInternetProtocol*)this;
|
*ppvObject = (IInternetProtocol*)this;
|
||||||
AddRef();
|
AddRef();
|
||||||
@@ -1033,13 +1106,10 @@ HRESULT VirtualProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink
|
|||||||
wxUnusedVar(grfPI);
|
wxUnusedVar(grfPI);
|
||||||
wxUnusedVar(dwReserved);
|
wxUnusedVar(dwReserved);
|
||||||
m_protocolSink = pOIProtSink;
|
m_protocolSink = pOIProtSink;
|
||||||
//We have to clean up incoming paths from the webview control as they are
|
|
||||||
//not properly escaped, see also the comment in filesys.cpp line 668
|
//We get the file itself from the protocol handler
|
||||||
wxString path = wxString(szUrl).BeforeFirst(':') + ":" +
|
m_file = m_handler->GetFile(szUrl);
|
||||||
EscapeFileNameCharsInURL(wxString(szUrl).AfterFirst(':'));
|
|
||||||
path.Replace("///", "/");
|
|
||||||
path.Replace("test", "file");
|
|
||||||
m_file = m_fileSys->OpenFile(path);
|
|
||||||
|
|
||||||
if(!m_file)
|
if(!m_file)
|
||||||
return INET_E_RESOURCE_NOT_FOUND;
|
return INET_E_RESOURCE_NOT_FOUND;
|
||||||
@@ -1106,7 +1176,10 @@ HRESULT VirtualProtocol::ParseUrl(LPCWSTR pwzUrl, PARSEACTION ParseAction,
|
|||||||
DWORD cchResult, DWORD *pcchResult,
|
DWORD cchResult, DWORD *pcchResult,
|
||||||
DWORD dwReserved)
|
DWORD dwReserved)
|
||||||
{
|
{
|
||||||
return INET_E_DEFAULT_ACTION;
|
//return INET_E_DEFAULT_ACTION;
|
||||||
|
wcscpy(pwzResult, pwzUrl);
|
||||||
|
*pcchResult = wcslen(pwzResult);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT VirtualProtocol::QueryInfo(LPCWSTR pwzUrl, QUERYOPTION OueryOption,
|
HRESULT VirtualProtocol::QueryInfo(LPCWSTR pwzUrl, QUERYOPTION OueryOption,
|
||||||
@@ -1122,7 +1195,7 @@ HRESULT ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid,
|
|||||||
{
|
{
|
||||||
if (pUnkOuter)
|
if (pUnkOuter)
|
||||||
return CLASS_E_NOAGGREGATION;
|
return CLASS_E_NOAGGREGATION;
|
||||||
VirtualProtocol* vp = new VirtualProtocol;
|
VirtualProtocol* vp = new VirtualProtocol(m_handler);
|
||||||
vp->AddRef();
|
vp->AddRef();
|
||||||
HRESULT hr = vp->QueryInterface(riid, ppvObject);
|
HRESULT hr = vp->QueryInterface(riid, ppvObject);
|
||||||
vp->Release();
|
vp->Release();
|
||||||
|
Reference in New Issue
Block a user