]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/webview_webkit.cpp
Make BOM-detection code in wxConvAuto public.
[wxWidgets.git] / src / gtk / webview_webkit.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/webview_webkit.cpp
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
13 #if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT
14
15 #include "wx/stockitem.h"
16 #include "wx/gtk/webview_webkit.h"
17 #include "wx/gtk/control.h"
18 #include "wx/gtk/private.h"
19 #include "wx/filesys.h"
20 #include "wx/base64.h"
21 #include "webkit/webkit.h"
22
23 // ----------------------------------------------------------------------------
24 // GTK callbacks
25 // ----------------------------------------------------------------------------
26
27 extern "C"
28 {
29
30 static void
31 wxgtk_webview_webkit_load_status(GtkWidget* widget,
32 GParamSpec*,
33 wxWebViewWebKit *webKitCtrl)
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 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
57 webKitCtrl->m_busy = false;
58 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED,
59 webKitCtrl->GetId(),
60 url, target);
61
62 if (webKitCtrl && webKitCtrl->GetEventHandler())
63 webKitCtrl->GetEventHandler()->ProcessEvent(event);
64 }
65 else if (status == WEBKIT_LOAD_COMMITTED)
66 {
67 webKitCtrl->m_busy = true;
68 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
69 webKitCtrl->GetId(),
70 url, target);
71
72 if (webKitCtrl && webKitCtrl->GetEventHandler())
73 webKitCtrl->GetEventHandler()->ProcessEvent(event);
74 }
75 }
76
77 static gboolean
78 wxgtk_webview_webkit_navigation(WebKitWebView *,
79 WebKitWebFrame *frame,
80 WebKitNetworkRequest *request,
81 WebKitWebNavigationAction *,
82 WebKitWebPolicyDecision *policy_decision,
83 wxWebViewWebKit *webKitCtrl)
84 {
85 if(webKitCtrl->m_guard)
86 {
87 webKitCtrl->m_guard = false;
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);
92 return FALSE;
93 }
94
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);
100 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
101 webKitCtrl->GetId(),
102 wxString( uri, wxConvUTF8 ),
103 target);
104
105 if (webKitCtrl && webKitCtrl->GetEventHandler())
106 webKitCtrl->GetEventHandler()->ProcessEvent(event);
107
108 if (!event.IsAllowed())
109 {
110 webKitCtrl->m_busy = false;
111 webkit_web_policy_decision_ignore(policy_decision);
112 return TRUE;
113 }
114 else
115 {
116 wxString wxuri = uri;
117 wxSharedPtr<wxWebViewHandler> handler;
118 wxVector<wxSharedPtr<wxWebViewHandler> > hanlders = webKitCtrl->GetHandlers();
119 //We are not vetoed so see if we match one of the additional handlers
120 for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = hanlders.begin();
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 {
132 webKitCtrl->m_guard = true;
133 wxFSFile* file = handler->GetFile(wxuri);
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;
141 }
142 return FALSE;
143 }
144 }
145
146 static gboolean
147 wxgtk_webview_webkit_error(WebKitWebView*,
148 WebKitWebFrame*,
149 gchar *uri,
150 gpointer web_error,
151 wxWebViewWebKit* webKitWindow)
152 {
153 webKitWindow->m_busy = false;
154 wxWebViewNavigationError type = wxWEB_NAV_ERR_OTHER;
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
273 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR,
274 webKitWindow->GetId(),
275 uri, "");
276 event.SetString(description);
277 event.SetInt(type);
278
279 if (webKitWindow && webKitWindow->GetEventHandler())
280 {
281 webKitWindow->GetEventHandler()->ProcessEvent(event);
282 }
283
284 return FALSE;
285 }
286
287 static gboolean
288 wxgtk_webview_webkit_new_window(WebKitWebView*,
289 WebKitWebFrame *frame,
290 WebKitNetworkRequest *request,
291 WebKitWebNavigationAction*,
292 WebKitWebPolicyDecision *policy_decision,
293 wxWebViewWebKit *webKitCtrl)
294 {
295 const gchar* uri = webkit_network_request_get_uri(request);
296
297 wxString target = webkit_web_frame_get_name (frame);
298 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
299 webKitCtrl->GetId(),
300 wxString( uri, wxConvUTF8 ),
301 target);
302
303 if (webKitCtrl && webKitCtrl->GetEventHandler())
304 webKitCtrl->GetEventHandler()->ProcessEvent(event);
305
306 //We always want the user to handle this themselves
307 webkit_web_policy_decision_ignore(policy_decision);
308 return TRUE;
309 }
310
311 static void
312 wxgtk_webview_webkit_title_changed(WebKitWebView*,
313 WebKitWebFrame*,
314 gchar *title,
315 wxWebViewWebKit *webKitCtrl)
316 {
317 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED,
318 webKitCtrl->GetId(),
319 webKitCtrl->GetCurrentURL(),
320 "");
321 event.SetString(wxString(title, wxConvUTF8));
322
323 if (webKitCtrl && webKitCtrl->GetEventHandler())
324 webKitCtrl->GetEventHandler()->ProcessEvent(event);
325
326 }
327
328 static void
329 wxgtk_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
338 wxSharedPtr<wxWebViewHandler> handler;
339 wxVector<wxSharedPtr<wxWebViewHandler> > hanlders = webKitCtrl->GetHandlers();
340
341 //We are not vetoed so see if we match one of the additional handlers
342 for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = hanlders.begin();
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 {
362 //We load the data into a data url to save it being written out again
363 size_t size = file->GetStream()->GetLength();
364 char *buffer = new char[size];
365 file->GetStream()->Read(buffer, size);
366 wxString data = wxBase64Encode(buffer, size);
367 delete[] buffer;
368 wxString mime = file->GetMimeType();
369 wxString path = "data:" + mime + ";base64," + data;
370 //Then we can redirect the call
371 webkit_network_request_set_uri(request, path);
372 }
373
374 }
375 }
376
377 } // extern "C"
378
379 //-----------------------------------------------------------------------------
380 // wxWebViewWebKit
381 //-----------------------------------------------------------------------------
382
383 wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewWebKit, wxWebView);
384
385 bool wxWebViewWebKit::Create(wxWindow *parent,
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;
395 m_guard = false;
396
397 if (!PreCreation( parent, pos, size ) ||
398 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
399 {
400 wxFAIL_MSG( wxT("wxWebViewWebKit creation failed") );
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",
417 G_CALLBACK(wxgtk_webview_webkit_load_status),
418 this);
419 g_signal_connect_after(web_view, "navigation-policy-decision-requested",
420 G_CALLBACK(wxgtk_webview_webkit_navigation),
421 this);
422 g_signal_connect_after(web_view, "load-error",
423 G_CALLBACK(wxgtk_webview_webkit_error),
424 this);
425
426 g_signal_connect_after(web_view, "new-window-policy-decision-requested",
427 G_CALLBACK(wxgtk_webview_webkit_new_window), this);
428
429 g_signal_connect_after(web_view, "title-changed",
430 G_CALLBACK(wxgtk_webview_webkit_title_changed), this);
431
432 g_signal_connect_after(web_view, "resource-request-starting",
433 G_CALLBACK(wxgtk_webview_webkit_resource_req), this);
434
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
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
447 m_ready = true;
448
449 return true;
450 }
451
452 bool wxWebViewWebKit::Enable( bool enable )
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
465 GdkWindow*
466 wxWebViewWebKit::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
467 {
468 GdkWindow* window = gtk_widget_get_parent_window(m_widget);
469 return window;
470 }
471
472 void wxWebViewWebKit::ZoomIn()
473 {
474 webkit_web_view_zoom_in (WEBKIT_WEB_VIEW(web_view));
475 }
476
477 void wxWebViewWebKit::ZoomOut()
478 {
479 webkit_web_view_zoom_out (WEBKIT_WEB_VIEW(web_view));
480 }
481
482 void wxWebViewWebKit::SetWebkitZoom(float level)
483 {
484 webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(web_view), level);
485 }
486
487 float wxWebViewWebKit::GetWebkitZoom() const
488 {
489 return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW(web_view));
490 }
491
492 void wxWebViewWebKit::Stop()
493 {
494 webkit_web_view_stop_loading (WEBKIT_WEB_VIEW(web_view));
495 }
496
497 void wxWebViewWebKit::Reload(wxWebViewReloadFlags flags)
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
509 void wxWebViewWebKit::LoadURL(const wxString& url)
510 {
511 webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), wxGTK_CONV(url));
512 }
513
514
515 void wxWebViewWebKit::GoBack()
516 {
517 webkit_web_view_go_back (WEBKIT_WEB_VIEW(web_view));
518 }
519
520 void wxWebViewWebKit::GoForward()
521 {
522 webkit_web_view_go_forward (WEBKIT_WEB_VIEW(web_view));
523 }
524
525
526 bool wxWebViewWebKit::CanGoBack() const
527 {
528 return webkit_web_view_can_go_back (WEBKIT_WEB_VIEW(web_view));
529 }
530
531
532 bool wxWebViewWebKit::CanGoForward() const
533 {
534 return webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW(web_view));
535 }
536
537 void 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
544 void 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 }
557
558 wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewWebKit::GetBackwardHistory()
559 {
560 wxVector<wxSharedPtr<wxWebViewHistoryItem> > backhist;
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);
569 wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(
570 webkit_web_history_item_get_uri(gtkitem),
571 webkit_web_history_item_get_title(gtkitem));
572 wxitem->m_histItem = gtkitem;
573 wxSharedPtr<wxWebViewHistoryItem> item(wxitem);
574 backhist.push_back(item);
575 }
576 return backhist;
577 }
578
579 wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewWebKit::GetForwardHistory()
580 {
581 wxVector<wxSharedPtr<wxWebViewHistoryItem> > forwardhist;
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);
589 wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(
590 webkit_web_history_item_get_uri(gtkitem),
591 webkit_web_history_item_get_title(gtkitem));
592 wxitem->m_histItem = gtkitem;
593 wxSharedPtr<wxWebViewHistoryItem> item(wxitem);
594 forwardhist.push_back(item);
595 }
596 return forwardhist;
597 }
598
599 void wxWebViewWebKit::LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)
600 {
601 WebKitWebHistoryItem* gtkitem = item->m_histItem;
602 if(gtkitem)
603 {
604 WebKitWebBackForwardList* history;
605 history = webkit_web_view_get_back_forward_list(WEBKIT_WEB_VIEW(web_view));
606 webkit_web_view_go_to_back_forward_item(WEBKIT_WEB_VIEW(web_view),
607 WEBKIT_WEB_HISTORY_ITEM(gtkitem));
608 }
609 }
610
611 bool wxWebViewWebKit::CanCut() const
612 {
613 return webkit_web_view_can_cut_clipboard(WEBKIT_WEB_VIEW(web_view));
614 }
615
616 bool wxWebViewWebKit::CanCopy() const
617 {
618 return webkit_web_view_can_copy_clipboard(WEBKIT_WEB_VIEW(web_view));
619 }
620
621 bool wxWebViewWebKit::CanPaste() const
622 {
623 return webkit_web_view_can_paste_clipboard(WEBKIT_WEB_VIEW(web_view));
624 }
625
626 void wxWebViewWebKit::Cut()
627 {
628 webkit_web_view_cut_clipboard(WEBKIT_WEB_VIEW(web_view));
629 }
630
631 void wxWebViewWebKit::Copy()
632 {
633 webkit_web_view_copy_clipboard(WEBKIT_WEB_VIEW(web_view));
634 }
635
636 void wxWebViewWebKit::Paste()
637 {
638 webkit_web_view_paste_clipboard(WEBKIT_WEB_VIEW(web_view));
639 }
640
641 bool wxWebViewWebKit::CanUndo() const
642 {
643 return webkit_web_view_can_undo(WEBKIT_WEB_VIEW(web_view));
644 }
645
646 bool wxWebViewWebKit::CanRedo() const
647 {
648 return webkit_web_view_can_redo(WEBKIT_WEB_VIEW(web_view));
649 }
650
651 void wxWebViewWebKit::Undo()
652 {
653 webkit_web_view_undo(WEBKIT_WEB_VIEW(web_view));
654 }
655
656 void wxWebViewWebKit::Redo()
657 {
658 webkit_web_view_redo(WEBKIT_WEB_VIEW(web_view));
659 }
660
661 wxString wxWebViewWebKit::GetCurrentURL() const
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
670 wxString wxWebViewWebKit::GetCurrentTitle() const
671 {
672 return wxString::FromUTF8(webkit_web_view_get_title(
673 WEBKIT_WEB_VIEW(web_view)));
674 }
675
676
677 wxString wxWebViewWebKit::GetPageSource() const
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
690 wxWebViewZoom wxWebViewWebKit::GetZoom() const
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
722 void wxWebViewWebKit::SetZoom(wxWebViewZoom zoom)
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
752 void wxWebViewWebKit::SetZoomType(wxWebViewZoomType type)
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
759 wxWebViewZoomType wxWebViewWebKit::GetZoomType() const
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
768 bool wxWebViewWebKit::CanSetZoomType(wxWebViewZoomType) const
769 {
770 // this port supports all zoom types
771 return true;
772 }
773
774 void wxWebViewWebKit::SetPage(const wxString& html, const wxString& baseUri)
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
783 void wxWebViewWebKit::Print()
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
798 bool wxWebViewWebKit::IsBusy() const
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
824 void wxWebViewWebKit::SetEditable(bool enable)
825 {
826 webkit_web_view_set_editable(WEBKIT_WEB_VIEW(web_view), enable);
827 }
828
829 bool wxWebViewWebKit::IsEditable() const
830 {
831 return webkit_web_view_get_editable(WEBKIT_WEB_VIEW(web_view));
832 }
833
834 void wxWebViewWebKit::DeleteSelection()
835 {
836 webkit_web_view_delete_selection(WEBKIT_WEB_VIEW(web_view));
837 }
838
839 bool wxWebViewWebKit::HasSelection() const
840 {
841 return webkit_web_view_has_selection(WEBKIT_WEB_VIEW(web_view));
842 }
843
844 void wxWebViewWebKit::SelectAll()
845 {
846 webkit_web_view_select_all(WEBKIT_WEB_VIEW(web_view));
847 }
848
849 wxString wxWebViewWebKit::GetSelectedText() const
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 }
864
865 wxString wxWebViewWebKit::GetSelectedSource() const
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
890 void 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
903 wxString wxWebViewWebKit::GetPageText() const
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
914 void wxWebViewWebKit::RunScript(const wxString& javascript)
915 {
916 webkit_web_view_execute_script(WEBKIT_WEB_VIEW(web_view),
917 javascript.mb_str(wxConvUTF8));
918 }
919
920 void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
921 {
922 m_handlerList.push_back(handler);
923 }
924
925 // static
926 wxVisualAttributes
927 wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
928 {
929 return GetDefaultAttributesFromGTKWidget(webkit_web_view_new);
930 }
931
932
933 #endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT