]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/webview_webkit.cpp
Added wxRichTextXMLHandler::RegisterNodeName so custom content classes can be added...
[wxWidgets.git] / src / gtk / webview_webkit.cpp
CommitLineData
61b98a2d 1/////////////////////////////////////////////////////////////////////////////
8290e3cd 2// Name: src/gtk/webview_webkit.cpp
61b98a2d
SL
3// Purpose: GTK WebKit backend for web view component
4// Author: Marianne Gagnon, Robert Roebling
5// Id: $Id$
6// Copyright: (c) 2010 Marianne Gagnon, 1998 Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
9d2f31db 13#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT
61b98a2d
SL
14
15#include "wx/stockitem.h"
8290e3cd 16#include "wx/gtk/webview_webkit.h"
61b98a2d
SL
17#include "wx/gtk/control.h"
18#include "wx/gtk/private.h"
f2049b68 19#include "wx/filesys.h"
eea4d01c 20#include "wx/base64.h"
a0ff3611 21#include <webkit/webkit.h>
61b98a2d
SL
22
23// ----------------------------------------------------------------------------
24// GTK callbacks
25// ----------------------------------------------------------------------------
26
27extern "C"
28{
29
30static void
34326da7 31wxgtk_webview_webkit_load_status(GtkWidget* widget,
d363c7db
SL
32 GParamSpec*,
33 wxWebViewWebKit *webKitCtrl)
61b98a2d 34{
61b98a2d
SL
35 wxString url = webKitCtrl->GetCurrentURL();
36
37 WebKitLoadStatus status;
38 g_object_get(G_OBJECT(widget), "load-status", &status, NULL);
39
40 wxString target; // TODO: get target (if possible)
41
42 if (status == WEBKIT_LOAD_FINISHED)
43 {
ce88a107
SL
44 WebKitWebBackForwardList* hist = webkit_web_view_get_back_forward_list(WEBKIT_WEB_VIEW(widget));
45 WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_current_item(hist);
46 //We have to check if we are actually storing history
47 //If the item isn't added we add it ourselves, it isn't added otherwise
48 //with a custom scheme.
49 if(WEBKIT_IS_WEB_HISTORY_ITEM(item) && webkit_web_history_item_get_uri(item) != url)
50 {
f0776dc4
VZ
51 WebKitWebHistoryItem*
52 newitem = webkit_web_history_item_new_with_data
53 (
54 url.utf8_str(),
55 webKitCtrl->GetCurrentTitle().utf8_str()
56 );
ce88a107
SL
57 webkit_web_back_forward_list_add_item(hist, newitem);
58 }
59
61b98a2d 60 webKitCtrl->m_busy = false;
04fa04d8
SL
61 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED,
62 webKitCtrl->GetId(),
3225a4b8 63 url, target);
61b98a2d
SL
64
65 if (webKitCtrl && webKitCtrl->GetEventHandler())
04fa04d8 66 webKitCtrl->GetEventHandler()->ProcessEvent(event);
61b98a2d
SL
67 }
68 else if (status == WEBKIT_LOAD_COMMITTED)
69 {
70 webKitCtrl->m_busy = true;
04fa04d8
SL
71 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
72 webKitCtrl->GetId(),
3225a4b8 73 url, target);
61b98a2d
SL
74
75 if (webKitCtrl && webKitCtrl->GetEventHandler())
04fa04d8 76 webKitCtrl->GetEventHandler()->ProcessEvent(event);
61b98a2d
SL
77 }
78}
79
780f7262 80static gboolean
36b52591 81wxgtk_webview_webkit_navigation(WebKitWebView *,
780f7262
SL
82 WebKitWebFrame *frame,
83 WebKitNetworkRequest *request,
153530af 84 WebKitWebNavigationAction *,
780f7262
SL
85 WebKitWebPolicyDecision *policy_decision,
86 wxWebViewWebKit *webKitCtrl)
61b98a2d 87{
36b52591
SL
88 if(webKitCtrl->m_guard)
89 {
90 webKitCtrl->m_guard = false;
34326da7 91 //We set this to make sure that we don't try to load the page again from
211da8a5
SL
92 //the resource request callback
93 webKitCtrl->m_vfsurl = webkit_network_request_get_uri(request);
94 webkit_web_policy_decision_use(policy_decision);
36b52591
SL
95 return FALSE;
96 }
97
61b98a2d
SL
98 webKitCtrl->m_busy = true;
99
100 const gchar* uri = webkit_network_request_get_uri(request);
101
102 wxString target = webkit_web_frame_get_name (frame);
04fa04d8
SL
103 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
104 webKitCtrl->GetId(),
105 wxString( uri, wxConvUTF8 ),
3225a4b8 106 target);
61b98a2d
SL
107
108 if (webKitCtrl && webKitCtrl->GetEventHandler())
04fa04d8 109 webKitCtrl->GetEventHandler()->ProcessEvent(event);
61b98a2d 110
3225a4b8 111 if (!event.IsAllowed())
61b98a2d
SL
112 {
113 webKitCtrl->m_busy = false;
780f7262
SL
114 webkit_web_policy_decision_ignore(policy_decision);
115 return TRUE;
61b98a2d
SL
116 }
117 else
118 {
f2049b68 119 wxString wxuri = uri;
7d8d6163
SL
120 wxSharedPtr<wxWebViewHandler> handler;
121 wxVector<wxSharedPtr<wxWebViewHandler> > hanlders = webKitCtrl->GetHandlers();
f2049b68 122 //We are not vetoed so see if we match one of the additional handlers
7d8d6163 123 for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = hanlders.begin();
f2049b68
SL
124 it != hanlders.end(); ++it)
125 {
126 if(wxuri.substr(0, (*it)->GetName().length()) == (*it)->GetName())
127 {
128 handler = (*it);
129 }
130 }
34326da7 131 //If we found a handler we can then use it to load the file directly
f2049b68
SL
132 //ourselves
133 if(handler)
134 {
36b52591 135 webKitCtrl->m_guard = true;
f2049b68 136 wxFSFile* file = handler->GetFile(wxuri);
36b52591
SL
137 if(file)
138 {
139 webKitCtrl->SetPage(*file->GetStream(), wxuri);
140 }
141 //We need to throw some sort of error here if file is NULL
142 webkit_web_policy_decision_ignore(policy_decision);
143 return TRUE;
f2049b68 144 }
780f7262 145 return FALSE;
61b98a2d
SL
146 }
147}
148
149static gboolean
d363c7db
SL
150wxgtk_webview_webkit_error(WebKitWebView*,
151 WebKitWebFrame*,
152 gchar *uri,
153 gpointer web_error,
154 wxWebViewWebKit* webKitWindow)
61b98a2d
SL
155{
156 webKitWindow->m_busy = false;
04fa04d8 157 wxWebViewNavigationError type = wxWEB_NAV_ERR_OTHER;
61b98a2d
SL
158
159 GError* error = (GError*)web_error;
160 wxString description(error->message, wxConvUTF8);
161
162 if (strcmp(g_quark_to_string(error->domain), "soup_http_error_quark") == 0)
163 {
164 switch (error->code)
165 {
166 case SOUP_STATUS_CANCELLED:
167 type = wxWEB_NAV_ERR_USER_CANCELLED;
168 break;
169
170 case SOUP_STATUS_CANT_RESOLVE:
171 case SOUP_STATUS_NOT_FOUND:
172 type = wxWEB_NAV_ERR_NOT_FOUND;
173 break;
174
175 case SOUP_STATUS_CANT_RESOLVE_PROXY:
176 case SOUP_STATUS_CANT_CONNECT:
177 case SOUP_STATUS_CANT_CONNECT_PROXY:
178 case SOUP_STATUS_SSL_FAILED:
179 case SOUP_STATUS_IO_ERROR:
180 type = wxWEB_NAV_ERR_CONNECTION;
181 break;
182
183 case SOUP_STATUS_MALFORMED:
184 //case SOUP_STATUS_TOO_MANY_REDIRECTS:
185 type = wxWEB_NAV_ERR_REQUEST;
186 break;
187
188 //case SOUP_STATUS_NO_CONTENT:
189 //case SOUP_STATUS_RESET_CONTENT:
190
191 case SOUP_STATUS_BAD_REQUEST:
192 type = wxWEB_NAV_ERR_REQUEST;
193 break;
194
195 case SOUP_STATUS_UNAUTHORIZED:
196 case SOUP_STATUS_FORBIDDEN:
197 type = wxWEB_NAV_ERR_AUTH;
198 break;
199
200 case SOUP_STATUS_METHOD_NOT_ALLOWED:
201 case SOUP_STATUS_NOT_ACCEPTABLE:
202 type = wxWEB_NAV_ERR_SECURITY;
203 break;
204
205 case SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED:
206 type = wxWEB_NAV_ERR_AUTH;
207 break;
208
209 case SOUP_STATUS_REQUEST_TIMEOUT:
210 type = wxWEB_NAV_ERR_CONNECTION;
211 break;
212
213 //case SOUP_STATUS_PAYMENT_REQUIRED:
214 case SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE:
215 case SOUP_STATUS_REQUEST_URI_TOO_LONG:
216 case SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE:
217 type = wxWEB_NAV_ERR_REQUEST;
218 break;
219
220 case SOUP_STATUS_BAD_GATEWAY:
221 case SOUP_STATUS_SERVICE_UNAVAILABLE:
222 case SOUP_STATUS_GATEWAY_TIMEOUT:
223 type = wxWEB_NAV_ERR_CONNECTION;
224 break;
225
226 case SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED:
227 type = wxWEB_NAV_ERR_REQUEST;
228 break;
229 //case SOUP_STATUS_INSUFFICIENT_STORAGE:
230 //case SOUP_STATUS_NOT_EXTENDED:
231 }
232 }
233 else if (strcmp(g_quark_to_string(error->domain),
234 "webkit-network-error-quark") == 0)
235 {
236 switch (error->code)
237 {
238 //WEBKIT_NETWORK_ERROR_FAILED:
239 //WEBKIT_NETWORK_ERROR_TRANSPORT:
240
241 case WEBKIT_NETWORK_ERROR_UNKNOWN_PROTOCOL:
242 type = wxWEB_NAV_ERR_REQUEST;
243 break;
244
245 case WEBKIT_NETWORK_ERROR_CANCELLED:
246 type = wxWEB_NAV_ERR_USER_CANCELLED;
247 break;
248
249 case WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST:
250 type = wxWEB_NAV_ERR_NOT_FOUND;
251 break;
252 }
253 }
254 else if (strcmp(g_quark_to_string(error->domain),
255 "webkit-policy-error-quark") == 0)
256 {
257 switch (error->code)
258 {
259 //case WEBKIT_POLICY_ERROR_FAILED:
260 //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE:
261 //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL:
262 //case WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE:
263 case WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT:
264 type = wxWEB_NAV_ERR_SECURITY;
265 break;
266 }
267 }
268 /*
269 webkit_plugin_error_quark
270 else
271 {
272 printf("Error domain %s\n", g_quark_to_string(error->domain));
273 }
274 */
275
04fa04d8
SL
276 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR,
277 webKitWindow->GetId(),
3225a4b8 278 uri, "");
04fa04d8
SL
279 event.SetString(description);
280 event.SetInt(type);
61b98a2d
SL
281
282 if (webKitWindow && webKitWindow->GetEventHandler())
283 {
04fa04d8 284 webKitWindow->GetEventHandler()->ProcessEvent(event);
61b98a2d
SL
285 }
286
287 return FALSE;
288}
289
0016bf1d 290static gboolean
d363c7db
SL
291wxgtk_webview_webkit_new_window(WebKitWebView*,
292 WebKitWebFrame *frame,
293 WebKitNetworkRequest *request,
294 WebKitWebNavigationAction*,
295 WebKitWebPolicyDecision *policy_decision,
296 wxWebViewWebKit *webKitCtrl)
0016bf1d
SL
297{
298 const gchar* uri = webkit_network_request_get_uri(request);
299
300 wxString target = webkit_web_frame_get_name (frame);
04fa04d8
SL
301 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
302 webKitCtrl->GetId(),
303 wxString( uri, wxConvUTF8 ),
3225a4b8 304 target);
0016bf1d
SL
305
306 if (webKitCtrl && webKitCtrl->GetEventHandler())
04fa04d8 307 webKitCtrl->GetEventHandler()->ProcessEvent(event);
0016bf1d 308
75b3bb61
SL
309 //We always want the user to handle this themselves
310 webkit_web_policy_decision_ignore(policy_decision);
0016bf1d
SL
311 return TRUE;
312}
61b98a2d 313
153530af 314static void
bd6f9534
SL
315wxgtk_webview_webkit_title_changed(WebKitWebView*,
316 WebKitWebFrame*,
153530af
SL
317 gchar *title,
318 wxWebViewWebKit *webKitCtrl)
319{
04fa04d8
SL
320 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED,
321 webKitCtrl->GetId(),
322 webKitCtrl->GetCurrentURL(),
3225a4b8 323 "");
04fa04d8 324 event.SetString(wxString(title, wxConvUTF8));
153530af
SL
325
326 if (webKitCtrl && webKitCtrl->GetEventHandler())
04fa04d8 327 webKitCtrl->GetEventHandler()->ProcessEvent(event);
153530af
SL
328
329}
330
211da8a5
SL
331static void
332wxgtk_webview_webkit_resource_req(WebKitWebView *,
333 WebKitWebFrame *,
334 WebKitWebResource *,
335 WebKitNetworkRequest *request,
336 WebKitNetworkResponse *,
337 wxWebViewWebKit *webKitCtrl)
338{
339 wxString uri = webkit_network_request_get_uri(request);
34326da7 340
7d8d6163
SL
341 wxSharedPtr<wxWebViewHandler> handler;
342 wxVector<wxSharedPtr<wxWebViewHandler> > hanlders = webKitCtrl->GetHandlers();
34326da7 343
211da8a5 344 //We are not vetoed so see if we match one of the additional handlers
7d8d6163 345 for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = hanlders.begin();
211da8a5
SL
346 it != hanlders.end(); ++it)
347 {
348 if(uri.substr(0, (*it)->GetName().length()) == (*it)->GetName())
349 {
350 handler = (*it);
351 }
352 }
34326da7 353 //If we found a handler we can then use it to load the file directly
211da8a5
SL
354 //ourselves
355 if(handler)
356 {
357 //If it is requsting the page itself then return as we have already
358 //loaded it from the archive
359 if(webKitCtrl->m_vfsurl == uri)
360 return;
361
362 wxFSFile* file = handler->GetFile(uri);
363 if(file)
364 {
eea4d01c 365 //We load the data into a data url to save it being written out again
211da8a5
SL
366 size_t size = file->GetStream()->GetLength();
367 char *buffer = new char[size];
211da8a5 368 file->GetStream()->Read(buffer, size);
eea4d01c 369 wxString data = wxBase64Encode(buffer, size);
211da8a5 370 delete[] buffer;
eea4d01c
SL
371 wxString mime = file->GetMimeType();
372 wxString path = "data:" + mime + ";base64," + data;
211da8a5 373 //Then we can redirect the call
f0776dc4 374 webkit_network_request_set_uri(request, path.utf8_str());
211da8a5 375 }
34326da7 376
211da8a5
SL
377 }
378}
379
61b98a2d
SL
380} // extern "C"
381
382//-----------------------------------------------------------------------------
b64b4e70 383// wxWebViewWebKit
61b98a2d
SL
384//-----------------------------------------------------------------------------
385
cddf4541 386wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewWebKit, wxWebView);
61b98a2d 387
b64b4e70 388bool wxWebViewWebKit::Create(wxWindow *parent,
61b98a2d
SL
389 wxWindowID id,
390 const wxString &url,
391 const wxPoint& pos,
392 const wxSize& size,
393 long style,
394 const wxString& name)
395{
61b98a2d 396 m_busy = false;
36b52591 397 m_guard = false;
61b98a2d
SL
398
399 if (!PreCreation( parent, pos, size ) ||
400 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
401 {
b64b4e70 402 wxFAIL_MSG( wxT("wxWebViewWebKit creation failed") );
61b98a2d
SL
403 return false;
404 }
405
d3e592af
PC
406 m_widget = gtk_scrolled_window_new(NULL, NULL);
407 g_object_ref(m_widget);
4c9bde5e 408 m_web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
61b98a2d
SL
409
410 /* Place the WebKitWebView in the GtkScrolledWindow */
4c9bde5e
PC
411 gtk_container_add(GTK_CONTAINER(m_widget), GTK_WIDGET(m_web_view));
412 gtk_widget_show(GTK_WIDGET(m_web_view));
61b98a2d 413
4c9bde5e 414 g_signal_connect_after(m_web_view, "navigation-policy-decision-requested",
780f7262 415 G_CALLBACK(wxgtk_webview_webkit_navigation),
61b98a2d 416 this);
34326da7 417 g_signal_connect_after(m_web_view, "load-error",
d363c7db 418 G_CALLBACK(wxgtk_webview_webkit_error),
61b98a2d
SL
419 this);
420
4c9bde5e 421 g_signal_connect_after(m_web_view, "new-window-policy-decision-requested",
d363c7db 422 G_CALLBACK(wxgtk_webview_webkit_new_window), this);
61b98a2d 423
4c9bde5e 424 g_signal_connect_after(m_web_view, "title-changed",
153530af
SL
425 G_CALLBACK(wxgtk_webview_webkit_title_changed), this);
426
4c9bde5e 427 g_signal_connect_after(m_web_view, "resource-request-starting",
211da8a5
SL
428 G_CALLBACK(wxgtk_webview_webkit_resource_req), this);
429
61b98a2d
SL
430 m_parent->DoAddChild( this );
431
432 PostCreation(size);
433
434 /* Open a webpage */
4c9bde5e 435 webkit_web_view_load_uri(m_web_view, url.utf8_str());
61b98a2d 436
152a5808
SL
437 //Get the initial history limit so we can enable and disable it later
438 WebKitWebBackForwardList* history;
4c9bde5e 439 history = webkit_web_view_get_back_forward_list(m_web_view);
152a5808
SL
440 m_historyLimit = webkit_web_back_forward_list_get_limit(history);
441
7cf17ea2
PC
442 // last to avoid getting signal too early
443 g_signal_connect_after(m_web_view, "notify::load-status",
444 G_CALLBACK(wxgtk_webview_webkit_load_status),
445 this);
61b98a2d
SL
446
447 return true;
448}
449
b64b4e70 450bool wxWebViewWebKit::Enable( bool enable )
61b98a2d
SL
451{
452 if (!wxControl::Enable(enable))
453 return false;
454
455 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
456
457 //if (enable)
458 // GTKFixSensitivity();
459
460 return true;
461}
462
463GdkWindow*
b64b4e70 464wxWebViewWebKit::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
61b98a2d
SL
465{
466 GdkWindow* window = gtk_widget_get_parent_window(m_widget);
467 return window;
468}
469
b64b4e70 470void wxWebViewWebKit::ZoomIn()
61b98a2d 471{
4c9bde5e 472 webkit_web_view_zoom_in(m_web_view);
61b98a2d
SL
473}
474
b64b4e70 475void wxWebViewWebKit::ZoomOut()
61b98a2d 476{
4c9bde5e 477 webkit_web_view_zoom_out(m_web_view);
61b98a2d
SL
478}
479
b64b4e70 480void wxWebViewWebKit::SetWebkitZoom(float level)
61b98a2d 481{
4c9bde5e 482 webkit_web_view_set_zoom_level(m_web_view, level);
61b98a2d
SL
483}
484
e669ddde 485float wxWebViewWebKit::GetWebkitZoom() const
61b98a2d 486{
4c9bde5e 487 return webkit_web_view_get_zoom_level(m_web_view);
61b98a2d
SL
488}
489
b64b4e70 490void wxWebViewWebKit::Stop()
61b98a2d 491{
4c9bde5e 492 webkit_web_view_stop_loading(m_web_view);
61b98a2d
SL
493}
494
b64b4e70 495void wxWebViewWebKit::Reload(wxWebViewReloadFlags flags)
61b98a2d
SL
496{
497 if (flags & wxWEB_VIEW_RELOAD_NO_CACHE)
498 {
4c9bde5e 499 webkit_web_view_reload_bypass_cache(m_web_view);
61b98a2d
SL
500 }
501 else
502 {
4c9bde5e 503 webkit_web_view_reload(m_web_view);
61b98a2d
SL
504 }
505}
506
4d0dddc7 507void wxWebViewWebKit::LoadURL(const wxString& url)
61b98a2d 508{
4c9bde5e 509 webkit_web_view_load_uri(m_web_view, wxGTK_CONV(url));
61b98a2d
SL
510}
511
512
b64b4e70 513void wxWebViewWebKit::GoBack()
61b98a2d 514{
4c9bde5e 515 webkit_web_view_go_back(m_web_view);
61b98a2d
SL
516}
517
b64b4e70 518void wxWebViewWebKit::GoForward()
61b98a2d 519{
4c9bde5e 520 webkit_web_view_go_forward(m_web_view);
61b98a2d
SL
521}
522
523
e669ddde 524bool wxWebViewWebKit::CanGoBack() const
61b98a2d 525{
4c9bde5e 526 return webkit_web_view_can_go_back(m_web_view);
61b98a2d
SL
527}
528
529
e669ddde 530bool wxWebViewWebKit::CanGoForward() const
61b98a2d 531{
4c9bde5e 532 return webkit_web_view_can_go_forward(m_web_view);
61b98a2d
SL
533}
534
152a5808
SL
535void wxWebViewWebKit::ClearHistory()
536{
537 WebKitWebBackForwardList* history;
4c9bde5e 538 history = webkit_web_view_get_back_forward_list(m_web_view);
152a5808
SL
539 webkit_web_back_forward_list_clear(history);
540}
541
542void wxWebViewWebKit::EnableHistory(bool enable)
543{
544 WebKitWebBackForwardList* history;
4c9bde5e 545 history = webkit_web_view_get_back_forward_list(m_web_view);
152a5808
SL
546 if(enable)
547 {
548 webkit_web_back_forward_list_set_limit(history, m_historyLimit);
549 }
550 else
551 {
552 webkit_web_back_forward_list_set_limit(history, 0);
553 }
554}
61b98a2d 555
c13d6ac1 556wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewWebKit::GetBackwardHistory()
19fc1a2f 557{
34326da7 558 wxVector<wxSharedPtr<wxWebViewHistoryItem> > backhist;
19fc1a2f 559 WebKitWebBackForwardList* history;
4c9bde5e 560 history = webkit_web_view_get_back_forward_list(m_web_view);
34326da7 561 GList* list = webkit_web_back_forward_list_get_back_list_with_limit(history,
19fc1a2f
SL
562 m_historyLimit);
563 //We need to iterate in reverse to get the order we desire
564 for(int i = g_list_length(list) - 1; i >= 0 ; i--)
565 {
566 WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)g_list_nth_data(list, i);
c13d6ac1 567 wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(
263e3a83
SL
568 webkit_web_history_item_get_uri(gtkitem),
569 webkit_web_history_item_get_title(gtkitem));
570 wxitem->m_histItem = gtkitem;
c13d6ac1 571 wxSharedPtr<wxWebViewHistoryItem> item(wxitem);
19fc1a2f 572 backhist.push_back(item);
19fc1a2f
SL
573 }
574 return backhist;
575}
576
c13d6ac1 577wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewWebKit::GetForwardHistory()
19fc1a2f 578{
34326da7 579 wxVector<wxSharedPtr<wxWebViewHistoryItem> > forwardhist;
19fc1a2f 580 WebKitWebBackForwardList* history;
4c9bde5e 581 history = webkit_web_view_get_back_forward_list(m_web_view);
34326da7 582 GList* list = webkit_web_back_forward_list_get_forward_list_with_limit(history,
19fc1a2f
SL
583 m_historyLimit);
584 for(guint i = 0; i < g_list_length(list); i++)
585 {
586 WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)g_list_nth_data(list, i);
c13d6ac1 587 wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(
263e3a83
SL
588 webkit_web_history_item_get_uri(gtkitem),
589 webkit_web_history_item_get_title(gtkitem));
590 wxitem->m_histItem = gtkitem;
c13d6ac1 591 wxSharedPtr<wxWebViewHistoryItem> item(wxitem);
19fc1a2f 592 forwardhist.push_back(item);
19fc1a2f
SL
593 }
594 return forwardhist;
595}
596
c13d6ac1 597void wxWebViewWebKit::LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)
19fc1a2f 598{
a0ff3611 599 WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)item->m_histItem;
19fc1a2f
SL
600 if(gtkitem)
601 {
34326da7 602 webkit_web_view_go_to_back_forward_item(m_web_view,
263e3a83 603 WEBKIT_WEB_HISTORY_ITEM(gtkitem));
19fc1a2f
SL
604 }
605}
606
e669ddde 607bool wxWebViewWebKit::CanCut() const
ae26e17b 608{
4c9bde5e 609 return webkit_web_view_can_cut_clipboard(m_web_view);
ae26e17b
SL
610}
611
e669ddde 612bool wxWebViewWebKit::CanCopy() const
ae26e17b 613{
4c9bde5e 614 return webkit_web_view_can_copy_clipboard(m_web_view);
ae26e17b
SL
615}
616
e669ddde 617bool wxWebViewWebKit::CanPaste() const
ae26e17b 618{
4c9bde5e 619 return webkit_web_view_can_paste_clipboard(m_web_view);
ae26e17b
SL
620}
621
622void wxWebViewWebKit::Cut()
623{
4c9bde5e 624 webkit_web_view_cut_clipboard(m_web_view);
ae26e17b
SL
625}
626
627void wxWebViewWebKit::Copy()
628{
4c9bde5e 629 webkit_web_view_copy_clipboard(m_web_view);
ae26e17b
SL
630}
631
632void wxWebViewWebKit::Paste()
633{
4c9bde5e 634 webkit_web_view_paste_clipboard(m_web_view);
ae26e17b
SL
635}
636
e669ddde 637bool wxWebViewWebKit::CanUndo() const
97e49559 638{
4c9bde5e 639 return webkit_web_view_can_undo(m_web_view);
97e49559
SL
640}
641
e669ddde 642bool wxWebViewWebKit::CanRedo() const
97e49559 643{
4c9bde5e 644 return webkit_web_view_can_redo(m_web_view);
97e49559
SL
645}
646
647void wxWebViewWebKit::Undo()
648{
4c9bde5e 649 webkit_web_view_undo(m_web_view);
97e49559
SL
650}
651
652void wxWebViewWebKit::Redo()
653{
4c9bde5e 654 webkit_web_view_redo(m_web_view);
97e49559
SL
655}
656
e669ddde 657wxString wxWebViewWebKit::GetCurrentURL() const
61b98a2d
SL
658{
659 // FIXME: check which encoding the web kit control uses instead of
660 // assuming UTF8 (here and elsewhere too)
4c9bde5e 661 return wxString::FromUTF8(webkit_web_view_get_uri(m_web_view));
61b98a2d
SL
662}
663
664
e669ddde 665wxString wxWebViewWebKit::GetCurrentTitle() const
61b98a2d 666{
4c9bde5e 667 return wxString::FromUTF8(webkit_web_view_get_title(m_web_view));
61b98a2d
SL
668}
669
670
e669ddde 671wxString wxWebViewWebKit::GetPageSource() const
61b98a2d 672{
4c9bde5e 673 WebKitWebFrame* frame = webkit_web_view_get_main_frame(m_web_view);
61b98a2d
SL
674 WebKitWebDataSource* src = webkit_web_frame_get_data_source (frame);
675
676 // TODO: check encoding with
677 // const gchar*
678 // webkit_web_data_source_get_encoding(WebKitWebDataSource *data_source);
679 return wxString(webkit_web_data_source_get_data (src)->str, wxConvUTF8);
680}
681
682
e669ddde 683wxWebViewZoom wxWebViewWebKit::GetZoom() const
61b98a2d
SL
684{
685 float zoom = GetWebkitZoom();
686
687 // arbitrary way to map float zoom to our common zoom enum
688 if (zoom <= 0.65)
689 {
690 return wxWEB_VIEW_ZOOM_TINY;
691 }
692 else if (zoom > 0.65 && zoom <= 0.90)
693 {
694 return wxWEB_VIEW_ZOOM_SMALL;
695 }
696 else if (zoom > 0.90 && zoom <= 1.15)
697 {
698 return wxWEB_VIEW_ZOOM_MEDIUM;
699 }
700 else if (zoom > 1.15 && zoom <= 1.45)
701 {
702 return wxWEB_VIEW_ZOOM_LARGE;
703 }
704 else if (zoom > 1.45)
705 {
706 return wxWEB_VIEW_ZOOM_LARGEST;
707 }
708
709 // to shut up compilers, this can never be reached logically
710 wxASSERT(false);
711 return wxWEB_VIEW_ZOOM_MEDIUM;
712}
713
714
b64b4e70 715void wxWebViewWebKit::SetZoom(wxWebViewZoom zoom)
61b98a2d
SL
716{
717 // arbitrary way to map our common zoom enum to float zoom
718 switch (zoom)
719 {
720 case wxWEB_VIEW_ZOOM_TINY:
721 SetWebkitZoom(0.6f);
722 break;
723
724 case wxWEB_VIEW_ZOOM_SMALL:
725 SetWebkitZoom(0.8f);
726 break;
727
728 case wxWEB_VIEW_ZOOM_MEDIUM:
729 SetWebkitZoom(1.0f);
730 break;
731
732 case wxWEB_VIEW_ZOOM_LARGE:
733 SetWebkitZoom(1.3);
734 break;
735
736 case wxWEB_VIEW_ZOOM_LARGEST:
737 SetWebkitZoom(1.6);
738 break;
739
740 default:
741 wxASSERT(false);
742 }
743}
744
b64b4e70 745void wxWebViewWebKit::SetZoomType(wxWebViewZoomType type)
61b98a2d 746{
4c9bde5e 747 webkit_web_view_set_full_content_zoom(m_web_view,
61b98a2d
SL
748 (type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT ?
749 TRUE : FALSE));
750}
751
b64b4e70 752wxWebViewZoomType wxWebViewWebKit::GetZoomType() const
61b98a2d 753{
4c9bde5e 754 gboolean fczoom = webkit_web_view_get_full_content_zoom(m_web_view);
61b98a2d
SL
755
756 if (fczoom) return wxWEB_VIEW_ZOOM_TYPE_LAYOUT;
757 else return wxWEB_VIEW_ZOOM_TYPE_TEXT;
758}
759
b64b4e70 760bool wxWebViewWebKit::CanSetZoomType(wxWebViewZoomType) const
61b98a2d
SL
761{
762 // this port supports all zoom types
763 return true;
764}
765
b64b4e70 766void wxWebViewWebKit::SetPage(const wxString& html, const wxString& baseUri)
61b98a2d 767{
4c9bde5e 768 webkit_web_view_load_string (m_web_view,
61b98a2d
SL
769 html.mb_str(wxConvUTF8),
770 "text/html",
771 "UTF-8",
772 baseUri.mb_str(wxConvUTF8));
773}
774
b64b4e70 775void wxWebViewWebKit::Print()
61b98a2d 776{
4c9bde5e 777 WebKitWebFrame* frame = webkit_web_view_get_main_frame(m_web_view);
61b98a2d
SL
778 webkit_web_frame_print (frame);
779
780 // GtkPrintOperationResult webkit_web_frame_print_full
781 // (WebKitWebFrame *frame,
782 // GtkPrintOperation *operation,
783 // GtkPrintOperationAction action,
784 // GError **error);
785
786}
787
788
e669ddde 789bool wxWebViewWebKit::IsBusy() const
61b98a2d
SL
790{
791 return m_busy;
792
793 // This code looks nice but returns true after a page was cancelled
794 /*
795 WebKitLoadStatus status = webkit_web_view_get_load_status
796 (WEBKIT_WEB_VIEW(web_view));
797
798
799#if WEBKIT_CHECK_VERSION(1,1,16)
800 // WEBKIT_LOAD_FAILED is new in webkit 1.1.16
801 if (status == WEBKIT_LOAD_FAILED)
802 {
803 return false;
804 }
805#endif
806 if (status == WEBKIT_LOAD_FINISHED)
807 {
808 return false;
809 }
810
811 return true;
812 */
813}
814
c7cbe308
SL
815void wxWebViewWebKit::SetEditable(bool enable)
816{
4c9bde5e 817 webkit_web_view_set_editable(m_web_view, enable);
c7cbe308
SL
818}
819
e669ddde 820bool wxWebViewWebKit::IsEditable() const
c7cbe308 821{
4c9bde5e 822 return webkit_web_view_get_editable(m_web_view);
c7cbe308
SL
823}
824
63a65070
SL
825void wxWebViewWebKit::DeleteSelection()
826{
4c9bde5e 827 webkit_web_view_delete_selection(m_web_view);
63a65070
SL
828}
829
e669ddde 830bool wxWebViewWebKit::HasSelection() const
63a65070 831{
4c9bde5e 832 return webkit_web_view_has_selection(m_web_view);
63a65070
SL
833}
834
835void wxWebViewWebKit::SelectAll()
836{
4c9bde5e 837 webkit_web_view_select_all(m_web_view);
63a65070
SL
838}
839
e669ddde 840wxString wxWebViewWebKit::GetSelectedText() const
c9355a3d 841{
34326da7 842 WebKitDOMDocument* doc;
c9355a3d
SL
843 WebKitDOMDOMWindow* win;
844 WebKitDOMDOMSelection* sel;
845 WebKitDOMRange* range;
846
4c9bde5e 847 doc = webkit_web_view_get_dom_document(m_web_view);
c9355a3d
SL
848 win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc));
849 sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win));
34326da7 850 range = webkit_dom_dom_selection_get_range_at(WEBKIT_DOM_DOM_SELECTION(sel),
c9355a3d 851 0, NULL);
34326da7 852 return wxString(webkit_dom_range_get_text(WEBKIT_DOM_RANGE(range)),
c9355a3d
SL
853 wxConvUTF8);
854}
63a65070 855
e669ddde 856wxString wxWebViewWebKit::GetSelectedSource() const
0fe8a1b6 857{
34326da7 858 WebKitDOMDocument* doc;
0fe8a1b6
SL
859 WebKitDOMDOMWindow* win;
860 WebKitDOMDOMSelection* sel;
861 WebKitDOMRange* range;
862 WebKitDOMElement* div;
863 WebKitDOMDocumentFragment* clone;
864 WebKitDOMHTMLElement* html;
865
4c9bde5e 866 doc = webkit_web_view_get_dom_document(m_web_view);
0fe8a1b6
SL
867 win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc));
868 sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win));
34326da7 869 range = webkit_dom_dom_selection_get_range_at(WEBKIT_DOM_DOM_SELECTION(sel),
0fe8a1b6
SL
870 0, NULL);
871 div = webkit_dom_document_create_element(WEBKIT_DOM_DOCUMENT(doc), "div", NULL);
872
873 clone = webkit_dom_range_clone_contents(WEBKIT_DOM_RANGE(range), NULL);
874 webkit_dom_node_append_child(&div->parent_instance, &clone->parent_instance, NULL);
875 html = (WebKitDOMHTMLElement*)div;
876
34326da7 877 return wxString(webkit_dom_html_element_get_inner_html(WEBKIT_DOM_HTML_ELEMENT(html)),
0fe8a1b6
SL
878 wxConvUTF8);
879}
880
41933aa5
SL
881void wxWebViewWebKit::ClearSelection()
882{
34326da7 883 WebKitDOMDocument* doc;
41933aa5
SL
884 WebKitDOMDOMWindow* win;
885 WebKitDOMDOMSelection* sel;
886
4c9bde5e 887 doc = webkit_web_view_get_dom_document(m_web_view);
41933aa5
SL
888 win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc));
889 sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win));
890 webkit_dom_dom_selection_remove_all_ranges(WEBKIT_DOM_DOM_SELECTION(sel));
891
892}
893
e669ddde 894wxString wxWebViewWebKit::GetPageText() const
241b769f 895{
34326da7 896 WebKitDOMDocument* doc;
241b769f
SL
897 WebKitDOMHTMLElement* body;
898
4c9bde5e 899 doc = webkit_web_view_get_dom_document(m_web_view);
241b769f 900 body = webkit_dom_document_get_body(WEBKIT_DOM_DOCUMENT(doc));
34326da7 901 return wxString(webkit_dom_html_element_get_inner_text(WEBKIT_DOM_HTML_ELEMENT(body)),
241b769f
SL
902 wxConvUTF8);
903}
904
c9ccc09c
SL
905void wxWebViewWebKit::RunScript(const wxString& javascript)
906{
34326da7 907 webkit_web_view_execute_script(m_web_view,
c9ccc09c
SL
908 javascript.mb_str(wxConvUTF8));
909}
910
7d8d6163 911void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
f2049b68
SL
912{
913 m_handlerList.push_back(handler);
914}
915
61b98a2d
SL
916// static
917wxVisualAttributes
b64b4e70 918wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
61b98a2d
SL
919{
920 return GetDefaultAttributesFromGTKWidget(webkit_web_view_new);
921}
922
923
9d2f31db 924#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT