2009-03-28 Jan Michael Alonzo <jmalonzo@webkit.org>
[WebKit-https.git] / WebKit / gtk / webkit / webkitwebview.cpp
1 /*
2  *  Copyright (C) 2007, 2008 Holger Hans Peter Freyther
3  *  Copyright (C) 2007, 2008, 2009 Christian Dywan <christian@imendio.com>
4  *  Copyright (C) 2007 Xan Lopez <xan@gnome.org>
5  *  Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
6  *  Copyright (C) 2008 Jan Alonzo <jmalonzo@unpluggable.com>
7  *  Copyright (C) 2008 Gustavo Noronha Silva <gns@gnome.org>
8  *  Copyright (C) 2008 Nuanti Ltd.
9  *  Copyright (C) 2008 Collabora Ltd.
10  *  Copyright (C) 2009 Igalia S.L.
11  *
12  *  This library is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public
14  *  License as published by the Free Software Foundation; either
15  *  version 2 of the License, or (at your option) any later version.
16  *
17  *  This library is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  *  Lesser General Public License for more details.
21  *
22  *  You should have received a copy of the GNU Lesser General Public
23  *  License along with this library; if not, write to the Free Software
24  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
25  */
26
27 #include "config.h"
28
29 #include "webkitdownload.h"
30 #include "webkitwebview.h"
31 #include "webkitenumtypes.h"
32 #include "webkitmarshal.h"
33 #include "webkitprivate.h"
34 #include "webkitwebinspector.h"
35 #include "webkitwebbackforwardlist.h"
36 #include "webkitwebhistoryitem.h"
37
38 #include "AXObjectCache.h"
39 #include "NotImplemented.h"
40 #include "BackForwardList.h"
41 #include "CString.h"
42 #include "ChromeClientGtk.h"
43 #include "ContextMenu.h"
44 #include "ContextMenuClientGtk.h"
45 #include "ContextMenuController.h"
46 #include "Cursor.h"
47 #include "Document.h"
48 #include "DocumentLoader.h"
49 #include "DragClientGtk.h"
50 #include "Editor.h"
51 #include "EditorClientGtk.h"
52 #include "EventHandler.h"
53 #include "FloatQuad.h"
54 #include "FocusController.h"
55 #include "FrameLoaderTypes.h"
56 #include "HitTestRequest.h"
57 #include "HitTestResult.h"
58 #include "GraphicsContext.h"
59 #include "InspectorClientGtk.h"
60 #include "FrameLoader.h"
61 #include "FrameView.h"
62 #include "PasteboardHelper.h"
63 #include "PlatformKeyboardEvent.h"
64 #include "PlatformWheelEvent.h"
65 #include "ResourceHandle.h"
66 #include "ScriptValue.h"
67 #include "Scrollbar.h"
68 #include <wtf/GOwnPtr.h>
69
70 #include <gdk/gdkkeysyms.h>
71
72 /**
73  * SECTION:webkitwebview
74  * @short_description: The central class of the WebKit/Gtk+ API
75  * @see_also: #WebKitWebSettings, #WebKitWebFrame
76  *
77  * #WebKitWebView is the central class of the WebKit/Gtk+ API. It is a
78  * #GtkWidget implementing the scrolling interface which means you can
79  * embed in a #GtkScrolledWindow. It is responsible for managing the
80  * drawing of the content, forwarding of events. You can load any URI
81  * into the #WebKitWebView or any kind of data string. With #WebKitWebSettings
82  * you can control various aspects of the rendering and loading of the content.
83  * Each #WebKitWebView has exactly one #WebKitWebFrame as main frame. A
84  * #WebKitWebFrame can have n children.
85  *
86  * <programlisting>
87  * /<!-- -->* Create the widgets *<!-- -->/
88  * GtkWidget *main_window = gtk_window_new (GTK_WIDGET_TOPLEVEL);
89  * GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
90  * GtkWidget *web_view = webkit_web_view_new ();
91  *
92  * /<!-- -->* Place the WebKitWebView in the GtkScrolledWindow *<!-- -->/
93  * gtk_container_add (GTK_CONTAINER (scrolled_window), web_view);
94  * gtk_container_add (GTK_CONTAINER (main_window), scrolled_window);
95  *
96  * /<!-- -->* Open a webpage *<!-- -->/
97  * webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), "http://www.gnome.org");
98  *
99  * /<!-- -->* Show the result *<!-- -->/
100  * gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);
101  * gtk_widget_show_all (main_window);
102  * </programlisting>
103  */
104
105 static const double defaultDPI = 96.0;
106
107 using namespace WebKit;
108 using namespace WebCore;
109
110 extern "C" {
111
112 enum {
113     /* normal signals */
114     NAVIGATION_REQUESTED,
115     NEW_WINDOW_POLICY_DECISION_REQUESTED,
116     NAVIGATION_POLICY_DECISION_REQUESTED,
117     MIME_TYPE_POLICY_DECISION_REQUESTED,
118     CREATE_WEB_VIEW,
119     WEB_VIEW_READY,
120     WINDOW_OBJECT_CLEARED,
121     LOAD_STARTED,
122     LOAD_COMMITTED,
123     LOAD_PROGRESS_CHANGED,
124     LOAD_FINISHED,
125     TITLE_CHANGED,
126     HOVERING_OVER_LINK,
127     POPULATE_POPUP,
128     STATUS_BAR_TEXT_CHANGED,
129     ICOND_LOADED,
130     SELECTION_CHANGED,
131     CONSOLE_MESSAGE,
132     SCRIPT_ALERT,
133     SCRIPT_CONFIRM,
134     SCRIPT_PROMPT,
135     SELECT_ALL,
136     COPY_CLIPBOARD,
137     PASTE_CLIPBOARD,
138     CUT_CLIPBOARD,
139     DOWNLOAD_REQUESTED,
140     LAST_SIGNAL
141 };
142
143 enum {
144     PROP_0,
145
146     PROP_TITLE,
147     PROP_URI,
148     PROP_COPY_TARGET_LIST,
149     PROP_PASTE_TARGET_LIST,
150     PROP_EDITABLE,
151     PROP_SETTINGS,
152     PROP_WEB_INSPECTOR,
153     PROP_WINDOW_FEATURES,
154     PROP_TRANSPARENT,
155     PROP_ZOOM_LEVEL,
156     PROP_FULL_CONTENT_ZOOM,
157     PROP_ENCODING,
158     PROP_CUSTOM_ENCODING
159 };
160
161 static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, };
162
163 G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)
164
165 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView);
166 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures);
167
168 static void webkit_web_view_context_menu_position_func(GtkMenu*, gint* x, gint* y, gboolean* pushIn, WebKitWebViewPrivate* data)
169 {
170     *pushIn = FALSE;
171     *x = data->lastPopupXPosition;
172     *y = data->lastPopupYPosition;
173 }
174
175 static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
176 {
177     Page* page = core(webView);
178     page->contextMenuController()->clearContextMenu();
179     Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
180
181     if (!focusedFrame->view())
182         return FALSE;
183
184     focusedFrame->view()->setCursor(pointerCursor());
185     bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
186     if (!handledEvent)
187         return FALSE;
188
189     ContextMenu* coreMenu = page->contextMenuController()->contextMenu();
190     if (!coreMenu)
191         return FALSE;
192
193     GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
194     if (!menu)
195         return FALSE;
196
197     g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
198
199     GList* items = gtk_container_get_children(GTK_CONTAINER(menu));
200     bool empty = !g_list_nth(items, 0);
201     g_list_free(items);
202     if (empty)
203         return FALSE;
204
205     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
206     priv->lastPopupXPosition = event.globalX();
207     priv->lastPopupYPosition = event.globalY();
208     gtk_menu_popup(menu, NULL, NULL,
209                    reinterpret_cast<GtkMenuPositionFunc>(webkit_web_view_context_menu_position_func),
210                    priv, event.button() + 1, gtk_get_current_event_time());
211     return TRUE;
212 }
213
214 static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget)
215 {
216     static const int contextMenuMargin = 1;
217
218     // The context menu event was generated from the keyboard, so show the context menu by the current selection.
219     Page* page = core(WEBKIT_WEB_VIEW(widget));
220     FrameView* view = page->mainFrame()->view();
221     if (!view)
222         return FALSE;    
223
224     Position start = page->mainFrame()->selection()->selection().start();
225     Position end = page->mainFrame()->selection()->selection().end();
226
227     int rightAligned = FALSE;
228     IntPoint location;
229
230     if (!start.node() || !end.node())
231         location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
232     else {
233         RenderObject* renderer = start.node()->renderer();
234         if (!renderer)
235             return FALSE;
236
237         // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:],
238         // now Frame::firstRectForRange(), which perhaps this should call).
239         int extraWidthToEndOfLine = 0;
240
241         InlineBox* startInlineBox;
242         int startCaretOffset;
243         start.getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
244         IntRect startCaretRect = renderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
245         if (startCaretRect != IntRect())
246             startCaretRect = renderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox();
247
248         InlineBox* endInlineBox;
249         int endCaretOffset;
250         end.getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
251         IntRect endCaretRect = renderer->localCaretRect(endInlineBox, endCaretOffset);
252         if (endCaretRect != IntRect())
253             endCaretRect = renderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox();
254
255         IntRect firstRect;
256         if (startCaretRect.y() == endCaretRect.y())
257             firstRect = IntRect(MIN(startCaretRect.x(), endCaretRect.x()),
258                                 startCaretRect.y(),
259                                 abs(endCaretRect.x() - startCaretRect.x()),
260                                 MAX(startCaretRect.height(), endCaretRect.height()));
261         else
262             firstRect = IntRect(startCaretRect.x(),
263                                 startCaretRect.y(),
264                                 startCaretRect.width() + extraWidthToEndOfLine,
265                                 startCaretRect.height());
266
267         location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
268     }
269
270     int x, y;
271     gdk_window_get_origin(GTK_WIDGET(view->hostWindow()->platformWindow())->window, &x, &y);
272
273     // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
274     // Ideally we'd have the position of a context menu event be separate from its target node.
275     location = view->contentsToWindow(location) + IntSize(0, -1);
276     IntPoint global = location + IntSize(x, y);
277     PlatformMouseEvent event(location, global, NoButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time());
278
279     return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
280 }
281
282 static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
283 {
284     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
285
286     switch(prop_id) {
287     case PROP_TITLE:
288         g_value_set_string(value, webkit_web_view_get_title(webView));
289         break;
290     case PROP_URI:
291         g_value_set_string(value, webkit_web_view_get_uri(webView));
292         break;
293 #if GTK_CHECK_VERSION(2,10,0)
294     case PROP_COPY_TARGET_LIST:
295         g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView));
296         break;
297     case PROP_PASTE_TARGET_LIST:
298         g_value_set_boxed(value, webkit_web_view_get_paste_target_list(webView));
299         break;
300 #endif
301     case PROP_EDITABLE:
302         g_value_set_boolean(value, webkit_web_view_get_editable(webView));
303         break;
304     case PROP_SETTINGS:
305         g_value_set_object(value, webkit_web_view_get_settings(webView));
306         break;
307     case PROP_WEB_INSPECTOR:
308         g_value_set_object(value, webkit_web_view_get_inspector(webView));
309         break;
310     case PROP_WINDOW_FEATURES:
311         g_value_set_object(value, webkit_web_view_get_window_features(webView));
312         break;
313     case PROP_TRANSPARENT:
314         g_value_set_boolean(value, webkit_web_view_get_transparent(webView));
315         break;
316     case PROP_ZOOM_LEVEL:
317         g_value_set_float(value, webkit_web_view_get_zoom_level(webView));
318         break;
319     case PROP_FULL_CONTENT_ZOOM:
320         g_value_set_boolean(value, webkit_web_view_get_full_content_zoom(webView));
321         break;
322     case PROP_ENCODING:
323         g_value_set_string(value, webkit_web_view_get_encoding(webView));
324         break;
325     case PROP_CUSTOM_ENCODING:
326         g_value_set_string(value, webkit_web_view_get_custom_encoding(webView));
327         break;
328     default:
329         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
330     }
331 }
332
333 static void webkit_web_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec)
334 {
335     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
336
337     switch(prop_id) {
338     case PROP_EDITABLE:
339         webkit_web_view_set_editable(webView, g_value_get_boolean(value));
340         break;
341     case PROP_SETTINGS:
342         webkit_web_view_set_settings(webView, WEBKIT_WEB_SETTINGS(g_value_get_object(value)));
343         break;
344     case PROP_WINDOW_FEATURES:
345         webkit_web_view_set_window_features(webView, WEBKIT_WEB_WINDOW_FEATURES(g_value_get_object(value)));
346         break;
347     case PROP_TRANSPARENT:
348         webkit_web_view_set_transparent(webView, g_value_get_boolean(value));
349         break;
350     case PROP_ZOOM_LEVEL:
351         webkit_web_view_set_zoom_level(webView, g_value_get_float(value));
352         break;
353     case PROP_FULL_CONTENT_ZOOM:
354         webkit_web_view_set_full_content_zoom(webView, g_value_get_boolean(value));
355         break;
356     case PROP_CUSTOM_ENCODING:
357         webkit_web_view_set_custom_encoding(webView, g_value_get_string(value));
358         break;
359     default:
360         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
361     }
362 }
363
364 static bool shouldCoalesce(GdkRectangle rect, GdkRectangle* rects, int count)
365 {
366     const int cRectThreshold = 10;
367     const float cWastedSpaceThreshold = 0.75f;
368     bool useUnionedRect = (count <= 1) || (count > cRectThreshold);
369     if (!useUnionedRect) {
370         // Attempt to guess whether or not we should use the unioned rect or the individual rects.
371         // We do this by computing the percentage of "wasted space" in the union.  If that wasted space
372         // is too large, then we will do individual rect painting instead.
373         float unionPixels = (rect.width * rect.height);
374         float singlePixels = 0;
375         for (int i = 0; i < count; ++i)
376             singlePixels += rects[i].width * rects[i].height;
377         float wastedSpace = 1 - (singlePixels / unionPixels);
378         if (wastedSpace <= cWastedSpaceThreshold)
379             useUnionedRect = true;
380     }
381     return useUnionedRect;
382 }
383
384 static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
385 {
386     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
387     WebKitWebViewPrivate* priv = webView->priv;
388
389     Frame* frame = core(webView)->mainFrame();
390     if (frame->contentRenderer() && frame->view()) {
391         frame->view()->layoutIfNeededRecursive();
392
393         cairo_t* cr = gdk_cairo_create(event->window);
394         GraphicsContext ctx(cr);
395         cairo_destroy(cr);
396         ctx.setGdkExposeEvent(event);
397
398         GOwnPtr<GdkRectangle> rects;
399         int rectCount;
400         gdk_region_get_rectangles(event->region, &rects.outPtr(), &rectCount);
401
402         // Avoid recursing into the render tree excessively
403         bool coalesce = shouldCoalesce(event->area, rects.get(), rectCount);
404
405         if (coalesce) {
406             IntRect rect = event->area;
407             ctx.clip(rect);
408             if (priv->transparent)
409                 ctx.clearRect(rect);
410             frame->view()->paint(&ctx, rect);
411         } else {
412             for (int i = 0; i < rectCount; i++) {
413                 IntRect rect = rects.get()[i];
414                 ctx.save();
415                 ctx.clip(rect);
416                 if (priv->transparent)
417                     ctx.clearRect(rect);
418                 frame->view()->paint(&ctx, rect);
419                 ctx.restore();
420             }
421         }
422     }
423
424     return FALSE;
425 }
426
427 static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* event)
428 {
429     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
430
431     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
432     PlatformKeyboardEvent keyboardEvent(event);
433
434     if (!frame->view())
435         return FALSE;
436
437     if (frame->eventHandler()->keyEvent(keyboardEvent))
438         return TRUE;
439
440     FrameView* view = frame->view();
441     SelectionController::EAlteration alteration;
442     if (event->state & GDK_SHIFT_MASK)
443         alteration = SelectionController::EXTEND;
444     else
445         alteration = SelectionController::MOVE;
446
447     // TODO: We probably want to use GTK+ key bindings here and perhaps take an
448     // approach more like the Win and Mac ports for key handling.
449     switch (event->keyval) {
450     case GDK_Down:
451         view->scrollBy(IntSize(0, cScrollbarPixelsPerLineStep));
452         return TRUE;
453     case GDK_Up:
454         view->scrollBy(IntSize(0, -cScrollbarPixelsPerLineStep));
455         return TRUE;
456     case GDK_Right:
457         view->scrollBy(IntSize(cScrollbarPixelsPerLineStep, 0));
458         return TRUE;
459     case GDK_Left:
460         view->scrollBy(IntSize(-cScrollbarPixelsPerLineStep, 0));
461         return TRUE;
462     case GDK_space:
463         if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
464             view->scrollBy(IntSize(0, -view->visibleHeight()));
465         else
466             view->scrollBy(IntSize(0, view->visibleHeight()));
467         return TRUE;
468     case GDK_Page_Up:
469         view->scrollBy(IntSize(0, -view->visibleHeight()));
470         return TRUE;
471     case GDK_Page_Down:
472         view->scrollBy(IntSize(0, view->visibleHeight()));
473         return TRUE;
474     case GDK_Home:
475         view->scrollBy(IntSize(0, -view->contentsHeight()));
476         return TRUE;
477     case GDK_End:
478         view->scrollBy(IntSize(0, view->contentsHeight()));
479         return TRUE;
480     }
481
482     /* Chain up to our parent class for binding activation */
483     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_press_event(widget, event);
484 }
485
486 static gboolean webkit_web_view_key_release_event(GtkWidget* widget, GdkEventKey* event)
487 {
488     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
489
490     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
491     if (!frame->view())
492         return FALSE;
493
494     PlatformKeyboardEvent keyboardEvent(event);
495
496     if (frame->eventHandler()->keyEvent(keyboardEvent))
497         return TRUE;
498
499     /* Chain up to our parent class for binding activation */
500     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_release_event(widget, event);
501 }
502
503 static gboolean webkit_web_view_button_press_event(GtkWidget* widget, GdkEventButton* event)
504 {
505     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
506
507     // FIXME: need to keep track of subframe focus for key events
508     gtk_widget_grab_focus(widget);
509
510     if (event->button == 3)
511         return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
512
513     Frame* frame = core(webView)->mainFrame();
514     if (!frame->view())
515         return FALSE;
516
517     return frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
518 }
519
520 static gboolean webkit_web_view_button_release_event(GtkWidget* widget, GdkEventButton* event)
521 {
522     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
523
524     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
525
526     if (focusedFrame && focusedFrame->editor()->canEdit()) {
527 #ifdef MAEMO_CHANGES
528         WebKitWebViewPrivate* priv = webView->priv;
529         hildon_gtk_im_context_filter_event(priv->imContext, (GdkEvent*)event);
530 #endif
531     }
532
533     Frame* mainFrame = core(webView)->mainFrame();
534     if (mainFrame->view())
535         mainFrame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
536
537     /* We always return FALSE here because WebKit can, for the same click, decide
538      * to not handle press-event but handle release-event, which can totally confuse
539      * some GTK+ containers when there are no other events in between. This way we
540      * guarantee that this case never happens, and that if press-event goes through
541      * release-event also goes through.
542      */
543
544     return FALSE;
545 }
546
547 static gboolean webkit_web_view_motion_event(GtkWidget* widget, GdkEventMotion* event)
548 {
549     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
550
551     Frame* frame = core(webView)->mainFrame();
552     if (!frame->view())
553         return FALSE;
554
555     return frame->eventHandler()->mouseMoved(PlatformMouseEvent(event));
556 }
557
558 static gboolean webkit_web_view_scroll_event(GtkWidget* widget, GdkEventScroll* event)
559 {
560     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
561
562     Frame* frame = core(webView)->mainFrame();
563     if (!frame->view())
564         return FALSE;
565
566     PlatformWheelEvent wheelEvent(event);
567     return frame->eventHandler()->handleWheelEvent(wheelEvent);
568 }
569
570 static void webkit_web_view_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
571 {
572     GTK_WIDGET_CLASS(webkit_web_view_parent_class)->size_allocate(widget,allocation);
573
574     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
575
576     Frame* frame = core(webView)->mainFrame();
577     if (!frame->view())
578         return;
579
580     frame->view()->resize(allocation->width, allocation->height);
581     frame->view()->forceLayout();
582     frame->view()->adjustViewSize();
583 }
584
585 static gboolean webkit_web_view_focus_in_event(GtkWidget* widget, GdkEventFocus* event)
586 {
587     // TODO: Improve focus handling as suggested in
588     // http://bugs.webkit.org/show_bug.cgi?id=16910
589     GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
590     if (GTK_WIDGET_TOPLEVEL(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) {
591         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
592
593         Frame* frame = core(webView)->mainFrame();
594         core(webView)->focusController()->setActive(frame);
595     }
596     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_in_event(widget, event);
597 }
598
599 static gboolean webkit_web_view_focus_out_event(GtkWidget* widget, GdkEventFocus* event)
600 {
601     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
602
603     core(webView)->focusController()->setActive(false);
604
605     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_out_event(widget, event);
606 }
607
608 static void webkit_web_view_realize(GtkWidget* widget)
609 {
610     GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
611
612     GdkWindowAttr attributes;
613     attributes.window_type = GDK_WINDOW_CHILD;
614     attributes.x = widget->allocation.x;
615     attributes.y = widget->allocation.y;
616     attributes.width = widget->allocation.width;
617     attributes.height = widget->allocation.height;
618     attributes.wclass = GDK_INPUT_OUTPUT;
619     attributes.visual = gtk_widget_get_visual (widget);
620     attributes.colormap = gtk_widget_get_colormap (widget);
621     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
622                             | GDK_EXPOSURE_MASK
623                             | GDK_BUTTON_PRESS_MASK
624                             | GDK_BUTTON_RELEASE_MASK
625                             | GDK_POINTER_MOTION_MASK
626                             | GDK_KEY_PRESS_MASK
627                             | GDK_KEY_RELEASE_MASK
628                             | GDK_BUTTON_MOTION_MASK
629                             | GDK_BUTTON1_MOTION_MASK
630                             | GDK_BUTTON2_MOTION_MASK
631                             | GDK_BUTTON3_MOTION_MASK;
632
633     gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
634     widget->window = gdk_window_new(gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
635     gdk_window_set_user_data(widget->window, widget);
636
637     widget->style = gtk_style_attach(widget->style, widget->window);
638     gdk_window_set_background(widget->window, &widget->style->base[GTK_WIDGET_STATE(widget)]);
639
640     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
641     WebKitWebViewPrivate* priv = webView->priv;
642     gtk_im_context_set_client_window(priv->imContext, widget->window);
643 }
644
645 static void webkit_web_view_set_scroll_adjustments(WebKitWebView* webView, GtkAdjustment* hadj, GtkAdjustment* vadj)
646 {
647     if (!core(webView))
648         return;
649
650     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
651
652     if (hadj)
653         g_object_ref(hadj);
654     if (vadj)
655         g_object_ref(vadj);
656
657     WebKitWebViewPrivate* priv = webView->priv;
658
659     if (priv->horizontalAdjustment)
660         g_object_unref(priv->horizontalAdjustment);
661     if (priv->verticalAdjustment)
662         g_object_unref(priv->verticalAdjustment);
663
664     priv->horizontalAdjustment = hadj;
665     priv->verticalAdjustment = vadj;
666
667     if (!view)
668         return;
669
670     view->setGtkAdjustments(hadj, vadj);
671 }
672
673 static void webkit_web_view_container_add(GtkContainer* container, GtkWidget* widget)
674 {
675     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
676     WebKitWebViewPrivate* priv = webView->priv;
677
678     priv->children.add(widget);
679     if (GTK_WIDGET_REALIZED(container))
680         gtk_widget_set_parent_window(widget, GTK_WIDGET(webView)->window);
681     gtk_widget_set_parent(widget, GTK_WIDGET(container));
682 }
683
684 static void webkit_web_view_container_remove(GtkContainer* container, GtkWidget* widget)
685 {
686     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
687     WebKitWebViewPrivate* priv = webView->priv;
688
689     if (priv->children.contains(widget)) {
690         gtk_widget_unparent(widget);
691         priv->children.remove(widget);
692     }
693 }
694
695 static void webkit_web_view_container_forall(GtkContainer* container, gboolean, GtkCallback callback, gpointer callbackData)
696 {
697     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
698     WebKitWebViewPrivate* priv = webView->priv;
699
700     HashSet<GtkWidget*> children = priv->children;
701     HashSet<GtkWidget*>::const_iterator end = children.end();
702     for (HashSet<GtkWidget*>::const_iterator current = children.begin(); current != end; ++current)
703         (*callback)(*current, callbackData);
704 }
705
706 static WebKitWebView* webkit_web_view_real_create_web_view(WebKitWebView*, WebKitWebFrame*)
707 {
708     return 0;
709 }
710
711 static gboolean webkit_web_view_real_web_view_ready(WebKitWebView*)
712 {
713     return FALSE;
714 }
715
716 static WebKitNavigationResponse webkit_web_view_real_navigation_requested(WebKitWebView*, WebKitWebFrame*, WebKitNetworkRequest*)
717 {
718     return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
719 }
720
721 static void webkit_web_view_real_window_object_cleared(WebKitWebView*, WebKitWebFrame*, JSGlobalContextRef context, JSObjectRef window_object)
722 {
723     notImplemented();
724 }
725
726 static gchar* webkit_web_view_real_choose_file(WebKitWebView*, WebKitWebFrame*, const gchar* old_name)
727 {
728     notImplemented();
729     return g_strdup(old_name);
730 }
731
732 typedef enum {
733     WEBKIT_SCRIPT_DIALOG_ALERT,
734     WEBKIT_SCRIPT_DIALOG_CONFIRM,
735     WEBKIT_SCRIPT_DIALOG_PROMPT
736  } WebKitScriptDialogType;
737
738 static gboolean webkit_web_view_script_dialog(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, WebKitScriptDialogType type, const gchar* defaultValue, gchar** value)
739 {
740     GtkMessageType messageType;
741     GtkButtonsType buttons;
742     gint defaultResponse;
743     GtkWidget* window;
744     GtkWidget* dialog;
745     GtkWidget* entry = 0;
746     gboolean didConfirm = FALSE;
747
748     switch (type) {
749     case WEBKIT_SCRIPT_DIALOG_ALERT:
750         messageType = GTK_MESSAGE_WARNING;
751         buttons = GTK_BUTTONS_CLOSE;
752         defaultResponse = GTK_RESPONSE_CLOSE;
753         break;
754     case WEBKIT_SCRIPT_DIALOG_CONFIRM:
755         messageType = GTK_MESSAGE_QUESTION;
756         buttons = GTK_BUTTONS_YES_NO;
757         defaultResponse = GTK_RESPONSE_YES;
758         break;
759     case WEBKIT_SCRIPT_DIALOG_PROMPT:
760         messageType = GTK_MESSAGE_QUESTION;
761         buttons = GTK_BUTTONS_OK_CANCEL;
762         defaultResponse = GTK_RESPONSE_OK;
763         break;
764     default:
765         g_warning("Unknown value for WebKitScriptDialogType.");
766         return FALSE;
767     }
768
769     window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
770     dialog = gtk_message_dialog_new(GTK_WIDGET_TOPLEVEL(window) ? GTK_WINDOW(window) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, messageType, buttons, "%s", message);
771     gchar* title = g_strconcat("JavaScript - ", webkit_web_frame_get_uri(frame), NULL);
772     gtk_window_set_title(GTK_WINDOW(dialog), title);
773     g_free(title);
774
775     if (type == WEBKIT_SCRIPT_DIALOG_PROMPT) {
776         entry = gtk_entry_new();
777         gtk_entry_set_text(GTK_ENTRY(entry), defaultValue);
778         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry);
779         gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
780         gtk_widget_show(entry);
781     }
782
783     gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
784     gint response = gtk_dialog_run(GTK_DIALOG(dialog));
785
786     switch (response) {
787     case GTK_RESPONSE_YES:
788         didConfirm = TRUE;
789         break;
790     case GTK_RESPONSE_OK:
791         didConfirm = TRUE;
792         if (entry)
793             *value = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
794         else
795             *value = 0;
796         break;
797     case GTK_RESPONSE_NO:
798     case GTK_RESPONSE_CANCEL:
799         didConfirm = FALSE;
800         break;
801
802     }
803     gtk_widget_destroy(GTK_WIDGET(dialog));
804     return didConfirm;
805 }
806
807 static gboolean webkit_web_view_real_script_alert(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message)
808 {
809     webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_ALERT, 0, 0);
810     return TRUE;
811 }
812
813 static gboolean webkit_web_view_real_script_confirm(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm)
814 {
815     *didConfirm = webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_CONFIRM, 0, 0);
816     return TRUE;
817 }
818
819 static gboolean webkit_web_view_real_script_prompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value)
820 {
821     if (!webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_PROMPT, defaultValue, value))
822         *value = NULL;
823     return TRUE;
824 }
825
826 static gboolean webkit_web_view_real_console_message(WebKitWebView* webView, const gchar* message, unsigned int line, const gchar* sourceId)
827 {
828     g_print("console message: %s @%d: %s\n", sourceId, line, message);
829     return TRUE;
830 }
831
832 static void webkit_web_view_real_select_all(WebKitWebView* webView)
833 {
834     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
835     frame->editor()->command("SelectAll").execute();
836 }
837
838 static void webkit_web_view_real_cut_clipboard(WebKitWebView* webView)
839 {
840     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
841     frame->editor()->command("Cut").execute();
842 }
843
844 static void webkit_web_view_real_copy_clipboard(WebKitWebView* webView)
845 {
846     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
847     frame->editor()->command("Copy").execute();
848 }
849
850 static void webkit_web_view_real_paste_clipboard(WebKitWebView* webView)
851 {
852     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
853     frame->editor()->command("Paste").execute();
854 }
855
856 static void webkit_web_view_dispose(GObject* object)
857 {
858     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
859     WebKitWebViewPrivate* priv = webView->priv;
860
861     priv->disposing = TRUE;
862
863     if (priv->corePage) {
864         webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(object));
865
866         core(priv->mainFrame)->loader()->detachFromParent();
867         delete priv->corePage;
868         priv->corePage = NULL;
869     }
870
871     if (priv->horizontalAdjustment) {
872         g_object_unref(priv->horizontalAdjustment);
873         priv->horizontalAdjustment = NULL;
874     }
875
876     if (priv->verticalAdjustment) {
877         g_object_unref(priv->verticalAdjustment);
878         priv->verticalAdjustment = NULL;
879     }
880
881     if (priv->backForwardList) {
882         g_object_unref(priv->backForwardList);
883         priv->backForwardList = NULL;
884
885         g_signal_handlers_disconnect_by_func(priv->webSettings, (gpointer)webkit_web_view_settings_notify, webView);
886         g_object_unref(priv->webSettings);
887         priv->webSettings = NULL;
888
889         g_object_unref(priv->webInspector);
890         priv->webInspector = NULL;
891
892         g_object_unref(priv->webWindowFeatures);
893         priv->webWindowFeatures = NULL;
894
895         g_object_unref(priv->imContext);
896         priv->imContext = NULL;
897
898         gtk_target_list_unref(priv->copy_target_list);
899         priv->copy_target_list = NULL;
900
901         gtk_target_list_unref(priv->paste_target_list);
902         priv->paste_target_list = NULL;
903
904         delete priv->userAgent;
905         priv->userAgent = NULL;
906     }
907
908     G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object);
909 }
910
911 static void webkit_web_view_finalize(GObject* object)
912 {
913     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
914     WebKitWebViewPrivate* priv = webView->priv;
915
916     g_free(priv->encoding);
917     g_free(priv->customEncoding);
918
919     G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
920 }
921
922 static gboolean webkit_create_web_view_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
923 {
924     gpointer newWebView = g_value_get_object(handlerReturn);
925     g_value_set_object(returnAccu, newWebView);
926
927     // Continue if we don't have a newWebView
928     return !newWebView;
929 }
930
931 static gboolean webkit_navigation_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
932 {
933     WebKitNavigationResponse navigationResponse = (WebKitNavigationResponse)g_value_get_enum(handlerReturn);
934     g_value_set_enum(returnAccu, navigationResponse);
935
936     if (navigationResponse != WEBKIT_NAVIGATION_RESPONSE_ACCEPT)
937         return FALSE;
938
939     return TRUE;
940 }
941
942 static AtkObject* webkit_web_view_get_accessible(GtkWidget* widget)
943 {
944     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
945     if (!core(webView))
946         return NULL;
947
948     AXObjectCache::enableAccessibility();
949
950     Frame* coreFrame = core(webView)->mainFrame();
951     if (!coreFrame)
952         return NULL;
953
954     Document* doc = coreFrame->document();
955     if (!doc)
956         return NULL;
957
958     AccessibilityObject* coreAccessible = doc->axObjectCache()->get(doc->renderer());
959     if (!coreAccessible || !coreAccessible->wrapper())
960         return NULL;
961
962     return coreAccessible->wrapper();
963 }
964
965 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
966 {
967     GtkBindingSet* binding_set;
968
969     webkit_init();
970
971     /*
972      * Signals
973      */
974
975     /**
976      * WebKitWebView::create-web-view:
977      * @web_view: the object on which the signal is emitted
978      * @frame: the #WebKitWebFrame
979      * @return: a newly allocated #WebKitWebView or %NULL
980      *
981      * Emitted when the creation of a new window is requested.
982      * If this signal is handled the signal handler should return the
983      * newly created #WebKitWebView.
984      *
985      * The new #WebKitWebView should not be displayed to the user
986      * until the #WebKitWebView::web-view-ready signal is emitted.
987      *
988      * The signal handlers should not try to deal with the reference
989      * count for the new #WebKitWebView. The widget to which the
990      * widget is added will handle that.
991      *
992      * Since 1.0.3
993      */
994     webkit_web_view_signals[CREATE_WEB_VIEW] = g_signal_new("create-web-view",
995             G_TYPE_FROM_CLASS(webViewClass),
996             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
997             G_STRUCT_OFFSET (WebKitWebViewClass, create_web_view),
998             webkit_create_web_view_request_handled,
999             NULL,
1000             webkit_marshal_OBJECT__OBJECT,
1001             WEBKIT_TYPE_WEB_VIEW , 1,
1002             WEBKIT_TYPE_WEB_FRAME);
1003
1004     /**
1005      * WebKitWebView::web-view-ready:
1006      * @web_view: the object on which the signal is emitted
1007      * @return: %TRUE to stop other handlers from being invoked for
1008      * the event, %FALSE to propagate the event further
1009      *
1010      * Emitted after #WebKitWebView::create-web-view when the new #WebKitWebView
1011      * should be displayed to the user. When this signal is emitted
1012      * all the information about how the window should look, including
1013      * size, position, whether the location, status and scroll bars
1014      * should be displayed, is already set on the
1015      * #WebKitWebWindowFeatures object contained by the #WebKitWebView.
1016      *
1017      * Notice that some of that information may change during the life
1018      * time of the window, so you may want to connect to the ::notify
1019      * signal of the #WebKitWebWindowFeatures object to handle those.
1020      *
1021      * Since 1.0.3
1022      */
1023     webkit_web_view_signals[WEB_VIEW_READY] = g_signal_new("web-view-ready",
1024             G_TYPE_FROM_CLASS(webViewClass),
1025             (GSignalFlags)(G_SIGNAL_RUN_LAST),
1026             G_STRUCT_OFFSET (WebKitWebViewClass, web_view_ready),
1027             g_signal_accumulator_true_handled,
1028             NULL,
1029             webkit_marshal_BOOLEAN__VOID,
1030             G_TYPE_BOOLEAN, 0);
1031
1032     /**
1033      * WebKitWebView::navigation-requested:
1034      * @web_view: the object on which the signal is emitted
1035      * @frame: the #WebKitWebFrame that required the navigation
1036      * @request: a #WebKitNetworkRequest
1037      * @return: a WebKitNavigationResponse
1038      *
1039      * Emitted when @frame requests a navigation to another page.
1040      *
1041      * Deprecated: Use WebKitWebView::navigation-policy-decision-requested
1042      * instead
1043      */
1044     webkit_web_view_signals[NAVIGATION_REQUESTED] = g_signal_new("navigation-requested",
1045             G_TYPE_FROM_CLASS(webViewClass),
1046             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1047             G_STRUCT_OFFSET (WebKitWebViewClass, navigation_requested),
1048             webkit_navigation_request_handled,
1049             NULL,
1050             webkit_marshal_ENUM__OBJECT_OBJECT,
1051             WEBKIT_TYPE_NAVIGATION_RESPONSE, 2,
1052             WEBKIT_TYPE_WEB_FRAME,
1053             WEBKIT_TYPE_NETWORK_REQUEST);
1054
1055     /**
1056      * WebKitWebView::new-window-policy-decision-requested:
1057      * @web_view: the object on which the signal is emitted
1058      * @frame: the #WebKitWebFrame that required the navigation
1059      * @request: a #WebKitNetworkRequest
1060      * @navigation_action: a #WebKitWebNavigation
1061      * @policy_decision: a #WebKitWebPolicyDecision
1062      * @return: TRUE if the signal will be handled, FALSE to have the
1063      *          default behavior apply
1064      *
1065      * Emitted when @frame requests opening a new window. With this
1066      * signal the browser can use the context of the request to decide
1067      * about the new window. If the request is not handled the default
1068      * behavior is to allow opening the new window to load the url,
1069      * which will cause a create-web-view signal emission where the
1070      * browser handles the new window action but without information
1071      * of the context that caused the navigation. The following
1072      * navigation-policy-decision-requested emissions will load the
1073      * page after the creation of the new window just with the
1074      * information of this new navigation context, without any
1075      * information about the action that made this new window to be
1076      * opened.
1077      *
1078      * Since: 1.1.4
1079      */
1080     webkit_web_view_signals[NEW_WINDOW_POLICY_DECISION_REQUESTED] =
1081         g_signal_new("new-window-policy-decision-requested",
1082             G_TYPE_FROM_CLASS(webViewClass),
1083             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1084             0,
1085             g_signal_accumulator_true_handled,
1086             NULL,
1087             webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT,
1088             G_TYPE_BOOLEAN, 4,
1089             WEBKIT_TYPE_WEB_FRAME,
1090             WEBKIT_TYPE_NETWORK_REQUEST,
1091             WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
1092             WEBKIT_TYPE_WEB_POLICY_DECISION);
1093
1094     /**
1095      * WebKitWebView::navigation-policy-decision-requested:
1096      * @web_view: the object on which the signal is emitted
1097      * @frame: the #WebKitWebFrame that required the navigation
1098      * @request: a #WebKitNetworkRequest
1099      * @navigation_action: a #WebKitWebNavigation
1100      * @policy_decision: a #WebKitWebPolicyDecision
1101      * @return: TRUE if the signal will be handled, FALSE to have the
1102      *          default behavior apply
1103      *
1104      * Emitted when @frame requests a navigation to another page.
1105      * If this signal is not handled, the default behavior is to allow the
1106      * navigation.
1107      *
1108      * Since: 1.0.3
1109      */
1110     webkit_web_view_signals[NAVIGATION_POLICY_DECISION_REQUESTED] = g_signal_new("navigation-policy-decision-requested",
1111             G_TYPE_FROM_CLASS(webViewClass),
1112             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1113             0,
1114             g_signal_accumulator_true_handled,
1115             NULL,
1116             webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT,
1117             G_TYPE_BOOLEAN, 4,
1118             WEBKIT_TYPE_WEB_FRAME,
1119             WEBKIT_TYPE_NETWORK_REQUEST,
1120             WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
1121             WEBKIT_TYPE_WEB_POLICY_DECISION);
1122
1123     /**
1124      * WebKitWebView::mime-type-policy-decision-requested:
1125      * @web_view: the object on which the signal is emitted
1126      * @frame: the #WebKitWebFrame that required the policy decision
1127      * @request: a WebKitNetworkRequest
1128      * @mimetype: the MIME type attempted to load
1129      * @policy_decision: a #WebKitWebPolicyDecision
1130      * @return: TRUE if the signal will be handled, FALSE to have the
1131      *          default behavior apply
1132      *
1133      * Decide whether or not to display the given MIME type.  If this
1134      * signal is not handled, the default behavior is to show the
1135      * content of the requested URI if WebKit can show this MIME
1136      * type; if WebKit is not able to show the MIME type nothing
1137      * happens.
1138      *
1139      * Since: 1.0.3
1140      */
1141     webkit_web_view_signals[MIME_TYPE_POLICY_DECISION_REQUESTED] = g_signal_new("mime-type-policy-decision-requested",
1142             G_TYPE_FROM_CLASS(webViewClass),
1143             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1144             0,
1145             g_signal_accumulator_true_handled,
1146             NULL,
1147             webkit_marshal_BOOLEAN__OBJECT_OBJECT_STRING_OBJECT,
1148             G_TYPE_BOOLEAN, 4,
1149             WEBKIT_TYPE_WEB_FRAME,
1150             WEBKIT_TYPE_NETWORK_REQUEST,
1151             G_TYPE_STRING,
1152             WEBKIT_TYPE_WEB_POLICY_DECISION);
1153
1154     /**
1155      * WebKitWebView::window-object-cleared:
1156      * @web_view: the object on which the signal is emitted
1157      * @frame: the #WebKitWebFrame to which @window_object belongs
1158      * @context: the #JSGlobalContextRef holding the global object and other
1159      * execution state; equivalent to the return value of
1160      * webkit_web_frame_get_global_context(@frame)
1161      *
1162      * @window_object: the #JSObjectRef representing the frame's JavaScript
1163      * window object
1164      *
1165      * Emitted when the JavaScript window object in a #WebKitWebFrame has been
1166      * cleared in preparation for a new load. This is the preferred place to
1167      * set custom properties on the window object using the JavaScriptCore API.
1168      */
1169     webkit_web_view_signals[WINDOW_OBJECT_CLEARED] = g_signal_new("window-object-cleared",
1170             G_TYPE_FROM_CLASS(webViewClass),
1171             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1172             G_STRUCT_OFFSET (WebKitWebViewClass, window_object_cleared),
1173             NULL,
1174             NULL,
1175             webkit_marshal_VOID__OBJECT_POINTER_POINTER,
1176             G_TYPE_NONE, 3,
1177             WEBKIT_TYPE_WEB_FRAME,
1178             G_TYPE_POINTER,
1179             G_TYPE_POINTER);
1180
1181     /**
1182      * WebKitWebView::download-requested:
1183      * @web_view: the object on which the signal is emitted
1184      * @download: a #WebKitDownload object that lets you control the
1185      * download process
1186      * @return: %TRUE if the download should be performed, %FALSE to cancel it.
1187      *
1188      * A new Download is being requested. By default, if the signal is
1189      * not handled, the download is cancelled. Notice that while
1190      * handling this signal you must set the target URI using
1191      * webkit_download_set_target_uri().
1192      *
1193      * If you intend to handle downloads yourself rather than using
1194      * the #WebKitDownload helper object you must handle this signal,
1195      * and return %FALSE.
1196      *
1197      * Since: 1.1.2
1198      */
1199     webkit_web_view_signals[DOWNLOAD_REQUESTED] = g_signal_new("download-requested",
1200             G_TYPE_FROM_CLASS(webViewClass),
1201             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1202             0,
1203             g_signal_accumulator_true_handled,
1204             NULL,
1205             webkit_marshal_BOOLEAN__OBJECT,
1206             G_TYPE_BOOLEAN, 1,
1207             G_TYPE_OBJECT);
1208
1209     /**
1210      * WebKitWebView::load-started:
1211      * @web_view: the object on which the signal is emitted
1212      * @frame: the frame going to do the load
1213      *
1214      * When a #WebKitWebFrame begins to load this signal is emitted.
1215      */
1216     webkit_web_view_signals[LOAD_STARTED] = g_signal_new("load-started",
1217             G_TYPE_FROM_CLASS(webViewClass),
1218             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1219             0,
1220             NULL,
1221             NULL,
1222             g_cclosure_marshal_VOID__OBJECT,
1223             G_TYPE_NONE, 1,
1224             WEBKIT_TYPE_WEB_FRAME);
1225
1226     /**
1227      * WebKitWebView::load-committed:
1228      * @web_view: the object on which the signal is emitted
1229      * @frame: the main frame that received the first data
1230      *
1231      * When a #WebKitWebFrame loaded the first data this signal is emitted.
1232      */
1233     webkit_web_view_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
1234             G_TYPE_FROM_CLASS(webViewClass),
1235             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1236             0,
1237             NULL,
1238             NULL,
1239             g_cclosure_marshal_VOID__OBJECT,
1240             G_TYPE_NONE, 1,
1241             WEBKIT_TYPE_WEB_FRAME);
1242
1243
1244     /**
1245      * WebKitWebView::load-progress-changed:
1246      * @web_view: the #WebKitWebView
1247      * @progress: the global progress
1248      */
1249     webkit_web_view_signals[LOAD_PROGRESS_CHANGED] = g_signal_new("load-progress-changed",
1250             G_TYPE_FROM_CLASS(webViewClass),
1251             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1252             0,
1253             NULL,
1254             NULL,
1255             g_cclosure_marshal_VOID__INT,
1256             G_TYPE_NONE, 1,
1257             G_TYPE_INT);
1258
1259     webkit_web_view_signals[LOAD_FINISHED] = g_signal_new("load-finished",
1260             G_TYPE_FROM_CLASS(webViewClass),
1261             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1262             0,
1263             NULL,
1264             NULL,
1265             g_cclosure_marshal_VOID__OBJECT,
1266             G_TYPE_NONE, 1,
1267             WEBKIT_TYPE_WEB_FRAME);
1268
1269     /**
1270      * WebKitWebView::title-changed:
1271      * @web_view: the object on which the signal is emitted
1272      * @frame: the main frame
1273      * @title: the new title
1274      *
1275      * When a #WebKitWebFrame changes the document title this signal is emitted.
1276      *
1277      * Deprecated: 1.1.4: Use "notify::title" instead.
1278      */
1279     webkit_web_view_signals[TITLE_CHANGED] = g_signal_new("title-changed",
1280             G_TYPE_FROM_CLASS(webViewClass),
1281             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1282             0,
1283             NULL,
1284             NULL,
1285             webkit_marshal_VOID__OBJECT_STRING,
1286             G_TYPE_NONE, 2,
1287             WEBKIT_TYPE_WEB_FRAME,
1288             G_TYPE_STRING);
1289
1290     /**
1291      * WebKitWebView::hovering-over-link:
1292      * @web_view: the object on which the signal is emitted
1293      * @title: the link's title
1294      * @uri: the URI the link points to
1295      *
1296      * When the cursor is over a link, this signal is emitted.
1297      */
1298     webkit_web_view_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
1299             G_TYPE_FROM_CLASS(webViewClass),
1300             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1301             0,
1302             NULL,
1303             NULL,
1304             webkit_marshal_VOID__STRING_STRING,
1305             G_TYPE_NONE, 2,
1306             G_TYPE_STRING,
1307             G_TYPE_STRING);
1308
1309     /**
1310      * WebKitWebView::populate-popup:
1311      * @web_view: the object on which the signal is emitted
1312      * @menu: the context menu
1313      *
1314      * When a context menu is about to be displayed this signal is emitted.
1315      *
1316      * Add menu items to #menu to extend the context menu.
1317      */
1318     webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
1319             G_TYPE_FROM_CLASS(webViewClass),
1320             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1321             0,
1322             NULL,
1323             NULL,
1324             g_cclosure_marshal_VOID__OBJECT,
1325             G_TYPE_NONE, 1,
1326             GTK_TYPE_MENU);
1327
1328     webkit_web_view_signals[STATUS_BAR_TEXT_CHANGED] = g_signal_new("status-bar-text-changed",
1329             G_TYPE_FROM_CLASS(webViewClass),
1330             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1331             0,
1332             NULL,
1333             NULL,
1334             g_cclosure_marshal_VOID__STRING,
1335             G_TYPE_NONE, 1,
1336             G_TYPE_STRING);
1337
1338     webkit_web_view_signals[ICOND_LOADED] = g_signal_new("icon-loaded",
1339             G_TYPE_FROM_CLASS(webViewClass),
1340             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1341             0,
1342             NULL,
1343             NULL,
1344             g_cclosure_marshal_VOID__VOID,
1345             G_TYPE_NONE, 0);
1346
1347     webkit_web_view_signals[SELECTION_CHANGED] = g_signal_new("selection-changed",
1348             G_TYPE_FROM_CLASS(webViewClass),
1349             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1350             0,
1351             NULL,
1352             NULL,
1353             g_cclosure_marshal_VOID__VOID,
1354             G_TYPE_NONE, 0);
1355
1356     /**
1357      * WebKitWebView::console-message:
1358      * @web_view: the object on which the signal is emitted
1359      * @message: the message text
1360      * @line: the line where the error occured
1361      * @source_id: the source id
1362      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1363      *
1364      * A JavaScript console message was created.
1365      */
1366     webkit_web_view_signals[CONSOLE_MESSAGE] = g_signal_new("console-message",
1367             G_TYPE_FROM_CLASS(webViewClass),
1368             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1369             G_STRUCT_OFFSET(WebKitWebViewClass, console_message),
1370             g_signal_accumulator_true_handled,
1371             NULL,
1372             webkit_marshal_BOOLEAN__STRING_INT_STRING,
1373             G_TYPE_BOOLEAN, 3,
1374             G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
1375
1376     /**
1377      * WebKitWebView::script-alert:
1378      * @web_view: the object on which the signal is emitted
1379      * @frame: the relevant frame
1380      * @message: the message text
1381      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1382      *
1383      * A JavaScript alert dialog was created.
1384      */
1385     webkit_web_view_signals[SCRIPT_ALERT] = g_signal_new("script-alert",
1386             G_TYPE_FROM_CLASS(webViewClass),
1387             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1388             G_STRUCT_OFFSET(WebKitWebViewClass, script_alert),
1389             g_signal_accumulator_true_handled,
1390             NULL,
1391             webkit_marshal_BOOLEAN__OBJECT_STRING,
1392             G_TYPE_BOOLEAN, 2,
1393             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING);
1394
1395     /**
1396      * WebKitWebView::script-confirm:
1397      * @web_view: the object on which the signal is emitted
1398      * @frame: the relevant frame
1399      * @message: the message text
1400      * @confirmed: whether the dialog has been confirmed
1401      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1402      *
1403      * A JavaScript confirm dialog was created, providing Yes and No buttons.
1404      */
1405     webkit_web_view_signals[SCRIPT_CONFIRM] = g_signal_new("script-confirm",
1406             G_TYPE_FROM_CLASS(webViewClass),
1407             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1408             G_STRUCT_OFFSET(WebKitWebViewClass, script_confirm),
1409             g_signal_accumulator_true_handled,
1410             NULL,
1411             webkit_marshal_BOOLEAN__OBJECT_STRING_POINTER,
1412             G_TYPE_BOOLEAN, 3,
1413             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_POINTER);
1414
1415     /**
1416      * WebKitWebView::script-prompt:
1417      * @web_view: the object on which the signal is emitted
1418      * @frame: the relevant frame
1419      * @message: the message text
1420      * @default: the default value
1421      * @text: To be filled with the return value or NULL if the dialog was cancelled.
1422      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1423      *
1424      * A JavaScript prompt dialog was created, providing an entry to input text.
1425      */
1426     webkit_web_view_signals[SCRIPT_PROMPT] = g_signal_new("script-prompt",
1427             G_TYPE_FROM_CLASS(webViewClass),
1428             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1429             G_STRUCT_OFFSET(WebKitWebViewClass, script_prompt),
1430             g_signal_accumulator_true_handled,
1431             NULL,
1432             webkit_marshal_BOOLEAN__OBJECT_STRING_STRING_STRING,
1433             G_TYPE_BOOLEAN, 4,
1434             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
1435
1436     /**
1437      * WebKitWebView::select-all:
1438      * @web_view: the object which received the signal
1439      *
1440      * The #WebKitWebView::select-all signal is a keybinding signal which gets emitted to
1441      * select the complete contents of the text view.
1442      *
1443      * The default bindings for this signal is Ctrl-a.
1444      */
1445     webkit_web_view_signals[SELECT_ALL] = g_signal_new("select-all",
1446             G_TYPE_FROM_CLASS(webViewClass),
1447             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1448             G_STRUCT_OFFSET(WebKitWebViewClass, select_all),
1449             NULL, NULL,
1450             g_cclosure_marshal_VOID__VOID,
1451             G_TYPE_NONE, 0);
1452
1453     /**
1454      * WebKitWebView::cut-clipboard:
1455      * @web_view: the object which received the signal
1456      *
1457      * The #WebKitWebView::cut-clipboard signal is a keybinding signal which gets emitted to
1458      * cut the selection to the clipboard.
1459      *
1460      * The default bindings for this signal are Ctrl-x and Shift-Delete.
1461      */
1462     webkit_web_view_signals[CUT_CLIPBOARD] = g_signal_new("cut-clipboard",
1463             G_TYPE_FROM_CLASS(webViewClass),
1464             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1465             G_STRUCT_OFFSET(WebKitWebViewClass, cut_clipboard),
1466             NULL, NULL,
1467             g_cclosure_marshal_VOID__VOID,
1468             G_TYPE_NONE, 0);
1469
1470     /**
1471      * WebKitWebView::copy-clipboard:
1472      * @web_view: the object which received the signal
1473      *
1474      * The #WebKitWebView::copy-clipboard signal is a keybinding signal which gets emitted to
1475      * copy the selection to the clipboard.
1476      *
1477      * The default bindings for this signal are Ctrl-c and Ctrl-Insert.
1478      */
1479     webkit_web_view_signals[COPY_CLIPBOARD] = g_signal_new("copy-clipboard",
1480             G_TYPE_FROM_CLASS(webViewClass),
1481             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1482             G_STRUCT_OFFSET(WebKitWebViewClass, copy_clipboard),
1483             NULL, NULL,
1484             g_cclosure_marshal_VOID__VOID,
1485             G_TYPE_NONE, 0);
1486
1487     /**
1488      * WebKitWebView::paste-clipboard:
1489      * @web_view: the object which received the signal
1490      *
1491      * The #WebKitWebView::paste-clipboard signal is a keybinding signal which gets emitted to
1492      * paste the contents of the clipboard into the Web view.
1493      *
1494      * The default bindings for this signal are Ctrl-v and Shift-Insert.
1495      */
1496     webkit_web_view_signals[PASTE_CLIPBOARD] = g_signal_new("paste-clipboard",
1497             G_TYPE_FROM_CLASS(webViewClass),
1498             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1499             G_STRUCT_OFFSET(WebKitWebViewClass, paste_clipboard),
1500             NULL, NULL,
1501             g_cclosure_marshal_VOID__VOID,
1502             G_TYPE_NONE, 0);
1503
1504     /*
1505      * implementations of virtual methods
1506      */
1507     webViewClass->create_web_view = webkit_web_view_real_create_web_view;
1508     webViewClass->web_view_ready = webkit_web_view_real_web_view_ready;
1509     webViewClass->navigation_requested = webkit_web_view_real_navigation_requested;
1510     webViewClass->window_object_cleared = webkit_web_view_real_window_object_cleared;
1511     webViewClass->choose_file = webkit_web_view_real_choose_file;
1512     webViewClass->script_alert = webkit_web_view_real_script_alert;
1513     webViewClass->script_confirm = webkit_web_view_real_script_confirm;
1514     webViewClass->script_prompt = webkit_web_view_real_script_prompt;
1515     webViewClass->console_message = webkit_web_view_real_console_message;
1516     webViewClass->select_all = webkit_web_view_real_select_all;
1517     webViewClass->cut_clipboard = webkit_web_view_real_cut_clipboard;
1518     webViewClass->copy_clipboard = webkit_web_view_real_copy_clipboard;
1519     webViewClass->paste_clipboard = webkit_web_view_real_paste_clipboard;
1520
1521     GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
1522     objectClass->dispose = webkit_web_view_dispose;
1523     objectClass->finalize = webkit_web_view_finalize;
1524     objectClass->get_property = webkit_web_view_get_property;
1525     objectClass->set_property = webkit_web_view_set_property;
1526
1527     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webViewClass);
1528     widgetClass->realize = webkit_web_view_realize;
1529     widgetClass->expose_event = webkit_web_view_expose_event;
1530     widgetClass->key_press_event = webkit_web_view_key_press_event;
1531     widgetClass->key_release_event = webkit_web_view_key_release_event;
1532     widgetClass->button_press_event = webkit_web_view_button_press_event;
1533     widgetClass->button_release_event = webkit_web_view_button_release_event;
1534     widgetClass->motion_notify_event = webkit_web_view_motion_event;
1535     widgetClass->scroll_event = webkit_web_view_scroll_event;
1536     widgetClass->size_allocate = webkit_web_view_size_allocate;
1537     widgetClass->popup_menu = webkit_web_view_popup_menu_handler;
1538     widgetClass->focus_in_event = webkit_web_view_focus_in_event;
1539     widgetClass->focus_out_event = webkit_web_view_focus_out_event;
1540     widgetClass->get_accessible = webkit_web_view_get_accessible;
1541
1542     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webViewClass);
1543     containerClass->add = webkit_web_view_container_add;
1544     containerClass->remove = webkit_web_view_container_remove;
1545     containerClass->forall = webkit_web_view_container_forall;
1546
1547     /*
1548      * make us scrollable (e.g. addable to a GtkScrolledWindow)
1549      */
1550     webViewClass->set_scroll_adjustments = webkit_web_view_set_scroll_adjustments;
1551     GTK_WIDGET_CLASS(webViewClass)->set_scroll_adjustments_signal = g_signal_new("set-scroll-adjustments",
1552             G_TYPE_FROM_CLASS(webViewClass),
1553             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1554             G_STRUCT_OFFSET(WebKitWebViewClass, set_scroll_adjustments),
1555             NULL, NULL,
1556             webkit_marshal_VOID__OBJECT_OBJECT,
1557             G_TYPE_NONE, 2,
1558             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1559
1560     /*
1561      * Key bindings
1562      */
1563
1564     binding_set = gtk_binding_set_by_class(webViewClass);
1565
1566     gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
1567                                  "select_all", 0);
1568
1569     /* Cut/copy/paste */
1570
1571     gtk_binding_entry_add_signal(binding_set, GDK_x, GDK_CONTROL_MASK,
1572                                  "cut_clipboard", 0);
1573     gtk_binding_entry_add_signal(binding_set, GDK_c, GDK_CONTROL_MASK,
1574                                  "copy_clipboard", 0);
1575     gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK,
1576                                  "paste_clipboard", 0);
1577
1578     gtk_binding_entry_add_signal(binding_set, GDK_Delete, GDK_SHIFT_MASK,
1579                                  "cut_clipboard", 0);
1580     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_CONTROL_MASK,
1581                                  "copy_clipboard", 0);
1582     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_SHIFT_MASK,
1583                                  "paste_clipboard", 0);
1584
1585     /*
1586      * properties
1587      */
1588
1589     /**
1590     * WebKitWebView:title:
1591     *
1592     * Returns the @web_view's document title.
1593     *
1594     * Since: 1.1.4
1595     */
1596     g_object_class_install_property(objectClass, PROP_TITLE,
1597                                     g_param_spec_string("title",
1598                                                         "Title",
1599                                                         "Returns the @web_view's document title",
1600                                                         NULL,
1601                                                         WEBKIT_PARAM_READABLE));
1602
1603     /**
1604     * WebKitWebView:uri:
1605     *
1606     * Returns the current URI of the contents displayed by the @web_view.
1607     *
1608     * Since: 1.1.4
1609     */
1610     g_object_class_install_property(objectClass, PROP_URI,
1611                                     g_param_spec_string("uri",
1612                                                         "URI",
1613                                                         "Returns the current URI of the contents displayed by the @web_view",
1614                                                         NULL,
1615                                                         WEBKIT_PARAM_READABLE));
1616
1617 #if GTK_CHECK_VERSION(2,10,0)
1618     /**
1619     * WebKitWebView:copy-target-list:
1620     *
1621     * The list of targets this web view supports for clipboard copying.
1622     *
1623     * Since: 1.0.2
1624     */
1625     g_object_class_install_property(objectClass, PROP_COPY_TARGET_LIST,
1626                                     g_param_spec_boxed("copy-target-list",
1627                                                        "Copy target list",
1628                                                        "The list of targets this web view supports for clipboard copying",
1629                                                        GTK_TYPE_TARGET_LIST,
1630                                                        WEBKIT_PARAM_READABLE));
1631
1632     /**
1633     * WebKitWebView:paste-target-list:
1634     *
1635     * The list of targets this web view supports for clipboard pasting.
1636     *
1637     * Since: 1.0.2
1638     */
1639     g_object_class_install_property(objectClass, PROP_PASTE_TARGET_LIST,
1640                                     g_param_spec_boxed("paste-target-list",
1641                                                        "Paste target list",
1642                                                        "The list of targets this web view supports for clipboard pasting",
1643                                                        GTK_TYPE_TARGET_LIST,
1644                                                        WEBKIT_PARAM_READABLE));
1645 #endif
1646
1647     g_object_class_install_property(objectClass, PROP_SETTINGS,
1648                                     g_param_spec_object("settings",
1649                                                         "Settings",
1650                                                         "An associated WebKitWebSettings instance",
1651                                                         WEBKIT_TYPE_WEB_SETTINGS,
1652                                                         WEBKIT_PARAM_READWRITE));
1653
1654     /**
1655     * WebKitWebView:web-inspector:
1656     *
1657     * The associated WebKitWebInspector instance.
1658     *
1659     * Since: 1.0.3
1660     */
1661     g_object_class_install_property(objectClass, PROP_WEB_INSPECTOR,
1662                                     g_param_spec_object("web-inspector",
1663                                                         "Web Inspector",
1664                                                         "The associated WebKitWebInspector instance",
1665                                                         WEBKIT_TYPE_WEB_INSPECTOR,
1666                                                         WEBKIT_PARAM_READABLE));
1667
1668     /**
1669     * WebKitWebView:window-features:
1670     *
1671     * An associated WebKitWebWindowFeatures instance.
1672     *
1673     * Since: 1.0.3
1674     */
1675     g_object_class_install_property(objectClass, PROP_WINDOW_FEATURES,
1676                                     g_param_spec_object("window-features",
1677                                                         "Window Features",
1678                                                         "An associated WebKitWebWindowFeatures instance",
1679                                                         WEBKIT_TYPE_WEB_WINDOW_FEATURES,
1680                                                         WEBKIT_PARAM_READWRITE));
1681
1682     g_object_class_install_property(objectClass, PROP_EDITABLE,
1683                                     g_param_spec_boolean("editable",
1684                                                          "Editable",
1685                                                          "Whether content can be modified by the user",
1686                                                          FALSE,
1687                                                          WEBKIT_PARAM_READWRITE));
1688
1689     g_object_class_install_property(objectClass, PROP_TRANSPARENT,
1690                                     g_param_spec_boolean("transparent",
1691                                                          "Transparent",
1692                                                          "Whether content has a transparent background",
1693                                                          FALSE,
1694                                                          WEBKIT_PARAM_READWRITE));
1695
1696     /**
1697     * WebKitWebView:zoom-level:
1698     *
1699     * The level of zoom of the content.
1700     *
1701     * Since: 1.0.1
1702     */
1703     g_object_class_install_property(objectClass, PROP_ZOOM_LEVEL,
1704                                     g_param_spec_float("zoom-level",
1705                                                        "Zoom level",
1706                                                        "The level of zoom of the content",
1707                                                        G_MINFLOAT,
1708                                                        G_MAXFLOAT,
1709                                                        1.0f,
1710                                                        WEBKIT_PARAM_READWRITE));
1711
1712     /**
1713     * WebKitWebView:full-content-zoom:
1714     *
1715     * Whether the full content is scaled when zooming.
1716     *
1717     * Since: 1.0.1
1718     */
1719     g_object_class_install_property(objectClass, PROP_FULL_CONTENT_ZOOM,
1720                                     g_param_spec_boolean("full-content-zoom",
1721                                                          "Full content zoom",
1722                                                          "Whether the full content is scaled when zooming",
1723                                                          FALSE,
1724                                                          WEBKIT_PARAM_READWRITE));
1725
1726     /**
1727      * WebKitWebView:encoding:
1728      *
1729      * The default encoding of the web view.
1730      *
1731      * Since: 1.1.2
1732      */
1733     g_object_class_install_property(objectClass, PROP_ENCODING,
1734                                     g_param_spec_string("encoding",
1735                                                         "Encoding",
1736                                                         "The default encoding of the web view",
1737                                                         NULL,
1738                                                         WEBKIT_PARAM_READABLE));
1739
1740     /**
1741      * WebKitWebView:custom-encoding:
1742      *
1743      * The custom encoding of the web view.
1744      *
1745      * Since: 1.1.2
1746      */
1747     g_object_class_install_property(objectClass, PROP_CUSTOM_ENCODING,
1748                                     g_param_spec_string("custom-encoding",
1749                                                         "Custom Encoding",
1750                                                         "The custom encoding of the web view",
1751                                                         NULL,
1752                                                         WEBKIT_PARAM_READWRITE));
1753
1754     g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
1755 }
1756
1757 static gdouble webViewGetDPI(WebKitWebView* webView)
1758 {
1759     WebKitWebViewPrivate* priv = webView->priv;
1760     WebKitWebSettings* webSettings = priv->webSettings;
1761     gboolean enforce96DPI;
1762     g_object_get(webSettings, "enforce-96-dpi", &enforce96DPI, NULL);
1763     if (enforce96DPI)
1764         return 96.0;
1765
1766     gdouble DPI = defaultDPI;
1767 #if GTK_CHECK_VERSION(2,10,0)
1768     GdkScreen* screen = gtk_widget_has_screen(GTK_WIDGET(webView)) ? gtk_widget_get_screen(GTK_WIDGET(webView)) : gdk_screen_get_default();
1769     if (screen) {
1770         DPI = gdk_screen_get_resolution(screen);
1771         // gdk_screen_get_resolution() returns -1 when no DPI is set.
1772         if (DPI == -1)
1773             DPI = defaultDPI;
1774     }
1775 #endif
1776     ASSERT(DPI > 0);
1777     return DPI;
1778 }
1779
1780 static void webkit_web_view_screen_changed(WebKitWebView* webView, GdkScreen* previousScreen, gpointer userdata)
1781 {
1782     WebKitWebViewPrivate* priv = webView->priv;
1783     WebKitWebSettings* webSettings = priv->webSettings;
1784     Settings* settings = core(webView)->settings();
1785     gdouble DPI = webViewGetDPI(webView);
1786
1787     guint defaultFontSize, defaultMonospaceFontSize, minimumFontSize, minimumLogicalFontSize;
1788
1789     g_object_get(webSettings,
1790                  "default-font-size", &defaultFontSize,
1791                  "default-monospace-font-size", &defaultMonospaceFontSize,
1792                  "minimum-font-size", &minimumFontSize,
1793                  "minimum-logical-font-size", &minimumLogicalFontSize,
1794                  NULL);
1795
1796     settings->setDefaultFontSize(defaultFontSize / 72.0 * DPI);
1797     settings->setDefaultFixedFontSize(defaultMonospaceFontSize / 72.0 * DPI);
1798     settings->setMinimumFontSize(minimumFontSize / 72.0 * DPI);
1799     settings->setMinimumLogicalFontSize(minimumLogicalFontSize / 72.0 * DPI);
1800 }
1801
1802 static void webkit_web_view_update_settings(WebKitWebView* webView)
1803 {
1804     WebKitWebViewPrivate* priv = webView->priv;
1805     WebKitWebSettings* webSettings = priv->webSettings;
1806     Settings* settings = core(webView)->settings();
1807
1808     gchar* defaultEncoding, *cursiveFontFamily, *defaultFontFamily, *fantasyFontFamily, *monospaceFontFamily, *sansSerifFontFamily, *serifFontFamily, *userStylesheetUri;
1809     gboolean autoLoadImages, autoShrinkImages, printBackgrounds,
1810         enableScripts, enablePlugins, enableDeveloperExtras, resizableTextAreas,
1811         enablePrivateBrowsing;
1812
1813     g_object_get(webSettings,
1814                  "default-encoding", &defaultEncoding,
1815                  "cursive-font-family", &cursiveFontFamily,
1816                  "default-font-family", &defaultFontFamily,
1817                  "fantasy-font-family", &fantasyFontFamily,
1818                  "monospace-font-family", &monospaceFontFamily,
1819                  "sans-serif-font-family", &sansSerifFontFamily,
1820                  "serif-font-family", &serifFontFamily,
1821                  "auto-load-images", &autoLoadImages,
1822                  "auto-shrink-images", &autoShrinkImages,
1823                  "print-backgrounds", &printBackgrounds,
1824                  "enable-scripts", &enableScripts,
1825                  "enable-plugins", &enablePlugins,
1826                  "resizable-text-areas", &resizableTextAreas,
1827                  "user-stylesheet-uri", &userStylesheetUri,
1828                  "enable-developer-extras", &enableDeveloperExtras,
1829                  "enable-private-browsing", &enablePrivateBrowsing,
1830                  NULL);
1831
1832     settings->setDefaultTextEncodingName(defaultEncoding);
1833     settings->setCursiveFontFamily(cursiveFontFamily);
1834     settings->setStandardFontFamily(defaultFontFamily);
1835     settings->setFantasyFontFamily(fantasyFontFamily);
1836     settings->setFixedFontFamily(monospaceFontFamily);
1837     settings->setSansSerifFontFamily(sansSerifFontFamily);
1838     settings->setSerifFontFamily(serifFontFamily);
1839     settings->setLoadsImagesAutomatically(autoLoadImages);
1840     settings->setShrinksStandaloneImagesToFit(autoShrinkImages);
1841     settings->setShouldPrintBackgrounds(printBackgrounds);
1842     settings->setJavaScriptEnabled(enableScripts);
1843     settings->setPluginsEnabled(enablePlugins);
1844     settings->setTextAreasAreResizable(resizableTextAreas);
1845     settings->setUserStyleSheetLocation(KURL(KURL(), userStylesheetUri));
1846     settings->setDeveloperExtrasEnabled(enableDeveloperExtras);
1847     settings->setPrivateBrowsingEnabled(enablePrivateBrowsing);
1848
1849     g_free(defaultEncoding);
1850     g_free(cursiveFontFamily);
1851     g_free(defaultFontFamily);
1852     g_free(fantasyFontFamily);
1853     g_free(monospaceFontFamily);
1854     g_free(sansSerifFontFamily);
1855     g_free(serifFontFamily);
1856     g_free(userStylesheetUri);
1857
1858     webkit_web_view_screen_changed(webView, NULL, NULL);
1859 }
1860
1861 static inline gint pixelsFromSize(WebKitWebView* webView, gint size)
1862 {
1863     gdouble DPI = webViewGetDPI(webView);
1864     return size / 72.0 * DPI;
1865 }
1866
1867 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView)
1868 {
1869     Settings* settings = core(webView)->settings();
1870
1871     const gchar* name = g_intern_string(pspec->name);
1872     GValue value = { 0, { { 0 } } };
1873     g_value_init(&value, pspec->value_type);
1874     g_object_get_property(G_OBJECT(webSettings), name, &value);
1875
1876     if (name == g_intern_string("default-encoding"))
1877         settings->setDefaultTextEncodingName(g_value_get_string(&value));
1878     else if (name == g_intern_string("cursive-font-family"))
1879         settings->setCursiveFontFamily(g_value_get_string(&value));
1880     else if (name == g_intern_string("default-font-family"))
1881         settings->setStandardFontFamily(g_value_get_string(&value));
1882     else if (name == g_intern_string("fantasy-font-family"))
1883         settings->setFantasyFontFamily(g_value_get_string(&value));
1884     else if (name == g_intern_string("monospace-font-family"))
1885         settings->setFixedFontFamily(g_value_get_string(&value));
1886     else if (name == g_intern_string("sans-serif-font-family"))
1887         settings->setSansSerifFontFamily(g_value_get_string(&value));
1888     else if (name == g_intern_string("serif-font-family"))
1889         settings->setSerifFontFamily(g_value_get_string(&value));
1890     else if (name == g_intern_string("default-font-size"))
1891         settings->setDefaultFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1892     else if (name == g_intern_string("default-monospace-font-size"))
1893         settings->setDefaultFixedFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1894     else if (name == g_intern_string("minimum-font-size"))
1895         settings->setMinimumFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1896     else if (name == g_intern_string("minimum-logical-font-size"))
1897         settings->setMinimumLogicalFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1898     else if (name == g_intern_string("enforce-96-dpi"))
1899         webkit_web_view_screen_changed(webView, NULL, NULL);
1900     else if (name == g_intern_string("auto-load-images"))
1901         settings->setLoadsImagesAutomatically(g_value_get_boolean(&value));
1902     else if (name == g_intern_string("auto-shrink-images"))
1903         settings->setShrinksStandaloneImagesToFit(g_value_get_boolean(&value));
1904     else if (name == g_intern_string("print-backgrounds"))
1905         settings->setShouldPrintBackgrounds(g_value_get_boolean(&value));
1906     else if (name == g_intern_string("enable-scripts"))
1907         settings->setJavaScriptEnabled(g_value_get_boolean(&value));
1908     else if (name == g_intern_string("enable-plugins"))
1909         settings->setPluginsEnabled(g_value_get_boolean(&value));
1910     else if (name == g_intern_string("resizable-text-areas"))
1911         settings->setTextAreasAreResizable(g_value_get_boolean(&value));
1912     else if (name == g_intern_string("user-stylesheet-uri"))
1913         settings->setUserStyleSheetLocation(KURL(KURL(), g_value_get_string(&value)));
1914     else if (name == g_intern_string("enable-developer-extras"))
1915         settings->setDeveloperExtrasEnabled(g_value_get_boolean(&value));
1916     else if (name == g_intern_string("enable-private-browsing"))
1917         settings->setPrivateBrowsingEnabled(g_value_get_boolean(&value));
1918     else if (!g_object_class_find_property(G_OBJECT_GET_CLASS(webSettings), name))
1919         g_warning("Unexpected setting '%s'", name);
1920     g_value_unset(&value);
1921 }
1922
1923 static void webkit_web_view_init(WebKitWebView* webView)
1924 {
1925     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1926     webView->priv = priv;
1927
1928     priv->imContext = gtk_im_multicontext_new();
1929
1930     WebKit::InspectorClient* inspectorClient = new WebKit::InspectorClient(webView);
1931     priv->corePage = new Page(new WebKit::ChromeClient(webView), new WebKit::ContextMenuClient(webView), new WebKit::EditorClient(webView), new WebKit::DragClient, inspectorClient);
1932
1933     // We also add a simple wrapper class to provide the public
1934     // interface for the Web Inspector.
1935     priv->webInspector = WEBKIT_WEB_INSPECTOR(g_object_new(WEBKIT_TYPE_WEB_INSPECTOR, NULL));
1936     webkit_web_inspector_set_inspector_client(priv->webInspector, priv->corePage);
1937
1938     priv->horizontalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1939     priv->verticalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1940
1941     g_object_ref_sink(priv->horizontalAdjustment);
1942     g_object_ref_sink(priv->verticalAdjustment);
1943
1944     GTK_WIDGET_SET_FLAGS(webView, GTK_CAN_FOCUS);
1945     priv->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView));
1946     priv->lastPopupXPosition = priv->lastPopupYPosition = -1;
1947     priv->editable = false;
1948
1949     priv->backForwardList = webkit_web_back_forward_list_new_with_web_view(webView);
1950
1951     priv->zoomFullContent = FALSE;
1952
1953 #if GTK_CHECK_VERSION(2,10,0)
1954     GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
1955 #else
1956     GdkAtom textHtml = gdk_atom_intern("text/html", false);
1957 #endif
1958     /* Targets for copy */
1959     priv->copy_target_list = gtk_target_list_new(NULL, 0);
1960     gtk_target_list_add(priv->copy_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
1961     gtk_target_list_add_text_targets(priv->copy_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
1962
1963     /* Targets for pasting */
1964     priv->paste_target_list = gtk_target_list_new(NULL, 0);
1965     gtk_target_list_add(priv->paste_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
1966     gtk_target_list_add_text_targets(priv->paste_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
1967
1968     priv->webSettings = webkit_web_settings_new();
1969     webkit_web_view_update_settings(webView);
1970     g_signal_connect(webView, "screen-changed", G_CALLBACK(webkit_web_view_screen_changed), NULL);
1971     g_signal_connect(priv->webSettings, "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
1972
1973     priv->webWindowFeatures = webkit_web_window_features_new();
1974 }
1975
1976 GtkWidget* webkit_web_view_new(void)
1977 {
1978     WebKitWebView* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL));
1979
1980     return GTK_WIDGET(webView);
1981 }
1982
1983 // for internal use only
1984 void webkit_web_view_notify_ready(WebKitWebView* webView)
1985 {
1986     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1987
1988     gboolean isHandled = FALSE;
1989     g_signal_emit(webView, webkit_web_view_signals[WEB_VIEW_READY], 0, &isHandled);
1990 }
1991
1992
1993 void webkit_web_view_set_settings(WebKitWebView* webView, WebKitWebSettings* webSettings)
1994 {
1995     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1996     g_return_if_fail(WEBKIT_IS_WEB_SETTINGS(webSettings));
1997
1998     WebKitWebViewPrivate* priv = webView->priv;
1999     g_signal_handlers_disconnect_by_func(priv->webSettings, (gpointer)webkit_web_view_settings_notify, webView);
2000     g_object_unref(priv->webSettings);
2001     g_object_ref(webSettings);
2002     priv->webSettings = webSettings;
2003     webkit_web_view_update_settings(webView);
2004     g_signal_connect(webSettings, "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
2005     g_object_notify(G_OBJECT(webView), "settings");
2006 }
2007
2008 WebKitWebSettings* webkit_web_view_get_settings(WebKitWebView* webView)
2009 {
2010     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2011
2012     WebKitWebViewPrivate* priv = webView->priv;
2013     return priv->webSettings;
2014 }
2015
2016 /**
2017  * webkit_web_view_get_inspector:
2018  * @web_view: a #WebKitWebView
2019  *
2020  * Obtains the #WebKitWebInspector associated with the
2021  * #WebKitWebView. Every #WebKitWebView object has a
2022  * #WebKitWebInspector object attached to it as soon as it is created,
2023  * so this function will only return NULL if the argument is not a
2024  * valid #WebKitWebView.
2025  *
2026  * Returns: the #WebKitWebInspector instance associated with the
2027  * #WebKitWebView; %NULL is only returned if the argument is not a
2028  * valid #WebKitWebView.
2029  *
2030  * Since: 1.0.3
2031  */
2032 WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView)
2033 {
2034     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2035
2036     WebKitWebViewPrivate* priv = webView->priv;
2037     return priv->webInspector;
2038 }
2039
2040 // internal
2041 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures)
2042 {
2043     WebKitWebViewPrivate* priv = webView->priv;
2044
2045     if(webkit_web_window_features_equal(priv->webWindowFeatures, webWindowFeatures))
2046       return;
2047
2048     g_object_unref(priv->webWindowFeatures);
2049     g_object_ref(webWindowFeatures);
2050     priv->webWindowFeatures = webWindowFeatures;
2051 }
2052
2053 /**
2054  * webkit_web_view_get_window_features
2055  * @web_view: a #WebKitWebView
2056  *
2057  * Returns the instance of #WebKitWebWindowFeatures held by the given
2058  * #WebKitWebView.
2059  *
2060  * Return value: the #WebKitWebWindowFeatures
2061  *
2062  * Since: 1.0.3
2063  */
2064 WebKitWebWindowFeatures* webkit_web_view_get_window_features(WebKitWebView* webView)
2065 {
2066     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2067
2068     WebKitWebViewPrivate* priv = webView->priv;
2069     return priv->webWindowFeatures;
2070 }
2071
2072 /**
2073  * webkit_web_view_get_title:
2074  * @web_view: a #WebKitWebView
2075  *
2076  * Returns the @web_view's document title
2077  *
2078  * Since: 1.1.4
2079  *
2080  * Return value: the title of @web_view
2081  */
2082 G_CONST_RETURN gchar* webkit_web_view_get_title(WebKitWebView* webView)
2083 {
2084     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2085
2086     WebKitWebViewPrivate* priv = webView->priv;
2087     return priv->mainFrame->priv->title;
2088 }
2089
2090 /**
2091  * webkit_web_view_get_uri:
2092  * @web_view: a #WebKitWebView
2093  *
2094  * Returns the current URI of the contents displayed by the @web_view
2095  *
2096  * Since: 1.1.4
2097  *
2098  * Return value: the URI of @web_view
2099  */
2100 G_CONST_RETURN gchar* webkit_web_view_get_uri(WebKitWebView* webView)
2101 {
2102     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2103
2104     WebKitWebViewPrivate* priv = webView->priv;
2105     return priv->mainFrame->priv->uri;
2106 }
2107
2108 /**
2109  * webkit_web_view_set_maintains_back_forward_list:
2110  * @web_view: a #WebKitWebView
2111  * @flag: to tell the view to maintain a back or forward list
2112  *
2113  * Set the view to maintain a back or forward list of history items.
2114  */
2115 void webkit_web_view_set_maintains_back_forward_list(WebKitWebView* webView, gboolean flag)
2116 {
2117     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2118
2119     core(webView)->backForwardList()->setEnabled(flag);
2120 }
2121
2122 /**
2123  * webkit_web_view_get_back_forward_list:
2124  * @web_view: a #WebKitWebView
2125  *
2126  * Returns a #WebKitWebBackForwardList
2127  *
2128  * Return value: the #WebKitWebBackForwardList
2129  */
2130 WebKitWebBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
2131 {
2132     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2133
2134     WebKitWebViewPrivate* priv = webView->priv;
2135
2136     if (!core(webView) || !core(webView)->backForwardList()->enabled())
2137         return NULL;
2138
2139     return priv->backForwardList;
2140 }
2141
2142 /**
2143  * webkit_web_view_go_to_back_forward_item:
2144  * @web_view: a #WebKitWebView
2145  * @item: a #WebKitWebHistoryItem*
2146  *
2147  * Go to the specified #WebKitWebHistoryItem
2148  *
2149  * Return value: %TRUE if loading of item is successful, %FALSE if not
2150  */
2151 gboolean webkit_web_view_go_to_back_forward_item(WebKitWebView* webView, WebKitWebHistoryItem* item)
2152 {
2153     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2154     g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(item), FALSE);
2155
2156     WebKitWebBackForwardList* backForwardList = webkit_web_view_get_back_forward_list(webView);
2157     if (!webkit_web_back_forward_list_contains_item(backForwardList, item))
2158         return FALSE;
2159
2160     core(webView)->goToItem(core(item), FrameLoadTypeIndexedBackForward);
2161     return TRUE;
2162 }
2163
2164 /**
2165  * webkit_web_view_go_back:
2166  * @web_view: a #WebKitWebView
2167  *
2168  * Loads the previous history item.
2169  */
2170 void webkit_web_view_go_back(WebKitWebView* webView)
2171 {
2172     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2173
2174     core(webView)->goBack();
2175 }
2176
2177 /**
2178  * webkit_web_view_go_back_or_forward:
2179  * @web_view: a #WebKitWebView
2180  * @steps: the number of steps
2181  *
2182  * Loads the history item that is the number of @steps away from the current
2183  * item. Negative values represent steps backward while positive values
2184  * represent steps forward.
2185  */
2186 void webkit_web_view_go_back_or_forward(WebKitWebView* webView, gint steps)
2187 {
2188     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2189
2190     Frame* frame = core(webView)->mainFrame();
2191     frame->loader()->goBackOrForward(steps);
2192 }
2193
2194 /**
2195  * webkit_web_view_go_forward:
2196  * @web_view: a #WebKitWebView
2197  *
2198  * Loads the next history item.
2199  */
2200 void webkit_web_view_go_forward(WebKitWebView* webView)
2201 {
2202     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2203
2204     core(webView)->goForward();
2205 }
2206
2207 /**
2208  * webkit_web_view_can_go_back:
2209  * @web_view: a #WebKitWebView
2210  *
2211  * Determines whether #web_view has a previous history item.
2212  *
2213  * Return value: %TRUE if able to move back, %FALSE otherwise
2214  */
2215 gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
2216 {
2217     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2218
2219     if (!core(webView) || !core(webView)->backForwardList()->backItem())
2220         return FALSE;
2221
2222     return TRUE;
2223 }
2224
2225 /**
2226  * webkit_web_view_can_go_back_or_forward:
2227  * @web_view: a #WebKitWebView
2228  * @steps: the number of steps
2229  *
2230  * Determines whether #web_view has a history item of @steps. Negative values
2231  * represent steps backward while positive values represent steps forward.
2232  *
2233  * Return value: %TRUE if able to move back or forward the given number of
2234  * steps, %FALSE otherwise
2235  */
2236 gboolean webkit_web_view_can_go_back_or_forward(WebKitWebView* webView, gint steps)
2237 {
2238     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2239
2240     Frame* frame = core(webView)->mainFrame();
2241     return frame->loader()->canGoBackOrForward(steps);
2242 }
2243
2244 /**
2245  * webkit_web_view_can_go_forward:
2246  * @web_view: a #WebKitWebView
2247  *
2248  * Determines whether #web_view has a next history item.
2249  *
2250  * Return value: %TRUE if able to move forward, %FALSE otherwise
2251  */
2252 gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
2253 {
2254     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2255
2256     Page* page = core(webView);
2257
2258     if (!page)
2259         return FALSE;
2260
2261     if (!page->backForwardList()->forwardItem())
2262         return FALSE;
2263
2264     return TRUE;
2265 }
2266
2267 /**
2268  * webkit_web_view_open:
2269  * @web_view: a #WebKitWebView
2270  * @uri: an URI
2271  *
2272  * Requests loading of the specified URI string.
2273  *
2274  * Deprecated: 1.1.1: Use webkit_web_view_load_uri() instead.
2275   */
2276 void webkit_web_view_open(WebKitWebView* webView, const gchar* uri)
2277 {
2278     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2279     g_return_if_fail(uri);
2280
2281     // We used to support local paths, unlike the newer
2282     // function webkit_web_view_load_uri
2283     if (g_path_is_absolute(uri)) {
2284         gchar* fileUri = g_strdup_printf("file://%s", uri);
2285         webkit_web_view_load_uri(webView, fileUri);
2286         g_free(fileUri);
2287     }
2288     else
2289         webkit_web_view_load_uri(webView, uri);
2290 }
2291
2292 void webkit_web_view_reload(WebKitWebView* webView)
2293 {
2294     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2295
2296     core(webView)->mainFrame()->loader()->reload();
2297 }
2298
2299 /**
2300  * webkit_web_view_reload_bypass_cache:
2301  * @web_view: a #WebKitWebView
2302  *
2303  * Reloads the @web_view without using any cached data.
2304  *
2305  * Since: 1.0.3
2306  */
2307 void webkit_web_view_reload_bypass_cache(WebKitWebView* webView)
2308 {
2309     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2310
2311     core(webView)->mainFrame()->loader()->reload(true);
2312 }
2313
2314 /**
2315  * webkit_web_view_load_uri:
2316  * @web_view: a #WebKitWebView
2317  * @uri: an URI string
2318  *
2319  * Requests loading of the specified URI string.
2320  *
2321  * Since: 1.1.1
2322  */
2323 void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
2324 {
2325     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2326     g_return_if_fail(uri);
2327
2328     WebKitWebFrame* frame = webView->priv->mainFrame;
2329     webkit_web_frame_load_uri(frame, uri);
2330 }
2331
2332 /**
2333 +  * webkit_web_view_load_string:
2334 +  * @web_view: a #WebKitWebView
2335 +  * @content: an URI string
2336 +  * @mime_type: the MIME type, or %NULL
2337 +  * @encoding: the encoding, or %NULL
2338 +  * @base_uri: the base URI for relative locations
2339 +  *
2340 +  * Requests loading of the given @content with the specified @mime_type,
2341 +  * @encoding and @base_uri.
2342 +  *
2343 +  * If @mime_type is %NULL, "text/html" is assumed.
2344 +  *
2345 +  * If @encoding is %NULL, "UTF-8" is assumed.
2346 +  */
2347 void webkit_web_view_load_string(WebKitWebView* webView, const gchar* content, const gchar* mimeType, const gchar* encoding, const gchar* baseUri)
2348 {
2349     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2350     g_return_if_fail(content);
2351
2352     WebKitWebFrame* frame = webView->priv->mainFrame;
2353     webkit_web_frame_load_string(frame, content, mimeType, encoding, baseUri);
2354 }
2355 /**
2356  * webkit_web_view_load_html_string:
2357  * @web_view: a #WebKitWebView
2358  * @content: an URI string
2359  * @base_uri: the base URI for relative locations
2360  *
2361  * Requests loading of the given @content with the specified @base_uri.
2362  *
2363  * Deprecated: 1.1.1: Use webkit_web_view_load_string() instead.
2364  */
2365 void webkit_web_view_load_html_string(WebKitWebView* webView, const gchar* content, const gchar* baseUri)
2366 {
2367     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2368     g_return_if_fail(content);
2369
2370     webkit_web_view_load_string(webView, content, NULL, NULL, baseUri);
2371 }
2372
2373 /**
2374  * webkit_web_view_load_request:
2375  * @web_view: a #WebKitWebView
2376  * @request: a #WebKitNetworkRequest
2377  *
2378  * Requests loading of the specified asynchronous client request.
2379  *
2380  * Creates a provisional data source that will transition to a committed data
2381  * source once any data has been received. Use webkit_web_view_stop_loading() to
2382  * stop the load.
2383  *
2384  * Since: 1.1.1
2385  */
2386 void webkit_web_view_load_request(WebKitWebView* webView, WebKitNetworkRequest* request)
2387 {
2388     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2389     g_return_if_fail(WEBKIT_IS_NETWORK_REQUEST(request));
2390
2391     WebKitWebFrame* frame = webView->priv->mainFrame;
2392     webkit_web_frame_load_request(frame, request);
2393 }
2394
2395 void webkit_web_view_stop_loading(WebKitWebView* webView)
2396 {
2397     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2398
2399     Frame* frame = core(webView)->mainFrame();
2400
2401     if (FrameLoader* loader = frame->loader())
2402         loader->stopAllLoaders();
2403 }
2404
2405 /**
2406  * webkit_web_view_search_text:
2407  * @web_view: a #WebKitWebView
2408  * @text: a string to look for
2409  * @forward: whether to find forward or not
2410  * @case_sensitive: whether to respect the case of text
2411  * @wrap: whether to continue looking at the beginning after reaching the end
2412  *
2413  * Looks for a specified string inside #web_view.
2414  *
2415  * Return value: %TRUE on success or %FALSE on failure
2416  */
2417 gboolean webkit_web_view_search_text(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, gboolean forward, gboolean shouldWrap)
2418 {
2419     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2420     g_return_val_if_fail(string, FALSE);
2421
2422     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
2423     FindDirection direction = forward ? FindDirectionForward : FindDirectionBackward;
2424
2425     return core(webView)->findString(String::fromUTF8(string), caseSensitivity, direction, shouldWrap);
2426 }
2427
2428 /**
2429  * webkit_web_view_mark_text_matches:
2430  * @web_view: a #WebKitWebView
2431  * @string: a string to look for
2432  * @case_sensitive: whether to respect the case of text
2433  * @limit: the maximum number of strings to look for or %0 for all
2434  *
2435  * Attempts to highlight all occurances of #string inside #web_view.
2436  *
2437  * Return value: the number of strings highlighted
2438  */
2439 guint webkit_web_view_mark_text_matches(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, guint limit)
2440 {
2441     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2442     g_return_val_if_fail(string, 0);
2443
2444     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
2445
2446     return core(webView)->markAllMatchesForText(String::fromUTF8(string), caseSensitivity, false, limit);
2447 }
2448
2449 /**
2450  * webkit_web_view_set_highlight_text_matches:
2451  * @web_view: a #WebKitWebView
2452  * @highlight: whether to highlight text matches
2453  *
2454  * Highlights text matches previously marked by webkit_web_view_mark_text_matches.
2455  */
2456 void webkit_web_view_set_highlight_text_matches(WebKitWebView* webView, gboolean shouldHighlight)
2457 {
2458     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2459
2460     core(webView)->mainFrame()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
2461 }
2462
2463 /**
2464  * webkit_web_view_unmark_text_matches:
2465  * @web_view: a #WebKitWebView
2466  *
2467  * Removes highlighting previously set by webkit_web_view_mark_text_matches.
2468  */
2469 void webkit_web_view_unmark_text_matches(WebKitWebView* webView)
2470 {
2471     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2472
2473     return core(webView)->unmarkAllTextMatches();
2474 }
2475
2476 WebKitWebFrame* webkit_web_view_get_main_frame(WebKitWebView* webView)
2477 {
2478     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2479
2480     WebKitWebViewPrivate* priv = webView->priv;
2481     return priv->mainFrame;
2482 }
2483
2484 /**
2485  * webkit_web_view_get_focused_frame:
2486  * @web_view: a #WebKitWebView
2487  *
2488  * Returns the frame that has focus or an active text selection.
2489  *
2490  * Return value: The focused #WebKitWebFrame or %NULL if no frame is focused
2491  */
2492 WebKitWebFrame* webkit_web_view_get_focused_frame(WebKitWebView* webView)
2493 {
2494     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2495
2496     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
2497     return kit(focusedFrame);
2498 }
2499
2500 void webkit_web_view_execute_script(WebKitWebView* webView, const gchar* script)
2501 {
2502     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2503     g_return_if_fail(script);
2504
2505     if (FrameLoader* loader = core(webView)->mainFrame()->loader())
2506         loader->executeScript(String::fromUTF8(script), true);
2507 }
2508
2509 /**
2510  * webkit_web_view_cut_clipboard:
2511  * @web_view: a #WebKitWebView
2512  *
2513  * Determines whether or not it is currently possible to cut to the clipboard.
2514  *
2515  * Return value: %TRUE if a selection can be cut, %FALSE if not
2516  */
2517 gboolean webkit_web_view_can_cut_clipboard(WebKitWebView* webView)
2518 {
2519     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2520
2521     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2522     return frame->editor()->canCut() || frame->editor()->canDHTMLCut();
2523 }
2524
2525 /**
2526  * webkit_web_view_copy_clipboard:
2527  * @web_view: a #WebKitWebView
2528  *
2529  * Determines whether or not it is currently possible to copy to the clipboard.
2530  *
2531  * Return value: %TRUE if a selection can be copied, %FALSE if not
2532  */
2533 gboolean webkit_web_view_can_copy_clipboard(WebKitWebView* webView)
2534 {
2535     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2536
2537     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2538     return frame->editor()->canCopy() || frame->editor()->canDHTMLCopy();
2539 }
2540
2541 /**
2542  * webkit_web_view_paste_clipboard:
2543  * @web_view: a #WebKitWebView
2544  *
2545  * Determines whether or not it is currently possible to paste from the clipboard.
2546  *
2547  * Return value: %TRUE if a selection can be pasted, %FALSE if not
2548  */
2549 gboolean webkit_web_view_can_paste_clipboard(WebKitWebView* webView)
2550 {
2551     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2552
2553     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2554     return frame->editor()->canPaste() || frame->editor()->canDHTMLPaste();
2555 }
2556
2557 /**
2558  * webkit_web_view_cut_clipboard:
2559  * @web_view: a #WebKitWebView
2560  *
2561  * Cuts the current selection inside the @web_view to the clipboard.
2562  */
2563 void webkit_web_view_cut_clipboard(WebKitWebView* webView)
2564 {
2565     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2566
2567     if (webkit_web_view_can_cut_clipboard(webView))
2568         g_signal_emit(webView, webkit_web_view_signals[CUT_CLIPBOARD], 0);
2569 }
2570
2571 /**
2572  * webkit_web_view_copy_clipboard:
2573  * @web_view: a #WebKitWebView
2574  *
2575  * Copies the current selection inside the @web_view to the clipboard.
2576  */
2577 void webkit_web_view_copy_clipboard(WebKitWebView* webView)
2578 {
2579     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2580
2581     if (webkit_web_view_can_copy_clipboard(webView))
2582         g_signal_emit(webView, webkit_web_view_signals[COPY_CLIPBOARD], 0);
2583 }
2584
2585 /**
2586  * webkit_web_view_paste_clipboard:
2587  * @web_view: a #WebKitWebView
2588  *
2589  * Pastes the current contents of the clipboard to the @web_view.
2590  */
2591 void webkit_web_view_paste_clipboard(WebKitWebView* webView)
2592 {
2593     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2594
2595     if (webkit_web_view_can_paste_clipboard(webView))
2596         g_signal_emit(webView, webkit_web_view_signals[PASTE_CLIPBOARD], 0);
2597 }
2598
2599 /**
2600  * webkit_web_view_delete_selection:
2601  * @web_view: a #WebKitWebView
2602  *
2603  * Deletes the current selection inside the @web_view.
2604  */
2605 void webkit_web_view_delete_selection(WebKitWebView* webView)
2606 {
2607     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2608
2609     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2610     frame->editor()->performDelete();
2611 }
2612
2613 /**
2614  * webkit_web_view_has_selection:
2615  * @web_view: a #WebKitWebView
2616  *
2617  * Determines whether text was selected.
2618  *
2619  * Return value: %TRUE if there is selected text, %FALSE if not
2620  */
2621 gboolean webkit_web_view_has_selection(WebKitWebView* webView)
2622 {
2623     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2624
2625     return !core(webView)->selection().isNone();
2626 }
2627
2628 /**
2629  * webkit_web_view_get_selected_text:
2630  * @web_view: a #WebKitWebView
2631  *
2632  * Retrieves the selected text if any.
2633  *
2634  * Return value: a newly allocated string with the selection or %NULL
2635  */
2636 gchar* webkit_web_view_get_selected_text(WebKitWebView* webView)
2637 {
2638     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2639
2640     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2641     return g_strdup(frame->selectedText().utf8().data());
2642 }
2643
2644 /**
2645  * webkit_web_view_select_all:
2646  * @web_view: a #WebKitWebView
2647  *
2648  * Attempts to select everything inside the @web_view.
2649  */
2650 void webkit_web_view_select_all(WebKitWebView* webView)
2651 {
2652     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2653
2654     g_signal_emit(webView, webkit_web_view_signals[SELECT_ALL], 0);
2655 }
2656
2657 /**
2658  * webkit_web_view_get_editable:
2659  * @web_view: a #WebKitWebView
2660  *
2661  * Returns whether the user is allowed to edit the document.
2662  *
2663  * Returns %TRUE if @web_view allows the user to edit the HTML document, %FALSE if
2664  * it doesn't. You can change @web_view's document programmatically regardless of
2665  * this setting.
2666  *
2667  * Return value: a #gboolean indicating the editable state
2668  */
2669 gboolean webkit_web_view_get_editable(WebKitWebView* webView)
2670 {
2671     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2672
2673     WebKitWebViewPrivate* priv = webView->priv;
2674
2675     return priv->editable;
2676 }
2677
2678 /**
2679  * webkit_web_view_set_editable:
2680  * @web_view: a #WebKitWebView
2681  * @flag: a #gboolean indicating the editable state
2682  *
2683  * Sets whether @web_view allows the user to edit its HTML document.
2684  *
2685  * If @flag is %TRUE, @web_view allows the user to edit the document. If @flag is
2686  * %FALSE, an element in @web_view's document can only be edited if the
2687  * CONTENTEDITABLE attribute has been set on the element or one of its parent
2688  * elements. You can change @web_view's document programmatically regardless of
2689  * this setting. By default a #WebKitWebView is not editable.
2690
2691  * Normally, an HTML document is not editable unless the elements within the
2692  * document are editable. This function provides a low-level way to make the
2693  * contents of a #WebKitWebView editable without altering the document or DOM
2694  * structure.
2695  */
2696 void webkit_web_view_set_editable(WebKitWebView* webView, gboolean flag)
2697 {
2698     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2699
2700     WebKitWebViewPrivate* priv = webView->priv;
2701
2702     Frame* frame = core(webView)->mainFrame();
2703     g_return_if_fail(frame);
2704
2705     // TODO: What happens when the frame is replaced?
2706     flag = flag != FALSE;
2707     if (flag == priv->editable)
2708         return;
2709
2710     priv->editable = flag;
2711
2712     if (flag) {
2713         frame->applyEditingStyleToBodyElement();
2714         // TODO: If the WebKitWebView is made editable and the selection is empty, set it to something.
2715         //if (!webkit_web_view_get_selected_dom_range(webView))
2716         //    mainFrame->setSelectionFromNone();
2717     } else
2718         frame->removeEditingStyleFromBodyElement();
2719     g_object_notify(G_OBJECT(webView), "editable");
2720 }
2721
2722 /**
2723  * webkit_web_view_get_copy_target_list:
2724  * @web_view: a #WebKitWebView
2725  *
2726  * This function returns the list of targets this #WebKitWebView can
2727  * provide for clipboard copying and as DND source. The targets in the list are
2728  * added with %info values from the #WebKitWebViewTargetInfo enum,
2729  * using gtk_target_list_add() and
2730  * gtk_target_list_add_text_targets().
2731  *
2732  * Return value: the #GtkTargetList
2733  **/
2734 GtkTargetList* webkit_web_view_get_copy_target_list(WebKitWebView* webView)
2735 {
2736     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2737
2738     WebKitWebViewPrivate* priv = webView->priv;
2739     return priv->copy_target_list;
2740 }
2741
2742 /**
2743  * webkit_web_view_get_paste_target_list:
2744  * @web_view: a #WebKitWebView
2745  *
2746  * This function returns the list of targets this #WebKitWebView can
2747  * provide for clipboard pasting and as DND destination. The targets in the list are
2748  * added with %info values from the #WebKitWebViewTargetInfo enum,
2749  * using gtk_target_list_add() and
2750  * gtk_target_list_add_text_targets().
2751  *
2752  * Return value: the #GtkTargetList
2753  **/
2754 GtkTargetList* webkit_web_view_get_paste_target_list(WebKitWebView* webView)
2755 {
2756     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2757
2758     WebKitWebViewPrivate* priv = webView->priv;
2759     return priv->paste_target_list;
2760 }
2761
2762 /**
2763  * webkit_web_view_can_show_mime_type:
2764  * @web_view: a #WebKitWebView
2765  * @mime_type: a MIME type
2766  *
2767  * This functions returns whether or not a MIME type can be displayed using this view.
2768  *
2769  * Return value: a #gboolean indicating if the MIME type can be displayed
2770  *
2771  * Since: 1.0.3
2772  **/
2773
2774 gboolean webkit_web_view_can_show_mime_type(WebKitWebView* webView, const gchar* mimeType)
2775 {
2776     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2777
2778     Frame* frame = core(webkit_web_view_get_main_frame(webView));
2779     if (FrameLoader* loader = frame->loader())
2780         return loader->canShowMIMEType(String::fromUTF8(mimeType));
2781     else
2782         return FALSE;
2783 }
2784
2785 /**
2786  * webkit_web_view_get_transparent:
2787  * @web_view: a #WebKitWebView
2788  *
2789  * Returns whether the #WebKitWebView has a transparent background.
2790  *
2791  * Return value: %FALSE when the #WebKitWebView draws a solid background
2792  * (the default), otherwise %TRUE.
2793  */
2794 gboolean webkit_web_view_get_transparent(WebKitWebView* webView)
2795 {
2796     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2797
2798     WebKitWebViewPrivate* priv = webView->priv;
2799     return priv->transparent;
2800 }
2801
2802 /**
2803  * webkit_web_view_set_transparent:
2804  * @web_view: a #WebKitWebView
2805  *
2806  * Sets whether the #WebKitWebView has a transparent background.
2807  *
2808  * Pass %FALSE to have the #WebKitWebView draw a solid background
2809  * (the default), otherwise %TRUE.
2810  */
2811 void webkit_web_view_set_transparent(WebKitWebView* webView, gboolean flag)
2812 {
2813     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2814
2815     WebKitWebViewPrivate* priv = webView->priv;
2816     priv->transparent = flag;
2817
2818     // TODO: This needs to be made persistent or it could become a problem when
2819     // the main frame is replaced.
2820     Frame* frame = core(webView)->mainFrame();
2821     g_return_if_fail(frame);
2822     frame->view()->setTransparent(flag);
2823     g_object_notify(G_OBJECT(webView), "transparent");
2824 }
2825
2826 /**
2827  * webkit_web_view_get_zoom_level:
2828  * @web_view: a #WebKitWebView
2829  *
2830  * Returns the zoom level of @web_view, i.e. the factor by which elements in
2831  * the page are scaled with respect to their original size.
2832  * If the "full-content-zoom" property is set to %FALSE (the default)
2833  * the zoom level changes the text size, or if %TRUE, scales all
2834  * elements in the page.
2835  *
2836  * Return value: the zoom level of @web_view
2837  *
2838  * Since: 1.0.1
2839  */
2840 gfloat webkit_web_view_get_zoom_level(WebKitWebView* webView)
2841 {
2842     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1.0f);
2843
2844     Frame* frame = core(webView)->mainFrame();
2845     if (!frame)
2846         return 1.0f;
2847
2848     return frame->zoomFactor();
2849 }
2850
2851 static void webkit_web_view_apply_zoom_level(WebKitWebView* webView, gfloat zoomLevel)
2852 {
2853     Frame* frame = core(webView)->mainFrame();
2854     if (!frame)
2855         return;
2856
2857     WebKitWebViewPrivate* priv = webView->priv;
2858     frame->setZoomFactor(zoomLevel, !priv->zoomFullContent);
2859 }
2860
2861 /**
2862  * webkit_web_view_set_zoom_level:
2863  * @web_view: a #WebKitWebView
2864  * @zoom_level: the new zoom level
2865  *
2866  * Sets the zoom level of @web_view, i.e. the factor by which elements in
2867  * the page are scaled with respect to their original size.
2868  * If the "full-content-zoom" property is set to %FALSE (the default)
2869  * the zoom level changes the text size, or if %TRUE, scales all
2870  * elements in the page.
2871  *
2872  * Since: 1.0.1
2873  */
2874 void webkit_web_view_set_zoom_level(WebKitWebView* webView, gfloat zoomLevel)
2875 {
2876     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2877
2878     webkit_web_view_apply_zoom_level(webView, zoomLevel);
2879     g_object_notify(G_OBJECT(webView), "zoom-level");
2880 }
2881
2882 /**
2883  * webkit_web_view_zoom_in:
2884  * @web_view: a #WebKitWebView
2885  *
2886  * Increases the zoom level of @web_view. The current zoom
2887  * level is incremented by the value of the "zoom-step"
2888  * property of the #WebKitWebSettings associated with @web_view.
2889  *
2890  * Since: 1.0.1
2891  */
2892 void webkit_web_view_zoom_in(WebKitWebView* webView)
2893 {
2894     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2895
2896     WebKitWebViewPrivate* priv = webView->priv;
2897     gfloat zoomMultiplierRatio;
2898     g_object_get(priv->webSettings, "zoom-step", &zoomMultiplierRatio, NULL);
2899
2900     webkit_web_view_set_zoom_level(webView, webkit_web_view_get_zoom_level(webView) + zoomMultiplierRatio);
2901 }
2902
2903 /**
2904  * webkit_web_view_zoom_out:
2905  * @web_view: a #WebKitWebView
2906  *
2907  * Decreases the zoom level of @web_view. The current zoom
2908  * level is decremented by the value of the "zoom-step"
2909  * property of the #WebKitWebSettings associated with @web_view.
2910  *
2911  * Since: 1.0.1
2912  */
2913 void webkit_web_view_zoom_out(WebKitWebView* webView)
2914 {
2915     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2916
2917     WebKitWebViewPrivate* priv = webView->priv;
2918     gfloat zoomMultiplierRatio;
2919     g_object_get(priv->webSettings, "zoom-step", &zoomMultiplierRatio, NULL);
2920
2921     webkit_web_view_set_zoom_level(webView, webkit_web_view_get_zoom_level(webView) - zoomMultiplierRatio);
2922 }
2923
2924 /**
2925  * webkit_web_view_get_full_content_zoom:
2926  * @web_view: a #WebKitWebView
2927  *
2928  * Returns whether the zoom level affects only text or all elements.
2929  *
2930  * Return value: %FALSE if only text should be scaled (the default),
2931  * %TRUE if the full content of the view should be scaled.
2932  *
2933  * Since: 1.0.1
2934  */
2935 gboolean webkit_web_view_get_full_content_zoom(WebKitWebView* webView)
2936 {
2937     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2938
2939     WebKitWebViewPrivate* priv = webView->priv;
2940     return priv->zoomFullContent;
2941 }
2942
2943 /**
2944  * webkit_web_view_set_full_content_zoom:
2945  * @web_view: a #WebKitWebView
2946  * @full_content_zoom: %FALSE if only text should be scaled (the default),
2947  * %TRUE if the full content of the view should be scaled.
2948  *
2949  * Sets whether the zoom level affects only text or all elements.
2950  *
2951  * Since: 1.0.1
2952  */
2953 void webkit_web_view_set_full_content_zoom(WebKitWebView* webView, gboolean zoomFullContent)
2954 {
2955     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2956
2957     WebKitWebViewPrivate* priv = webView->priv;
2958     if (priv->zoomFullContent == zoomFullContent)
2959       return;
2960
2961     priv->zoomFullContent = zoomFullContent;
2962     webkit_web_view_apply_zoom_level(webView, webkit_web_view_get_zoom_level(webView));
2963
2964     g_object_notify(G_OBJECT(webView), "full-content-zoom");
2965 }
2966
2967 /**
2968  * webkit_get_default_session:
2969  *
2970  * Retrieves the default #SoupSession used by all web views.
2971  * Note that the session features are added by WebKit on demand,
2972  * so if you insert your own #SoupCookieJar before any network
2973  * traffic occurs, WebKit will use it instead of the default.
2974  *
2975  * Return value: the default #SoupSession
2976  *
2977  * Since: 1.1.1
2978  */
2979 SoupSession* webkit_get_default_session ()
2980 {
2981     return ResourceHandle::defaultSession();
2982 }
2983
2984 }
2985
2986 /**
2987  * webkit_web_view_get_encoding:
2988  * @web_view: a #WebKitWebView
2989  *
2990  * Returns the default encoding of the #WebKitWebView.
2991  *
2992  * Return value: the default encoding
2993  *
2994  * Since: 1.1.1
2995  */
2996 const gchar* webkit_web_view_get_encoding(WebKitWebView* webView)
2997 {
2998     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2999
3000     String encoding = core(webView)->mainFrame()->loader()->encoding();
3001
3002     if (!encoding.isEmpty()) {
3003         WebKitWebViewPrivate* priv = webView->priv;
3004         g_free(priv->encoding);
3005         priv->encoding = g_strdup(encoding.utf8().data());
3006         return priv->encoding;
3007     } else
3008       return NULL;
3009 }
3010
3011 /**
3012  * webkit_web_view_set_custom_encoding:
3013  * @web_view: a #WebKitWebView
3014  * @encoding: the new encoding, or %NULL to restore the default encoding
3015  *
3016  * Sets the current #WebKitWebView encoding, without modifying the default one,
3017  * and reloads the page.
3018  *
3019  * Since: 1.1.1
3020  */
3021 void webkit_web_view_set_custom_encoding(WebKitWebView* webView, const char* encoding)
3022 {
3023     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3024
3025     core(webView)->mainFrame()->loader()->reloadWithOverrideEncoding(String::fromUTF8(encoding));
3026 }
3027
3028 /**
3029  * webkit_web_view_get_custom_encoding:
3030  * @web_view: a #WebKitWebView
3031  *
3032  * Returns the current encoding of the #WebKitWebView, not the default-encoding
3033  * of WebKitWebSettings.
3034  *
3035  * Return value: a string containing the current custom encoding for @web_view, or %NULL if there's none set.
3036  *
3037  * Since: 1.1.1
3038  */
3039 const char* webkit_web_view_get_custom_encoding(WebKitWebView* webView)
3040 {
3041     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
3042
3043     String overrideEncoding = core(webView)->mainFrame()->loader()->documentLoader()->overrideEncoding();
3044
3045     if (!overrideEncoding.isEmpty()) {
3046         WebKitWebViewPrivate* priv = webView->priv;
3047         g_free (priv->customEncoding);
3048         priv->customEncoding = g_strdup(overrideEncoding.utf8().data());
3049         return priv->customEncoding;
3050     } else
3051       return NULL;
3052 }