[GTK] Auto generate webkitmarshal.list
[WebKit-https.git] / WebKit / gtk / webkit / webkitwebframe.cpp
1 /*
2  * Copyright (C) 2007, 2008 Holger Hans Peter Freyther
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  * Copyright (C) 2007 Apple Inc.
5  * Copyright (C) 2008 Christian Dywan <christian@imendio.com>
6  * Copyright (C) 2008 Collabora Ltd.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include "config.h"
25
26 #include "webkitwebframe.h"
27 #include "webkitwebview.h"
28 #include "webkitmarshal.h"
29 #include "webkitprivate.h"
30
31 #include "CString.h"
32 #include "FrameLoader.h"
33 #include "FrameLoaderClientGtk.h"
34 #include "FrameTree.h"
35 #include "FrameView.h"
36 #include "GraphicsContext.h"
37 #include "HTMLFrameOwnerElement.h"
38 #include "JSDOMWindow.h"
39 #include "PrintContext.h"
40 #include "RenderView.h"
41 #include "JSDOMBinding.h"
42 #include "ScriptController.h"
43
44 #include <JavaScriptCore/APICast.h>
45
46 using namespace WebKit;
47 using namespace WebCore;
48 using namespace std;
49
50 extern "C" {
51
52 enum {
53     CLEARED,
54     LOAD_COMMITTED,
55     LOAD_DONE,
56     TITLE_CHANGED,
57     HOVERING_OVER_LINK,
58     LAST_SIGNAL
59 };
60
61 enum {
62     PROP_0,
63
64     PROP_NAME,
65     PROP_TITLE,
66     PROP_URI
67 };
68
69 static guint webkit_web_frame_signals[LAST_SIGNAL] = { 0, };
70
71 G_DEFINE_TYPE(WebKitWebFrame, webkit_web_frame, G_TYPE_OBJECT)
72
73 static void webkit_web_frame_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
74 {
75     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(object);
76
77     switch(prop_id) {
78     case PROP_NAME:
79         g_value_set_string(value, webkit_web_frame_get_name(frame));
80         break;
81     case PROP_TITLE:
82         g_value_set_string(value, webkit_web_frame_get_title(frame));
83         break;
84     case PROP_URI:
85         g_value_set_string(value, webkit_web_frame_get_uri(frame));
86         break;
87     default:
88         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
89         break;
90     }
91 }
92
93 static void webkit_web_frame_finalize(GObject* object)
94 {
95     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(object);
96     WebKitWebFramePrivate* priv = frame->priv;
97
98     priv->coreFrame->loader()->cancelAndClear();
99     priv->coreFrame = 0;
100
101     g_free(priv->name);
102     g_free(priv->title);
103     g_free(priv->uri);
104
105     G_OBJECT_CLASS(webkit_web_frame_parent_class)->finalize(object);
106 }
107
108 static void webkit_web_frame_class_init(WebKitWebFrameClass* frameClass)
109 {
110     webkit_init();
111
112     /*
113      * signals
114      */
115     webkit_web_frame_signals[CLEARED] = g_signal_new("cleared",
116             G_TYPE_FROM_CLASS(frameClass),
117             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
118             0,
119             NULL,
120             NULL,
121             g_cclosure_marshal_VOID__VOID,
122             G_TYPE_NONE, 0);
123
124     webkit_web_frame_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
125             G_TYPE_FROM_CLASS(frameClass),
126             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
127             0,
128             NULL,
129             NULL,
130             g_cclosure_marshal_VOID__VOID,
131             G_TYPE_NONE, 0);
132
133     webkit_web_frame_signals[LOAD_DONE] = g_signal_new("load-done",
134             G_TYPE_FROM_CLASS(frameClass),
135             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
136             0,
137             NULL,
138             NULL,
139             g_cclosure_marshal_VOID__BOOLEAN,
140             G_TYPE_NONE, 1,
141             G_TYPE_BOOLEAN);
142
143     webkit_web_frame_signals[TITLE_CHANGED] = g_signal_new("title-changed",
144             G_TYPE_FROM_CLASS(frameClass),
145             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
146             0,
147             NULL,
148             NULL,
149             webkit_marshal_VOID__STRING,
150             G_TYPE_NONE, 1,
151             G_TYPE_STRING);
152
153     webkit_web_frame_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
154             G_TYPE_FROM_CLASS(frameClass),
155             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
156             0,
157             NULL,
158             NULL,
159             webkit_marshal_VOID__STRING_STRING,
160             G_TYPE_NONE, 2,
161             G_TYPE_STRING, G_TYPE_STRING);
162
163     /*
164      * implementations of virtual methods
165      */
166     GObjectClass* objectClass = G_OBJECT_CLASS(frameClass);
167     objectClass->finalize = webkit_web_frame_finalize;
168     objectClass->get_property = webkit_web_frame_get_property;
169
170     /*
171      * properties
172      */
173     g_object_class_install_property(objectClass, PROP_NAME,
174                                     g_param_spec_string("name",
175                                                         "Name",
176                                                         "The name of the frame",
177                                                         NULL,
178                                                         WEBKIT_PARAM_READABLE));
179
180     g_object_class_install_property(objectClass, PROP_TITLE,
181                                     g_param_spec_string("title",
182                                                         "Title",
183                                                         "The document title of the frame",
184                                                         NULL,
185                                                         WEBKIT_PARAM_READABLE));
186
187     g_object_class_install_property(objectClass, PROP_URI,
188                                     g_param_spec_string("uri",
189                                                         "URI",
190                                                         "The current URI of the contents displayed by the frame",
191                                                         NULL,
192                                                         WEBKIT_PARAM_READABLE));
193
194     g_type_class_add_private(frameClass, sizeof(WebKitWebFramePrivate));
195 }
196
197 static void webkit_web_frame_init(WebKitWebFrame* frame)
198 {
199     WebKitWebFramePrivate* priv = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
200
201     // TODO: Move constructor code here.
202     frame->priv = priv;
203 }
204
205 /**
206  * webkit_web_frame_new:
207  * @web_view: the controlling #WebKitWebView
208  *
209  * Creates a new #WebKitWebFrame initialized with a controlling #WebKitWebView.
210  *
211  * Returns: a new #WebKitWebFrame
212  **/
213 WebKitWebFrame* webkit_web_frame_new(WebKitWebView* webView)
214 {
215     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
216
217     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
218     WebKitWebFramePrivate* priv = frame->priv;
219     WebKitWebViewPrivate* viewPriv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
220
221     priv->webView = webView;
222     priv->client = new WebKit::FrameLoaderClient(frame);
223     priv->coreFrame = Frame::create(viewPriv->corePage, 0, priv->client).get();
224     priv->coreFrame->init();
225
226     return frame;
227 }
228
229 WebKitWebFrame* webkit_web_frame_init_with_web_view(WebKitWebView* webView, HTMLFrameOwnerElement* element)
230 {
231     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
232     WebKitWebFramePrivate* priv = frame->priv;
233     WebKitWebViewPrivate* viewPriv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
234
235     priv->webView = webView;
236     priv->client = new WebKit::FrameLoaderClient(frame);
237     priv->coreFrame = Frame::create(viewPriv->corePage, element, priv->client).releaseRef();
238     priv->coreFrame->init();
239
240     return frame;
241 }
242
243 /**
244  * webkit_web_frame_get_title:
245  * @frame: a #WebKitWebFrame
246  *
247  * Returns the @frame's document title
248  *
249  * Return value: the title of @frame
250  */
251 G_CONST_RETURN gchar* webkit_web_frame_get_title(WebKitWebFrame* frame)
252 {
253     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
254
255     WebKitWebFramePrivate* priv = frame->priv;
256     return priv->title;
257 }
258
259 /**
260  * webkit_web_frame_get_uri:
261  * @frame: a #WebKitWebFrame
262  *
263  * Returns the current URI of the contents displayed by the @frame
264  *
265  * Return value: the URI of @frame
266  */
267 G_CONST_RETURN gchar* webkit_web_frame_get_uri(WebKitWebFrame* frame)
268 {
269     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
270
271     WebKitWebFramePrivate* priv = frame->priv;
272     return priv->uri;
273 }
274
275 /**
276  * webkit_web_frame_get_web_view:
277  * @frame: a #WebKitWebFrame
278  *
279  * Returns the #WebKitWebView that manages this #WebKitWebFrame.
280  *
281  * The #WebKitWebView returned manages the entire hierarchy of #WebKitWebFrame
282  * objects that contains @frame.
283  *
284  * Return value: the #WebKitWebView that manages @frame
285  */
286 WebKitWebView* webkit_web_frame_get_web_view(WebKitWebFrame* frame)
287 {
288     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
289
290     WebKitWebFramePrivate* priv = frame->priv;
291     return priv->webView;
292 }
293
294 /**
295  * webkit_web_frame_get_name:
296  * @frame: a #WebKitWebFrame
297  *
298  * Returns the @frame's name
299  *
300  * Return value: the name of @frame
301  */
302 G_CONST_RETURN gchar* webkit_web_frame_get_name(WebKitWebFrame* frame)
303 {
304     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
305
306     WebKitWebFramePrivate* priv = frame->priv;
307
308     if (priv->name)
309         return priv->name;
310
311     Frame* coreFrame = core(frame);
312     ASSERT(coreFrame);
313
314     String string = coreFrame->tree()->name();
315     priv->name = g_strdup(string.utf8().data());
316     return priv->name;
317 }
318
319 /**
320  * webkit_web_frame_get_parent:
321  * @frame: a #WebKitWebFrame
322  *
323  * Returns the @frame's parent frame, or %NULL if it has none.
324  *
325  * Return value: the parent #WebKitWebFrame or %NULL in case there is none
326  */
327 WebKitWebFrame* webkit_web_frame_get_parent(WebKitWebFrame* frame)
328 {
329     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
330
331     Frame* coreFrame = core(frame);
332     ASSERT(coreFrame);
333
334     return kit(coreFrame->tree()->parent());
335 }
336
337 /**
338  * webkit_web_frame_load_request:
339  * @frame: a #WebKitWebFrame
340  * @request: a #WebKitNetworkRequest
341  *
342  * Connects to a given URI by initiating an asynchronous client request.
343  *
344  * Creates a provisional data source that will transition to a committed data
345  * source once any data has been received. Use webkit_web_frame_stop_loading() to
346  * stop the load. This function is typically invoked on the main frame.
347  */
348 void webkit_web_frame_load_request(WebKitWebFrame* frame, WebKitNetworkRequest* request)
349 {
350     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
351     g_return_if_fail(WEBKIT_IS_NETWORK_REQUEST(request));
352
353     Frame* coreFrame = core(frame);
354     ASSERT(coreFrame);
355
356     // TODO: Use the ResourceRequest carried by WebKitNetworkRequest when it is implemented.
357     String string = String::fromUTF8(webkit_network_request_get_uri(request));
358     coreFrame->loader()->load(ResourceRequest(KURL(string)));
359 }
360
361 /**
362  * webkit_web_frame_stop_loading:
363  * @frame: a #WebKitWebFrame
364  *
365  * Stops any pending loads on @frame's data source, and those of its children.
366  */
367 void webkit_web_frame_stop_loading(WebKitWebFrame* frame)
368 {
369     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
370
371     Frame* coreFrame = core(frame);
372     ASSERT(coreFrame);
373
374     coreFrame->loader()->stopAllLoaders();
375 }
376
377 /**
378  * webkit_web_frame_reload:
379  * @frame: a #WebKitWebFrame
380  *
381  * Reloads the initial request.
382  */
383 void webkit_web_frame_reload(WebKitWebFrame* frame)
384 {
385     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
386
387     Frame* coreFrame = core(frame);
388     ASSERT(coreFrame);
389
390     coreFrame->loader()->reload();
391 }
392
393 /**
394  * webkit_web_frame_find_frame:
395  * @frame: a #WebKitWebFrame
396  * @name: the name of the frame to be found
397  *
398  * For pre-defined names, returns @frame if @name is "_self" or "_current",
399  * returns @frame's parent frame if @name is "_parent", and returns the main
400  * frame if @name is "_top". Also returns @frame if it is the main frame and
401  * @name is either "_parent" or "_top". For other names, this function returns
402  * the first frame that matches @name. This function searches @frame and its
403  * descendents first, then @frame's parent and its children moving up the
404  * hierarchy until a match is found. If no match is found in @frame's
405  * hierarchy, this function will search for a matching frame in other main
406  * frame hierarchies. Returns %NULL if no match is found.
407  *
408  * Return value: the found #WebKitWebFrame or %NULL in case none is found
409  */
410 WebKitWebFrame* webkit_web_frame_find_frame(WebKitWebFrame* frame, const gchar* name)
411 {
412     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
413     g_return_val_if_fail(name, NULL);
414
415     Frame* coreFrame = core(frame);
416     ASSERT(coreFrame);
417
418     String nameString = String::fromUTF8(name);
419     return kit(coreFrame->tree()->find(AtomicString(nameString)));
420 }
421
422 /**
423  * webkit_web_frame_get_global_context:
424  * @frame: a #WebKitWebFrame
425  *
426  * Gets the global JavaScript execution context. Use this function to bridge
427  * between the WebKit and JavaScriptCore APIs.
428  *
429  * Return value: the global JavaScript context
430  */
431 JSGlobalContextRef webkit_web_frame_get_global_context(WebKitWebFrame* frame)
432 {
433     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
434
435     Frame* coreFrame = core(frame);
436     ASSERT(coreFrame);
437
438     return toGlobalRef(coreFrame->script()->globalObject()->globalExec());
439 }
440
441 /**
442  * webkit_web_frame_get_children:
443  * @frame: a #WebKitWebFrame
444  *
445  * Return value: child frames of @frame
446  */
447 GSList* webkit_web_frame_get_children(WebKitWebFrame* frame)
448 {
449     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
450
451     Frame* coreFrame = core(frame);
452     ASSERT(coreFrame);
453
454     GSList* children = NULL;
455     for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
456         FrameLoader* loader = child->loader();
457         WebKit::FrameLoaderClient* client = static_cast<WebKit::FrameLoaderClient*>(loader->client());
458         if (client)
459           children = g_slist_append(children, client->webFrame());
460     }
461
462     return children;
463 }
464
465 /**
466  * webkit_web_frame_get_inner_text:
467  * @frame: a #WebKitWebFrame
468  *
469  * Return value: inner text of @frame
470  */
471 gchar* webkit_web_frame_get_inner_text(WebKitWebFrame* frame)
472 {
473     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
474
475     Frame* coreFrame = core(frame);
476     ASSERT(coreFrame);
477
478     FrameView* view = coreFrame->view();
479
480     if (view && view->layoutPending())
481         view->layout();
482
483     Element* documentElement = coreFrame->document()->documentElement();
484     String string =  documentElement->innerText();
485     return g_strdup(string.utf8().data());
486 }
487
488 #if GTK_CHECK_VERSION(2,10,0)
489
490 static void begin_print(GtkPrintOperation* op, GtkPrintContext* context, gpointer user_data)
491 {
492     PrintContext* printContext = reinterpret_cast<PrintContext*>(user_data);
493
494     float width = gtk_print_context_get_width(context);
495     float height = gtk_print_context_get_height(context);
496     FloatRect printRect = FloatRect(0, 0, width, height);
497
498     printContext->begin(width);
499
500     // TODO: Margin adjustments and header/footer support
501     float headerHeight = 0;
502     float footerHeight = 0;
503     float pageHeight; // height of the page adjusted by margins
504     printContext->computePageRects(printRect, headerHeight, footerHeight, 1.0, pageHeight);
505     gtk_print_operation_set_n_pages(op, printContext->pageCount());
506 }
507
508 static void draw_page(GtkPrintOperation* op, GtkPrintContext* context, gint page_nr, gpointer user_data)
509 {
510     PrintContext* printContext = reinterpret_cast<PrintContext*>(user_data);
511
512     cairo_t* cr = gtk_print_context_get_cairo_context(context);
513     GraphicsContext ctx(cr);
514     float width = gtk_print_context_get_width(context);
515     printContext->spoolPage(ctx, page_nr, width);
516 }
517
518 static void end_print(GtkPrintOperation* op, GtkPrintContext* context, gpointer user_data)
519 {
520     PrintContext* printContext = reinterpret_cast<PrintContext*>(user_data);
521     printContext->end();
522 }
523
524 void webkit_web_frame_print(WebKitWebFrame* frame)
525 {
526     GtkWidget* topLevel = gtk_widget_get_toplevel(GTK_WIDGET(webkit_web_frame_get_web_view(frame)));
527     if (!GTK_WIDGET_TOPLEVEL(topLevel))
528         topLevel = NULL;
529
530     Frame* coreFrame = core(frame);
531     ASSERT(coreFrame);
532
533     PrintContext printContext(coreFrame);
534
535     GtkPrintOperation* op = gtk_print_operation_new();
536     g_signal_connect(G_OBJECT(op), "begin-print", G_CALLBACK(begin_print), &printContext);
537     g_signal_connect(G_OBJECT(op), "draw-page", G_CALLBACK(draw_page), &printContext);
538     g_signal_connect(G_OBJECT(op), "end-print", G_CALLBACK(end_print), &printContext);
539     GError *error = NULL;
540     gtk_print_operation_run(op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW(topLevel), &error);
541     g_object_unref(op);
542
543     if (error) {
544         GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(topLevel),
545                                                    GTK_DIALOG_DESTROY_WITH_PARENT,
546                                                    GTK_MESSAGE_ERROR,
547                                                    GTK_BUTTONS_CLOSE,
548                                                    "%s", error->message);
549         g_error_free(error);
550
551         g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
552         gtk_widget_show(dialog);
553     }
554 }
555
556 #else
557
558 void webkit_web_frame_print(WebKitWebFrame*)
559 {
560     g_warning("Printing support is not available in older versions of GTK+");
561 }
562
563 #endif
564
565 }