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