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