• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webkitgeolocationpolicydecisionprivate.h"
52 #include "webkitnetworkrequest.h"
53 #include "webkitsecurityoriginprivate.h"
54 #include "webkitviewportattributesprivate.h"
55 #include "webkitwebframeprivate.h"
56 #include "webkitwebview.h"
57 #include "webkitwebviewprivate.h"
58 #include "webkitwebwindowfeaturesprivate.h"
59 #include <glib.h>
60 #include <glib/gi18n-lib.h>
61 #include <gtk/gtk.h>
62 #include <wtf/text/CString.h>
63 
64 #if ENABLE(DATABASE)
65 #include "DatabaseTracker.h"
66 #endif
67 
68 using namespace WebCore;
69 
70 namespace WebKit {
71 
ChromeClient(WebKitWebView * webView)72 ChromeClient::ChromeClient(WebKitWebView* webView)
73     : m_webView(webView)
74     , m_closeSoonTimer(0)
75     , m_pendingScrollInvalidations(false)
76 {
77     ASSERT(m_webView);
78 }
79 
chromeDestroyed()80 void ChromeClient::chromeDestroyed()
81 {
82     if (m_closeSoonTimer)
83         g_source_remove(m_closeSoonTimer);
84 
85     delete this;
86 }
87 
windowRect()88 FloatRect ChromeClient::windowRect()
89 {
90     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
91     if (gtk_widget_is_toplevel(window)) {
92         gint left, top, width, height;
93         gtk_window_get_position(GTK_WINDOW(window), &left, &top);
94         gtk_window_get_size(GTK_WINDOW(window), &width, &height);
95         return IntRect(left, top, width, height);
96     }
97     return FloatRect();
98 }
99 
setWindowRect(const FloatRect & rect)100 void ChromeClient::setWindowRect(const FloatRect& rect)
101 {
102     IntRect intrect = IntRect(rect);
103     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
104 
105     g_object_set(webWindowFeatures,
106                  "x", intrect.x(),
107                  "y", intrect.y(),
108                  "width", intrect.width(),
109                  "height", intrect.height(),
110                  NULL);
111 
112     gboolean autoResizeWindow;
113     WebKitWebSettings* settings = webkit_web_view_get_settings(m_webView);
114     g_object_get(settings, "auto-resize-window", &autoResizeWindow, NULL);
115 
116     if (!autoResizeWindow)
117         return;
118 
119     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
120     if (gtk_widget_is_toplevel(window)) {
121         gtk_window_move(GTK_WINDOW(window), intrect.x(), intrect.y());
122         gtk_window_resize(GTK_WINDOW(window), intrect.width(), intrect.height());
123     }
124 }
125 
pageRect()126 FloatRect ChromeClient::pageRect()
127 {
128     GtkAllocation allocation;
129 #if GTK_CHECK_VERSION(2, 18, 0)
130     gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation);
131 #else
132     allocation = GTK_WIDGET(m_webView)->allocation;
133 #endif
134     return IntRect(allocation.x, allocation.y, allocation.width, allocation.height);
135 }
136 
scaleFactor()137 float ChromeClient::scaleFactor()
138 {
139     // Not implementable
140     return 1.0;
141 }
142 
focus()143 void ChromeClient::focus()
144 {
145     gtk_widget_grab_focus(GTK_WIDGET(m_webView));
146 }
147 
unfocus()148 void ChromeClient::unfocus()
149 {
150     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
151     if (gtk_widget_is_toplevel(window))
152         gtk_window_set_focus(GTK_WINDOW(window), NULL);
153 }
154 
createWindow(Frame * frame,const FrameLoadRequest & frameLoadRequest,const WindowFeatures & coreFeatures,const NavigationAction &)155 Page* ChromeClient::createWindow(Frame* frame, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& coreFeatures, const NavigationAction&)
156 {
157     WebKitWebView* webView = 0;
158 
159     g_signal_emit_by_name(m_webView, "create-web-view", kit(frame), &webView);
160 
161     if (!webView)
162         return 0;
163 
164     GRefPtr<WebKitWebWindowFeatures> webWindowFeatures(adoptGRef(kitNew(coreFeatures)));
165     g_object_set(webView, "window-features", webWindowFeatures.get(), NULL);
166 
167     return core(webView);
168 }
169 
show()170 void ChromeClient::show()
171 {
172     webkit_web_view_notify_ready(m_webView);
173 }
174 
canRunModal()175 bool ChromeClient::canRunModal()
176 {
177     notImplemented();
178     return false;
179 }
180 
runModal()181 void ChromeClient::runModal()
182 {
183     notImplemented();
184 }
185 
setToolbarsVisible(bool visible)186 void ChromeClient::setToolbarsVisible(bool visible)
187 {
188     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
189 
190     g_object_set(webWindowFeatures, "toolbar-visible", visible, NULL);
191 }
192 
toolbarsVisible()193 bool ChromeClient::toolbarsVisible()
194 {
195     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
196     gboolean visible;
197 
198     g_object_get(webWindowFeatures, "toolbar-visible", &visible, NULL);
199     return visible;
200 }
201 
setStatusbarVisible(bool visible)202 void ChromeClient::setStatusbarVisible(bool visible)
203 {
204     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
205 
206     g_object_set(webWindowFeatures, "statusbar-visible", visible, NULL);
207 }
208 
statusbarVisible()209 bool ChromeClient::statusbarVisible()
210 {
211     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
212     gboolean visible;
213 
214     g_object_get(webWindowFeatures, "statusbar-visible", &visible, NULL);
215     return visible;
216 }
217 
setScrollbarsVisible(bool visible)218 void ChromeClient::setScrollbarsVisible(bool visible)
219 {
220     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
221 
222     g_object_set(webWindowFeatures, "scrollbar-visible", visible, NULL);
223 }
224 
scrollbarsVisible()225 bool ChromeClient::scrollbarsVisible()
226 {
227     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
228     gboolean visible;
229 
230     g_object_get(webWindowFeatures, "scrollbar-visible", &visible, NULL);
231     return visible;
232 }
233 
setMenubarVisible(bool visible)234 void ChromeClient::setMenubarVisible(bool visible)
235 {
236     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
237 
238     g_object_set(webWindowFeatures, "menubar-visible", visible, NULL);
239 }
240 
menubarVisible()241 bool ChromeClient::menubarVisible()
242 {
243     WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView);
244     gboolean visible;
245 
246     g_object_get(webWindowFeatures, "menubar-visible", &visible, NULL);
247     return visible;
248 }
249 
setResizable(bool)250 void ChromeClient::setResizable(bool)
251 {
252     // Ignored for now
253 }
254 
emitCloseWebViewSignalLater(WebKitWebView * view)255 static gboolean emitCloseWebViewSignalLater(WebKitWebView* view)
256 {
257     gboolean isHandled;
258     g_signal_emit_by_name(view, "close-web-view", &isHandled);
259     return FALSE;
260 }
261 
closeWindowSoon()262 void ChromeClient::closeWindowSoon()
263 {
264     // We may not have a WebView as create-web-view can return NULL.
265     if (!m_webView)
266         return;
267     if (m_closeSoonTimer) // Don't call close-web-view more than once.
268         return;
269 
270     // We need to remove the parent WebView from WebViewSets here, before it actually
271     // closes, to make sure that JavaScript code that executes before it closes
272     // can't find it. Otherwise, window.open will select a closed WebView instead of
273     // opening a new one <rdar://problem/3572585>.
274     m_webView->priv->corePage->setGroupName("");
275 
276     // We also need to stop the load to prevent further parsing or JavaScript execution
277     // after the window has torn down <rdar://problem/4161660>.
278     webkit_web_view_stop_loading(m_webView);
279 
280     // Clients commonly destroy the web view during the close-web-view signal, but our caller
281     // may need to send more signals to the web view. For instance, if this happened in the
282     // onload handler, it will need to call FrameLoaderClient::dispatchDidHandleOnloadEvents.
283     // Instead of firing the close-web-view signal now, fire it after the caller finishes.
284     // This seems to match the Mac/Windows port behavior.
285     m_closeSoonTimer = g_timeout_add(0, reinterpret_cast<GSourceFunc>(emitCloseWebViewSignalLater), m_webView);
286 }
287 
canTakeFocus(FocusDirection)288 bool ChromeClient::canTakeFocus(FocusDirection)
289 {
290     return gtk_widget_get_can_focus(GTK_WIDGET(m_webView));
291 }
292 
takeFocus(FocusDirection)293 void ChromeClient::takeFocus(FocusDirection)
294 {
295     unfocus();
296 }
297 
focusedNodeChanged(Node *)298 void ChromeClient::focusedNodeChanged(Node*)
299 {
300 }
301 
focusedFrameChanged(Frame *)302 void ChromeClient::focusedFrameChanged(Frame*)
303 {
304 }
305 
canRunBeforeUnloadConfirmPanel()306 bool ChromeClient::canRunBeforeUnloadConfirmPanel()
307 {
308     return true;
309 }
310 
runBeforeUnloadConfirmPanel(const WTF::String & message,WebCore::Frame * frame)311 bool ChromeClient::runBeforeUnloadConfirmPanel(const WTF::String& message, WebCore::Frame* frame)
312 {
313     return runJavaScriptConfirm(frame, message);
314 }
315 
addMessageToConsole(WebCore::MessageSource source,WebCore::MessageType type,WebCore::MessageLevel level,const WTF::String & message,unsigned int lineNumber,const WTF::String & sourceId)316 void ChromeClient::addMessageToConsole(WebCore::MessageSource source, WebCore::MessageType type, WebCore::MessageLevel level, const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceId)
317 {
318     gboolean retval;
319     g_signal_emit_by_name(m_webView, "console-message", message.utf8().data(), lineNumber, sourceId.utf8().data(), &retval);
320 }
321 
runJavaScriptAlert(Frame * frame,const String & message)322 void ChromeClient::runJavaScriptAlert(Frame* frame, const String& message)
323 {
324     gboolean retval;
325     g_signal_emit_by_name(m_webView, "script-alert", kit(frame), message.utf8().data(), &retval);
326 }
327 
runJavaScriptConfirm(Frame * frame,const String & message)328 bool ChromeClient::runJavaScriptConfirm(Frame* frame, const String& message)
329 {
330     gboolean retval;
331     gboolean didConfirm;
332     g_signal_emit_by_name(m_webView, "script-confirm", kit(frame), message.utf8().data(), &didConfirm, &retval);
333     return didConfirm == TRUE;
334 }
335 
runJavaScriptPrompt(Frame * frame,const String & message,const String & defaultValue,String & result)336 bool ChromeClient::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
337 {
338     gboolean retval;
339     gchar* value = 0;
340     g_signal_emit_by_name(m_webView, "script-prompt", kit(frame), message.utf8().data(), defaultValue.utf8().data(), &value, &retval);
341     if (value) {
342         result = String::fromUTF8(value);
343         g_free(value);
344         return true;
345     }
346     return false;
347 }
348 
setStatusbarText(const String & string)349 void ChromeClient::setStatusbarText(const String& string)
350 {
351     CString stringMessage = string.utf8();
352     g_signal_emit_by_name(m_webView, "status-bar-text-changed", stringMessage.data());
353 }
354 
shouldInterruptJavaScript()355 bool ChromeClient::shouldInterruptJavaScript()
356 {
357     notImplemented();
358     return false;
359 }
360 
keyboardUIMode()361 KeyboardUIMode ChromeClient::keyboardUIMode()
362 {
363     bool tabsToLinks = true;
364     if (DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled())
365         tabsToLinks = DumpRenderTreeSupportGtk::linksIncludedInFocusChain();
366 
367     return tabsToLinks ? KeyboardAccessTabsToLinks : KeyboardAccessDefault;
368 }
369 
windowResizerRect() const370 IntRect ChromeClient::windowResizerRect() const
371 {
372     notImplemented();
373     return IntRect();
374 }
375 
invalidateWindow(const IntRect &,bool immediate)376 void ChromeClient::invalidateWindow(const IntRect&, bool immediate)
377 {
378     // If we've invalidated regions for scrolling, force GDK to process those invalidations
379     // now. This will also cause child windows to move right away. This prevents redraw
380     // artifacts with child windows (e.g. Flash plugin instances).
381     if (immediate && m_pendingScrollInvalidations) {
382         m_pendingScrollInvalidations = false;
383         if (GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView)))
384             gdk_window_process_updates(window, TRUE);
385     }
386 }
387 
invalidateContentsAndWindow(const IntRect & updateRect,bool immediate)388 void ChromeClient::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate)
389 {
390     GdkRectangle rect = updateRect;
391     GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView));
392 
393     if (window && !updateRect.isEmpty()) {
394         gdk_window_invalidate_rect(window, &rect, FALSE);
395         // We don't currently do immediate updates since they delay other UI elements.
396         //if (immediate)
397         //    gdk_window_process_updates(window, FALSE);
398     }
399 }
400 
invalidateContentsForSlowScroll(const IntRect & updateRect,bool immediate)401 void ChromeClient::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
402 {
403     invalidateContentsAndWindow(updateRect, immediate);
404 }
405 
scroll(const IntSize & delta,const IntRect & rectToScroll,const IntRect & clipRect)406 void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, const IntRect& clipRect)
407 {
408     GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView));
409     if (!window)
410         return;
411 
412     m_pendingScrollInvalidations = true;
413 
414     // We cannot use gdk_window_scroll here because it is only able to
415     // scroll the whole window at once, and we often need to scroll
416     // portions of the window only (think frames).
417     GdkRectangle area = clipRect;
418     GdkRectangle moveRect;
419 
420     GdkRectangle sourceRect = area;
421     sourceRect.x -= delta.width();
422     sourceRect.y -= delta.height();
423 
424 #ifdef GTK_API_VERSION_2
425     GdkRegion* invalidRegion = gdk_region_rectangle(&area);
426 
427     if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
428         GdkRegion* moveRegion = gdk_region_rectangle(&moveRect);
429         gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
430         gdk_region_offset(moveRegion, delta.width(), delta.height());
431         gdk_region_subtract(invalidRegion, moveRegion);
432         gdk_region_destroy(moveRegion);
433     }
434 
435     gdk_window_invalidate_region(window, invalidRegion, FALSE);
436     gdk_region_destroy(invalidRegion);
437 #else
438     cairo_region_t* invalidRegion = cairo_region_create_rectangle(&area);
439 
440     if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
441         cairo_region_t* moveRegion = cairo_region_create_rectangle(&moveRect);
442         gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
443         cairo_region_translate(moveRegion, delta.width(), delta.height());
444         cairo_region_subtract(invalidRegion, moveRegion);
445         cairo_region_destroy(moveRegion);
446     }
447 
448     gdk_window_invalidate_region(window, invalidRegion, FALSE);
449     cairo_region_destroy(invalidRegion);
450 #endif
451 }
452 
453 // FIXME: this does not take into account the WM decorations
widgetScreenPosition(GtkWidget * widget)454 static IntPoint widgetScreenPosition(GtkWidget* widget)
455 {
456     GtkWidget* window = gtk_widget_get_toplevel(widget);
457     int widgetX = 0, widgetY = 0;
458 
459     gtk_widget_translate_coordinates(widget, window, 0, 0, &widgetX, &widgetY);
460 
461     IntPoint result(widgetX, widgetY);
462     int originX, originY;
463     gdk_window_get_origin(gtk_widget_get_window(window), &originX, &originY);
464     result.move(originX, originY);
465 
466     return result;
467 }
468 
windowToScreen(const IntRect & rect) const469 IntRect ChromeClient::windowToScreen(const IntRect& rect) const
470 {
471     IntRect result(rect);
472     IntPoint screenPosition = widgetScreenPosition(GTK_WIDGET(m_webView));
473     result.move(screenPosition.x(), screenPosition.y());
474 
475     return result;
476 }
477 
screenToWindow(const IntPoint & point) const478 IntPoint ChromeClient::screenToWindow(const IntPoint& point) const
479 {
480     IntPoint result(point);
481     IntPoint screenPosition = widgetScreenPosition(GTK_WIDGET(m_webView));
482     result.move(-screenPosition.x(), -screenPosition.y());
483 
484     return result;
485 }
486 
platformPageClient() const487 PlatformPageClient ChromeClient::platformPageClient() const
488 {
489     return GTK_WIDGET(m_webView);
490 }
491 
contentsSizeChanged(Frame * frame,const IntSize & size) const492 void ChromeClient::contentsSizeChanged(Frame* frame, const IntSize& size) const
493 {
494     // We need to queue a resize request only if the size changed,
495     // otherwise we get into an infinite loop!
496     GtkWidget* widget = GTK_WIDGET(m_webView);
497     GtkRequisition requisition;
498 #if GTK_CHECK_VERSION(2, 20, 0)
499     gtk_widget_get_requisition(widget, &requisition);
500 #else
501     requisition = widget->requisition;
502 #endif
503     if (gtk_widget_get_realized(widget)
504         && (requisition.height != size.height())
505         || (requisition.width != size.width()))
506         gtk_widget_queue_resize_no_redraw(widget);
507 }
508 
scrollbarsModeDidChange() const509 void ChromeClient::scrollbarsModeDidChange() const
510 {
511     WebKitWebFrame* webFrame = webkit_web_view_get_main_frame(m_webView);
512 
513     g_object_notify(G_OBJECT(webFrame), "horizontal-scrollbar-policy");
514     g_object_notify(G_OBJECT(webFrame), "vertical-scrollbar-policy");
515 
516     gboolean isHandled;
517     g_signal_emit_by_name(webFrame, "scrollbars-policy-changed", &isHandled);
518 
519     if (isHandled)
520         return;
521 
522     GtkWidget* parent = gtk_widget_get_parent(GTK_WIDGET(m_webView));
523     if (!parent || !GTK_IS_SCROLLED_WINDOW(parent))
524         return;
525 
526     GtkPolicyType horizontalPolicy = webkit_web_frame_get_horizontal_scrollbar_policy(webFrame);
527     GtkPolicyType verticalPolicy = webkit_web_frame_get_vertical_scrollbar_policy(webFrame);
528 
529     // ScrolledWindow doesn't like to display only part of a widget if
530     // the scrollbars are completely disabled; We have a disparity
531     // here on what the policy requested by the web app is and what we
532     // can represent; the idea is not to show scrollbars, only.
533     if (horizontalPolicy == GTK_POLICY_NEVER)
534         horizontalPolicy = GTK_POLICY_AUTOMATIC;
535 
536     if (verticalPolicy == GTK_POLICY_NEVER)
537         verticalPolicy = GTK_POLICY_AUTOMATIC;
538 
539     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(parent),
540                                    horizontalPolicy, verticalPolicy);
541 }
542 
mouseDidMoveOverElement(const HitTestResult & hit,unsigned modifierFlags)543 void ChromeClient::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags)
544 {
545     // check if the element is a link...
546     bool isLink = hit.isLiveLink();
547     if (isLink) {
548         KURL url = hit.absoluteLinkURL();
549         if (!url.isEmpty() && url != m_hoveredLinkURL) {
550             TextDirection dir;
551             CString titleString = hit.title(dir).utf8();
552             CString urlString = url.string().utf8();
553             g_signal_emit_by_name(m_webView, "hovering-over-link", titleString.data(), urlString.data());
554             m_hoveredLinkURL = url;
555         }
556     } else if (!isLink && !m_hoveredLinkURL.isEmpty()) {
557         g_signal_emit_by_name(m_webView, "hovering-over-link", 0, 0);
558         m_hoveredLinkURL = KURL();
559     }
560 
561     if (Node* node = hit.innerNonSharedNode()) {
562         Frame* frame = node->document()->frame();
563         FrameView* view = frame ? frame->view() : 0;
564         m_webView->priv->tooltipArea = view ? view->contentsToWindow(node->getRect()) : IntRect();
565     } else
566         m_webView->priv->tooltipArea = IntRect();
567 }
568 
setToolTip(const String & toolTip,TextDirection)569 void ChromeClient::setToolTip(const String& toolTip, TextDirection)
570 {
571     webkit_web_view_set_tooltip_text(m_webView, toolTip.utf8().data());
572 }
573 
print(Frame * frame)574 void ChromeClient::print(Frame* frame)
575 {
576     WebKitWebFrame* webFrame = kit(frame);
577     gboolean isHandled = false;
578     g_signal_emit_by_name(m_webView, "print-requested", webFrame, &isHandled);
579 
580     if (isHandled)
581         return;
582 
583     webkit_web_frame_print(webFrame);
584 }
585 
586 #if ENABLE(DATABASE)
exceededDatabaseQuota(Frame * frame,const String & databaseName)587 void ChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseName)
588 {
589     guint64 defaultQuota = webkit_get_default_web_database_quota();
590     DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), defaultQuota);
591 
592     WebKitWebFrame* webFrame = kit(frame);
593     WebKitSecurityOrigin* origin = webkit_web_frame_get_security_origin(webFrame);
594     WebKitWebDatabase* webDatabase = webkit_security_origin_get_web_database(origin, databaseName.utf8().data());
595     g_signal_emit_by_name(m_webView, "database-quota-exceeded", webFrame, webDatabase);
596 }
597 #endif
598 
599 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
reachedMaxAppCacheSize(int64_t spaceNeeded)600 void ChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
601 {
602     // FIXME: Free some space.
603     notImplemented();
604 }
605 
reachedApplicationCacheOriginQuota(SecurityOrigin *)606 void ChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin*)
607 {
608     notImplemented();
609 }
610 #endif
611 
runOpenPanel(Frame *,PassRefPtr<FileChooser> prpFileChooser)612 void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
613 {
614     RefPtr<FileChooser> chooser = prpFileChooser;
615 
616     GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Upload File"),
617                                                     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(m_webView))),
618                                                     GTK_FILE_CHOOSER_ACTION_OPEN,
619                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
620                                                     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
621                                                     NULL);
622 
623     gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), chooser->allowsMultipleFiles());
624 
625     if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
626         if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog))) {
627             GSList* filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
628             Vector<String> names;
629             for (GSList* item = filenames ; item ; item = item->next) {
630                 if (!item->data)
631                     continue;
632                 names.append(filenameToString(static_cast<char*>(item->data)));
633                 g_free(item->data);
634             }
635             g_slist_free(filenames);
636             chooser->chooseFiles(names);
637         } else {
638             gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
639             if (filename)
640                 chooser->chooseFile(filenameToString(filename));
641             g_free(filename);
642         }
643     }
644     gtk_widget_destroy(dialog);
645 }
646 
chooseIconForFiles(const Vector<WTF::String> & filenames,WebCore::FileChooser * chooser)647 void ChromeClient::chooseIconForFiles(const Vector<WTF::String>& filenames, WebCore::FileChooser* chooser)
648 {
649     chooser->iconLoaded(Icon::createIconForFiles(filenames));
650 }
651 
dispatchViewportDataDidChange(const ViewportArguments & arguments) const652 void ChromeClient::dispatchViewportDataDidChange(const ViewportArguments& arguments) const
653 {
654     // Recompute the viewport attributes making it valid.
655     webkitViewportAttributesRecompute(webkit_web_view_get_viewport_attributes(m_webView));
656 }
657 
setCursor(const Cursor & cursor)658 void ChromeClient::setCursor(const Cursor& cursor)
659 {
660     // [GTK] Widget::setCursor() gets called frequently
661     // http://bugs.webkit.org/show_bug.cgi?id=16388
662     // Setting the cursor may be an expensive operation in some backends,
663     // so don't re-set the cursor if it's already set to the target value.
664     GdkWindow* window = gtk_widget_get_window(platformPageClient());
665     GdkCursor* currentCursor = gdk_window_get_cursor(window);
666     GdkCursor* newCursor = cursor.platformCursor().get();
667     if (currentCursor != newCursor)
668         gdk_window_set_cursor(window, newCursor);
669 }
670 
requestGeolocationPermissionForFrame(Frame * frame,Geolocation * geolocation)671 void ChromeClient::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
672 {
673     WebKitWebFrame* webFrame = kit(frame);
674     GRefPtr<WebKitGeolocationPolicyDecision> policyDecision(adoptGRef(webkit_geolocation_policy_decision_new(webFrame, geolocation)));
675 
676     gboolean isHandled = FALSE;
677     g_signal_emit_by_name(m_webView, "geolocation-policy-decision-requested", webFrame, policyDecision.get(), &isHandled);
678     if (!isHandled)
679         webkit_geolocation_policy_deny(policyDecision.get());
680 }
681 
cancelGeolocationPermissionRequestForFrame(WebCore::Frame * frame,WebCore::Geolocation *)682 void ChromeClient::cancelGeolocationPermissionRequestForFrame(WebCore::Frame* frame, WebCore::Geolocation*)
683 {
684     g_signal_emit_by_name(m_webView, "geolocation-policy-decision-cancelled", kit(frame));
685 }
686 
selectItemWritingDirectionIsNatural()687 bool ChromeClient::selectItemWritingDirectionIsNatural()
688 {
689     return true;
690 }
691 
selectItemAlignmentFollowsMenuWritingDirection()692 bool ChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
693 {
694     return false;
695 }
696 
createPopupMenu(WebCore::PopupMenuClient * client) const697 PassRefPtr<WebCore::PopupMenu> ChromeClient::createPopupMenu(WebCore::PopupMenuClient* client) const
698 {
699     return adoptRef(new PopupMenuGtk(client));
700 }
701 
createSearchPopupMenu(WebCore::PopupMenuClient * client) const702 PassRefPtr<WebCore::SearchPopupMenu> ChromeClient::createSearchPopupMenu(WebCore::PopupMenuClient* client) const
703 {
704     return adoptRef(new SearchPopupMenuGtk(client));
705 }
706 
707 #if ENABLE(VIDEO)
708 
supportsFullscreenForNode(const Node * node)709 bool ChromeClient::supportsFullscreenForNode(const Node* node)
710 {
711     return node->hasTagName(HTMLNames::videoTag);
712 }
713 
enterFullscreenForNode(Node * node)714 void ChromeClient::enterFullscreenForNode(Node* node)
715 {
716     webViewEnterFullscreen(m_webView, node);
717 }
718 
exitFullscreenForNode(Node * node)719 void ChromeClient::exitFullscreenForNode(Node* node)
720 {
721     webViewExitFullscreen(m_webView);
722 }
723 #endif
724 
725 #if ENABLE(FULLSCREEN_API)
supportsFullScreenForElement(const WebCore::Element * element,bool withKeyboard)726 bool ChromeClient::supportsFullScreenForElement(const WebCore::Element* element, bool withKeyboard)
727 {
728     if (withKeyboard)
729         return false;
730 
731     return true;
732 }
733 
enterFullScreenForElement(WebCore::Element * element)734 void ChromeClient::enterFullScreenForElement(WebCore::Element* element)
735 {
736     element->document()->webkitWillEnterFullScreenForElement(element);
737     element->document()->webkitDidEnterFullScreenForElement(element);
738 }
739 
exitFullScreenForElement(WebCore::Element * element)740 void ChromeClient::exitFullScreenForElement(WebCore::Element* element)
741 {
742     element->document()->webkitWillExitFullScreenForElement(element);
743     element->document()->webkitDidExitFullScreenForElement(element);
744 }
745 #endif
746 
747 
748 }
749