]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/webview_webkit.cpp
Don't use a depreciated method for loading a url.
[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_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 "webkit/webkit.h"
20
21 // ----------------------------------------------------------------------------
22 // GTK callbacks
23 // ----------------------------------------------------------------------------
24
25 extern "C"
26 {
27
28 static void
29 wxgtk_webkitctrl_load_status_callback(GtkWidget* widget, GParamSpec* arg1,
30 wxWebViewWebKit *webKitCtrl)
31 {
32 if (!webKitCtrl->m_ready) return;
33
34 wxString url = webKitCtrl->GetCurrentURL();
35
36 WebKitLoadStatus status;
37 g_object_get(G_OBJECT(widget), "load-status", &status, NULL);
38
39 wxString target; // TODO: get target (if possible)
40
41 if (status == WEBKIT_LOAD_FINISHED)
42 {
43 webKitCtrl->m_busy = false;
44 wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_LOADED,
45 webKitCtrl->GetId(),
46 url, target, false);
47
48 if (webKitCtrl && webKitCtrl->GetEventHandler())
49 webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent);
50 }
51 else if (status == WEBKIT_LOAD_COMMITTED)
52 {
53 webKitCtrl->m_busy = true;
54 wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
55 webKitCtrl->GetId(),
56 url, target, false);
57
58 if (webKitCtrl && webKitCtrl->GetEventHandler())
59 webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent);
60 }
61 }
62
63 static WebKitNavigationResponse
64 wxgtk_webkitctrl_navigation_requ_callback(WebKitWebView *web_view,
65 WebKitWebFrame *frame,
66 WebKitNetworkRequest *request,
67 wxWebViewWebKit *webKitCtrl)
68 {
69 webKitCtrl->m_busy = true;
70
71 const gchar* uri = webkit_network_request_get_uri(request);
72
73 wxString target = webkit_web_frame_get_name (frame);
74 wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
75 webKitCtrl->GetId(),
76 wxString( uri, wxConvUTF8 ),
77 target,
78 true);
79
80 if (webKitCtrl && webKitCtrl->GetEventHandler())
81 webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent);
82
83 if (thisEvent.IsVetoed())
84 {
85 webKitCtrl->m_busy = false;
86 return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
87 }
88 else
89 {
90 return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
91 }
92 }
93
94 static gboolean
95 wxgtk_webkitctrl_error (WebKitWebView *web_view,
96 WebKitWebFrame *web_frame,
97 gchar *uri,
98 gpointer web_error,
99 wxWebViewWebKit* webKitWindow)
100 {
101 webKitWindow->m_busy = false;
102 wxWebNavigationError type = wxWEB_NAV_ERR_OTHER;
103
104 GError* error = (GError*)web_error;
105 wxString description(error->message, wxConvUTF8);
106
107 if (strcmp(g_quark_to_string(error->domain), "soup_http_error_quark") == 0)
108 {
109 switch (error->code)
110 {
111 case SOUP_STATUS_CANCELLED:
112 type = wxWEB_NAV_ERR_USER_CANCELLED;
113 break;
114
115 case SOUP_STATUS_CANT_RESOLVE:
116 case SOUP_STATUS_NOT_FOUND:
117 type = wxWEB_NAV_ERR_NOT_FOUND;
118 break;
119
120 case SOUP_STATUS_CANT_RESOLVE_PROXY:
121 case SOUP_STATUS_CANT_CONNECT:
122 case SOUP_STATUS_CANT_CONNECT_PROXY:
123 case SOUP_STATUS_SSL_FAILED:
124 case SOUP_STATUS_IO_ERROR:
125 type = wxWEB_NAV_ERR_CONNECTION;
126 break;
127
128 case SOUP_STATUS_MALFORMED:
129 //case SOUP_STATUS_TOO_MANY_REDIRECTS:
130 type = wxWEB_NAV_ERR_REQUEST;
131 break;
132
133 //case SOUP_STATUS_NO_CONTENT:
134 //case SOUP_STATUS_RESET_CONTENT:
135
136 case SOUP_STATUS_BAD_REQUEST:
137 type = wxWEB_NAV_ERR_REQUEST;
138 break;
139
140 case SOUP_STATUS_UNAUTHORIZED:
141 case SOUP_STATUS_FORBIDDEN:
142 type = wxWEB_NAV_ERR_AUTH;
143 break;
144
145 case SOUP_STATUS_METHOD_NOT_ALLOWED:
146 case SOUP_STATUS_NOT_ACCEPTABLE:
147 type = wxWEB_NAV_ERR_SECURITY;
148 break;
149
150 case SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED:
151 type = wxWEB_NAV_ERR_AUTH;
152 break;
153
154 case SOUP_STATUS_REQUEST_TIMEOUT:
155 type = wxWEB_NAV_ERR_CONNECTION;
156 break;
157
158 //case SOUP_STATUS_PAYMENT_REQUIRED:
159 case SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE:
160 case SOUP_STATUS_REQUEST_URI_TOO_LONG:
161 case SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE:
162 type = wxWEB_NAV_ERR_REQUEST;
163 break;
164
165 case SOUP_STATUS_BAD_GATEWAY:
166 case SOUP_STATUS_SERVICE_UNAVAILABLE:
167 case SOUP_STATUS_GATEWAY_TIMEOUT:
168 type = wxWEB_NAV_ERR_CONNECTION;
169 break;
170
171 case SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED:
172 type = wxWEB_NAV_ERR_REQUEST;
173 break;
174 //case SOUP_STATUS_INSUFFICIENT_STORAGE:
175 //case SOUP_STATUS_NOT_EXTENDED:
176 }
177 }
178 else if (strcmp(g_quark_to_string(error->domain),
179 "webkit-network-error-quark") == 0)
180 {
181 switch (error->code)
182 {
183 //WEBKIT_NETWORK_ERROR_FAILED:
184 //WEBKIT_NETWORK_ERROR_TRANSPORT:
185
186 case WEBKIT_NETWORK_ERROR_UNKNOWN_PROTOCOL:
187 type = wxWEB_NAV_ERR_REQUEST;
188 break;
189
190 case WEBKIT_NETWORK_ERROR_CANCELLED:
191 type = wxWEB_NAV_ERR_USER_CANCELLED;
192 break;
193
194 case WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST:
195 type = wxWEB_NAV_ERR_NOT_FOUND;
196 break;
197 }
198 }
199 else if (strcmp(g_quark_to_string(error->domain),
200 "webkit-policy-error-quark") == 0)
201 {
202 switch (error->code)
203 {
204 //case WEBKIT_POLICY_ERROR_FAILED:
205 //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE:
206 //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL:
207 //case WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE:
208 case WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT:
209 type = wxWEB_NAV_ERR_SECURITY;
210 break;
211 }
212 }
213 /*
214 webkit_plugin_error_quark
215 else
216 {
217 printf("Error domain %s\n", g_quark_to_string(error->domain));
218 }
219 */
220
221 wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR,
222 webKitWindow->GetId(),
223 uri,
224 wxEmptyString,
225 false);
226 thisEvent.SetString(description);
227 thisEvent.SetInt(type);
228
229 if (webKitWindow && webKitWindow->GetEventHandler())
230 {
231 webKitWindow->GetEventHandler()->ProcessEvent(thisEvent);
232 }
233
234 return FALSE;
235 }
236
237
238 } // extern "C"
239
240 //-----------------------------------------------------------------------------
241 // wxWebViewWebKit
242 //-----------------------------------------------------------------------------
243
244 //IMPLEMENT_DYNAMIC_CLASS(wxWebViewWebKit, wxControl)
245
246 bool wxWebViewWebKit::Create(wxWindow *parent,
247 wxWindowID id,
248 const wxString &url,
249 const wxPoint& pos,
250 const wxSize& size,
251 long style,
252 const wxString& name)
253 {
254 m_ready = false;
255 m_busy = false;
256
257 if (!PreCreation( parent, pos, size ) ||
258 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
259 {
260 wxFAIL_MSG( wxT("wxWebViewWebKit creation failed") );
261 return false;
262 }
263
264 GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
265 web_view = webkit_web_view_new ();
266 g_object_ref(web_view); // TODO: check memory management
267
268 m_widget = scrolled_window;
269 g_object_ref(m_widget); // TODO: check memory management
270
271 /* Place the WebKitWebView in the GtkScrolledWindow */
272 gtk_container_add (GTK_CONTAINER (scrolled_window), web_view);
273 gtk_widget_show(m_widget);
274 gtk_widget_show(web_view);
275
276 g_signal_connect_after(web_view, "notify::load-status",
277 G_CALLBACK(wxgtk_webkitctrl_load_status_callback),
278 this);
279 g_signal_connect_after(web_view, "navigation-requested",
280 G_CALLBACK(wxgtk_webkitctrl_navigation_requ_callback),
281 this);
282 g_signal_connect_after(web_view, "load-error",
283 G_CALLBACK(wxgtk_webkitctrl_error),
284 this);
285
286 // this signal can be added if we care about new frames open requests
287 //g_signal_connect_after(web_view, "new-window-policy-decision-requested",
288 // G_CALLBACK(...), this);
289
290 m_parent->DoAddChild( this );
291
292 PostCreation(size);
293
294 /* Open a webpage */
295 webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url);
296
297 m_ready = true;
298
299 return true;
300 }
301
302 bool wxWebViewWebKit::Enable( bool enable )
303 {
304 if (!wxControl::Enable(enable))
305 return false;
306
307 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
308
309 //if (enable)
310 // GTKFixSensitivity();
311
312 return true;
313 }
314
315 GdkWindow*
316 wxWebViewWebKit::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
317 {
318 GdkWindow* window = gtk_widget_get_parent_window(m_widget);
319 return window;
320 }
321
322 void wxWebViewWebKit::ZoomIn()
323 {
324 webkit_web_view_zoom_in (WEBKIT_WEB_VIEW(web_view));
325 }
326
327 void wxWebViewWebKit::ZoomOut()
328 {
329 webkit_web_view_zoom_out (WEBKIT_WEB_VIEW(web_view));
330 }
331
332 void wxWebViewWebKit::SetWebkitZoom(float level)
333 {
334 webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(web_view), level);
335 }
336
337 float wxWebViewWebKit::GetWebkitZoom()
338 {
339 return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW(web_view));
340 }
341
342 void wxWebViewWebKit::Stop()
343 {
344 webkit_web_view_stop_loading (WEBKIT_WEB_VIEW(web_view));
345 }
346
347 void wxWebViewWebKit::Reload(wxWebViewReloadFlags flags)
348 {
349 if (flags & wxWEB_VIEW_RELOAD_NO_CACHE)
350 {
351 webkit_web_view_reload_bypass_cache (WEBKIT_WEB_VIEW(web_view));
352 }
353 else
354 {
355 webkit_web_view_reload (WEBKIT_WEB_VIEW(web_view));
356 }
357 }
358
359 void wxWebViewWebKit::LoadUrl(const wxString& url)
360 {
361 webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), wxGTK_CONV(url));
362 }
363
364
365 void wxWebViewWebKit::GoBack()
366 {
367 webkit_web_view_go_back (WEBKIT_WEB_VIEW(web_view));
368 }
369
370 void wxWebViewWebKit::GoForward()
371 {
372 webkit_web_view_go_forward (WEBKIT_WEB_VIEW(web_view));
373 }
374
375
376 bool wxWebViewWebKit::CanGoBack()
377 {
378 return webkit_web_view_can_go_back (WEBKIT_WEB_VIEW(web_view));
379 }
380
381
382 bool wxWebViewWebKit::CanGoForward()
383 {
384 return webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW(web_view));
385 }
386
387
388 wxString wxWebViewWebKit::GetCurrentURL()
389 {
390 // FIXME: check which encoding the web kit control uses instead of
391 // assuming UTF8 (here and elsewhere too)
392 return wxString::FromUTF8(webkit_web_view_get_uri(
393 WEBKIT_WEB_VIEW(web_view)));
394 }
395
396
397 wxString wxWebViewWebKit::GetCurrentTitle()
398 {
399 return wxString::FromUTF8(webkit_web_view_get_title(
400 WEBKIT_WEB_VIEW(web_view)));
401 }
402
403
404 wxString wxWebViewWebKit::GetPageSource()
405 {
406 WebKitWebFrame* frame = webkit_web_view_get_main_frame(
407 WEBKIT_WEB_VIEW(web_view));
408 WebKitWebDataSource* src = webkit_web_frame_get_data_source (frame);
409
410 // TODO: check encoding with
411 // const gchar*
412 // webkit_web_data_source_get_encoding(WebKitWebDataSource *data_source);
413 return wxString(webkit_web_data_source_get_data (src)->str, wxConvUTF8);
414 }
415
416
417 wxWebViewZoom wxWebViewWebKit::GetZoom()
418 {
419 float zoom = GetWebkitZoom();
420
421 // arbitrary way to map float zoom to our common zoom enum
422 if (zoom <= 0.65)
423 {
424 return wxWEB_VIEW_ZOOM_TINY;
425 }
426 else if (zoom > 0.65 && zoom <= 0.90)
427 {
428 return wxWEB_VIEW_ZOOM_SMALL;
429 }
430 else if (zoom > 0.90 && zoom <= 1.15)
431 {
432 return wxWEB_VIEW_ZOOM_MEDIUM;
433 }
434 else if (zoom > 1.15 && zoom <= 1.45)
435 {
436 return wxWEB_VIEW_ZOOM_LARGE;
437 }
438 else if (zoom > 1.45)
439 {
440 return wxWEB_VIEW_ZOOM_LARGEST;
441 }
442
443 // to shut up compilers, this can never be reached logically
444 wxASSERT(false);
445 return wxWEB_VIEW_ZOOM_MEDIUM;
446 }
447
448
449 void wxWebViewWebKit::SetZoom(wxWebViewZoom zoom)
450 {
451 // arbitrary way to map our common zoom enum to float zoom
452 switch (zoom)
453 {
454 case wxWEB_VIEW_ZOOM_TINY:
455 SetWebkitZoom(0.6f);
456 break;
457
458 case wxWEB_VIEW_ZOOM_SMALL:
459 SetWebkitZoom(0.8f);
460 break;
461
462 case wxWEB_VIEW_ZOOM_MEDIUM:
463 SetWebkitZoom(1.0f);
464 break;
465
466 case wxWEB_VIEW_ZOOM_LARGE:
467 SetWebkitZoom(1.3);
468 break;
469
470 case wxWEB_VIEW_ZOOM_LARGEST:
471 SetWebkitZoom(1.6);
472 break;
473
474 default:
475 wxASSERT(false);
476 }
477 }
478
479 void wxWebViewWebKit::SetZoomType(wxWebViewZoomType type)
480 {
481 webkit_web_view_set_full_content_zoom(WEBKIT_WEB_VIEW(web_view),
482 (type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT ?
483 TRUE : FALSE));
484 }
485
486 wxWebViewZoomType wxWebViewWebKit::GetZoomType() const
487 {
488 gboolean fczoom = webkit_web_view_get_full_content_zoom(
489 WEBKIT_WEB_VIEW(web_view));
490
491 if (fczoom) return wxWEB_VIEW_ZOOM_TYPE_LAYOUT;
492 else return wxWEB_VIEW_ZOOM_TYPE_TEXT;
493 }
494
495 bool wxWebViewWebKit::CanSetZoomType(wxWebViewZoomType) const
496 {
497 // this port supports all zoom types
498 return true;
499 }
500
501 void wxWebViewWebKit::SetPage(const wxString& html, const wxString& baseUri)
502 {
503 webkit_web_view_load_string (WEBKIT_WEB_VIEW(web_view),
504 html.mb_str(wxConvUTF8),
505 "text/html",
506 "UTF-8",
507 baseUri.mb_str(wxConvUTF8));
508 }
509
510 void wxWebViewWebKit::Print()
511 {
512 WebKitWebFrame* frame = webkit_web_view_get_main_frame(
513 WEBKIT_WEB_VIEW(web_view));
514 webkit_web_frame_print (frame);
515
516 // GtkPrintOperationResult webkit_web_frame_print_full
517 // (WebKitWebFrame *frame,
518 // GtkPrintOperation *operation,
519 // GtkPrintOperationAction action,
520 // GError **error);
521
522 }
523
524
525 bool wxWebViewWebKit::IsBusy()
526 {
527 return m_busy;
528
529 // This code looks nice but returns true after a page was cancelled
530 /*
531 WebKitLoadStatus status = webkit_web_view_get_load_status
532 (WEBKIT_WEB_VIEW(web_view));
533
534
535 #if WEBKIT_CHECK_VERSION(1,1,16)
536 // WEBKIT_LOAD_FAILED is new in webkit 1.1.16
537 if (status == WEBKIT_LOAD_FAILED)
538 {
539 return false;
540 }
541 #endif
542 if (status == WEBKIT_LOAD_FINISHED)
543 {
544 return false;
545 }
546
547 return true;
548 */
549 }
550
551 // static
552 wxVisualAttributes
553 wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
554 {
555 return GetDefaultAttributesFromGTKWidget(webkit_web_view_new);
556 }
557
558
559 #endif // wxHAVE_WEB_BACKEND_GTK_WEBKIT