2011-02-04 Martin Robinson <mrobinson@igalia.com>
[WebKit.git] / Source / WebKit / gtk / webkit / webkitwebframe.cpp
1 /*
2  * Copyright (C) 2007, 2008 Holger Hans Peter Freyther
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  * Copyright (C) 2007 Apple Inc.
5  * Copyright (C) 2008 Christian Dywan <christian@imendio.com>
6  * Copyright (C) 2008 Collabora Ltd.
7  * Copyright (C) 2008 Nuanti Ltd.
8  * Copyright (C) 2009 Jan Alonzo <jmalonzo@gmail.com>
9  * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26
27 #include "config.h"
28 #include "webkitwebframe.h"
29
30 #include "AXObjectCache.h"
31 #include "AccessibilityObjectWrapperAtk.h"
32 #include "AnimationController.h"
33 #include "DOMObjectCache.h"
34 #include "DocumentLoader.h"
35 #include "DocumentLoaderGtk.h"
36 #include "FrameLoader.h"
37 #include "FrameLoaderClientGtk.h"
38 #include "FrameTree.h"
39 #include "FrameView.h"
40 #include "GCController.h"
41 #include "GraphicsContext.h"
42 #include "GtkVersioning.h"
43 #include "HTMLFrameOwnerElement.h"
44 #include "JSDOMBinding.h"
45 #include "JSDOMWindow.h"
46 #include "JSElement.h"
47 #include "PrintContext.h"
48 #include "RenderListItem.h"
49 #include "RenderTreeAsText.h"
50 #include "RenderView.h"
51 #include "ScriptController.h"
52 #include "SubstituteData.h"
53 #include "webkitenumtypes.h"
54 #include "webkitglobalsprivate.h"
55 #include "webkitmarshal.h"
56 #include "webkitnetworkrequestprivate.h"
57 #include "webkitnetworkresponseprivate.h"
58 #include "webkitsecurityoriginprivate.h"
59 #include "webkitwebframeprivate.h"
60 #include "webkitwebview.h"
61 #include "webkitwebviewprivate.h"
62 #include <JavaScriptCore/APICast.h>
63 #include <atk/atk.h>
64 #include <glib/gi18n-lib.h>
65 #include <wtf/text/CString.h>
66
67 #if ENABLE(SVG)
68 #include "SVGSMILElement.h"
69 #endif
70
71 /**
72  * SECTION:webkitwebframe
73  * @short_description: The content of a #WebKitWebView
74  *
75  * A #WebKitWebView contains a main #WebKitWebFrame. A #WebKitWebFrame
76  * contains the content of one URI. The URI and name of the frame can
77  * be retrieved, the load status and progress can be observed using the
78  * signals and can be controlled using the methods of the #WebKitWebFrame.
79  * A #WebKitWebFrame can have any number of children and one child can
80  * be found by using #webkit_web_frame_find_frame.
81  *
82  * <informalexample><programlisting>
83  * /<!-- -->* Get the frame from the #WebKitWebView *<!-- -->/
84  * WebKitWebFrame *frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW(my_view));
85  * g_print("The URI of this frame is '%s'", webkit_web_frame_get_uri (frame));
86  * </programlisting></informalexample>
87  */
88
89 using namespace WebKit;
90 using namespace WebCore;
91 using namespace std;
92
93 enum {
94     CLEARED,
95     LOAD_COMMITTED,
96     LOAD_DONE,
97     TITLE_CHANGED,
98     HOVERING_OVER_LINK,
99     SCROLLBARS_POLICY_CHANGED,
100     LAST_SIGNAL
101 };
102
103 enum {
104     PROP_0,
105
106     PROP_NAME,
107     PROP_TITLE,
108     PROP_URI,
109     PROP_LOAD_STATUS,
110     PROP_HORIZONTAL_SCROLLBAR_POLICY,
111     PROP_VERTICAL_SCROLLBAR_POLICY
112 };
113
114 static guint webkit_web_frame_signals[LAST_SIGNAL] = { 0, };
115
116 G_DEFINE_TYPE(WebKitWebFrame, webkit_web_frame, G_TYPE_OBJECT)
117
118 static void webkit_web_frame_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* paramSpec)
119 {
120     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(object);
121
122     switch (propertyId) {
123     case PROP_NAME:
124         g_value_set_string(value, webkit_web_frame_get_name(frame));
125         break;
126     case PROP_TITLE:
127         g_value_set_string(value, webkit_web_frame_get_title(frame));
128         break;
129     case PROP_URI:
130         g_value_set_string(value, webkit_web_frame_get_uri(frame));
131         break;
132     case PROP_LOAD_STATUS:
133         g_value_set_enum(value, webkit_web_frame_get_load_status(frame));
134         break;
135     case PROP_HORIZONTAL_SCROLLBAR_POLICY:
136         g_value_set_enum(value, webkit_web_frame_get_horizontal_scrollbar_policy(frame));
137         break;
138     case PROP_VERTICAL_SCROLLBAR_POLICY:
139         g_value_set_enum(value, webkit_web_frame_get_vertical_scrollbar_policy(frame));
140         break;
141     default:
142         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, paramSpec);
143         break;
144     }
145 }
146
147 // Called from the FrameLoaderClient when it is destroyed. Normally
148 // the unref in the FrameLoaderClient is destroying this object as
149 // well but due reference counting a user might have added a reference...
150 void webkit_web_frame_core_frame_gone(WebKitWebFrame* frame)
151 {
152     ASSERT(WEBKIT_IS_WEB_FRAME(frame));
153     WebKitWebFramePrivate* priv = frame->priv;
154     if (priv->coreFrame)
155         DOMObjectCache::clearByFrame(priv->coreFrame);
156     priv->coreFrame = 0;
157 }
158
159 static WebKitWebDataSource* webkit_web_frame_get_data_source_from_core_loader(WebCore::DocumentLoader* loader)
160 {
161     return loader ? static_cast<WebKit::DocumentLoader*>(loader)->dataSource() : 0;
162 }
163
164 static void webkit_web_frame_finalize(GObject* object)
165 {
166     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(object);
167     WebKitWebFramePrivate* priv = frame->priv;
168
169     if (priv->coreFrame) {
170         DOMObjectCache::clearByFrame(priv->coreFrame);
171         priv->coreFrame->loader()->cancelAndClear();
172         priv->coreFrame = 0;
173     }
174
175     g_free(priv->name);
176     g_free(priv->title);
177     g_free(priv->uri);
178
179     G_OBJECT_CLASS(webkit_web_frame_parent_class)->finalize(object);
180 }
181
182 static void webkit_web_frame_class_init(WebKitWebFrameClass* frameClass)
183 {
184     webkitInit();
185
186     /*
187      * signals
188      */
189     webkit_web_frame_signals[CLEARED] = g_signal_new("cleared",
190             G_TYPE_FROM_CLASS(frameClass),
191             (GSignalFlags)G_SIGNAL_RUN_LAST,
192             0,
193             0,
194             0,
195             g_cclosure_marshal_VOID__VOID,
196             G_TYPE_NONE, 0);
197
198     /**
199      * WebKitWebFrame::load-done
200      * @web_frame: the object on which the signal is emitted
201      *
202      * Emitted when frame loading is done.
203      *
204      * Deprecated: Use the "load-status" property instead.
205      */
206     webkit_web_frame_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
207             G_TYPE_FROM_CLASS(frameClass),
208             (GSignalFlags)G_SIGNAL_RUN_LAST,
209             0,
210             0,
211             0,
212             g_cclosure_marshal_VOID__VOID,
213             G_TYPE_NONE, 0);
214
215     /**
216      * WebKitWebFrame::load-done
217      * @web_frame: the object on which the signal is emitted
218      *
219      * Emitted when frame loading is done.
220      *
221      * Deprecated: Use the "load-status" property instead, and/or
222      * WebKitWebView::load-error to be notified of load errors
223      */
224     webkit_web_frame_signals[LOAD_DONE] = g_signal_new("load-done",
225             G_TYPE_FROM_CLASS(frameClass),
226             (GSignalFlags)G_SIGNAL_RUN_LAST,
227             0,
228             0,
229             0,
230             g_cclosure_marshal_VOID__BOOLEAN,
231             G_TYPE_NONE, 1,
232             G_TYPE_BOOLEAN);
233
234     /**
235      * WebKitWebFrame::title-changed:
236      * @frame: the object on which the signal is emitted
237      * @title: the new title
238      *
239      * When a #WebKitWebFrame changes the document title this signal is emitted.
240      *
241      * Deprecated: 1.1.18: Use "notify::title" instead.
242      */
243     webkit_web_frame_signals[TITLE_CHANGED] = g_signal_new("title-changed",
244             G_TYPE_FROM_CLASS(frameClass),
245             (GSignalFlags)G_SIGNAL_RUN_LAST,
246             0,
247             0,
248             0,
249             webkit_marshal_VOID__STRING,
250             G_TYPE_NONE, 1,
251             G_TYPE_STRING);
252
253     webkit_web_frame_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
254             G_TYPE_FROM_CLASS(frameClass),
255             (GSignalFlags)G_SIGNAL_RUN_LAST,
256             0,
257             0,
258             0,
259             webkit_marshal_VOID__STRING_STRING,
260             G_TYPE_NONE, 2,
261             G_TYPE_STRING, G_TYPE_STRING);
262
263     /**
264      * WebKitWebFrame::scrollbars-policy-changed:
265      * @web_view: the object which received the signal
266      *
267      * Signal emitted when policy for one or both of the scrollbars of
268      * the view has changed. The default handler will apply the new
269      * policy to the container that holds the #WebKitWebFrame if it is
270      * a #GtkScrolledWindow and the frame is the main frame. If you do
271      * not want this to be handled automatically, you need to handle
272      * this signal.
273      *
274      * The exception to this rule is that policies to disable the
275      * scrollbars are applied as %GTK_POLICY_AUTOMATIC instead, since
276      * the size request of the widget would force browser windows to
277      * not be resizable.
278      *
279      * You can obtain the new policies from the
280      * WebKitWebFrame:horizontal-scrollbar-policy and
281      * WebKitWebFrame:vertical-scrollbar-policy properties.
282      *
283      * Return value: %TRUE to stop other handlers from being invoked for the
284      * event. %FALSE to propagate the event further.
285      *
286      * Since: 1.1.14
287      */
288     webkit_web_frame_signals[SCROLLBARS_POLICY_CHANGED] = g_signal_new("scrollbars-policy-changed",
289             G_TYPE_FROM_CLASS(frameClass),
290             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
291             0,
292             g_signal_accumulator_true_handled,
293             0,
294             webkit_marshal_BOOLEAN__VOID,
295             G_TYPE_BOOLEAN, 0);
296
297     /*
298      * implementations of virtual methods
299      */
300     GObjectClass* objectClass = G_OBJECT_CLASS(frameClass);
301     objectClass->finalize = webkit_web_frame_finalize;
302     objectClass->get_property = webkit_web_frame_get_property;
303
304     /*
305      * properties
306      */
307     g_object_class_install_property(objectClass, PROP_NAME,
308                                     g_param_spec_string("name",
309                                                         _("Name"),
310                                                         _("The name of the frame"),
311                                                         0,
312                                                         WEBKIT_PARAM_READABLE));
313
314     g_object_class_install_property(objectClass, PROP_TITLE,
315                                     g_param_spec_string("title",
316                                                         _("Title"),
317                                                         _("The document title of the frame"),
318                                                         0,
319                                                         WEBKIT_PARAM_READABLE));
320
321     g_object_class_install_property(objectClass, PROP_URI,
322                                     g_param_spec_string("uri",
323                                                         _("URI"),
324                                                         _("The current URI of the contents displayed by the frame"),
325                                                         0,
326                                                         WEBKIT_PARAM_READABLE));
327
328     /**
329     * WebKitWebFrame:load-status:
330     *
331     * Determines the current status of the load.
332     *
333     * Since: 1.1.7
334     */
335     g_object_class_install_property(objectClass, PROP_LOAD_STATUS,
336                                     g_param_spec_enum("load-status",
337                                                       "Load Status",
338                                                       "Determines the current status of the load",
339                                                       WEBKIT_TYPE_LOAD_STATUS,
340                                                       WEBKIT_LOAD_FINISHED,
341                                                       WEBKIT_PARAM_READABLE));
342
343     /**
344      * WebKitWebFrame:horizontal-scrollbar-policy:
345      *
346      * Determines the current policy for the horizontal scrollbar of
347      * the frame. For the main frame, make sure to set the same policy
348      * on the scrollable widget containing the #WebKitWebView, unless
349      * you know what you are doing.
350      *
351      * Since: 1.1.14
352      */
353     g_object_class_install_property(objectClass, PROP_HORIZONTAL_SCROLLBAR_POLICY,
354                                     g_param_spec_enum("horizontal-scrollbar-policy",
355                                                       _("Horizontal Scrollbar Policy"),
356                                                       _("Determines the current policy for the horizontal scrollbar of the frame."),
357                                                       GTK_TYPE_POLICY_TYPE,
358                                                       GTK_POLICY_AUTOMATIC,
359                                                       WEBKIT_PARAM_READABLE));
360
361     /**
362      * WebKitWebFrame:vertical-scrollbar-policy:
363      *
364      * Determines the current policy for the vertical scrollbar of
365      * the frame. For the main frame, make sure to set the same policy
366      * on the scrollable widget containing the #WebKitWebView, unless
367      * you know what you are doing.
368      *
369      * Since: 1.1.14
370      */
371     g_object_class_install_property(objectClass, PROP_VERTICAL_SCROLLBAR_POLICY,
372                                     g_param_spec_enum("vertical-scrollbar-policy",
373                                                       _("Vertical Scrollbar Policy"),
374                                                       _("Determines the current policy for the vertical scrollbar of the frame."),
375                                                       GTK_TYPE_POLICY_TYPE,
376                                                       GTK_POLICY_AUTOMATIC,
377                                                       WEBKIT_PARAM_READABLE));
378
379     g_type_class_add_private(frameClass, sizeof(WebKitWebFramePrivate));
380 }
381
382 static void webkit_web_frame_init(WebKitWebFrame* frame)
383 {
384     WebKitWebFramePrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(frame, WEBKIT_TYPE_WEB_FRAME, WebKitWebFramePrivate);
385
386     // TODO: Move constructor code here.
387     frame->priv = priv;
388 }
389
390
391 /**
392  * webkit_web_frame_new:
393  * @web_view: the controlling #WebKitWebView
394  *
395  * Creates a new #WebKitWebFrame initialized with a controlling #WebKitWebView.
396  *
397  * Returns: a new #WebKitWebFrame
398  *
399  * Deprecated: 1.0.2: #WebKitWebFrame can only be used to inspect existing
400  * frames.
401  **/
402 WebKitWebFrame* webkit_web_frame_new(WebKitWebView* webView)
403 {
404     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
405
406     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
407     WebKitWebFramePrivate* priv = frame->priv;
408     WebKitWebViewPrivate* viewPriv = webView->priv;
409
410     priv->webView = webView;
411     WebKit::FrameLoaderClient* client = new WebKit::FrameLoaderClient(frame);
412     priv->coreFrame = Frame::create(viewPriv->corePage, 0, client).get();
413     priv->coreFrame->init();
414
415     priv->origin = 0;
416
417     return frame;
418 }
419
420 /**
421  * webkit_web_frame_get_title:
422  * @frame: a #WebKitWebFrame
423  *
424  * Returns the @frame's document title
425  *
426  * Return value: the title of @frame
427  */
428 G_CONST_RETURN gchar* webkit_web_frame_get_title(WebKitWebFrame* frame)
429 {
430     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
431
432     WebKitWebFramePrivate* priv = frame->priv;
433     return priv->title;
434 }
435
436 /**
437  * webkit_web_frame_get_uri:
438  * @frame: a #WebKitWebFrame
439  *
440  * Returns the current URI of the contents displayed by the @frame
441  *
442  * Return value: the URI of @frame
443  */
444 G_CONST_RETURN gchar* webkit_web_frame_get_uri(WebKitWebFrame* frame)
445 {
446     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
447
448     WebKitWebFramePrivate* priv = frame->priv;
449     return priv->uri;
450 }
451
452 /**
453  * webkit_web_frame_get_web_view:
454  * @frame: a #WebKitWebFrame
455  *
456  * Returns the #WebKitWebView that manages this #WebKitWebFrame.
457  *
458  * The #WebKitWebView returned manages the entire hierarchy of #WebKitWebFrame
459  * objects that contains @frame.
460  *
461  * Return value: (transfer none): the #WebKitWebView that manages @frame
462  */
463 WebKitWebView* webkit_web_frame_get_web_view(WebKitWebFrame* frame)
464 {
465     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
466
467     WebKitWebFramePrivate* priv = frame->priv;
468     return priv->webView;
469 }
470
471 /**
472  * webkit_web_frame_get_name:
473  * @frame: a #WebKitWebFrame
474  *
475  * Returns the @frame's name
476  *
477  * Return value: the name of @frame. This method will return NULL if
478  * the #WebKitWebFrame is invalid or an empty string if it is not backed
479  * by a live WebCore frame.
480  */
481 G_CONST_RETURN gchar* webkit_web_frame_get_name(WebKitWebFrame* frame)
482 {
483     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
484     Frame* coreFrame = core(frame);
485     if (!coreFrame)
486         return "";
487
488     WebKitWebFramePrivate* priv = frame->priv;
489     CString frameName = coreFrame->tree()->uniqueName().string().utf8();
490     if (!g_strcmp0(frameName.data(), priv->name))
491         return priv->name;
492
493     g_free(priv->name);
494     priv->name = g_strdup(frameName.data());
495     return priv->name;
496 }
497
498 /**
499  * webkit_web_frame_get_parent:
500  * @frame: a #WebKitWebFrame
501  *
502  * Returns the @frame's parent frame, or %NULL if it has none.
503  *
504  * Return value: (transfer none): the parent #WebKitWebFrame or %NULL in case there is none
505  */
506 WebKitWebFrame* webkit_web_frame_get_parent(WebKitWebFrame* frame)
507 {
508     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
509
510     Frame* coreFrame = core(frame);
511     if (!coreFrame)
512         return 0;
513
514     return kit(coreFrame->tree()->parent());
515 }
516
517 /**
518  * webkit_web_frame_load_uri:
519  * @frame: a #WebKitWebFrame
520  * @uri: an URI string
521  *
522  * Requests loading of the specified URI string.
523  *
524  * Since: 1.1.1
525  */
526 void webkit_web_frame_load_uri(WebKitWebFrame* frame, const gchar* uri)
527 {
528     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
529     g_return_if_fail(uri);
530
531     Frame* coreFrame = core(frame);
532     if (!coreFrame)
533         return;
534
535     coreFrame->loader()->load(ResourceRequest(KURL(KURL(), String::fromUTF8(uri))), false);
536 }
537
538 static void webkit_web_frame_load_data(WebKitWebFrame* frame, const gchar* content, const gchar* mimeType, const gchar* encoding, const gchar* baseURL, const gchar* unreachableURL)
539 {
540     Frame* coreFrame = core(frame);
541     ASSERT(coreFrame);
542
543     KURL baseKURL = baseURL ? KURL(KURL(), String::fromUTF8(baseURL)) : blankURL();
544
545     ResourceRequest request(baseKURL);
546
547     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(content, strlen(content));
548     SubstituteData substituteData(sharedBuffer.release(),
549                                   mimeType ? String::fromUTF8(mimeType) : String::fromUTF8("text/html"),
550                                   encoding ? String::fromUTF8(encoding) : String::fromUTF8("UTF-8"),
551                                   KURL(KURL(), String::fromUTF8(unreachableURL)),
552                                   KURL(KURL(), String::fromUTF8(unreachableURL)));
553
554     coreFrame->loader()->load(request, substituteData, false);
555 }
556
557 /**
558  * webkit_web_frame_load_string:
559  * @frame: a #WebKitWebFrame
560  * @content: an URI string
561  * @mime_type: the MIME type, or %NULL
562  * @encoding: the encoding, or %NULL
563  * @base_uri: the base URI for relative locations
564  *
565  * Requests loading of the given @content with the specified @mime_type,
566  * @encoding and @base_uri.
567  *
568  * If @mime_type is %NULL, "text/html" is assumed.
569  *
570  * If @encoding is %NULL, "UTF-8" is assumed.
571  *
572  * Since: 1.1.1
573  */
574 void webkit_web_frame_load_string(WebKitWebFrame* frame, const gchar* content, const gchar* contentMimeType, const gchar* contentEncoding, const gchar* baseUri)
575 {
576     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
577     g_return_if_fail(content);
578
579     webkit_web_frame_load_data(frame, content, contentMimeType, contentEncoding, baseUri, 0);
580 }
581
582 /**
583  * webkit_web_frame_load_alternate_string:
584  * @frame: a #WebKitWebFrame
585  * @content: the alternate content to display as the main page of the @frame
586  * @base_url: the base URI for relative locations
587  * @unreachable_url: the URL for the alternate page content
588  *
589  * Request loading of an alternate content for a URL that is unreachable.
590  * Using this method will preserve the back-forward list. The URI passed in
591  * @base_url has to be an absolute URI.
592  *
593  * Since: 1.1.6
594  */
595 void webkit_web_frame_load_alternate_string(WebKitWebFrame* frame, const gchar* content, const gchar* baseURL, const gchar* unreachableURL)
596 {
597     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
598     g_return_if_fail(content);
599
600     webkit_web_frame_load_data(frame, content, 0, 0, baseURL, unreachableURL);
601 }
602
603 /**
604  * webkit_web_frame_load_request:
605  * @frame: a #WebKitWebFrame
606  * @request: a #WebKitNetworkRequest
607  *
608  * Connects to a given URI by initiating an asynchronous client request.
609  *
610  * Creates a provisional data source that will transition to a committed data
611  * source once any data has been received. Use webkit_web_frame_stop_loading() to
612  * stop the load. This function is typically invoked on the main frame.
613  */
614 void webkit_web_frame_load_request(WebKitWebFrame* frame, WebKitNetworkRequest* request)
615 {
616     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
617     g_return_if_fail(WEBKIT_IS_NETWORK_REQUEST(request));
618
619     Frame* coreFrame = core(frame);
620     if (!coreFrame)
621         return;
622
623     coreFrame->loader()->load(core(request), false);
624 }
625
626 /**
627  * webkit_web_frame_stop_loading:
628  * @frame: a #WebKitWebFrame
629  *
630  * Stops any pending loads on @frame's data source, and those of its children.
631  */
632 void webkit_web_frame_stop_loading(WebKitWebFrame* frame)
633 {
634     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
635
636     Frame* coreFrame = core(frame);
637     if (!coreFrame)
638         return;
639
640     coreFrame->loader()->stopAllLoaders();
641 }
642
643 /**
644  * webkit_web_frame_reload:
645  * @frame: a #WebKitWebFrame
646  *
647  * Reloads the initial request.
648  */
649 void webkit_web_frame_reload(WebKitWebFrame* frame)
650 {
651     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
652
653     Frame* coreFrame = core(frame);
654     if (!coreFrame)
655         return;
656
657     coreFrame->loader()->reload();
658 }
659
660 /**
661  * webkit_web_frame_find_frame:
662  * @frame: a #WebKitWebFrame
663  * @name: the name of the frame to be found
664  *
665  * For pre-defined names, returns @frame if @name is "_self" or "_current",
666  * returns @frame's parent frame if @name is "_parent", and returns the main
667  * frame if @name is "_top". Also returns @frame if it is the main frame and
668  * @name is either "_parent" or "_top". For other names, this function returns
669  * the first frame that matches @name. This function searches @frame and its
670  * descendents first, then @frame's parent and its children moving up the
671  * hierarchy until a match is found. If no match is found in @frame's
672  * hierarchy, this function will search for a matching frame in other main
673  * frame hierarchies. Returns %NULL if no match is found.
674  *
675  * Return value: (transfer none): the found #WebKitWebFrame or %NULL in case none is found
676  */
677 WebKitWebFrame* webkit_web_frame_find_frame(WebKitWebFrame* frame, const gchar* name)
678 {
679     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
680     g_return_val_if_fail(name, 0);
681
682     Frame* coreFrame = core(frame);
683     if (!coreFrame)
684         return 0;
685
686     String nameString = String::fromUTF8(name);
687     return kit(coreFrame->tree()->find(AtomicString(nameString)));
688 }
689
690 /**
691  * webkit_web_frame_get_global_context:
692  * @frame: a #WebKitWebFrame
693  *
694  * Gets the global JavaScript execution context. Use this function to bridge
695  * between the WebKit and JavaScriptCore APIs.
696  *
697  * Return value: (transfer none): the global JavaScript context
698  */
699 JSGlobalContextRef webkit_web_frame_get_global_context(WebKitWebFrame* frame)
700 {
701     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
702
703     Frame* coreFrame = core(frame);
704     if (!coreFrame)
705         return 0;
706
707     return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
708 }
709
710 /**
711  * webkit_web_frame_get_data_source:
712  * @frame: a #WebKitWebFrame
713  *
714  * Returns the committed data source.
715  *
716  * Return value: (transfer none): the committed #WebKitWebDataSource.
717  *
718  * Since: 1.1.14
719  */
720 WebKitWebDataSource* webkit_web_frame_get_data_source(WebKitWebFrame* frame)
721 {
722     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
723
724     Frame* coreFrame = core(frame);
725     return webkit_web_frame_get_data_source_from_core_loader(coreFrame->loader()->documentLoader());
726 }
727
728 /**
729  * webkit_web_frame_get_provisional_data_source:
730  * @frame: a #WebKitWebFrame
731  *
732  * You use the webkit_web_frame_load_request method to initiate a request that
733  * creates a provisional data source. The provisional data source will
734  * transition to a committed data source once any data has been received. Use
735  * webkit_web_frame_get_data_source to get the committed data source.
736  *
737  * Return value: (transfer none): the provisional #WebKitWebDataSource or %NULL if a load
738  * request is not in progress.
739  *
740  * Since: 1.1.14
741  */
742 WebKitWebDataSource* webkit_web_frame_get_provisional_data_source(WebKitWebFrame* frame)
743 {
744     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
745
746     Frame* coreFrame = core(frame);
747     return webkit_web_frame_get_data_source_from_core_loader(coreFrame->loader()->provisionalDocumentLoader());
748 }
749
750 static void begin_print_callback(GtkPrintOperation* op, GtkPrintContext* context, gpointer user_data)
751 {
752     PrintContext* printContext = reinterpret_cast<PrintContext*>(user_data);
753
754     float width = gtk_print_context_get_width(context);
755     float height = gtk_print_context_get_height(context);
756     FloatRect printRect = FloatRect(0, 0, width, height);
757
758     printContext->begin(width);
759
760     // TODO: Margin adjustments and header/footer support
761     float headerHeight = 0;
762     float footerHeight = 0;
763     float pageHeight; // height of the page adjusted by margins
764     printContext->computePageRects(printRect, headerHeight, footerHeight, 1.0, pageHeight);
765     gtk_print_operation_set_n_pages(op, printContext->pageCount());
766 }
767
768 static void draw_page_callback(GtkPrintOperation* op, GtkPrintContext* context, gint page_nr, gpointer user_data)
769 {
770     PrintContext* printContext = reinterpret_cast<PrintContext*>(user_data);
771
772     if (page_nr >= static_cast<gint>(printContext->pageCount()))
773         return;
774
775     cairo_t* cr = gtk_print_context_get_cairo_context(context);
776     GraphicsContext ctx(cr);
777     float width = gtk_print_context_get_width(context);
778     printContext->spoolPage(ctx, page_nr, width);
779 }
780
781 static void end_print_callback(GtkPrintOperation* op, GtkPrintContext* context, gpointer user_data)
782 {
783     PrintContext* printContext = reinterpret_cast<PrintContext*>(user_data);
784     printContext->end();
785 }
786
787 /**
788  * webkit_web_frame_print_full:
789  * @frame: a #WebKitWebFrame to be printed
790  * @operation: the #GtkPrintOperation to be carried
791  * @action: the #GtkPrintOperationAction to be performed
792  * @error: #GError for error return
793  *
794  * Prints the given #WebKitWebFrame, using the given #GtkPrintOperation
795  * and #GtkPrintOperationAction. This function wraps a call to
796  * gtk_print_operation_run() for printing the contents of the
797  * #WebKitWebFrame.
798  *
799  * Since: 1.1.5
800  */
801 GtkPrintOperationResult webkit_web_frame_print_full(WebKitWebFrame* frame, GtkPrintOperation* operation, GtkPrintOperationAction action, GError** error)
802 {
803     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), GTK_PRINT_OPERATION_RESULT_ERROR);
804     g_return_val_if_fail(GTK_IS_PRINT_OPERATION(operation), GTK_PRINT_OPERATION_RESULT_ERROR);
805
806     GtkWidget* topLevel = gtk_widget_get_toplevel(GTK_WIDGET(webkit_web_frame_get_web_view(frame)));
807
808     if (!gtk_widget_is_toplevel(topLevel))
809         topLevel = 0;
810
811     Frame* coreFrame = core(frame);
812     if (!coreFrame)
813         return GTK_PRINT_OPERATION_RESULT_ERROR;
814
815     PrintContext printContext(coreFrame);
816
817     g_signal_connect(operation, "begin-print", G_CALLBACK(begin_print_callback), &printContext);
818     g_signal_connect(operation, "draw-page", G_CALLBACK(draw_page_callback), &printContext);
819     g_signal_connect(operation, "end-print", G_CALLBACK(end_print_callback), &printContext);
820
821     return gtk_print_operation_run(operation, action, GTK_WINDOW(topLevel), error);
822 }
823
824 /**
825  * webkit_web_frame_print:
826  * @frame: a #WebKitWebFrame
827  *
828  * Prints the given #WebKitWebFrame, by presenting a print dialog to the
829  * user. If you need more control over the printing process, see
830  * webkit_web_frame_print_full().
831  *
832  * Since: 1.1.5
833  */
834 void webkit_web_frame_print(WebKitWebFrame* frame)
835 {
836     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
837
838     WebKitWebFramePrivate* priv = frame->priv;
839     GtkPrintOperation* operation = gtk_print_operation_new();
840     GError* error = 0;
841
842     webkit_web_frame_print_full(frame, operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, &error);
843     g_object_unref(operation);
844
845     if (error) {
846         GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(priv->webView));
847         GtkWidget* dialog = gtk_message_dialog_new(gtk_widget_is_toplevel(window) ? GTK_WINDOW(window) : 0,
848                                                    GTK_DIALOG_DESTROY_WITH_PARENT,
849                                                    GTK_MESSAGE_ERROR,
850                                                    GTK_BUTTONS_CLOSE,
851                                                    "%s", error->message);
852
853         g_error_free(error);
854
855         g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
856         gtk_widget_show(dialog);
857     }
858 }
859
860 gchar* webkit_web_frame_get_response_mime_type(WebKitWebFrame* frame)
861 {
862     Frame* coreFrame = core(frame);
863     WebCore::DocumentLoader* docLoader = coreFrame->loader()->documentLoader();
864     String mimeType = docLoader->responseMIMEType();
865     return g_strdup(mimeType.utf8().data());
866 }
867
868 /**
869  * webkit_web_frame_get_load_status:
870  * @frame: a #WebKitWebView
871  *
872  * Determines the current status of the load.
873  *
874  * Since: 1.1.7
875  */
876 WebKitLoadStatus webkit_web_frame_get_load_status(WebKitWebFrame* frame)
877 {
878     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), WEBKIT_LOAD_FINISHED);
879
880     WebKitWebFramePrivate* priv = frame->priv;
881     return priv->loadStatus;
882 }
883
884 GtkPolicyType webkit_web_frame_get_horizontal_scrollbar_policy(WebKitWebFrame* frame)
885 {
886     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), GTK_POLICY_AUTOMATIC);
887
888     Frame* coreFrame = core(frame);
889     FrameView* view = coreFrame->view();
890     if (!view)
891         return GTK_POLICY_AUTOMATIC;
892
893     ScrollbarMode hMode = view->horizontalScrollbarMode();
894
895     if (hMode == ScrollbarAlwaysOn)
896         return GTK_POLICY_ALWAYS;
897
898     if (hMode == ScrollbarAlwaysOff)
899         return GTK_POLICY_NEVER;
900
901     return GTK_POLICY_AUTOMATIC;
902 }
903
904 GtkPolicyType webkit_web_frame_get_vertical_scrollbar_policy(WebKitWebFrame* frame)
905 {
906     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), GTK_POLICY_AUTOMATIC);
907
908     Frame* coreFrame = core(frame);
909     FrameView* view = coreFrame->view();
910     if (!view)
911         return GTK_POLICY_AUTOMATIC;
912
913     ScrollbarMode vMode = view->verticalScrollbarMode();
914
915     if (vMode == ScrollbarAlwaysOn)
916         return GTK_POLICY_ALWAYS;
917
918     if (vMode == ScrollbarAlwaysOff)
919         return GTK_POLICY_NEVER;
920
921     return GTK_POLICY_AUTOMATIC;
922 }
923
924 /**
925  * webkit_web_frame_get_security_origin:
926  * @frame: a #WebKitWebFrame
927  *
928  * Returns the @frame's security origin.
929  *
930  * Return value: (transfer none): the security origin of @frame
931  *
932  * Since: 1.1.14
933  */
934 WebKitSecurityOrigin* webkit_web_frame_get_security_origin(WebKitWebFrame* frame)
935 {
936     WebKitWebFramePrivate* priv = frame->priv;
937     if (!priv->coreFrame || !priv->coreFrame->document() || !priv->coreFrame->document()->securityOrigin())
938         return 0;
939
940     if (priv->origin && priv->origin->priv->coreOrigin.get() == priv->coreFrame->document()->securityOrigin())
941         return priv->origin;
942
943     if (priv->origin)
944         g_object_unref(priv->origin);
945
946     priv->origin = kit(priv->coreFrame->document()->securityOrigin());
947     return priv->origin;
948 }
949
950 /**
951  * webkit_web_frame_get_network_response:
952  * @frame: a #WebKitWebFrame
953  *
954  * Returns a #WebKitNetworkResponse object representing the response
955  * that was given to the request for the given frame, or NULL if the
956  * frame was not created by a load. You must unref the object when you
957  * are done with it.
958  *
959  * Return value: (transfer full): a #WebKitNetworkResponse object
960  *
961  * Since: 1.1.18
962  */
963 WebKitNetworkResponse* webkit_web_frame_get_network_response(WebKitWebFrame* frame)
964 {
965     Frame* coreFrame = core(frame);
966     if (!coreFrame)
967         return 0;
968
969     WebCore::DocumentLoader* loader = coreFrame->loader()->activeDocumentLoader();
970     if (!loader)
971         return 0;
972
973     return kitNew(loader->response());
974 }
975
976 namespace WebKit {
977
978 WebKitWebView* getViewFromFrame(WebKitWebFrame* frame)
979 {
980     WebKitWebFramePrivate* priv = frame->priv;
981     return priv->webView;
982 }
983
984 WebCore::Frame* core(WebKitWebFrame* frame)
985 {
986     if (!frame)
987         return 0;
988
989     WebKitWebFramePrivate* priv = frame->priv;
990     return priv ? priv->coreFrame : 0;
991 }
992
993 WebKitWebFrame* kit(WebCore::Frame* coreFrame)
994 {
995     if (!coreFrame)
996         return 0;
997
998     ASSERT(coreFrame->loader());
999     WebKit::FrameLoaderClient* client = static_cast<WebKit::FrameLoaderClient*>(coreFrame->loader()->client());
1000     return client ? client->webFrame() : 0;
1001 }
1002
1003 }