6116ae77860e0d45fa25f42b03541a70bde0084d
[WebKit-https.git] / Source / WebKit / qt / WebCoreSupport / ChromeClientQt.cpp
1 /*
2  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
4  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "ChromeClientQt.h"
32
33 #include "ApplicationCacheStorage.h"
34 #include "DatabaseTracker.h"
35 #include "FileChooser.h"
36 #include "Frame.h"
37 #include "FrameLoadRequest.h"
38 #include "FrameLoader.h"
39 #include "FrameLoaderClientQt.h"
40 #include "FrameView.h"
41 #include "Geolocation.h"
42 #if USE(ACCELERATED_COMPOSITING)
43 #include "GraphicsLayer.h"
44 #endif
45 #include "GeolocationPermissionClientQt.h"
46 #include "HitTestResult.h"
47 #include "Icon.h"
48 #include "NavigationAction.h"
49 #include "NetworkingContext.h"
50 #include "NotImplemented.h"
51 #include "NotificationPresenterClientQt.h"
52 #include "PageClientQt.h"
53 #include "PopupMenuQt.h"
54 #if defined(Q_WS_MAEMO_5)
55 #include "QtMaemoWebPopup.h"
56 #else
57 #include "QtFallbackWebPopup.h"
58 #endif
59 #include "QWebPageClient.h"
60 #include "ScrollbarTheme.h"
61 #include "SearchPopupMenuQt.h"
62 #include "SecurityOrigin.h"
63 #include "ViewportArguments.h"
64 #include "WindowFeatures.h"
65
66 #include "qgraphicswebview.h"
67 #include "qwebframe_p.h"
68 #include "qwebpage.h"
69 #include "qwebpage_p.h"
70 #include "qwebsecurityorigin.h"
71 #include "qwebsecurityorigin_p.h"
72 #include "qwebview.h"
73 #include <qdebug.h>
74 #include <qeventloop.h>
75 #include <qtextdocument.h>
76 #include <qtooltip.h>
77 #include <wtf/OwnPtr.h>
78
79 namespace WebCore {
80
81 bool ChromeClientQt::dumpVisitedLinksCallbacks = false;
82
83 ChromeClientQt::ChromeClientQt(QWebPage* webPage)
84     : m_webPage(webPage)
85     , m_eventLoop(0)
86 {
87     toolBarsVisible = statusBarVisible = menuBarVisible = true;
88 }
89
90 ChromeClientQt::~ChromeClientQt()
91 {
92     if (m_eventLoop)
93         m_eventLoop->exit();
94 }
95
96 void ChromeClientQt::setWindowRect(const FloatRect& rect)
97 {
98     if (!m_webPage)
99         return;
100     emit m_webPage->geometryChangeRequested(QRect(qRound(rect.x()), qRound(rect.y()),
101                             qRound(rect.width()), qRound(rect.height())));
102 }
103
104 /*!
105     windowRect represents the rect of the Window, including all interface elements
106     like toolbars/scrollbars etc. It is used by the viewport meta tag as well as
107     by the DOM Window object: outerHeight(), outerWidth(), screenX(), screenY().
108 */
109 FloatRect ChromeClientQt::windowRect()
110 {
111     if (!platformPageClient())
112         return FloatRect();
113     return platformPageClient()->windowRect();
114 }
115
116 FloatRect ChromeClientQt::pageRect()
117 {
118     if (!m_webPage)
119         return FloatRect();
120     return FloatRect(QRectF(QPointF(0, 0), m_webPage->viewportSize()));
121 }
122
123 float ChromeClientQt::scaleFactor()
124 {
125     if (!m_webPage)
126         return 1;
127     return m_webPage->d->pixelRatio;
128 }
129
130 void ChromeClientQt::focus()
131 {
132     if (!m_webPage)
133         return;
134     QWidget* view = m_webPage->view();
135     if (!view)
136         return;
137
138     view->setFocus();
139 }
140
141
142 void ChromeClientQt::unfocus()
143 {
144     if (!m_webPage)
145         return;
146     QWidget* view = m_webPage->view();
147     if (!view)
148         return;
149     view->clearFocus();
150 }
151
152 bool ChromeClientQt::canTakeFocus(FocusDirection)
153 {
154     // This is called when cycling through links/focusable objects and we
155     // reach the last focusable object. Then we want to claim that we can
156     // take the focus to avoid wrapping.
157     return true;
158 }
159
160 void ChromeClientQt::takeFocus(FocusDirection)
161 {
162     // don't do anything. This is only called when cycling to links/focusable objects,
163     // which in turn is called from focusNextPrevChild. We let focusNextPrevChild
164     // call QWidget::focusNextPrevChild accordingly, so there is no need to do anything
165     // here.
166 }
167
168
169 void ChromeClientQt::focusedNodeChanged(Node*)
170 {
171 }
172
173 void ChromeClientQt::focusedFrameChanged(Frame*)
174 {
175 }
176
177 Page* ChromeClientQt::createWindow(Frame*, const FrameLoadRequest& request, const WindowFeatures& features, const NavigationAction&)
178 {
179     QWebPage* newPage = m_webPage->createWindow(features.dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow);
180     if (!newPage)
181         return 0;
182
183     // A call to QWebPage::mainFrame() implicitly creates the main frame.
184     // Make sure it exists, as WebCore expects it when returning from this call.
185     newPage->mainFrame();
186     return newPage->d->page;
187 }
188
189 void ChromeClientQt::show()
190 {
191     if (!m_webPage)
192         return;
193     QWidget* view = m_webPage->view();
194     if (!view)
195         return;
196     view->window()->show();
197 }
198
199
200 bool ChromeClientQt::canRunModal()
201 {
202     return true;
203 }
204
205
206 void ChromeClientQt::runModal()
207 {
208     m_eventLoop = new QEventLoop();
209     QEventLoop* eventLoop = m_eventLoop;
210     m_eventLoop->exec();
211     delete eventLoop;
212 }
213
214
215 void ChromeClientQt::setToolbarsVisible(bool visible)
216 {
217     toolBarsVisible = visible;
218     emit m_webPage->toolBarVisibilityChangeRequested(visible);
219 }
220
221
222 bool ChromeClientQt::toolbarsVisible()
223 {
224     return toolBarsVisible;
225 }
226
227
228 void ChromeClientQt::setStatusbarVisible(bool visible)
229 {
230     emit m_webPage->statusBarVisibilityChangeRequested(visible);
231     statusBarVisible = visible;
232 }
233
234
235 bool ChromeClientQt::statusbarVisible()
236 {
237     return statusBarVisible;
238 }
239
240
241 void ChromeClientQt::setScrollbarsVisible(bool)
242 {
243     notImplemented();
244 }
245
246
247 bool ChromeClientQt::scrollbarsVisible()
248 {
249     notImplemented();
250     return true;
251 }
252
253
254 void ChromeClientQt::setMenubarVisible(bool visible)
255 {
256     menuBarVisible = visible;
257     emit m_webPage->menuBarVisibilityChangeRequested(visible);
258 }
259
260 bool ChromeClientQt::menubarVisible()
261 {
262     return menuBarVisible;
263 }
264
265 void ChromeClientQt::setResizable(bool)
266 {
267     notImplemented();
268 }
269
270 void ChromeClientQt::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message,
271                                          unsigned int lineNumber, const String& sourceID)
272 {
273     QString x = message;
274     QString y = sourceID;
275     m_webPage->javaScriptConsoleMessage(x, lineNumber, y);
276 }
277
278 void ChromeClientQt::chromeDestroyed()
279 {
280     delete this;
281 }
282
283 bool ChromeClientQt::canRunBeforeUnloadConfirmPanel()
284 {
285     return true;
286 }
287
288 bool ChromeClientQt::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
289 {
290     return runJavaScriptConfirm(frame, message);
291 }
292
293 void ChromeClientQt::closeWindowSoon()
294 {
295     m_webPage->mainFrame()->d->frame->loader()->stopAllLoaders();
296     emit m_webPage->windowCloseRequested();
297 }
298
299 void ChromeClientQt::runJavaScriptAlert(Frame* f, const String& msg)
300 {
301     QString x = msg;
302     QWebFrame* webFrame = qobject_cast<QWebFrame*>(f->loader()->networkingContext()->originatingObject());
303     m_webPage->javaScriptAlert(webFrame, x);
304 }
305
306 bool ChromeClientQt::runJavaScriptConfirm(Frame* f, const String& msg)
307 {
308     QString x = msg;
309     QWebFrame* webFrame = qobject_cast<QWebFrame*>(f->loader()->networkingContext()->originatingObject());
310     return m_webPage->javaScriptConfirm(webFrame, x);
311 }
312
313 bool ChromeClientQt::runJavaScriptPrompt(Frame* f, const String& message, const String& defaultValue, String& result)
314 {
315     QString x = result;
316     QWebFrame* webFrame = qobject_cast<QWebFrame*>(f->loader()->networkingContext()->originatingObject());
317     bool rc = m_webPage->javaScriptPrompt(webFrame, (QString)message, (QString)defaultValue, &x);
318
319     // Fix up a quirk in the QInputDialog class. If no input happened the string should be empty
320     // but it is null. See https://bugs.webkit.org/show_bug.cgi?id=30914.
321     if (rc && x.isNull())
322         result = String("");
323     else
324         result = x;
325
326     return rc;
327 }
328
329 void ChromeClientQt::setStatusbarText(const String& msg)
330 {
331     QString x = msg;
332     emit m_webPage->statusBarMessage(x);
333 }
334
335 bool ChromeClientQt::shouldInterruptJavaScript()
336 {
337     bool shouldInterrupt = false;
338     QMetaObject::invokeMethod(m_webPage, "shouldInterruptJavaScript", Qt::DirectConnection, Q_RETURN_ARG(bool, shouldInterrupt));
339     return shouldInterrupt;
340 }
341
342 bool ChromeClientQt::tabsToLinks() const
343 {
344     return m_webPage->settings()->testAttribute(QWebSettings::LinksIncludedInFocusChain);
345 }
346
347 IntRect ChromeClientQt::windowResizerRect() const
348 {
349 #if defined(Q_WS_MAC)
350     if (!m_webPage)
351         return IntRect();
352
353     QWebPageClient* pageClient = platformPageClient();
354     if (!pageClient)
355         return IntRect();
356
357     QWidget* ownerWidget = pageClient->ownerWidget();
358     if (!ownerWidget)
359         return IntRect();
360
361     QWidget* topLevelWidget = ownerWidget->window();
362     QRect topLevelGeometry(topLevelWidget->geometry());
363
364     // There's no API in Qt to query for the size of the resizer, so we assume
365     // it has the same width and height as the scrollbar thickness.
366     int scollbarThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
367
368     // There's no API in Qt to query for the position of the resizer. Sometimes
369     // it's drawn by the system, and sometimes it's a QSizeGrip. For RTL locales
370     // it might even be on the lower left side of the window, but in WebKit we
371     // always draw scrollbars on the right hand side, so we assume this to be the
372     // location when computing the resize rect to reserve for WebKit.
373     QPoint resizeCornerTopLeft = ownerWidget->mapFrom(topLevelWidget,
374             QPoint(topLevelGeometry.width(), topLevelGeometry.height())
375             - QPoint(scollbarThickness, scollbarThickness));
376
377     QRect resizeCornerRect = QRect(resizeCornerTopLeft, QSize(scollbarThickness, scollbarThickness));
378     return resizeCornerRect.intersected(pageClient->geometryRelativeToOwnerWidget());
379 #else
380     return IntRect();
381 #endif
382 }
383
384 void ChromeClientQt::invalidateWindow(const IntRect&, bool)
385 {
386     notImplemented();
387 }
388
389 void ChromeClientQt::invalidateContentsAndWindow(const IntRect& windowRect, bool immediate)
390 {
391     // No double buffer, so only update the QWidget if content changed.
392     if (platformPageClient()) {
393         QRect rect(windowRect);
394         rect = rect.intersected(QRect(QPoint(0, 0), m_webPage->viewportSize()));
395         if (!rect.isEmpty())
396             platformPageClient()->update(rect);
397     }
398     emit m_webPage->repaintRequested(windowRect);
399
400     // FIXME: There is no "immediate" support for window painting.  This should be done always whenever the flag
401     // is set.
402 }
403
404 void ChromeClientQt::invalidateContentsForSlowScroll(const IntRect& windowRect, bool immediate)
405 {
406     invalidateContentsAndWindow(windowRect, immediate);
407 }
408
409 void ChromeClientQt::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect&)
410 {
411     if (platformPageClient())
412         platformPageClient()->scroll(delta.width(), delta.height(), scrollViewRect);
413     emit m_webPage->scrollRequested(delta.width(), delta.height(), scrollViewRect);
414 }
415
416 #if ENABLE(TILED_BACKING_STORE)
417 void ChromeClientQt::delegatedScrollRequested(const IntSize& delta)
418 {
419     emit m_webPage->scrollRequested(delta.width(), delta.height(), QRect(QPoint(0, 0), m_webPage->viewportSize()));
420 }
421 #endif
422
423 IntRect ChromeClientQt::windowToScreen(const IntRect& rect) const
424 {
425     QWebPageClient* pageClient = platformPageClient();
426     if (!pageClient)
427         return rect;
428
429     QWidget* ownerWidget = pageClient->ownerWidget();
430     if (!ownerWidget)
431        return rect;
432
433     QRect screenRect(rect);
434     screenRect.translate(ownerWidget->mapToGlobal(QPoint(0, 0)));
435
436     return screenRect;
437 }
438
439 IntPoint ChromeClientQt::screenToWindow(const IntPoint& point) const
440 {
441     QWebPageClient* pageClient = platformPageClient();
442     if (!pageClient)
443         return point;
444
445     QWidget* ownerWidget = pageClient->ownerWidget();
446     if (!ownerWidget)
447         return point;
448
449     return ownerWidget->mapFromGlobal(point);
450 }
451
452 PlatformPageClient ChromeClientQt::platformPageClient() const
453 {
454     return m_webPage->d->client.get();
455 }
456
457 void ChromeClientQt::contentsSizeChanged(Frame* frame, const IntSize& size) const
458 {
459     if (frame->loader()->networkingContext())
460         QWebFramePrivate::kit(frame)->contentsSizeChanged(size);
461 }
462
463 void ChromeClientQt::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
464 {
465     TextDirection dir;
466     if (result.absoluteLinkURL() != lastHoverURL
467         || result.title(dir) != lastHoverTitle
468         || result.textContent() != lastHoverContent) {
469         lastHoverURL = result.absoluteLinkURL();
470         lastHoverTitle = result.title(dir);
471         lastHoverContent = result.textContent();
472         emit m_webPage->linkHovered(lastHoverURL.prettyURL(),
473                 lastHoverTitle, lastHoverContent);
474     }
475 }
476
477 void ChromeClientQt::setToolTip(const String &tip, TextDirection)
478 {
479 #ifndef QT_NO_TOOLTIP
480     QWidget* view = m_webPage->view();
481     if (!view)
482         return;
483
484     if (tip.isEmpty()) {
485         view->setToolTip(QString());
486         QToolTip::hideText();
487     } else {
488         QString dtip = QLatin1String("<p>") + Qt::escape(tip) + QLatin1String("</p>");
489         view->setToolTip(dtip);
490     }
491 #else
492     Q_UNUSED(tip);
493 #endif
494 }
495
496 void ChromeClientQt::print(Frame* frame)
497 {
498     emit m_webPage->printRequested(QWebFramePrivate::kit(frame));
499 }
500
501 #if ENABLE(DATABASE)
502 void ChromeClientQt::exceededDatabaseQuota(Frame* frame, const String& databaseName)
503 {
504     quint64 quota = QWebSettings::offlineStorageDefaultQuota();
505
506     if (!DatabaseTracker::tracker().hasEntryForOrigin(frame->document()->securityOrigin()))
507         DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), quota);
508
509     emit m_webPage->databaseQuotaExceeded(QWebFramePrivate::kit(frame), databaseName);
510 }
511 #endif
512
513 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
514 void ChromeClientQt::reachedMaxAppCacheSize(int64_t)
515 {
516     // FIXME: Free some space.
517     notImplemented();
518 }
519
520 void ChromeClientQt::reachedApplicationCacheOriginQuota(SecurityOrigin* origin)
521 {
522     int64_t quota;
523     quint64 defaultOriginQuota = WebCore::cacheStorage().defaultOriginQuota();
524
525     QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(origin);
526     QWebSecurityOrigin* securityOrigin = new QWebSecurityOrigin(priv);
527
528     if (!WebCore::cacheStorage().quotaForOrigin(origin, quota))
529        WebCore::cacheStorage().storeUpdatedQuotaForOrigin(origin, defaultOriginQuota);
530
531     emit m_webPage->applicationCacheQuotaExceeded(securityOrigin, defaultOriginQuota);
532 }
533 #endif
534
535 #if ENABLE(NOTIFICATIONS)
536 NotificationPresenter* ChromeClientQt::notificationPresenter() const
537 {
538     return NotificationPresenterClientQt::notificationPresenter();
539 }
540 #endif
541
542 void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser)
543 {
544     RefPtr<FileChooser> fileChooser = prpFileChooser;
545     bool supportMulti = m_webPage->supportsExtension(QWebPage::ChooseMultipleFilesExtension);
546
547     if (fileChooser->allowsMultipleFiles() && supportMulti) {
548         QWebPage::ChooseMultipleFilesExtensionOption option;
549         option.parentFrame = QWebFramePrivate::kit(frame);
550
551         if (!fileChooser->filenames().isEmpty())
552             for (unsigned i = 0; i < fileChooser->filenames().size(); ++i)
553                 option.suggestedFileNames += fileChooser->filenames()[i];
554
555         QWebPage::ChooseMultipleFilesExtensionReturn output;
556         m_webPage->extension(QWebPage::ChooseMultipleFilesExtension, &option, &output);
557
558         if (!output.fileNames.isEmpty()) {
559             Vector<String> names;
560             for (int i = 0; i < output.fileNames.count(); ++i)
561                 names.append(output.fileNames.at(i));
562             fileChooser->chooseFiles(names);
563         }
564     } else {
565         QString suggestedFile;
566         if (!fileChooser->filenames().isEmpty())
567             suggestedFile = fileChooser->filenames()[0];
568         QString file = m_webPage->chooseFile(QWebFramePrivate::kit(frame), suggestedFile);
569         if (!file.isEmpty())
570             fileChooser->chooseFile(file);
571     }
572 }
573
574 void ChromeClientQt::chooseIconForFiles(const Vector<String>& filenames, FileChooser* chooser)
575 {
576     chooser->iconLoaded(Icon::createIconForFiles(filenames));
577 }
578
579 void ChromeClientQt::setCursor(const Cursor& cursor)
580 {
581 #ifndef QT_NO_CURSOR
582     QWebPageClient* pageClient = platformPageClient();
583     if (!pageClient)
584         return;
585     pageClient->setCursor(*cursor.platformCursor());
586 #else
587     UNUSED_PARAM(cursor);
588 #endif
589 }
590
591 void ChromeClientQt::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
592 {
593 #if ENABLE(GEOLOCATION)
594     QWebFrame* webFrame = QWebFramePrivate::kit(frame);
595     GeolocationPermissionClientQt::geolocationPermissionClient()->requestGeolocationPermissionForFrame(webFrame, geolocation);
596 #endif
597 }
598
599 void ChromeClientQt::cancelGeolocationPermissionRequestForFrame(Frame* frame, Geolocation* geolocation)
600 {
601 #if ENABLE(GEOLOCATION)
602     QWebFrame* webFrame = QWebFramePrivate::kit(frame);
603     GeolocationPermissionClientQt::geolocationPermissionClient()->cancelGeolocationPermissionRequestForFrame(webFrame, geolocation);
604 #endif
605 }
606
607 #if USE(ACCELERATED_COMPOSITING)
608 void ChromeClientQt::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
609 {
610     if (platformPageClient())
611         platformPageClient()->setRootGraphicsLayer(graphicsLayer ? graphicsLayer->platformLayer() : 0);
612 }
613
614 void ChromeClientQt::setNeedsOneShotDrawingSynchronization()
615 {
616     // we want the layers to synchronize next time we update the screen anyway
617     if (platformPageClient())
618         platformPageClient()->markForSync(false);
619 }
620
621 void ChromeClientQt::scheduleCompositingLayerSync()
622 {
623     // we want the layers to synchronize ASAP
624     if (platformPageClient())
625         platformPageClient()->markForSync(true);
626 }
627
628 ChromeClient::CompositingTriggerFlags ChromeClientQt::allowedCompositingTriggers() const
629 {
630     if (platformPageClient() && platformPageClient()->allowsAcceleratedCompositing())
631         return AllTriggers;
632
633     return 0;
634 }
635
636 #endif
637
638 #if ENABLE(TILED_BACKING_STORE)
639 IntRect ChromeClientQt::visibleRectForTiledBackingStore() const
640 {
641     if (!platformPageClient() || !m_webPage)
642         return IntRect();
643
644     if (!platformPageClient()->viewResizesToContentsEnabled())
645         return QRect(m_webPage->mainFrame()->scrollPosition(), m_webPage->mainFrame()->geometry().size());
646
647     return enclosingIntRect(FloatRect(platformPageClient()->graphicsItemVisibleRect()));
648 }
649 #endif
650
651 QWebSelectMethod* ChromeClientQt::createSelectPopup() const
652 {
653     QWebSelectMethod* result = m_platformPlugin.createSelectInputMethod();
654     if (result)
655         return result;
656
657 #if defined(Q_WS_MAEMO_5)
658     return new QtMaemoWebPopup;
659 #elif !defined(QT_NO_COMBOBOX)
660     return new QtFallbackWebPopup(this);
661 #else
662     return 0;
663 #endif
664 }
665
666 void ChromeClientQt::dispatchViewportDataDidChange(const ViewportArguments&) const
667 {
668     emit m_webPage->viewportChangeRequested();
669 }
670
671 bool ChromeClientQt::selectItemWritingDirectionIsNatural()
672 {
673     return false;
674 }
675
676 PassRefPtr<PopupMenu> ChromeClientQt::createPopupMenu(PopupMenuClient* client) const
677 {
678     return adoptRef(new PopupMenuQt(client, this));
679 }
680
681 PassRefPtr<SearchPopupMenu> ChromeClientQt::createSearchPopupMenu(PopupMenuClient* client) const
682 {
683     return adoptRef(new SearchPopupMenuQt(createPopupMenu(client)));
684 }
685
686 void ChromeClientQt::populateVisitedLinks()
687 {
688     // We don't need to do anything here because history is tied to QWebPage rather than stored
689     // in a separate database
690     if (dumpVisitedLinksCallbacks) {
691         printf("Asked to populate visited links for WebView \"%s\"\n",
692                 qPrintable(m_webPage->mainFrame()->url().toString()));
693     }
694 }
695
696 } // namespace WebCore