1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Common interface and events for web view component
4 // Author: Marianne Gagnon
6 // Copyright: (c) 2010 Marianne Gagnon
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
15 #if defined(__BORLANDC__)
19 #include "wx/webview.h"
21 #include "wx/osx/webview_webkit.h"
22 #include "wx/gtk/webview_webkit.h"
23 #include "wx/msw/webview_ie.h"
24 #include "wx/filesys.h"
25 #include "wx/tokenzr.h"
27 // DLL options compatibility check:
29 WX_CHECK_BUILD_OPTIONS("wxWEB")
31 extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewNameStr
[] = "wxWebView";
32 extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewDefaultURLStr
[] = "about:blank";
34 IMPLEMENT_DYNAMIC_CLASS(wxWebNavigationEvent
, wxCommandEvent
)
36 wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATING
, wxWebNavigationEvent
);
37 wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATED
, wxWebNavigationEvent
);
38 wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_LOADED
, wxWebNavigationEvent
);
39 wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_ERROR
, wxWebNavigationEvent
);
40 wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_NEWWINDOW
, wxWebNavigationEvent
);
42 //Taken from wx/filesys.cpp
43 static wxString
EscapeFileNameCharsInURL(const char *in
)
47 for ( const unsigned char *p
= (const unsigned char*)in
; *p
; ++p
)
49 const unsigned char c
= *p
;
51 if ( c
== '/' || c
== '-' || c
== '.' || c
== '_' || c
== '~' ||
52 (c
>= '0' && c
<= '9') ||
53 (c
>= 'a' && c
<= 'z') ||
54 (c
>= 'A' && c
<= 'Z') )
60 s
<< wxString::Format("%%%02x", c
);
67 wxWebFileProtocolHandler::wxWebFileProtocolHandler()
70 m_fileSystem
= new wxFileSystem();
73 wxFSFile
* wxWebFileProtocolHandler::GetFile(const wxString
&uri
)
75 size_t pos
= uri
.find('?');
76 //There is no query string so we can load the file directly
77 if(pos
== wxString::npos
)
79 size_t doubleslash
= uri
.find("//");
80 //The path is incorrectly formed without // after the first protocol
81 if(doubleslash
== wxString::npos
)
84 wxString fspath
= "file:" +
85 EscapeFileNameCharsInURL(uri
.substr(doubleslash
+ 2));
86 return m_fileSystem
->OpenFile(fspath
);
88 //Otherwise we have a query string of some kind that we need to extract
90 //First we extract the query string, this should have two parameters,
91 //protocol=type and path=path
92 wxString query
= uri
.substr(pos
+ 1), protocol
, path
;
93 //We also trim the query off the end as we handle it alone
94 wxString lefturi
= uri
.substr(0, pos
);
95 wxStringTokenizer
tokenizer(query
, ";");
96 while(tokenizer
.HasMoreTokens() && (protocol
== "" || path
== ""))
98 wxString token
= tokenizer
.GetNextToken();
99 if(token
.substr(0, 9) == "protocol=")
101 protocol
= token
.substr(9);
103 else if(token
.substr(0, 5) == "path=")
105 path
= token
.substr(5);
108 if(protocol
== "" || path
== "")
111 //We now have the path and the protocol and so can format a correct uri
112 //to pass to wxFileSystem to get a wxFSFile
113 size_t doubleslash
= uri
.find("//");
114 //The path is incorrectly formed without // after the first protocol
115 if(doubleslash
== wxString::npos
)
118 wxString fspath
= "file:" +
119 EscapeFileNameCharsInURL(lefturi
.substr(doubleslash
+ 2))
120 + "#" + protocol
+":" + path
;
121 return m_fileSystem
->OpenFile(fspath
);
125 wxString
wxWebFileProtocolHandler::CombineURIs(const wxString
&baseuri
,
126 const wxString
&newuri
)
128 //If there is a colon in the path then we just return it
129 if(newuri
.find(':') != wxString::npos
)
133 //We have an absolute path and no query string
134 else if(newuri
.substr(0, 1) == "/" && baseuri
.find('?') == wxString::npos
)
136 //By finding the next / after file:// we get to the end of the
137 //(optional) hostname
138 size_t pos
= baseuri
.find('/', 7);
139 //So we return up to the end of the hostname, plus the newuri
140 return baseuri
.substr(0, pos
) + newuri
;
142 //We have an absolute path and a query string
143 else if(newuri
.substr(0, 1) == "/" && baseuri
.find('?') != wxString::npos
)
145 wxString query
= baseuri
.substr(baseuri
.find('?') + 1);
147 wxStringTokenizer
tokenizer(query
, ";");
148 while(tokenizer
.HasMoreTokens())
150 wxString token
= tokenizer
.GetNextToken();
151 if(token
.substr(0, 5) == "path=")
153 //As the path is absolue simply replace the old path with the
155 newquery
= newquery
+ "path=" + newuri
;
161 //We need to add the separators back
162 if(tokenizer
.HasMoreTokens())
165 return baseuri
.substr(0, baseuri
.find('?')) + "?" + newquery
;
167 //We have a relative path and no query string
168 else if(baseuri
.find('?') == wxString::npos
)
170 //By finding the next / after file:// we get to the end of the
171 //(optional) hostname
172 size_t pos
= baseuri
.find('/', 7);
173 wxString path
= baseuri
.substr(pos
);
174 //Then we remove the last filename
175 path
= path
.BeforeLast('/') + '/';
176 //Ensure that we have the leading / so we can normalise properly
177 if(path
.substr(0, 1) != "/")
180 //If we have a colon in the path (i.e. we are on windows) we need to
181 //handle it specially
182 if(path
.find(':') != wxString::npos
)
184 wxFileName
fn(path
.AfterFirst('/').AfterFirst('/') + newuri
);
185 fn
.Normalize(wxPATH_NORM_DOTS
, "", wxPATH_UNIX
);
186 return baseuri
.substr(0, pos
) + '/' +
187 path
.AfterFirst('/').BeforeFirst('/') + '/' +
188 fn
.GetFullPath(wxPATH_UNIX
);
192 //We can now use wxFileName to perform the normalisation
193 wxFileName
fn(path
+ newuri
);
194 fn
.Normalize(wxPATH_NORM_DOTS
, "", wxPATH_UNIX
);
195 return baseuri
.substr(0, pos
) + fn
.GetFullPath(wxPATH_UNIX
);
198 //We have a relative path and a query string
201 wxString query
= baseuri
.substr(baseuri
.find('?') + 1);
203 wxStringTokenizer
tokenizer(query
, ";");
204 while(tokenizer
.HasMoreTokens())
206 wxString token
= tokenizer
.GetNextToken();
207 if(token
.substr(0, 5) == "path=")
209 wxString path
= token
.substr(6);
210 //Then we remove the last filename
211 path
= path
.BeforeLast('/') + '/';
212 //Ensure that we have the leading / so we can normalise properly
213 //if(path.substr(0, 1) != "/")
214 // path = "/" + path;
216 //We can now use wxFileName to perform the normalisation
217 wxFileName
fn(path
+ newuri
);
218 fn
.Normalize(wxPATH_NORM_DOTS
, "", wxPATH_UNIX
);
219 newquery
= newquery
+ "path=" + fn
.GetFullPath(wxPATH_UNIX
);
225 //We need to add the separators back
226 if(tokenizer
.HasMoreTokens())
229 return baseuri
.substr(0, baseuri
.find('?')) + "?" + newquery
;
234 wxWebView
* wxWebView::New(wxWebViewBackend backend
)
238 #if defined(wxUSE_WEBVIEW_WEBKIT) && \
239 (defined(__WXGTK__) || defined(__WXOSX__))
240 case wxWEB_VIEW_BACKEND_WEBKIT
:
241 return new wxWebViewWebKit();
245 case wxWEB_VIEW_BACKEND_IE
:
246 return new wxWebViewIE();
249 case wxWEB_VIEW_BACKEND_DEFAULT
:
251 #if defined(wxUSE_WEBVIEW_WEBKIT) && \
252 (defined(__WXGTK__) || defined(__WXOSX__))
253 return new wxWebViewWebKit();
257 return new wxWebViewIE();
260 // fall-through intended
267 wxWebView
* wxWebView::New(wxWindow
* parent
,
272 wxWebViewBackend backend
,
274 const wxString
& name
)
278 #if defined(wxUSE_WEBVIEW_WEBKIT) && \
279 (defined(__WXGTK__) || defined(__WXOSX__))
280 case wxWEB_VIEW_BACKEND_WEBKIT
:
281 return new wxWebViewWebKit(parent
, id
, url
, pos
, size
, style
, name
);
285 case wxWEB_VIEW_BACKEND_IE
:
286 return new wxWebViewIE(parent
, id
, url
, pos
, size
, style
, name
);
289 case wxWEB_VIEW_BACKEND_DEFAULT
:
291 #if defined(wxUSE_WEBVIEW_WEBKIT) && \
292 (defined(__WXGTK__) || defined(__WXOSX__))
293 return new wxWebViewWebKit(parent
, id
, url
, pos
, size
, style
, name
);
297 return new wxWebViewIE(parent
, id
, url
, pos
, size
, style
, name
);
300 // fall-through intended