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