blob: eaaeb012f86d0a53110b579773f6d5b8c05d9342 [file] [log] [blame]
/*
* Copyright (C) 2006 Zack Rusin <zack@kde.org>
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "ChromeClientQt.h"
#include "ApplicationCacheStorage.h"
#include "ColorChooser.h"
#include "ColorChooserClient.h"
#include "DatabaseTracker.h"
#include "Document.h"
#include "FileChooser.h"
#include "FileIconLoader.h"
#include "Frame.h"
#include "FrameLoadRequest.h"
#include "FrameLoader.h"
#include "FrameLoaderClientQt.h"
#include "FrameView.h"
#include "Geolocation.h"
#if USE(ACCELERATED_COMPOSITING)
#include "GraphicsLayer.h"
#endif
#include "HTMLFormElement.h"
#include "HitTestResult.h"
#include "Icon.h"
#include "NavigationAction.h"
#include "NetworkingContext.h"
#include "NotImplemented.h"
#include "Page.h"
#include "PageClientQt.h"
#include "PopupMenuQt.h"
#include "QtFallbackWebPopup.h"
#include "QWebPageClient.h"
#include "ScrollbarTheme.h"
#include "SearchPopupMenuQt.h"
#include "SecurityOrigin.h"
#include "ViewportArguments.h"
#include "WindowFeatures.h"
#include "qgraphicswebview.h"
#include "qwebframe_p.h"
#include "qwebpage.h"
#include "qwebpage_p.h"
#include "qwebsecurityorigin.h"
#include "qwebsecurityorigin_p.h"
#include "qwebview.h"
#include <qabstractanimation.h>
#include <qdebug.h>
#include <qeventloop.h>
#include <qtooltip.h>
#include <wtf/OwnPtr.h>
#if ENABLE(VIDEO) && ((USE(GSTREAMER) && !defined(GST_API_VERSION_1)) || USE(QT_MULTIMEDIA) || USE(QTKIT))
#include "FullScreenVideoQt.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "HTMLVideoElement.h"
#if USE(QT_MULTIMEDIA)
#include "MediaPlayerPrivateQt.h"
#endif
#endif
namespace WebCore {
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
class RefreshAnimation : public QAbstractAnimation {
public:
RefreshAnimation(ChromeClientQt* chromeClient)
: QAbstractAnimation()
, m_chromeClient(chromeClient)
, m_animationScheduled(false)
{ }
virtual int duration() const { return -1; }
void scheduleAnimation()
{
m_animationScheduled = true;
if (state() != QAbstractAnimation::Running)
QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
}
protected:
virtual void updateCurrentTime(int currentTime)
{
UNUSED_PARAM(currentTime);
if (m_animationScheduled) {
m_animationScheduled = false;
m_chromeClient->serviceScriptedAnimations();
} else
stop();
}
private:
ChromeClientQt* m_chromeClient;
bool m_animationScheduled;
};
#endif
bool ChromeClientQt::dumpVisitedLinksCallbacks = false;
ChromeClientQt::ChromeClientQt(QWebPage* webPage)
: m_webPage(webPage)
, m_eventLoop(0)
#if ENABLE(VIDEO) && ((USE(GSTREAMER) && !defined(GST_API_VERSION_1)) || USE(QT_MULTIMEDIA) || USE(QTKIT))
, m_fullScreenVideo(0)
#endif
{
toolBarsVisible = statusBarVisible = menuBarVisible = true;
}
ChromeClientQt::~ChromeClientQt()
{
if (m_eventLoop)
m_eventLoop->exit();
#if ENABLE(VIDEO) && ((USE(GSTREAMER) && !defined(GST_API_VERSION_1)) || USE(QT_MULTIMEDIA) || USE(QTKIT))
delete m_fullScreenVideo;
#endif
}
void ChromeClientQt::setWindowRect(const FloatRect& rect)
{
if (!m_webPage)
return;
emit m_webPage->geometryChangeRequested(QRect(qRound(rect.x()), qRound(rect.y()),
qRound(rect.width()), qRound(rect.height())));
}
/*!
windowRect represents the rect of the Window, including all interface elements
like toolbars/scrollbars etc. It is used by the viewport meta tag as well as
by the DOM Window object: outerHeight(), outerWidth(), screenX(), screenY().
*/
FloatRect ChromeClientQt::windowRect()
{
if (!platformPageClient())
return FloatRect();
return platformPageClient()->windowRect();
}
bool ChromeClientQt::allowsAcceleratedCompositing() const
{
if (!platformPageClient())
return false;
return platformPageClient()->allowsAcceleratedCompositing();
}
FloatRect ChromeClientQt::pageRect()
{
if (!m_webPage)
return FloatRect();
return FloatRect(QRectF(QPointF(0, 0), m_webPage->viewportSize()));
}
void ChromeClientQt::focus()
{
if (!m_webPage)
return;
QWidget* view = m_webPage->view();
if (!view)
return;
view->setFocus();
}
void ChromeClientQt::unfocus()
{
if (!m_webPage)
return;
QWidget* view = m_webPage->view();
if (!view)
return;
view->clearFocus();
}
bool ChromeClientQt::canTakeFocus(FocusDirection)
{
// This is called when cycling through links/focusable objects and we
// reach the last focusable object. Then we want to claim that we can
// take the focus to avoid wrapping.
return true;
}
void ChromeClientQt::takeFocus(FocusDirection)
{
// don't do anything. This is only called when cycling to links/focusable objects,
// which in turn is called from focusNextPrevChild. We let focusNextPrevChild
// call QWidget::focusNextPrevChild accordingly, so there is no need to do anything
// here.
}
void ChromeClientQt::focusedNodeChanged(Node*)
{
}
void ChromeClientQt::focusedFrameChanged(Frame*)
{
}
Page* ChromeClientQt::createWindow(Frame*, const FrameLoadRequest& request, const WindowFeatures& features, const NavigationAction&)
{
QWebPage* newPage = m_webPage->createWindow(features.dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow);
if (!newPage)
return 0;
// A call to QWebPage::mainFrame() implicitly creates the main frame.
// Make sure it exists, as WebCore expects it when returning from this call.
newPage->mainFrame();
return newPage->d->page;
}
void ChromeClientQt::show()
{
if (!m_webPage)
return;
QWidget* view = m_webPage->view();
if (!view)
return;
view->window()->show();
}
bool ChromeClientQt::canRunModal()
{
return true;
}
void ChromeClientQt::runModal()
{
m_eventLoop = new QEventLoop();
QEventLoop* eventLoop = m_eventLoop;
m_eventLoop->exec();
delete eventLoop;
}
void ChromeClientQt::setToolbarsVisible(bool visible)
{
toolBarsVisible = visible;
emit m_webPage->toolBarVisibilityChangeRequested(visible);
}
bool ChromeClientQt::toolbarsVisible()
{
return toolBarsVisible;
}
void ChromeClientQt::setStatusbarVisible(bool visible)
{
emit m_webPage->statusBarVisibilityChangeRequested(visible);
statusBarVisible = visible;
}
bool ChromeClientQt::statusbarVisible()
{
return statusBarVisible;
}
void ChromeClientQt::setScrollbarsVisible(bool)
{
notImplemented();
}
bool ChromeClientQt::scrollbarsVisible()
{
notImplemented();
return true;
}
void ChromeClientQt::setMenubarVisible(bool visible)
{
menuBarVisible = visible;
emit m_webPage->menuBarVisibilityChangeRequested(visible);
}
bool ChromeClientQt::menubarVisible()
{
return menuBarVisible;
}
void ChromeClientQt::setResizable(bool)
{
notImplemented();
}
void ChromeClientQt::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message,
unsigned int lineNumber, const String& sourceID)
{
QString x = message;
QString y = sourceID;
m_webPage->javaScriptConsoleMessage(x, lineNumber, y);
}
void ChromeClientQt::chromeDestroyed()
{
delete this;
}
bool ChromeClientQt::canRunBeforeUnloadConfirmPanel()
{
return true;
}
bool ChromeClientQt::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
{
return runJavaScriptConfirm(frame, message);
}
void ChromeClientQt::closeWindowSoon()
{
m_webPage->d->page->setGroupName(String());
m_webPage->mainFrame()->d->frame->loader()->stopAllLoaders();
emit m_webPage->windowCloseRequested();
}
void ChromeClientQt::runJavaScriptAlert(Frame* f, const String& msg)
{
QString x = msg;
QWebFrame* webFrame = qobject_cast<QWebFrame*>(f->loader()->networkingContext()->originatingObject());
m_webPage->javaScriptAlert(webFrame, x);
}
bool ChromeClientQt::runJavaScriptConfirm(Frame* f, const String& msg)
{
QString x = msg;
QWebFrame* webFrame = qobject_cast<QWebFrame*>(f->loader()->networkingContext()->originatingObject());
return m_webPage->javaScriptConfirm(webFrame, x);
}
bool ChromeClientQt::runJavaScriptPrompt(Frame* f, const String& message, const String& defaultValue, String& result)
{
QString x = result;
QWebFrame* webFrame = qobject_cast<QWebFrame*>(f->loader()->networkingContext()->originatingObject());
bool rc = m_webPage->javaScriptPrompt(webFrame, (QString)message, (QString)defaultValue, &x);
// Fix up a quirk in the QInputDialog class. If no input happened the string should be empty
// but it is null. See https://bugs.webkit.org/show_bug.cgi?id=30914.
if (rc && x.isNull())
result = String("");
else
result = x;
return rc;
}
void ChromeClientQt::setStatusbarText(const String& msg)
{
QString x = msg;
emit m_webPage->statusBarMessage(x);
}
bool ChromeClientQt::shouldInterruptJavaScript()
{
bool shouldInterrupt = false;
QMetaObject::invokeMethod(m_webPage, "shouldInterruptJavaScript", Qt::DirectConnection, Q_RETURN_ARG(bool, shouldInterrupt));
return shouldInterrupt;
}
KeyboardUIMode ChromeClientQt::keyboardUIMode()
{
return m_webPage->settings()->testAttribute(QWebSettings::LinksIncludedInFocusChain)
? KeyboardAccessTabsToLinks : KeyboardAccessDefault;
}
IntRect ChromeClientQt::windowResizerRect() const
{
#if defined(Q_WS_MAC)
if (!m_webPage)
return IntRect();
QWebPageClient* pageClient = platformPageClient();
if (!pageClient)
return IntRect();
QWidget* ownerWidget = pageClient->ownerWidget();
if (!ownerWidget)
return IntRect();
QWidget* topLevelWidget = ownerWidget->window();
QRect topLevelGeometry(topLevelWidget->geometry());
// There's no API in Qt to query for the size of the resizer, so we assume
// it has the same width and height as the scrollbar thickness.
int scollbarThickness = ScrollbarTheme::theme()->scrollbarThickness();
// There's no API in Qt to query for the position of the resizer. Sometimes
// it's drawn by the system, and sometimes it's a QSizeGrip. For RTL locales
// it might even be on the lower left side of the window, but in WebKit we
// always draw scrollbars on the right hand side, so we assume this to be the
// location when computing the resize rect to reserve for WebKit.
QPoint resizeCornerTopLeft = ownerWidget->mapFrom(topLevelWidget,
QPoint(topLevelGeometry.width(), topLevelGeometry.height())
- QPoint(scollbarThickness, scollbarThickness));
QRect resizeCornerRect = QRect(resizeCornerTopLeft, QSize(scollbarThickness, scollbarThickness));
return resizeCornerRect.intersected(pageClient->geometryRelativeToOwnerWidget());
#else
return IntRect();
#endif
}
void ChromeClientQt::invalidateRootView(const IntRect& windowRect, bool)
{
#if USE(TILED_BACKING_STORE)
if (platformPageClient()) {
WebCore::TiledBackingStore* backingStore = QWebFramePrivate::core(m_webPage->mainFrame())->tiledBackingStore();
if (!backingStore)
return;
backingStore->invalidate(windowRect);
}
#else
Q_UNUSED(windowRect);
#endif
}
void ChromeClientQt::invalidateContentsAndRootView(const IntRect& windowRect, bool immediate)
{
// No double buffer, so only update the QWidget if content changed.
if (platformPageClient()) {
QRect rect(windowRect);
rect = rect.intersected(QRect(QPoint(0, 0), m_webPage->viewportSize()));
if (!rect.isEmpty())
platformPageClient()->update(rect);
}
QMetaObject::invokeMethod(m_webPage, "repaintRequested", Qt::QueuedConnection, Q_ARG(QRect, windowRect));
// FIXME: There is no "immediate" support for window painting. This should be done always whenever the flag
// is set.
}
void ChromeClientQt::invalidateContentsForSlowScroll(const IntRect& windowRect, bool immediate)
{
invalidateContentsAndRootView(windowRect, immediate);
}
void ChromeClientQt::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect&)
{
if (platformPageClient())
platformPageClient()->scroll(delta.width(), delta.height(), scrollViewRect);
emit m_webPage->scrollRequested(delta.width(), delta.height(), scrollViewRect);
}
#if USE(TILED_BACKING_STORE)
void ChromeClientQt::delegatedScrollRequested(const IntPoint& point)
{
QPoint currentPosition(m_webPage->mainFrame()->scrollPosition());
emit m_webPage->scrollRequested(point.x() - currentPosition.x(), point.y() - currentPosition.y(), QRect(QPoint(0, 0), m_webPage->viewportSize()));
}
#endif
IntRect ChromeClientQt::rootViewToScreen(const IntRect& rect) const
{
QWebPageClient* pageClient = platformPageClient();
if (!pageClient)
return rect;
QWidget* ownerWidget = pageClient->ownerWidget();
if (!ownerWidget)
return rect;
QRect screenRect(rect);
screenRect.translate(ownerWidget->mapToGlobal(QPoint(0, 0)));
return screenRect;
}
IntPoint ChromeClientQt::screenToRootView(const IntPoint& point) const
{
QWebPageClient* pageClient = platformPageClient();
if (!pageClient)
return point;
QWidget* ownerWidget = pageClient->ownerWidget();
if (!ownerWidget)
return point;
return ownerWidget->mapFromGlobal(point);
}
PlatformPageClient ChromeClientQt::platformPageClient() const
{
return m_webPage->d->client.get();
}
void ChromeClientQt::contentsSizeChanged(Frame* frame, const IntSize& size) const
{
if (frame->loader()->networkingContext())
QWebFramePrivate::kit(frame)->contentsSizeChanged(size);
}
void ChromeClientQt::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
{
TextDirection dir;
if (result.absoluteLinkURL() != lastHoverURL
|| result.title(dir) != lastHoverTitle
|| result.textContent() != lastHoverContent) {
lastHoverURL = result.absoluteLinkURL();
lastHoverTitle = result.title(dir);
lastHoverContent = result.textContent();
emit m_webPage->linkHovered(lastHoverURL.string(),
lastHoverTitle, lastHoverContent);
}
}
void ChromeClientQt::setToolTip(const String &tip, TextDirection)
{
#ifndef QT_NO_TOOLTIP
QWidget* view = m_webPage->view();
if (!view)
return;
if (tip.isEmpty()) {
view->setToolTip(QString());
QToolTip::hideText();
} else {
QString dtip = QLatin1String("<p>") + QString(tip).toHtmlEscaped() + QLatin1String("</p>");
view->setToolTip(dtip);
}
#else
Q_UNUSED(tip);
#endif
}
void ChromeClientQt::print(Frame* frame)
{
emit m_webPage->printRequested(QWebFramePrivate::kit(frame));
}
#if ENABLE(SQL_DATABASE)
void ChromeClientQt::exceededDatabaseQuota(Frame* frame, const String& databaseName)
{
quint64 quota = QWebSettings::offlineStorageDefaultQuota();
if (!DatabaseTracker::tracker().hasEntryForOrigin(frame->document()->securityOrigin()))
DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), quota);
emit m_webPage->databaseQuotaExceeded(QWebFramePrivate::kit(frame), databaseName);
}
#endif
void ChromeClientQt::reachedMaxAppCacheSize(int64_t)
{
// FIXME: Free some space.
notImplemented();
}
void ChromeClientQt::reachedApplicationCacheOriginQuota(SecurityOrigin* origin, int64_t totalSpaceNeeded)
{
int64_t quota;
quint64 defaultOriginQuota = WebCore::cacheStorage().defaultOriginQuota();
QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(origin);
QWebSecurityOrigin* securityOrigin = new QWebSecurityOrigin(priv);
if (!WebCore::cacheStorage().calculateQuotaForOrigin(origin, quota))
WebCore::cacheStorage().storeUpdatedQuotaForOrigin(origin, defaultOriginQuota);
emit m_webPage->applicationCacheQuotaExceeded(securityOrigin, defaultOriginQuota, static_cast<quint64>(totalSpaceNeeded));
}
#if ENABLE(INPUT_TYPE_COLOR)
PassOwnPtr<ColorChooser> ChromeClientQt::createColorChooser(ColorChooserClient* client, const Color& color)
{
const QColor selectedColor = m_webPage->d->colorSelectionRequested(QColor(color));
client->didChooseColor(selectedColor);
client->didEndChooser();
return nullptr;
}
#endif
void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser)
{
RefPtr<FileChooser> fileChooser = prpFileChooser;
bool supportMulti = m_webPage->supportsExtension(QWebPage::ChooseMultipleFilesExtension);
if (fileChooser->settings().allowsMultipleFiles && supportMulti) {
QWebPage::ChooseMultipleFilesExtensionOption option;
option.parentFrame = QWebFramePrivate::kit(frame);
if (!fileChooser->settings().selectedFiles.isEmpty())
for (unsigned i = 0; i < fileChooser->settings().selectedFiles.size(); ++i)
option.suggestedFileNames += fileChooser->settings().selectedFiles[i];
QWebPage::ChooseMultipleFilesExtensionReturn output;
m_webPage->extension(QWebPage::ChooseMultipleFilesExtension, &option, &output);
if (!output.fileNames.isEmpty()) {
Vector<String> names;
for (int i = 0; i < output.fileNames.count(); ++i)
names.append(output.fileNames.at(i));
fileChooser->chooseFiles(names);
}
} else {
QString suggestedFile;
if (!fileChooser->settings().selectedFiles.isEmpty())
suggestedFile = fileChooser->settings().selectedFiles[0];
QString file = m_webPage->chooseFile(QWebFramePrivate::kit(frame), suggestedFile);
if (!file.isEmpty())
fileChooser->chooseFile(file);
}
}
void ChromeClientQt::loadIconForFiles(const Vector<String>& filenames, FileIconLoader* loader)
{
loader->notifyFinished(Icon::createIconForFiles(filenames));
}
void ChromeClientQt::setCursor(const Cursor& cursor)
{
#ifndef QT_NO_CURSOR
QWebPageClient* pageClient = platformPageClient();
if (!pageClient)
return;
pageClient->setCursor(*cursor.platformCursor());
#else
UNUSED_PARAM(cursor);
#endif
}
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
void ChromeClientQt::scheduleAnimation()
{
if (!m_refreshAnimation)
m_refreshAnimation = adoptPtr(new RefreshAnimation(this));
m_refreshAnimation->scheduleAnimation();
}
void ChromeClientQt::serviceScriptedAnimations()
{
m_webPage->mainFrame()->d->frame->view()->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(currentTime()));
}
#endif
#if USE(ACCELERATED_COMPOSITING)
void ChromeClientQt::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
{
if (platformPageClient())
platformPageClient()->setRootGraphicsLayer(graphicsLayer);
}
void ChromeClientQt::setNeedsOneShotDrawingSynchronization()
{
// we want the layers to synchronize next time we update the screen anyway
if (platformPageClient())
platformPageClient()->markForSync(false);
}
void ChromeClientQt::scheduleCompositingLayerFlush()
{
// we want the layers to synchronize ASAP
if (platformPageClient())
platformPageClient()->markForSync(true);
}
ChromeClient::CompositingTriggerFlags ChromeClientQt::allowedCompositingTriggers() const
{
if (platformPageClient() && platformPageClient()->allowsAcceleratedCompositing())
return ThreeDTransformTrigger | VideoTrigger | CanvasTrigger | AnimationTrigger;
return 0;
}
#endif
#if USE(TILED_BACKING_STORE)
IntRect ChromeClientQt::visibleRectForTiledBackingStore() const
{
if (!platformPageClient() || !m_webPage)
return IntRect();
if (!platformPageClient()->viewResizesToContentsEnabled())
return QRect(m_webPage->mainFrame()->scrollPosition(), m_webPage->mainFrame()->geometry().size());
return enclosingIntRect(FloatRect(platformPageClient()->graphicsItemVisibleRect()));
}
#endif
#if ENABLE(VIDEO) && ((USE(GSTREAMER) && !defined(GST_API_VERSION_1)) || USE(QT_MULTIMEDIA) || USE(QTKIT))
FullScreenVideoQt* ChromeClientQt::fullScreenVideo()
{
if (!m_fullScreenVideo)
m_fullScreenVideo = new FullScreenVideoQt(this);
return m_fullScreenVideo;
}
bool ChromeClientQt::supportsFullscreenForNode(const Node* node)
{
ASSERT(node);
return node->hasTagName(HTMLNames::videoTag) && fullScreenVideo()->isValid();
}
bool ChromeClientQt::requiresFullscreenForVideoPlayback()
{
return fullScreenVideo()->requiresFullScreenForVideoPlayback();
}
void ChromeClientQt::enterFullscreenForNode(Node* node)
{
ASSERT(node && node->hasTagName(HTMLNames::videoTag));
fullScreenVideo()->enterFullScreenForNode(node);
}
void ChromeClientQt::exitFullscreenForNode(Node* node)
{
ASSERT(node && node->hasTagName(HTMLNames::videoTag));
fullScreenVideo()->exitFullScreenForNode(node);
}
#endif
PassOwnPtr<QWebSelectMethod> ChromeClientQt::createSelectPopup() const
{
OwnPtr<QWebSelectMethod> result = m_platformPlugin.createSelectInputMethod();
if (result)
return result.release();
#if !defined(QT_NO_COMBOBOX)
return adoptPtr(new QtFallbackWebPopup(this));
#else
return nullptr;
#endif
}
void ChromeClientQt::dispatchViewportPropertiesDidChange(const ViewportArguments&) const
{
emit m_webPage->viewportChangeRequested();
}
bool ChromeClientQt::selectItemWritingDirectionIsNatural()
{
return false;
}
bool ChromeClientQt::selectItemAlignmentFollowsMenuWritingDirection()
{
return false;
}
bool ChromeClientQt::hasOpenedPopup() const
{
notImplemented();
return false;
}
PassRefPtr<PopupMenu> ChromeClientQt::createPopupMenu(PopupMenuClient* client) const
{
return adoptRef(new PopupMenuQt(client, this));
}
PassRefPtr<SearchPopupMenu> ChromeClientQt::createSearchPopupMenu(PopupMenuClient* client) const
{
return adoptRef(new SearchPopupMenuQt(createPopupMenu(client)));
}
void ChromeClientQt::populateVisitedLinks()
{
// We don't need to do anything here because history is tied to QWebPage rather than stored
// in a separate database
if (dumpVisitedLinksCallbacks) {
printf("Asked to populate visited links for WebView \"%s\"\n",
qPrintable(m_webPage->mainFrame()->url().toString()));
}
}
} // namespace WebCore