]> git.saurik.com Git - wxWidgets.git/commitdiff
Initial implementation of wxWebProtocolHandler and wxWebFileProtocolHandler for the...
authorSteve Lamerton <steve.lamerton@gmail.com>
Thu, 28 Jul 2011 16:08:59 +0000 (16:08 +0000)
committerSteve Lamerton <steve.lamerton@gmail.com>
Thu, 28 Jul 2011 16:08:59 +0000 (16:08 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/SOC2011_WEBVIEW@68445 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/webview_ie.h
include/wx/webview.h
src/msw/webview_ie.cpp

index b9d9bcfb262cc6b28be3aa7c30dacdc3263372af..68dd4d712164c017bb38fa483f4d21a21b0a063f 100644 (file)
@@ -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
index ed94c826114f8955506d06960ae6e0cb53879996..2218a2aee8dd65b4419834a2bab305ac73f37e12 100644 (file)
@@ -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[];
 
index 761e9cc2698c3567831b9784930ceca58c59b889..8d9c8f974f7fdda3f1d5d19d6caec9ef9eadddd2 100644 (file)
@@ -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();