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