2010-12-06 Philippe Normand <pnormand@igalia.com>
[WebKit-https.git] / WebKit / gtk / WebCoreSupport / ChromeClientGtk.cpp
1 /*
2  * Copyright (C) 2007, 2008 Holger Hans Peter Freyther
3  * Copyright (C) 2007, 2008 Christian Dywan <christian@imendio.com>
4  * Copyright (C) 2008 Nuanti Ltd.
5  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
6  * Copyright (C) 2008 Gustavo Noronha Silva <gns@gnome.org>
7  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public
11  *  License as published by the Free Software Foundation; either
12  *  version 2 of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 #include "config.h"
25 #include "ChromeClientGtk.h"
26
27 #include "Chrome.h"
28 #include "Console.h"
29 #include "DumpRenderTreeSupportGtk.h"
30 #include "Element.h"
31 #include "FileChooser.h"
32 #include "FileSystem.h"
33 #include "FloatRect.h"
34 #include "FrameLoadRequest.h"
35 #include "FrameView.h"
36 #include "GtkVersioning.h"
37 #include "HTMLNames.h"
38 #include "HitTestResult.h"
39 #include "Icon.h"
40 #include "IntRect.h"
41 #include "KURL.h"
42 #include "NavigationAction.h"
43 #include "NotImplemented.h"
44 #include "PlatformString.h"
45 #include "PopupMenuClient.h"
46 #include "PopupMenuGtk.h"
47 #include "SearchPopupMenuGtk.h"
48 #include "SecurityOrigin.h"
49 #include "WindowFeatures.h"
50 #include "webkitgeolocationpolicydecision.h"
51 #include "webkitnetworkrequest.h"
52 #include "webkitprivate.h"
53 #include "webkitwebview.h"
54 #include "webkitwebviewprivate.h"
55 #include <glib.h>
56 #include <glib/gi18n-lib.h>
57 #include <gtk/gtk.h>
58 #include <wtf/text/CString.h>
59
60 #if ENABLE(DATABASE)
61 #include "DatabaseTracker.h"
62 #endif
63
64 using namespace WebCore;
65
66 namespace WebKit {
67
68 ChromeClient::ChromeClient(WebKitWebView* webView)
69     : m_webView(webView)
70 {
71     ASSERT(m_webView);
72 }
73
74 void ChromeClient::chromeDestroyed()
75 {
76     delete this;
77 }
78
79 FloatRect ChromeClient::windowRect()
80 {
81     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
82     if (gtk_widget_is_toplevel(window)) {
83         gint left, top, width, height;
84         gtk_window_get_position(GTK_WINDOW(window), &left, &top);
85         gtk_window_get_size(GTK_WINDOW(window), &width, &height);
86         return IntRect(left, top, width, height);
87     }
88     return FloatRect();
89 }
90
91 void ChromeClient::setWindowRect(const FloatRect& rect)
92 {
93     IntRect intrect = IntRect(rect);
94     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
95
96     g_object_set(webWindowFeatures,
97                  "x", intrect.x(),
98                  "y", intrect.y(),
99                  "width", intrect.width(),
100                  "height", intrect.height(),
101                  NULL);
102
103     gboolean autoResizeWindow;
104     WebKitWebSettings* settings = webkit_web_view_get_settings(m_webView);
105     g_object_get(settings, "auto-resize-window", &autoResizeWindow, NULL);
106
107     if (!autoResizeWindow)
108         return;
109
110     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
111     if (gtk_widget_is_toplevel(window)) {
112         gtk_window_move(GTK_WINDOW(window), intrect.x(), intrect.y());
113         gtk_window_resize(GTK_WINDOW(window), intrect.width(), intrect.height());
114     }
115 }
116
117 FloatRect ChromeClient::pageRect()
118 {
119     GtkAllocation allocation;
120 #if GTK_CHECK_VERSION(2, 18, 0)
121     gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation);
122 #else
123     allocation = GTK_WIDGET(m_webView)->allocation;
124 #endif
125     return IntRect(allocation.x, allocation.y, allocation.width, allocation.height);
126 }
127
128 float ChromeClient::scaleFactor()
129 {
130     // Not implementable
131     return 1.0;
132 }
133
134 void ChromeClient::focus()
135 {
136     gtk_widget_grab_focus(GTK_WIDGET(m_webView));
137 }
138
139 void ChromeClient::unfocus()
140 {
141     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
142     if (gtk_widget_is_toplevel(window))
143         gtk_window_set_focus(GTK_WINDOW(window), NULL);
144 }
145
146 Page* ChromeClient::createWindow(Frame* frame, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& coreFeatures, const NavigationAction&)
147 {
148     WebKitWebView* webView = 0;
149
150     g_signal_emit_by_name(m_webView, "create-web-view", kit(frame), &webView);
151
152     if (!webView)
153         return 0;
154
155     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_window_features_new_from_core_features(coreFeatures);
156     g_object_set(webView, "window-features", webWindowFeatures, NULL);
157     g_object_unref(webWindowFeatures);
158
159     if (!frameLoadRequest.isEmpty())
160         webkit_web_view_open(webView, frameLoadRequest.resourceRequest().url().string().utf8().data());
161
162     return core(webView);
163 }
164
165 void ChromeClient::show()
166 {
167     webkit_web_view_notify_ready(m_webView);
168 }
169
170 bool ChromeClient::canRunModal()
171 {
172     notImplemented();
173     return false;
174 }
175
176 void ChromeClient::runModal()
177 {
178     notImplemented();
179 }
180
181 void ChromeClient::setToolbarsVisible(bool visible)
182 {
183     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
184
185     g_object_set(webWindowFeatures, "toolbar-visible", visible, NULL);
186 }
187
188 bool ChromeClient::toolbarsVisible()
189 {
190     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
191     gboolean visible;
192
193     g_object_get(webWindowFeatures, "toolbar-visible", &visible, NULL);
194     return visible;
195 }
196
197 void ChromeClient::setStatusbarVisible(bool visible)
198 {
199     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
200
201     g_object_set(webWindowFeatures, "statusbar-visible", visible, NULL);
202 }
203
204 bool ChromeClient::statusbarVisible()
205 {
206     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
207     gboolean visible;
208
209     g_object_get(webWindowFeatures, "statusbar-visible", &visible, NULL);
210     return visible;
211 }
212
213 void ChromeClient::setScrollbarsVisible(bool visible)
214 {
215     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
216
217     g_object_set(webWindowFeatures, "scrollbar-visible", visible, NULL);
218 }
219
220 bool ChromeClient::scrollbarsVisible() {
221     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
222     gboolean visible;
223
224     g_object_get(webWindowFeatures, "scrollbar-visible", &visible, NULL);
225     return visible;
226 }
227
228 void ChromeClient::setMenubarVisible(bool visible)
229 {
230     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
231
232     g_object_set(webWindowFeatures, "menubar-visible", visible, NULL);
233 }
234
235 bool ChromeClient::menubarVisible()
236 {
237     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
238     gboolean visible;
239
240     g_object_get(webWindowFeatures, "menubar-visible", &visible, NULL);
241     return visible;
242 }
243
244 void ChromeClient::setResizable(bool)
245 {
246     // Ignored for now
247 }
248
249 void ChromeClient::closeWindowSoon()
250 {
251     // We may not have a WebView as create-web-view can return NULL.
252     if (!m_webView)
253         return;
254
255     webkit_web_view_stop_loading(m_webView);
256
257     gboolean isHandled = false;
258     g_signal_emit_by_name(m_webView, "close-web-view", &isHandled);
259
260     if (isHandled)
261         return;
262 }
263
264 bool ChromeClient::canTakeFocus(FocusDirection)
265 {
266     return gtk_widget_get_can_focus(GTK_WIDGET(m_webView));
267 }
268
269 void ChromeClient::takeFocus(FocusDirection)
270 {
271     unfocus();
272 }
273
274 void ChromeClient::focusedNodeChanged(Node*)
275 {
276 }
277
278 void ChromeClient::focusedFrameChanged(Frame*)
279 {
280 }
281
282 bool ChromeClient::canRunBeforeUnloadConfirmPanel()
283 {
284     return true;
285 }
286
287 bool ChromeClient::runBeforeUnloadConfirmPanel(const WTF::String& message, WebCore::Frame* frame)
288 {
289     return runJavaScriptConfirm(frame, message);
290 }
291
292 void ChromeClient::addMessageToConsole(WebCore::MessageSource source, WebCore::MessageType type, WebCore::MessageLevel level, const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceId)
293 {
294     gboolean retval;
295     g_signal_emit_by_name(m_webView, "console-message", message.utf8().data(), lineNumber, sourceId.utf8().data(), &retval);
296 }
297
298 void ChromeClient::runJavaScriptAlert(Frame* frame, const String& message)
299 {
300     gboolean retval;
301     g_signal_emit_by_name(m_webView, "script-alert", kit(frame), message.utf8().data(), &retval);
302 }
303
304 bool ChromeClient::runJavaScriptConfirm(Frame* frame, const String& message)
305 {
306     gboolean retval;
307     gboolean didConfirm;
308     g_signal_emit_by_name(m_webView, "script-confirm", kit(frame), message.utf8().data(), &didConfirm, &retval);
309     return didConfirm == TRUE;
310 }
311
312 bool ChromeClient::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
313 {
314     gboolean retval;
315     gchar* value = 0;
316     g_signal_emit_by_name(m_webView, "script-prompt", kit(frame), message.utf8().data(), defaultValue.utf8().data(), &value, &retval);
317     if (value) {
318         result = String::fromUTF8(value);
319         g_free(value);
320         return true;
321     }
322     return false;
323 }
324
325 void ChromeClient::setStatusbarText(const String& string)
326 {
327     CString stringMessage = string.utf8();
328     g_signal_emit_by_name(m_webView, "status-bar-text-changed", stringMessage.data());
329 }
330
331 bool ChromeClient::shouldInterruptJavaScript()
332 {
333     notImplemented();
334     return false;
335 }
336
337 bool ChromeClient::tabsToLinks() const
338 {
339     if (DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled())
340         return DumpRenderTreeSupportGtk::linksIncludedInFocusChain();
341
342     return true;
343 }
344
345 IntRect ChromeClient::windowResizerRect() const
346 {
347     notImplemented();
348     return IntRect();
349 }
350
351 void ChromeClient::invalidateWindow(const IntRect&, bool)
352 {
353     notImplemented();
354 }
355
356 void ChromeClient::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate)
357 {
358     GdkRectangle rect = updateRect;
359     GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView));
360
361     if (window) {
362         gdk_window_invalidate_rect(window, &rect, FALSE);
363         // We don't currently do immediate updates since they delay other UI elements.
364         //if (immediate)
365         //    gdk_window_process_updates(window, FALSE);
366     }
367 }
368
369 void ChromeClient::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
370 {
371     invalidateContentsAndWindow(updateRect, immediate);
372 }
373
374 void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, const IntRect& clipRect)
375 {
376     GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView));
377     if (!window)
378         return;
379
380     // We cannot use gdk_window_scroll here because it is only able to
381     // scroll the whole window at once, and we often need to scroll
382     // portions of the window only (think frames).
383     GdkRectangle area = clipRect;
384     GdkRectangle moveRect;
385
386     GdkRectangle sourceRect = area;
387     sourceRect.x -= delta.width();
388     sourceRect.y -= delta.height();
389
390 #ifdef GTK_API_VERSION_2
391     GdkRegion* invalidRegion = gdk_region_rectangle(&area);
392
393     if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
394         GdkRegion* moveRegion = gdk_region_rectangle(&moveRect);
395         gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
396         gdk_region_offset(moveRegion, delta.width(), delta.height());
397         gdk_region_subtract(invalidRegion, moveRegion);
398         gdk_region_destroy(moveRegion);
399     }
400
401     gdk_window_invalidate_region(window, invalidRegion, FALSE);
402     gdk_region_destroy(invalidRegion);
403 #else
404     cairo_region_t* invalidRegion = cairo_region_create_rectangle(&area);
405
406     if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
407         cairo_region_t* moveRegion = cairo_region_create_rectangle(&moveRect);
408         gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
409         cairo_region_translate(moveRegion, delta.width(), delta.height());
410         cairo_region_subtract(invalidRegion, moveRegion);
411         cairo_region_destroy(moveRegion);
412     }
413
414     gdk_window_invalidate_region(window, invalidRegion, FALSE);
415     cairo_region_destroy(invalidRegion);
416 #endif
417
418 }
419
420 // FIXME: this does not take into account the WM decorations
421 static IntPoint widgetScreenPosition(GtkWidget* widget)
422 {
423     GtkWidget* window = gtk_widget_get_toplevel(widget);
424     int widgetX = 0, widgetY = 0;
425
426     gtk_widget_translate_coordinates(widget, window, 0, 0, &widgetX, &widgetY);
427
428     IntPoint result(widgetX, widgetY);
429     int originX, originY;
430     gdk_window_get_origin(gtk_widget_get_window(window), &originX, &originY);
431     result.move(originX, originY);
432
433     return result;
434 }
435
436 IntRect ChromeClient::windowToScreen(const IntRect& rect) const
437 {
438     IntRect result(rect);
439     IntPoint screenPosition = widgetScreenPosition(GTK_WIDGET(m_webView));
440     result.move(screenPosition.x(), screenPosition.y());
441
442     return result;
443 }
444
445 IntPoint ChromeClient::screenToWindow(const IntPoint& point) const
446 {
447     IntPoint result(point);
448     IntPoint screenPosition = widgetScreenPosition(GTK_WIDGET(m_webView));
449     result.move(-screenPosition.x(), -screenPosition.y());
450
451     return result;
452 }
453
454 PlatformPageClient ChromeClient::platformPageClient() const
455 {
456     return GTK_WIDGET(m_webView);
457 }
458
459 void ChromeClient::contentsSizeChanged(Frame* frame, const IntSize& size) const
460 {
461     // We need to queue a resize request only if the size changed,
462     // otherwise we get into an infinite loop!
463     GtkWidget* widget = GTK_WIDGET(m_webView);
464     GtkRequisition requisition;
465 #if GTK_CHECK_VERSION(2, 20, 0)
466     gtk_widget_get_requisition(widget, &requisition);
467 #else
468     requisition = widget->requisition;
469 #endif
470     if (gtk_widget_get_realized(widget)
471         && (requisition.height != size.height())
472         || (requisition.width != size.width()))
473         gtk_widget_queue_resize_no_redraw(widget);
474 }
475
476 void ChromeClient::scrollbarsModeDidChange() const
477 {
478     WebKitWebFrame* webFrame = webkit_web_view_get_main_frame(m_webView);
479
480     g_object_notify(G_OBJECT(webFrame), "horizontal-scrollbar-policy");
481     g_object_notify(G_OBJECT(webFrame), "vertical-scrollbar-policy");
482
483     gboolean isHandled;
484     g_signal_emit_by_name(webFrame, "scrollbars-policy-changed", &isHandled);
485
486     if (isHandled)
487         return;
488
489     GtkWidget* parent = gtk_widget_get_parent(GTK_WIDGET(m_webView));
490     if (!parent || !GTK_IS_SCROLLED_WINDOW(parent))
491         return;
492
493     GtkPolicyType horizontalPolicy = webkit_web_frame_get_horizontal_scrollbar_policy(webFrame);
494     GtkPolicyType verticalPolicy = webkit_web_frame_get_vertical_scrollbar_policy(webFrame);
495
496     // ScrolledWindow doesn't like to display only part of a widget if
497     // the scrollbars are completely disabled; We have a disparity
498     // here on what the policy requested by the web app is and what we
499     // can represent; the idea is not to show scrollbars, only.
500     if (horizontalPolicy == GTK_POLICY_NEVER)
501         horizontalPolicy = GTK_POLICY_AUTOMATIC;
502
503     if (verticalPolicy == GTK_POLICY_NEVER)
504         verticalPolicy = GTK_POLICY_AUTOMATIC;
505
506     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(parent),
507                                    horizontalPolicy, verticalPolicy);
508 }
509
510 void ChromeClient::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags)
511 {
512     // check if the element is a link...
513     bool isLink = hit.isLiveLink();
514     if (isLink) {
515         KURL url = hit.absoluteLinkURL();
516         if (!url.isEmpty() && url != m_hoveredLinkURL) {
517             TextDirection dir;
518             CString titleString = hit.title(dir).utf8();
519             CString urlString = url.prettyURL().utf8();
520             g_signal_emit_by_name(m_webView, "hovering-over-link", titleString.data(), urlString.data());
521             m_hoveredLinkURL = url;
522         }
523     } else if (!isLink && !m_hoveredLinkURL.isEmpty()) {
524         g_signal_emit_by_name(m_webView, "hovering-over-link", 0, 0);
525         m_hoveredLinkURL = KURL();
526     }
527
528     if (Node* node = hit.innerNonSharedNode()) {
529         Frame* frame = node->document()->frame();
530         FrameView* view = frame ? frame->view() : 0;
531         m_webView->priv->tooltipArea = view ? view->contentsToWindow(node->getRect()) : IntRect();
532     } else
533         m_webView->priv->tooltipArea = IntRect();
534 }
535
536 void ChromeClient::setToolTip(const String& toolTip, TextDirection)
537 {
538     webkit_web_view_set_tooltip_text(m_webView, toolTip.utf8().data());
539 }
540
541 void ChromeClient::print(Frame* frame)
542 {
543     WebKitWebFrame* webFrame = kit(frame);
544     gboolean isHandled = false;
545     g_signal_emit_by_name(m_webView, "print-requested", webFrame, &isHandled);
546
547     if (isHandled)
548         return;
549
550     webkit_web_frame_print(webFrame);
551 }
552
553 #if ENABLE(DATABASE)
554 void ChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseName)
555 {
556     guint64 defaultQuota = webkit_get_default_web_database_quota();
557     DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), defaultQuota);
558
559     WebKitWebFrame* webFrame = kit(frame);
560     WebKitWebView* webView = getViewFromFrame(webFrame);
561
562     WebKitSecurityOrigin* origin = webkit_web_frame_get_security_origin(webFrame);
563     WebKitWebDatabase* webDatabase = webkit_security_origin_get_web_database(origin, databaseName.utf8().data());
564     g_signal_emit_by_name(webView, "database-quota-exceeded", webFrame, webDatabase);
565 }
566 #endif
567
568 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
569 void ChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
570 {
571     // FIXME: Free some space.
572     notImplemented();
573 }
574
575 void ChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin*)
576 {
577     notImplemented();
578 }
579 #endif
580
581 void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
582 {
583     RefPtr<FileChooser> chooser = prpFileChooser;
584
585     GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Upload File"),
586                                                     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(platformPageClient()))),
587                                                     GTK_FILE_CHOOSER_ACTION_OPEN,
588                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
589                                                     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
590                                                     NULL);
591
592     gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), chooser->allowsMultipleFiles());
593
594     if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
595         if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog))) {
596             GSList* filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
597             Vector<String> names;
598             for (GSList* item = filenames ; item ; item = item->next) {
599                 if (!item->data)
600                     continue;
601                 names.append(filenameToString(static_cast<char*>(item->data)));
602                 g_free(item->data);
603             }
604             g_slist_free(filenames);
605             chooser->chooseFiles(names);
606         } else {
607             gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
608             if (filename)
609                 chooser->chooseFile(filenameToString(filename));
610             g_free(filename);
611         }
612     }
613     gtk_widget_destroy(dialog);
614 }
615
616 void ChromeClient::chooseIconForFiles(const Vector<WTF::String>& filenames, WebCore::FileChooser* chooser)
617 {
618     chooser->iconLoaded(Icon::createIconForFiles(filenames));
619 }
620
621 void ChromeClient::dispatchViewportDataDidChange(const ViewportArguments& arguments) const
622 {
623     // Recompute the viewport attributes making it valid.
624     webkitViewportAttributesRecompute(webkit_web_view_get_viewport_attributes(m_webView));
625 }
626
627 void ChromeClient::setCursor(const Cursor&)
628 {
629     notImplemented();
630 }
631
632 void ChromeClient::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
633 {
634     WebKitWebFrame* webFrame = kit(frame);
635     WebKitWebView* webView = getViewFromFrame(webFrame);
636
637     PlatformRefPtr<WebKitGeolocationPolicyDecision> policyDecision(adoptPlatformRef(webkit_geolocation_policy_decision_new(webFrame, geolocation)));
638
639     gboolean isHandled = FALSE;
640     g_signal_emit_by_name(webView, "geolocation-policy-decision-requested", webFrame, policyDecision.get(), &isHandled);
641     if (!isHandled)
642         webkit_geolocation_policy_deny(policyDecision.get());
643 }
644
645 void ChromeClient::cancelGeolocationPermissionRequestForFrame(WebCore::Frame* frame, WebCore::Geolocation*)
646 {
647     WebKitWebFrame* webFrame = kit(frame);
648     WebKitWebView* webView = getViewFromFrame(webFrame);
649     g_signal_emit_by_name(webView, "geolocation-policy-decision-cancelled", webFrame);
650 }
651
652 bool ChromeClient::selectItemWritingDirectionIsNatural()
653 {
654     return true;
655 }
656
657 PassRefPtr<WebCore::PopupMenu> ChromeClient::createPopupMenu(WebCore::PopupMenuClient* client) const
658 {
659     return adoptRef(new PopupMenuGtk(client));
660 }
661
662 PassRefPtr<WebCore::SearchPopupMenu> ChromeClient::createSearchPopupMenu(WebCore::PopupMenuClient* client) const
663 {
664     return adoptRef(new SearchPopupMenuGtk(client));
665 }
666
667 #if ENABLE(VIDEO)
668
669 bool ChromeClient::supportsFullscreenForNode(const Node* node)
670 {
671     return node->hasTagName(HTMLNames::videoTag);
672 }
673
674 void ChromeClient::enterFullscreenForNode(Node* node)
675 {
676     WebCore::Frame* frame = node->document()->frame();
677     WebKitWebFrame* webFrame = kit(frame);
678     WebKitWebView* webView = getViewFromFrame(webFrame);
679     webViewEnterFullscreen(webView, node);
680 }
681
682 void ChromeClient::exitFullscreenForNode(Node* node)
683 {
684     WebCore::Frame* frame = node->document()->frame();
685     WebKitWebFrame* webFrame = kit(frame);
686     WebKitWebView* webView = getViewFromFrame(webFrame);
687     webViewExitFullscreen(webView);
688 }
689 #endif
690
691 #if ENABLE(FULLSCREEN_API)
692 bool ChromeClient::supportsFullScreenForElement(const WebCore::Element* element)
693 {
694     return true;
695 }
696
697 void ChromeClient::enterFullScreenForElement(WebCore::Element* element)
698 {
699     element->document()->webkitWillEnterFullScreenForElement(element);
700     element->document()->webkitDidEnterFullScreenForElement(element);
701 }
702
703 void ChromeClient::exitFullScreenForElement(WebCore::Element* element)
704 {
705     element->document()->webkitWillExitFullScreenForElement(element);
706     element->document()->webkitDidExitFullScreenForElement(element);
707 }
708 #endif
709
710
711 }