]> git.saurik.com Git - wxWidgets.git/blob - src/common/webview.cpp
Add CombineURIs implementation for wxWebFileProtocolHandler. Update the IE backend...
[wxWidgets.git] / src / common / webview.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: webview.cpp
3 // Purpose: Common interface and events for web view component
4 // Author: Marianne Gagnon
5 // Id: $Id$
6 // Copyright: (c) 2010 Marianne Gagnon
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
12
13 #if wxUSE_WEB
14
15 #if defined(__BORLANDC__)
16 #pragma hdrstop
17 #endif
18
19 #include "wx/webview.h"
20
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"
26
27 // DLL options compatibility check:
28 #include "wx/app.h"
29 WX_CHECK_BUILD_OPTIONS("wxWEB")
30
31 extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewNameStr[] = "wxWebView";
32 extern WXDLLIMPEXP_DATA_WEB(const char) wxWebViewDefaultURLStr[] = "about:blank";
33
34 IMPLEMENT_DYNAMIC_CLASS(wxWebNavigationEvent, wxCommandEvent)
35
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 );
41
42 //Taken from wx/filesys.cpp
43 static wxString EscapeFileNameCharsInURL(const char *in)
44 {
45 wxString s;
46
47 for ( const unsigned char *p = (const unsigned char*)in; *p; ++p )
48 {
49 const unsigned char c = *p;
50
51 if ( c == '/' || c == '-' || c == '.' || c == '_' || c == '~' ||
52 (c >= '0' && c <= '9') ||
53 (c >= 'a' && c <= 'z') ||
54 (c >= 'A' && c <= 'Z') )
55 {
56 s << c;
57 }
58 else
59 {
60 s << wxString::Format("%%%02x", c);
61 }
62 }
63
64 return s;
65 }
66
67 wxWebFileProtocolHandler::wxWebFileProtocolHandler()
68 {
69 m_protocol = "test";
70 m_fileSystem = new wxFileSystem();
71 }
72
73 wxFSFile* wxWebFileProtocolHandler::GetFile(const wxString &uri)
74 {
75 size_t pos = uri.find('?');
76 //There is no query string so we can load the file directly
77 if(pos == wxString::npos)
78 {
79 size_t doubleslash = uri.find("//");
80 //The path is incorrectly formed without // after the first protocol
81 if(doubleslash == wxString::npos)
82 return NULL;
83
84 wxString fspath = "file:" +
85 EscapeFileNameCharsInURL(uri.substr(doubleslash + 2));
86 return m_fileSystem->OpenFile(fspath);
87 }
88 //Otherwise we have a query string of some kind that we need to extract
89 else{
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 == ""))
97 {
98 wxString token = tokenizer.GetNextToken();
99 if(token.substr(0, 9) == "protocol=")
100 {
101 protocol = token.substr(9);
102 }
103 else if(token.substr(0, 5) == "path=")
104 {
105 path = token.substr(5);
106 }
107 }
108 if(protocol == "" || path == "")
109 return NULL;
110
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)
116 return NULL;
117
118 wxString fspath = "file:" +
119 EscapeFileNameCharsInURL(lefturi.substr(doubleslash + 2))
120 + "#" + protocol +":" + path;
121 return m_fileSystem->OpenFile(fspath);
122 }
123 }
124
125 wxString wxWebFileProtocolHandler::CombineURIs(const wxString &baseuri,
126 const wxString &newuri)
127 {
128 //If there is a colon in the path then we just return it
129 if(newuri.find(':') != wxString::npos)
130 {
131 return newuri;
132 }
133 //We have an absolute path and no query string
134 else if(newuri.substr(0, 1) == "/" && baseuri.find('?') == wxString::npos)
135 {
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;
141 }
142 //We have an absolute path and a query string
143 else if(newuri.substr(0, 1) == "/" && baseuri.find('?') != wxString::npos)
144 {
145 wxString query = baseuri.substr(baseuri.find('?') + 1);
146 wxString newquery;
147 wxStringTokenizer tokenizer(query, ";");
148 while(tokenizer.HasMoreTokens())
149 {
150 wxString token = tokenizer.GetNextToken();
151 if(token.substr(0, 5) == "path=")
152 {
153 //As the path is absolue simply replace the old path with the
154 //new one
155 newquery = newquery + "path=" + newuri;
156 }
157 else
158 {
159 newquery += token;
160 }
161 //We need to add the separators back
162 if(tokenizer.HasMoreTokens())
163 newquery += ';';
164 }
165 return baseuri.substr(0, baseuri.find('?')) + "?" + newquery;
166 }
167 //We have a relative path and no query string
168 else if(baseuri.find('?') == wxString::npos)
169 {
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) != "/")
178 path = "/" + path;
179
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)
183 {
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);
189 }
190 else
191 {
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);
196 }
197 }
198 //We have a relative path and a query string
199 else
200 {
201 wxString query = baseuri.substr(baseuri.find('?') + 1);
202 wxString newquery;
203 wxStringTokenizer tokenizer(query, ";");
204 while(tokenizer.HasMoreTokens())
205 {
206 wxString token = tokenizer.GetNextToken();
207 if(token.substr(0, 5) == "path=")
208 {
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;
215
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);
220 }
221 else
222 {
223 newquery += token;
224 }
225 //We need to add the separators back
226 if(tokenizer.HasMoreTokens())
227 newquery += ';';
228 }
229 return baseuri.substr(0, baseuri.find('?')) + "?" + newquery;
230 }
231 }
232
233 // static
234 wxWebView* wxWebView::New(wxWebViewBackend backend)
235 {
236 switch (backend)
237 {
238 #if defined(wxUSE_WEBVIEW_WEBKIT) && \
239 (defined(__WXGTK__) || defined(__WXOSX__))
240 case wxWEB_VIEW_BACKEND_WEBKIT:
241 return new wxWebViewWebKit();
242 #endif
243
244 #if wxUSE_WEBVIEW_IE
245 case wxWEB_VIEW_BACKEND_IE:
246 return new wxWebViewIE();
247 #endif
248
249 case wxWEB_VIEW_BACKEND_DEFAULT:
250
251 #if defined(wxUSE_WEBVIEW_WEBKIT) && \
252 (defined(__WXGTK__) || defined(__WXOSX__))
253 return new wxWebViewWebKit();
254 #endif
255
256 #if wxUSE_WEBVIEW_IE
257 return new wxWebViewIE();
258 #endif
259
260 // fall-through intended
261 default:
262 return NULL;
263 }
264 }
265
266 // static
267 wxWebView* wxWebView::New(wxWindow* parent,
268 wxWindowID id,
269 const wxString& url,
270 const wxPoint& pos,
271 const wxSize& size,
272 wxWebViewBackend backend,
273 long style,
274 const wxString& name)
275 {
276 switch (backend)
277 {
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);
282 #endif
283
284 #if wxUSE_WEBVIEW_IE
285 case wxWEB_VIEW_BACKEND_IE:
286 return new wxWebViewIE(parent, id, url, pos, size, style, name);
287 #endif
288
289 case wxWEB_VIEW_BACKEND_DEFAULT:
290
291 #if defined(wxUSE_WEBVIEW_WEBKIT) && \
292 (defined(__WXGTK__) || defined(__WXOSX__))
293 return new wxWebViewWebKit(parent, id, url, pos, size, style, name);
294 #endif
295
296 #if wxUSE_WEBVIEW_IE
297 return new wxWebViewIE(parent, id, url, pos, size, style, name);
298 #endif
299
300 // fall-through intended
301 default:
302 return NULL;
303 }
304 }
305
306 #endif // wxUSE_WEB