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 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
|
||||
{
|
||||
public:
|
||||
@@ -111,6 +125,9 @@ public:
|
||||
|
||||
virtual void RunScript(const wxString& javascript);
|
||||
|
||||
//Virtual Filesystem Support
|
||||
virtual void RegisterProtocol(wxWebProtocolHandler* hanlder);
|
||||
|
||||
// ---- IE-specific methods
|
||||
|
||||
// FIXME: I seem to be able to access remote webpages even in offline mode...
|
||||
@@ -167,10 +184,10 @@ protected:
|
||||
VOID * fileP;
|
||||
|
||||
wxFSFile* m_file;
|
||||
wxFileSystem* m_fileSys;
|
||||
wxWebProtocolHandler* m_handler;
|
||||
|
||||
public:
|
||||
VirtualProtocol();
|
||||
VirtualProtocol(wxWebProtocolHandler *handler);
|
||||
~VirtualProtocol();
|
||||
|
||||
//IUnknown
|
||||
@@ -228,6 +245,7 @@ class ClassFactory : public IClassFactory
|
||||
private:
|
||||
ULONG m_refCount;
|
||||
public:
|
||||
ClassFactory(wxWebProtocolHandler* handler) : m_handler(handler) {}
|
||||
//IUnknown
|
||||
ULONG STDMETHODCALLTYPE AddRef();
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
|
||||
@@ -237,6 +255,8 @@ public:
|
||||
HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown* pUnkOuter,
|
||||
REFIID riid, void** ppvObject);
|
||||
HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);
|
||||
private:
|
||||
wxWebProtocolHandler* m_handler;
|
||||
};
|
||||
|
||||
#endif // wxUSE_WEBVIEW_IE
|
||||
|
@@ -20,6 +20,8 @@
|
||||
#include "wx/sharedptr.h"
|
||||
#include "wx/vector.h"
|
||||
|
||||
class wxFSFile;
|
||||
|
||||
class WXDLLIMPEXP_WEB wxWebHistoryItem
|
||||
{
|
||||
public:
|
||||
@@ -104,6 +106,14 @@ enum wxWebViewBackend
|
||||
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) wxWebViewDefaultURLStr[];
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "wx/msw/registry.h"
|
||||
#include "wx/msw/missing.h"
|
||||
#include "wx/filesys.h"
|
||||
#include "wx/tokenzr.h"
|
||||
|
||||
//We link to urlmon as it is required for CoInternetGetSession
|
||||
#pragma comment(lib, "urlmon")
|
||||
@@ -55,6 +56,71 @@ static wxString EscapeFileNameCharsInURL(const char *in)
|
||||
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)
|
||||
EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent)
|
||||
EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg)
|
||||
@@ -93,17 +159,9 @@ bool wxWebViewIE::Create(wxWindow* parent,
|
||||
|
||||
m_webBrowser->put_RegisterAsBrowser(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
|
||||
//Virtual file systems
|
||||
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;
|
||||
//For testing purposes
|
||||
RegisterProtocol(new wxWebFileProtocolHandler());
|
||||
|
||||
m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser);
|
||||
|
||||
@@ -699,6 +757,22 @@ void wxWebViewIE::RunScript(const wxString& javascript)
|
||||
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)
|
||||
{
|
||||
IHTMLDocument2* document = GetDocument();
|
||||
@@ -970,16 +1044,15 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
VirtualProtocol::VirtualProtocol()
|
||||
VirtualProtocol::VirtualProtocol(wxWebProtocolHandler *handler)
|
||||
{
|
||||
m_refCount = 0;
|
||||
m_file = NULL;
|
||||
m_fileSys = new wxFileSystem;
|
||||
m_handler = handler;
|
||||
}
|
||||
|
||||
VirtualProtocol::~VirtualProtocol()
|
||||
{
|
||||
wxDELETE(m_fileSys);
|
||||
}
|
||||
|
||||
ULONG VirtualProtocol::AddRef()
|
||||
@@ -990,8 +1063,8 @@ ULONG VirtualProtocol::AddRef()
|
||||
|
||||
HRESULT VirtualProtocol::QueryInterface(REFIID riid, void **ppvObject)
|
||||
{
|
||||
if(riid == IID_IUnknown || riid == IID_IInternetProtocol
|
||||
|| riid == IID_IInternetProtocolRoot)
|
||||
if(riid == IID_IUnknown || riid == IID_IInternetProtocolRoot ||
|
||||
riid == IID_IInternetProtocol)
|
||||
{
|
||||
*ppvObject = (IInternetProtocol*)this;
|
||||
AddRef();
|
||||
@@ -1033,13 +1106,10 @@ HRESULT VirtualProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink
|
||||
wxUnusedVar(grfPI);
|
||||
wxUnusedVar(dwReserved);
|
||||
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
|
||||
wxString path = wxString(szUrl).BeforeFirst(':') + ":" +
|
||||
EscapeFileNameCharsInURL(wxString(szUrl).AfterFirst(':'));
|
||||
path.Replace("///", "/");
|
||||
path.Replace("test", "file");
|
||||
m_file = m_fileSys->OpenFile(path);
|
||||
|
||||
//We get the file itself from the protocol handler
|
||||
m_file = m_handler->GetFile(szUrl);
|
||||
|
||||
|
||||
if(!m_file)
|
||||
return INET_E_RESOURCE_NOT_FOUND;
|
||||
@@ -1106,7 +1176,10 @@ HRESULT VirtualProtocol::ParseUrl(LPCWSTR pwzUrl, PARSEACTION ParseAction,
|
||||
DWORD cchResult, DWORD *pcchResult,
|
||||
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,
|
||||
@@ -1122,7 +1195,7 @@ HRESULT ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid,
|
||||
{
|
||||
if (pUnkOuter)
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
VirtualProtocol* vp = new VirtualProtocol;
|
||||
VirtualProtocol* vp = new VirtualProtocol(m_handler);
|
||||
vp->AddRef();
|
||||
HRESULT hr = vp->QueryInterface(riid, ppvObject);
|
||||
vp->Release();
|
||||
|
Reference in New Issue
Block a user