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