Home | History | Annotate | Download | only in webkit
      1 /*
      2  * Copyright (C) 2007, 2008 Holger Hans Peter Freyther
      3  * Copyright (C) 2007 Alp Toker <alp (at) atoker.com>
      4  * Copyright (C) 2007 Apple Inc.
      5  * Copyright (C) 2008 Christian Dywan <christian (at) imendio.com>
      6  * Copyright (C) 2008 Collabora Ltd.
      7  * Copyright (C) 2008 Nuanti Ltd.
      8  * Copyright (C) 2009 Jan Alonzo <jmalonzo (at) gmail.com>
      9  * Copyright (C) 2009 Gustavo Noronha Silva <gns (at) 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 
     90 using namespace WebKit;
     91 using namespace WebCore;
     92 using namespace std;
     93 
     94 enum {
     95     CLEARED,
     96     LOAD_COMMITTED,
     97     LOAD_DONE,
     98     TITLE_CHANGED,
     99     HOVERING_OVER_LINK,
    100     SCROLLBARS_POLICY_CHANGED,
    101     LAST_SIGNAL
    102 };
    103 
    104 enum {
    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 
    115 static guint webkit_web_frame_signals[LAST_SIGNAL] = { 0, };
    116 
    117 G_DEFINE_TYPE(WebKitWebFrame, webkit_web_frame, G_TYPE_OBJECT)
    118 
    119 static 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...
    151 void 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 
    160 static 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 
    165 static 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 
    183 static 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 
    383 static 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  **/
    403 WebKitWebFrame* 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  */
    429 G_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  */
    445 G_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  */
    464 WebKitWebView* 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  */
    482 G_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  */
    507 WebKitWebFrame* 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  */
    527 void 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 
    539 static 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  */
    575 void 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  */
    596 void 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  */
    615 void 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  */
    633 void 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  */
    650 void 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  */
    678 WebKitWebFrame* 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  */
    700 JSGlobalContextRef 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  */
    721 WebKitWebDataSource* 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  */
    743 WebKitWebDataSource* 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 
    751 static 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 
    769 static 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 
    782 static 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  */
    802 GtkPrintOperationResult 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  */
    835 void 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 
    861 gchar* 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  */
    877 WebKitLoadStatus 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 
    885 GtkPolicyType 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 
    905 GtkPolicyType 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  */
    935 WebKitSecurityOrigin* 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  */
    964 WebKitNetworkResponse* 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 
    977 namespace WebKit {
    978 
    979 WebKitWebView* getViewFromFrame(WebKitWebFrame* frame)
    980 {
    981     WebKitWebFramePrivate* priv = frame->priv;
    982     return priv->webView;
    983 }
    984 
    985 WebCore::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 
    994 WebKitWebFrame* 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