c2515b28d0803ff713db9ccd26d88358617cb3da
[WebKit-https.git] / WebKit / gtk / WebView / webkitwebframe.cpp
1 /*
2  * Copyright (C) 2007 Holger Hans Peter Freyther
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22
23 #include "webkitwebframe.h"
24 #include "webkitwebview.h"
25 #include "webkit-marshal.h"
26 #include "webkitprivate.h"
27
28 #include "CString.h"
29 #include "FrameLoader.h"
30 #include "FrameLoaderClientGtk.h"
31 #include "FrameTree.h"
32 #include "FrameView.h"
33 #include "HTMLFrameOwnerElement.h"
34 #include "kjs_binding.h"
35 #include "kjs_proxy.h"
36 #include "kjs_window.h"
37
38 #include <JavaScriptCore/APICast.h>
39
40 using namespace WebKit;
41 using namespace WebCore;
42
43 extern "C" {
44
45 enum {
46     CLEARED,
47     LOAD_DONE,
48     TITLE_CHANGED,
49     HOVERING_OVER_LINK,
50     LAST_SIGNAL
51 };
52
53 static guint webkit_web_frame_signals[LAST_SIGNAL] = { 0, };
54
55 static void webkit_web_frame_real_title_changed(WebKitWebFrame* frame, gchar* title, gchar* location);
56
57 G_DEFINE_TYPE(WebKitWebFrame, webkit_web_frame, G_TYPE_OBJECT)
58
59 static void webkit_web_frame_finalize(GObject* object)
60 {
61     WebKitWebFramePrivate* privateData = WEBKIT_WEB_FRAME_GET_PRIVATE(WEBKIT_WEB_FRAME(object));
62     privateData->frame->loader()->cancelAndClear();
63     g_free(privateData->name);
64     g_free(privateData->title);
65     g_free(privateData->location);
66     delete privateData->frame;
67
68     G_OBJECT_CLASS(webkit_web_frame_parent_class)->finalize(object);
69 }
70
71 static void webkit_web_frame_class_init(WebKitWebFrameClass* frameClass)
72 {
73     g_type_class_add_private(frameClass, sizeof(WebKitWebFramePrivate));
74
75     /*
76      * signals
77      */
78     webkit_web_frame_signals[CLEARED] = g_signal_new("cleared",
79             G_TYPE_FROM_CLASS(frameClass),
80             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
81             0,
82             NULL,
83             NULL,
84             g_cclosure_marshal_VOID__VOID,
85             G_TYPE_NONE, 0);
86
87     webkit_web_frame_signals[LOAD_DONE] = g_signal_new("load-done",
88             G_TYPE_FROM_CLASS(frameClass),
89             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
90             0,
91             NULL,
92             NULL,
93             g_cclosure_marshal_VOID__BOOLEAN,
94             G_TYPE_NONE, 1,
95             G_TYPE_BOOLEAN);
96
97     webkit_web_frame_signals[TITLE_CHANGED] = g_signal_new("title-changed",
98             G_TYPE_FROM_CLASS(frameClass),
99             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
100             G_STRUCT_OFFSET(WebKitWebFrameClass, title_changed),
101             NULL,
102             NULL,
103             webkit_marshal_VOID__STRING_STRING,
104             G_TYPE_NONE, 2,
105             G_TYPE_STRING, G_TYPE_STRING);
106
107     webkit_web_frame_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
108             G_TYPE_FROM_CLASS(frameClass),
109             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
110             0,
111             NULL,
112             NULL,
113             webkit_marshal_VOID__STRING_STRING,
114             G_TYPE_NONE, 2,
115             G_TYPE_STRING, G_TYPE_STRING);
116
117     frameClass->title_changed = webkit_web_frame_real_title_changed;
118
119     /*
120      * implementations of virtual methods
121      */
122     G_OBJECT_CLASS(frameClass)->finalize = webkit_web_frame_finalize;
123 }
124
125 static void webkit_web_frame_real_title_changed(WebKitWebFrame* frame, gchar* title, gchar* location)
126 {
127     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
128     g_free(frameData->title);
129     g_free(frameData->location);
130     frameData->title = g_strdup(title);
131     frameData->location = g_strdup(location);
132 }
133
134 static void webkit_web_frame_init(WebKitWebFrame* frame)
135 {
136     // TODO: Move constructor code here.
137 }
138
139 /**
140  * webkit_web_frame_new:
141  * @web_view: the controlling #WebKitWebView
142  *
143  * Creates a new #WebKitWebFrame initialized with a controlling #WebKitWebView.
144  *
145  * Returns: a new #WebKitWebFrame
146  **/
147 WebKitWebFrame* webkit_web_frame_new(WebKitWebView* webView)
148 {
149     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
150
151     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
152     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
153     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
154
155     frameData->client = new WebKit::FrameLoaderClient(frame);
156     frameData->frame = new Frame(webViewData->corePage, 0, frameData->client);
157
158     FrameView* frameView = new FrameView(frameData->frame);
159     frameView->setContainingWindow(GTK_CONTAINER(webView));
160     frameView->setGtkAdjustments(GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)),
161                                  GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)));
162     frameData->frame->setView(frameView);
163     frameData->frame->init();
164     frameData->webView = webView;
165     frameData->name = 0;
166     frameData->title = 0;
167     frameData->location = 0;
168
169     return frame;
170 }
171
172 WebKitWebFrame* webkit_web_frame_init_with_web_view(WebKitWebView* webView, HTMLFrameOwnerElement* element)
173 {
174     WebKitWebFrame* frame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
175     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
176     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
177
178     frameData->client = new WebKit::FrameLoaderClient(frame);
179     frameData->frame = new Frame(webViewData->corePage, element, frameData->client);
180
181     FrameView* frameView = new FrameView(frameData->frame);
182     frameView->setContainingWindow(GTK_CONTAINER(webView));
183     frameData->frame->setView(frameView);
184     frameView->deref();
185     frameData->frame->init();
186     frameData->webView = webView;
187
188     return frame;
189 }
190
191 const gchar* webkit_web_frame_get_title(WebKitWebFrame* frame)
192 {
193     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
194
195     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
196     return frameData->title;
197 }
198
199 const gchar* webkit_web_frame_get_location(WebKitWebFrame* frame)
200 {
201     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
202
203     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
204     return frameData->location;
205 }
206
207 /**
208  * webkit_web_frame_get_web_view:
209  * @frame: a #WebKitWebFrame
210  *
211  * Returns the #WebKitWebView that manages this #WebKitWebFrame.
212  *
213  * The #WebKitWebView returned manages the entire hierarchy of #WebKitWebFrame
214  * objects that contains @frame.
215  *
216  * Return value: the #WebKitWebView that manages @frame
217  */
218 WebKitWebView* webkit_web_frame_get_web_view(WebKitWebFrame* frame)
219 {
220     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
221
222     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
223     return frameData->webView;
224 }
225
226 /**
227  * webkit_web_frame_get_name:
228  * @frame: a #WebKitWebFrame
229  *
230  * Returns the @frame's name
231  *
232  * Return value: the name of @frame
233  */
234 const gchar* webkit_web_frame_get_name(WebKitWebFrame* frame)
235 {
236     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
237
238     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(frame);
239
240     if (frameData->name)
241         return frameData->name;
242
243     Frame* coreFrame = core(frame);
244     g_return_val_if_fail(coreFrame, NULL);
245
246     String string = coreFrame->tree()->name();
247     frameData->name = g_strdup(string.utf8().data());
248
249     return frameData->name;
250 }
251
252 /**
253  * webkit_web_frame_get_parent:
254  * @frame: a #WebKitWebFrame
255  *
256  * Returns the @frame's parent frame, or %NULL if it has none.
257  *
258  * Return value: the parent #WebKitWebFrame or %NULL in case there is none
259  */
260 WebKitWebFrame* webkit_web_frame_get_parent(WebKitWebFrame* frame)
261 {
262     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
263
264     Frame* coreFrame = core(frame);
265     g_return_val_if_fail(coreFrame, NULL);
266
267     return kit(coreFrame->tree()->parent());
268 }
269
270 /**
271  * webkit_web_frame_load_request:
272  * @frame: a #WebKitWebFrame
273  * @request: a #WebKitNetworkRequest
274  *
275  * Connects to a given URI by initiating an asynchronous client request.
276  *
277  * Creates a provisional data source that will transition to a committed data
278  * source once any data has been received. Use webkit_web_frame_stop_loading() to
279  * stop the load. This function is typically invoked on the main frame.
280  */
281 void webkit_web_frame_load_request(WebKitWebFrame* frame, WebKitNetworkRequest* request)
282 {
283     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
284     g_return_if_fail(WEBKIT_IS_NETWORK_REQUEST(request));
285
286     Frame* coreFrame = core(frame);
287     g_return_if_fail(coreFrame);
288
289     // TODO: Use the ResourceRequest carried by WebKitNetworkRequest when it gets implemented.
290     DeprecatedString string = DeprecatedString::fromUtf8(webkit_network_request_get_uri(request));
291     coreFrame->loader()->load(ResourceRequest(KURL(string)));
292 }
293
294 /**
295  * webkit_web_frame_stop_loading:
296  * @frame: a #WebKitWebFrame
297  *
298  * Stops any pending loads on @frame's data source, and those of its children.
299  */
300 void webkit_web_frame_stop_loading(WebKitWebFrame* frame)
301 {
302     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
303
304     Frame* coreFrame = core(frame);
305     g_return_if_fail(coreFrame);
306
307     coreFrame->loader()->stopAllLoaders();
308 }
309
310 /**
311  * webkit_web_frame_reload:
312  * @frame: a #WebKitWebFrame
313  *
314  * Reloads the initial request.
315  */
316 void webkit_web_frame_reload(WebKitWebFrame* frame)
317 {
318     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
319
320     Frame* coreFrame = core(frame);
321     g_return_if_fail(coreFrame);
322
323     coreFrame->loader()->reload();
324 }
325
326 /**
327  * webkit_web_frame_find_frame:
328  * @frame: a #WebKitWebFrame
329  * @name: the name of the frame to be found
330  *
331  * For pre-defined names, returns @frame if @name is "_self" or "_current",
332  * returns @frame's parent frame if @name is "_parent", and returns the main
333  * frame if @name is "_top". Also returns @frame if it is the main frame and
334  * @name is either "_parent" or "_top". For other names, this function returns
335  * the first frame that matches @name. This function searches @frame and its
336  * descendents first, then @frame's parent and its children moving up the
337  * hierarchy until a match is found. If no match is found in @frame's
338  * hierarchy, this function will search for a matching frame in other main
339  * frame hierarchies. Returns %NULL if no match is found.
340  *
341  * Return value: the found #WebKitWebFrame or %NULL in case none is found
342  */
343 WebKitWebFrame* webkit_web_frame_find_frame(WebKitWebFrame* frame, const gchar* name)
344 {
345     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
346     g_return_val_if_fail(name, NULL);
347
348     Frame* coreFrame = core(frame);
349     g_return_val_if_fail(coreFrame, NULL);
350
351     String nameString = String::fromUTF8(name);
352     return kit(coreFrame->tree()->find(AtomicString(nameString)));
353 }
354
355 /**
356  * webkit_web_frame_get_global_context:
357  * @frame: a #WebKitWebFrame
358  *
359  * Gets the global JavaScript execution context. Use this function to bridge
360  * between the WebKit and JavaScriptCore APIs.
361  *
362  * Return value: the global JavaScript context
363  */
364 JSGlobalContextRef webkit_web_frame_get_global_context(WebKitWebFrame* frame)
365 {
366     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
367
368     Frame* coreFrame = core(frame);
369     g_return_val_if_fail(coreFrame, NULL);
370
371     return toGlobalRef(coreFrame->scriptProxy()->globalObject()->globalExec());
372 }
373
374 /**
375  * webkit_web_frame_get_children:
376  * @frame: a #WebKitWebFrame
377  *
378  * Return value: child frames of @frame
379  */
380 GSList* webkit_web_frame_get_children(WebKitWebFrame* frame)
381 {
382     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
383
384     GSList* children = NULL;
385     Frame* coreFrame = core(frame);
386
387     for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
388         FrameLoader* loader = child->loader();
389         WebKit::FrameLoaderClient* client = static_cast<WebKit::FrameLoaderClient*>(loader->client());
390         if (client)
391           children = g_slist_append(children, client->webFrame());
392     }
393
394     return children;
395 }
396
397 /**
398  * webkit_web_frame_get_inner_text:
399  * @frame: a #WebKitWebFrame
400  *
401  * Return value: inner text of @frame
402  */
403 gchar* webkit_web_frame_get_inner_text(WebKitWebFrame* frame)
404 {
405     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
406
407     Frame* coreFrame = core(frame);
408     FrameView* view = coreFrame->view();
409
410     if (view->layoutPending())
411         view->layout();
412
413     Element* documentElement = coreFrame->document()->documentElement();
414     String string =  documentElement->innerText();
415     return g_strdup(string.utf8().data());
416 }
417
418 }