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