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