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