diff options
Diffstat (limited to 'WebKit/qt/WebCoreSupport')
44 files changed, 6839 insertions, 716 deletions
diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp index 893a1b7..3fec1d3 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp @@ -1,6 +1,7 @@ /* * 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. * @@ -29,38 +30,54 @@ #include "config.h" #include "ChromeClientQt.h" +#include "DatabaseTracker.h" #include "FileChooser.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 "GeolocationPermissionClientQt.h" #include "HitTestResult.h" +#include "Icon.h" +#include "NavigationAction.h" +#include "NetworkingContext.h" #include "NotImplemented.h" -#include "WindowFeatures.h" -#include "DatabaseTracker.h" +#include "NotificationPresenterClientQt.h" +#include "PageClientQt.h" +#include "PopupMenuQt.h" +#if defined(Q_WS_MAEMO_5) +#include "QtMaemoWebPopup.h" +#else #include "QtFallbackWebPopup.h" +#endif #include "QWebPageClient.h" +#include "ScrollbarTheme.h" +#include "SearchPopupMenuQt.h" #include "SecurityOrigin.h" +#include "ViewportArguments.h" +#include "WindowFeatures.h" -#include <qdebug.h> -#include <qeventloop.h> -#include <qtextdocument.h> -#include <qtooltip.h> - +#include "qgraphicswebview.h" +#include "qwebframe_p.h" #include "qwebpage.h" #include "qwebpage_p.h" -#include "qwebframe_p.h" #include "qwebsecurityorigin.h" #include "qwebsecurityorigin_p.h" #include "qwebview.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "GraphicsLayerQt.h" -#endif +#include <qdebug.h> +#include <qeventloop.h> +#include <qtextdocument.h> +#include <qtooltip.h> namespace WebCore { +bool ChromeClientQt::dumpVisitedLinksCallbacks = false; + ChromeClientQt::ChromeClientQt(QWebPage* webPage) : m_webPage(webPage) , m_eventLoop(0) @@ -82,24 +99,23 @@ void ChromeClientQt::setWindowRect(const FloatRect& rect) 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 (!m_webPage) + if (!platformPageClient()) return FloatRect(); - - QWidget* view = m_webPage->view(); - if (!view) - return FloatRect(); - return IntRect(view->topLevelWidget()->geometry()); + return platformPageClient()->windowRect(); } - FloatRect ChromeClientQt::pageRect() { if (!m_webPage) return FloatRect(); - return FloatRect(QRectF(QPointF(0,0), m_webPage->viewportSize())); + return FloatRect(QRectF(QPointF(0, 0), m_webPage->viewportSize())); } @@ -149,17 +165,26 @@ void ChromeClientQt::takeFocus(FocusDirection) } -void ChromeClientQt::focusedNodeChanged(WebCore::Node*) +void ChromeClientQt::focusedNodeChanged(Node*) { } +void ChromeClientQt::focusedFrameChanged(Frame*) +{ +} -Page* ChromeClientQt::createWindow(Frame*, const FrameLoadRequest& request, const WindowFeatures& features) +Page* ChromeClientQt::createWindow(Frame*, const FrameLoadRequest& request, const WindowFeatures& features, const NavigationAction&) { - QWebPage *newPage = m_webPage->createWindow(features.dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow); + QWebPage* newPage = m_webPage->createWindow(features.dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow); if (!newPage) return 0; - newPage->mainFrame()->load(request.resourceRequest().url()); + + // A call to QWebPage::mainFrame() implicitly creates the main frame. + // Make sure it exists, as WebCore expects it when returning from this call. + QWebFrame* mainFrame = newPage->mainFrame(); + + if (!request.isEmpty()) + mainFrame->load(request.resourceRequest().url()); return newPage->d->page; } @@ -170,7 +195,7 @@ void ChromeClientQt::show() QWidget* view = m_webPage->view(); if (!view) return; - view->topLevelWidget()->show(); + view->window()->show(); } @@ -212,7 +237,6 @@ void ChromeClientQt::setStatusbarVisible(bool visible) bool ChromeClientQt::statusbarVisible() { return statusBarVisible; - return false; } @@ -277,22 +301,22 @@ void ChromeClientQt::closeWindowSoon() void ChromeClientQt::runJavaScriptAlert(Frame* f, const String& msg) { QString x = msg; - FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client()); - m_webPage->javaScriptAlert(fl->webFrame(), x); + 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; - FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client()); - return m_webPage->javaScriptConfirm(fl->webFrame(), x); + 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; - FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client()); - bool rc = m_webPage->javaScriptPrompt(fl->webFrame(), (QString)message, (QString)defaultValue, &x); + 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. @@ -324,26 +348,66 @@ bool ChromeClientQt::tabsToLinks() const 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::nativeTheme()->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::invalidateWindow(const IntRect&, bool) +{ + notImplemented(); } -void ChromeClientQt::repaint(const IntRect& windowRect, bool contentChanged, bool, bool) +void ChromeClientQt::invalidateContentsAndWindow(const IntRect& windowRect, bool immediate) { // No double buffer, so only update the QWidget if content changed. - if (contentChanged) { - if (platformPageClient()) { - QRect rect(windowRect); - rect = rect.intersected(QRect(QPoint(0, 0), m_webPage->viewportSize())); - if (!rect.isEmpty()) - platformPageClient()->update(rect); - } - emit m_webPage->repaintRequested(windowRect); + if (platformPageClient()) { + QRect rect(windowRect); + rect = rect.intersected(QRect(QPoint(0, 0), m_webPage->viewportSize())); + if (!rect.isEmpty()) + platformPageClient()->update(rect); } + emit m_webPage->repaintRequested(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) +{ + invalidateContentsAndWindow(windowRect, immediate); +} + void ChromeClientQt::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect&) { if (platformPageClient()) @@ -351,16 +415,40 @@ void ChromeClientQt::scroll(const IntSize& delta, const IntRect& scrollViewRect, emit m_webPage->scrollRequested(delta.width(), delta.height(), scrollViewRect); } +#if ENABLE(TILED_BACKING_STORE) +void ChromeClientQt::delegatedScrollRequested(const IntSize& delta) +{ + emit m_webPage->scrollRequested(delta.width(), delta.height(), QRect(QPoint(0, 0), m_webPage->viewportSize())); +} +#endif + IntRect ChromeClientQt::windowToScreen(const IntRect& rect) const { - notImplemented(); - return rect; + 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::screenToWindow(const IntPoint& point) const { - notImplemented(); - return point; + QWebPageClient* pageClient = platformPageClient(); + if (!pageClient) + return point; + + QWidget* ownerWidget = pageClient->ownerWidget(); + if (!ownerWidget) + return point; + + return ownerWidget->mapFromGlobal(point); } PlatformPageClient ChromeClientQt::platformPageClient() const @@ -370,7 +458,8 @@ PlatformPageClient ChromeClientQt::platformPageClient() const void ChromeClientQt::contentsSizeChanged(Frame* frame, const IntSize& size) const { - emit QWebFramePrivate::kit(frame)->contentsSizeChanged(size); + if (frame->loader()->networkingContext()) + QWebFramePrivate::kit(frame)->contentsSizeChanged(size); } void ChromeClientQt::mouseDidMoveOverElement(const HitTestResult& result, unsigned) @@ -406,7 +495,7 @@ void ChromeClientQt::setToolTip(const String &tip, TextDirection) #endif } -void ChromeClientQt::print(Frame *frame) +void ChromeClientQt::print(Frame* frame) { emit m_webPage->printRequested(QWebFramePrivate::kit(frame)); } @@ -429,6 +518,18 @@ void ChromeClientQt::reachedMaxAppCacheSize(int64_t) // FIXME: Free some space. notImplemented(); } + +void ChromeClientQt::reachedApplicationCacheOriginQuota(SecurityOrigin*) +{ + notImplemented(); +} +#endif + +#if ENABLE(NOTIFICATIONS) +NotificationPresenter* ChromeClientQt::notificationPresenter() const +{ + return NotificationPresenterClientQt::notificationPresenter(); +} #endif void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser) @@ -463,23 +564,44 @@ void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileC } } -bool ChromeClientQt::setCursor(PlatformCursorHandle) +void ChromeClientQt::chooseIconForFiles(const Vector<String>& filenames, FileChooser* chooser) { - notImplemented(); - return false; + chooser->iconLoaded(Icon::createIconForFiles(filenames)); } -void ChromeClientQt::requestGeolocationPermissionForFrame(Frame*, Geolocation*) +void ChromeClientQt::setCursor(const Cursor& cursor) { - // See the comment in WebCore/page/ChromeClient.h - notImplemented(); +#ifndef QT_NO_CURSOR + QWebPageClient* pageClient = platformPageClient(); + if (!pageClient) + return; + pageClient->setCursor(*cursor.platformCursor()); +#else + UNUSED_PARAM(cursor); +#endif +} + +void ChromeClientQt::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation) +{ +#if ENABLE(GEOLOCATION) + QWebFrame* webFrame = QWebFramePrivate::kit(frame); + GeolocationPermissionClientQt::geolocationPermissionClient()->requestGeolocationPermissionForFrame(webFrame, geolocation); +#endif +} + +void ChromeClientQt::cancelGeolocationPermissionRequestForFrame(Frame* frame, Geolocation* geolocation) +{ +#if ENABLE(GEOLOCATION) + QWebFrame* webFrame = QWebFramePrivate::kit(frame); + GeolocationPermissionClientQt::geolocationPermissionClient()->cancelGeolocationPermissionRequestForFrame(webFrame, geolocation); +#endif } #if USE(ACCELERATED_COMPOSITING) void ChromeClientQt::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer) -{ +{ if (platformPageClient()) - platformPageClient()->setRootGraphicsLayer(graphicsLayer ? graphicsLayer->nativeLayer() : 0); + platformPageClient()->setRootGraphicsLayer(graphicsLayer ? graphicsLayer->platformLayer() : 0); } void ChromeClientQt::setNeedsOneShotDrawingSynchronization() @@ -495,11 +617,70 @@ void ChromeClientQt::scheduleCompositingLayerSync() if (platformPageClient()) platformPageClient()->markForSync(true); } + +bool ChromeClientQt::allowsAcceleratedCompositing() const +{ + return (platformPageClient() && platformPageClient()->allowsAcceleratedCompositing()); +} + +#endif + +#if ENABLE(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 -QtAbstractWebPopup* ChromeClientQt::createSelectPopup() +QWebSelectMethod* ChromeClientQt::createSelectPopup() const { - return new QtFallbackWebPopup; + QWebSelectMethod* result = m_platformPlugin.createSelectInputMethod(); + if (result) + return result; + +#if defined(Q_WS_MAEMO_5) + return new QtMaemoWebPopup; +#elif !defined(QT_NO_COMBOBOX) + return new QtFallbackWebPopup(this); +#else + return 0; +#endif } +void ChromeClientQt::dispatchViewportDataDidChange(const ViewportArguments&) const +{ + emit m_webPage->viewportChangeRequested(); } + +bool ChromeClientQt::selectItemWritingDirectionIsNatural() +{ + 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 diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.h b/WebKit/qt/WebCoreSupport/ChromeClientQt.h index 6b3017d..b8bc72d 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.h +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * All rights reserved. * @@ -33,8 +34,12 @@ #include "RefCounted.h" #include "KURL.h" #include "PlatformString.h" +#include "QtPlatformPlugin.h" +QT_BEGIN_NAMESPACE class QEventLoop; +QT_END_NAMESPACE + class QWebPage; namespace WebCore { @@ -44,6 +49,7 @@ namespace WebCore { class Page; struct FrameLoadRequest; class QtAbstractWebPopup; + struct ViewportArguments; class ChromeClientQt : public ChromeClient { @@ -66,8 +72,9 @@ namespace WebCore { virtual void takeFocus(FocusDirection); virtual void focusedNodeChanged(Node*); + virtual void focusedFrameChanged(Frame*); - virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&); + virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&, const NavigationAction&); virtual void show(); virtual bool canRunModal(); @@ -105,8 +112,14 @@ namespace WebCore { virtual bool tabsToLinks() const; virtual IntRect windowResizerRect() const; - virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false); + virtual void invalidateWindow(const IntRect&, bool); + virtual void invalidateContentsAndWindow(const IntRect&, bool); + virtual void invalidateContentsForSlowScroll(const IntRect&, bool); virtual void scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); +#if ENABLE(TILED_BACKING_STORE) + virtual void delegatedScrollRequested(const IntSize& scrollDelta); +#endif + virtual IntPoint screenToWindow(const IntPoint&) const; virtual IntRect windowToScreen(const IntRect&) const; virtual PlatformPageClient platformPageClient() const; @@ -123,6 +136,14 @@ namespace WebCore { #endif #if ENABLE(OFFLINE_WEB_APPLICATIONS) virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); + virtual void reachedApplicationCacheOriginQuota(SecurityOrigin*); +#endif +#if ENABLE(CONTEXT_MENUS) + virtual void showContextMenu() { } +#endif + +#if ENABLE(NOTIFICATIONS) + virtual NotificationPresenter* notificationPresenter() const; #endif #if USE(ACCELERATED_COMPOSITING) @@ -131,6 +152,11 @@ namespace WebCore { virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*); virtual void setNeedsOneShotDrawingSynchronization(); virtual void scheduleCompositingLayerSync(); + virtual bool allowsAcceleratedCompositing() const; +#endif + +#if ENABLE(TILED_BACKING_STORE) + virtual IntRect visibleRectForTiledBackingStore() const; #endif #if ENABLE(TOUCH_EVENTS) @@ -138,28 +164,41 @@ namespace WebCore { #endif virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); + virtual void chooseIconForFiles(const Vector<String>&, FileChooser*); virtual void formStateDidChange(const Node*) { } virtual PassOwnPtr<HTMLParserQuirks> createHTMLParserQuirks() { return 0; } - virtual bool setCursor(PlatformCursorHandle); + virtual void setCursor(const Cursor&); virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const {} virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*); + virtual void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*); + + virtual bool selectItemWritingDirectionIsNatural(); + virtual PassRefPtr<PopupMenu> createPopupMenu(PopupMenuClient*) const; + virtual PassRefPtr<SearchPopupMenu> createSearchPopupMenu(PopupMenuClient*) const; + virtual void populateVisitedLinks(); - QtAbstractWebPopup* createSelectPopup(); + QWebSelectMethod* createSelectPopup() const; + + virtual void dispatchViewportDataDidChange(const ViewportArguments&) const; QWebPage* m_webPage; WebCore::KURL lastHoverURL; - WebCore::String lastHoverTitle; - WebCore::String lastHoverContent; + WTF::String lastHoverTitle; + WTF::String lastHoverContent; bool toolBarsVisible; bool statusBarVisible; bool menuBarVisible; QEventLoop* m_eventLoop; + + static bool dumpVisitedLinksCallbacks; + + mutable QtPlatformPlugin m_platformPlugin; }; } diff --git a/WebKit/qt/WebCoreSupport/ContextMenuClientQt.h b/WebKit/qt/WebCoreSupport/ContextMenuClientQt.h index 8440ff5..1b4475f 100644 --- a/WebKit/qt/WebCoreSupport/ContextMenuClientQt.h +++ b/WebKit/qt/WebCoreSupport/ContextMenuClientQt.h @@ -31,23 +31,22 @@ #include <RefCounted.h> namespace WebCore { - class ContextMenu; - - class ContextMenuClientQt : public ContextMenuClient - { - public: - virtual void contextMenuDestroyed(); - - virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*); - virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*); - - virtual void downloadURL(const KURL& url); - virtual void lookUpInDictionary(Frame*); - virtual void speak(const String&); - virtual bool isSpeaking(); - virtual void stopSpeaking(); - virtual void searchWithGoogle(const Frame*); - }; +class ContextMenu; + +class ContextMenuClientQt : public ContextMenuClient { +public: + virtual void contextMenuDestroyed(); + + virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*); + virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*); + + virtual void downloadURL(const KURL& url); + virtual void lookUpInDictionary(Frame*); + virtual void speak(const String&); + virtual bool isSpeaking(); + virtual void stopSpeaking(); + virtual void searchWithGoogle(const Frame*); +}; } #endif diff --git a/WebKit/qt/WebCoreSupport/DeviceMotionClientQt.cpp b/WebKit/qt/WebCoreSupport/DeviceMotionClientQt.cpp new file mode 100644 index 0000000..4761514 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceMotionClientQt.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "DeviceMotionClientQt.h" + +#include "DeviceMotionController.h" +#include "DeviceMotionProviderQt.h" + +#include "qwebpage.h" + +namespace WebCore { + +DeviceMotionClientQt::DeviceMotionClientQt(QWebPage* page) + : m_page(page) + , m_controller(0) + , m_provider(new DeviceMotionProviderQt()) +{ + + connect(m_provider, SIGNAL(deviceMotionChanged()), SLOT(changeDeviceMotion())); +} + +DeviceMotionClientQt::~DeviceMotionClientQt() +{ + disconnect(); + delete m_provider; +} + +void DeviceMotionClientQt::setController(DeviceMotionController* controller) +{ + m_controller = controller; +} + +void DeviceMotionClientQt::startUpdating() +{ + m_provider->start(); +} + +void DeviceMotionClientQt::stopUpdating() +{ + m_provider->stop(); +} + +DeviceMotionData* DeviceMotionClientQt::currentDeviceMotion() const +{ + return m_provider->currentDeviceMotion(); +} + +void DeviceMotionClientQt::deviceMotionControllerDestroyed() +{ + delete this; +} + +void DeviceMotionClientQt::changeDeviceMotion() +{ + if (!m_controller) + return; + + m_controller->didChangeDeviceMotion(currentDeviceMotion()); +} + +} // namespace WebCore + +#include "moc_DeviceMotionClientQt.cpp" diff --git a/WebKit/qt/WebCoreSupport/DeviceMotionClientQt.h b/WebKit/qt/WebCoreSupport/DeviceMotionClientQt.h new file mode 100644 index 0000000..ea843e2 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceMotionClientQt.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef DeviceMotionClientQt_h +#define DeviceMotionClientQt_h + +#include "DeviceMotionClient.h" +#include "DeviceMotionData.h" + +#include <QObject> + +class QWebPage; + +namespace WebCore { + +class DeviceMotionProviderQt; + +class DeviceMotionClientQt : public QObject, public DeviceMotionClient { + Q_OBJECT +public: + DeviceMotionClientQt(QWebPage*); + virtual ~DeviceMotionClientQt(); + + virtual void setController(DeviceMotionController*); + virtual void startUpdating(); + virtual void stopUpdating(); + virtual DeviceMotionData* currentDeviceMotion() const; + virtual void deviceMotionControllerDestroyed(); + +public Q_SLOTS: + void changeDeviceMotion(); + +private: + QWebPage* m_page; + DeviceMotionController* m_controller; + DeviceMotionProviderQt* m_provider; +}; + +} // namespece WebCore + +#endif // DeviceMotionClientQt_h diff --git a/WebKit/qt/WebCoreSupport/DeviceMotionProviderQt.cpp b/WebKit/qt/WebCoreSupport/DeviceMotionProviderQt.cpp new file mode 100644 index 0000000..ccf7697 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceMotionProviderQt.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "DeviceMotionProviderQt.h" + +#include "DeviceOrientationProviderQt.h" + +namespace WebCore { + +DeviceMotionProviderQt::DeviceMotionProviderQt() +{ + m_acceleration.addFilter(this); + m_motion = DeviceMotionData::create(); + m_deviceOrientation = new DeviceOrientationProviderQt(); +} + +DeviceMotionProviderQt::~DeviceMotionProviderQt() +{ + delete m_deviceOrientation; +} + +void DeviceMotionProviderQt::start() +{ + m_acceleration.start(); + m_deviceOrientation->start(); +} + +void DeviceMotionProviderQt::stop() +{ + m_acceleration.stop(); + m_deviceOrientation->stop(); +} + +bool DeviceMotionProviderQt::filter(QAccelerometerReading* reading) +{ + RefPtr<DeviceMotionData::Acceleration> accel = DeviceMotionData::Acceleration::create( + /* x available */ true, reading->x(), + /* y available */ true, reading->y(), + /* z available */ true, reading->z()); + + RefPtr<DeviceMotionData::RotationRate> rotation = DeviceMotionData::RotationRate::create( + m_deviceOrientation->hasAlpha(), m_deviceOrientation->orientation()->alpha(), + /* beta available */ true, m_deviceOrientation->orientation()->beta(), + /* gamma available */ true, m_deviceOrientation->orientation()->gamma()); + + m_motion = DeviceMotionData::create(accel, + accel, /* FIXME: Needs to provide acceleration include gravity. */ + rotation, + false, 0 /* The interval is treated internally by Qt mobility */); + + emit deviceMotionChanged(); + + return false; +} + +} // namespace WebCore + +#include "moc_DeviceMotionProviderQt.cpp" diff --git a/WebKit/qt/WebCoreSupport/DeviceMotionProviderQt.h b/WebKit/qt/WebCoreSupport/DeviceMotionProviderQt.h new file mode 100644 index 0000000..f3200d5 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceMotionProviderQt.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef DeviceMotionProviderQt_h +#define DeviceMotionProviderQt_h + +#include "DeviceMotionData.h" +#include "RefPtr.h" + +#include <QAccelerometerFilter> +#include <QObject> + +QTM_USE_NAMESPACE + +namespace WebCore { + +class DeviceOrientationProviderQt; + +class DeviceMotionProviderQt : public QObject, public QAccelerometerFilter { + Q_OBJECT +public: + DeviceMotionProviderQt(); + ~DeviceMotionProviderQt(); + + bool filter(QAccelerometerReading*); + void start(); + void stop(); + DeviceMotionData* currentDeviceMotion() const { return m_motion.get(); } + +Q_SIGNALS: + void deviceMotionChanged(); + +private: + RefPtr<DeviceMotionData> m_motion; + QAccelerometer m_acceleration; + DeviceOrientationProviderQt* m_deviceOrientation; +}; + +} // namespace WebCore + +#endif // DeviceMotionProviderQt_h diff --git a/WebKit/qt/WebCoreSupport/DeviceOrientationClientQt.cpp b/WebKit/qt/WebCoreSupport/DeviceOrientationClientQt.cpp new file mode 100644 index 0000000..1d0c6d1 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceOrientationClientQt.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "DeviceOrientationClientQt.h" + +#include "DeviceOrientationController.h" +#include "DeviceOrientationProviderQt.h" +#include "qwebpage.h" + +namespace WebCore { + +DeviceOrientationClientQt::DeviceOrientationClientQt(QWebPage* page) + : m_page(page) + , m_controller(0) + , m_provider(new DeviceOrientationProviderQt()) +{ + connect(m_provider, SIGNAL(deviceOrientationChanged(DeviceOrientation*)), SLOT(changeDeviceOrientation(DeviceOrientation*))); +} + +DeviceOrientationClientQt::~DeviceOrientationClientQt() +{ + disconnect(); + delete m_provider; +} + +void DeviceOrientationClientQt::setController(DeviceOrientationController* controller) +{ + m_controller = controller; +} + +void DeviceOrientationClientQt::startUpdating() +{ + m_provider->start(); +} + +void DeviceOrientationClientQt::stopUpdating() +{ + m_provider->stop(); +} + +DeviceOrientation* DeviceOrientationClientQt::lastOrientation() const +{ + return m_provider->orientation(); +} + +void DeviceOrientationClientQt::deviceOrientationControllerDestroyed() +{ + delete this; +} + +void DeviceOrientationClientQt::changeDeviceOrientation(DeviceOrientation* orientation) +{ + if (!m_controller) + return; + + m_controller->didChangeDeviceOrientation(orientation); +} + +} // namespace WebCore + +#include "moc_DeviceOrientationClientQt.cpp" diff --git a/WebKit/qt/WebCoreSupport/DeviceOrientationClientQt.h b/WebKit/qt/WebCoreSupport/DeviceOrientationClientQt.h new file mode 100644 index 0000000..61968c4 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceOrientationClientQt.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef DeviceOrientationClientQt_h +#define DeviceOrientationClientQt_h + +#include "DeviceOrientation.h" +#include "DeviceOrientationClient.h" + +#include <QObject> + +class QWebPage; + +namespace WebCore { + +class DeviceOrientationProviderQt; + +class DeviceOrientationClientQt : public QObject, public DeviceOrientationClient { + Q_OBJECT +public: + DeviceOrientationClientQt(QWebPage*); + virtual ~DeviceOrientationClientQt(); + + virtual void setController(DeviceOrientationController*); + virtual void startUpdating(); + virtual void stopUpdating(); + virtual DeviceOrientation* lastOrientation() const; + virtual void deviceOrientationControllerDestroyed(); + +public Q_SLOTS: + void changeDeviceOrientation(DeviceOrientation*); + +private: + QWebPage* m_page; + DeviceOrientationController* m_controller; + DeviceOrientationProviderQt* m_provider; +}; + +} // namespace WebCore + +#endif // DeviceOrientationClientQt_h diff --git a/WebKit/qt/WebCoreSupport/DeviceOrientationProviderQt.cpp b/WebKit/qt/WebCoreSupport/DeviceOrientationProviderQt.cpp new file mode 100644 index 0000000..051eba0 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceOrientationProviderQt.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "DeviceOrientationProviderQt.h" + +namespace WebCore { + +DeviceOrientationProviderQt::DeviceOrientationProviderQt() +{ + m_rotation.addFilter(this); + m_orientation = DeviceOrientation::create(); +} + +DeviceOrientationProviderQt::~DeviceOrientationProviderQt() +{ +} + +void DeviceOrientationProviderQt::start() +{ + m_rotation.start(); +} + +void DeviceOrientationProviderQt::stop() +{ + m_rotation.stop(); +} + +bool DeviceOrientationProviderQt::filter(QRotationReading* reading) +{ + // Provide device orientation data according W3C spec: + // http://dev.w3.org/geo/api/spec-source-orientation.html + // Qt mobility provide these data via QRotationSensor using the + // QRotationReading class: + // - the rotation around z axis (alpha) is given as z in QRotationReading; + // - the rotation around x axis (beta) is given as x in QRotationReading; + // - the rotation around y axis (gamma) is given as y in QRotationReading; + // See: http://doc.qt.nokia.com/qtmobility-1.0/qrotationreading.html + // The Z (alpha) rotation angle is checked via hasAlpha() private method, + // depending if the device is able do detect the alpha rotation. X (beta) and + // Y (gamma) axis are availble in this context. + m_orientation = DeviceOrientation::create(hasAlpha(), reading->z(), + /* x available */ true, reading->x(), + /* y available */ true, reading->y()); + emit deviceOrientationChanged(m_orientation.get()); + + return false; +} + +} + +#include "moc_DeviceOrientationProviderQt.cpp" diff --git a/WebKit/qt/WebCoreSupport/DeviceOrientationProviderQt.h b/WebKit/qt/WebCoreSupport/DeviceOrientationProviderQt.h new file mode 100644 index 0000000..86c224e --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DeviceOrientationProviderQt.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef DeviceOrientationProviderQt_h +#define DeviceOrientationProviderQt_h + +#include "DeviceOrientation.h" +#include "RefPtr.h" + +#include <QObject> +#include <QRotationFilter> + +QTM_USE_NAMESPACE + +namespace WebCore { + +class DeviceOrientationClientQt; + +class DeviceOrientationProviderQt : public QObject, public QRotationFilter { + Q_OBJECT +public: + DeviceOrientationProviderQt(); + ~DeviceOrientationProviderQt(); + + bool filter(QRotationReading*); + void start(); + void stop(); + bool isActive() const { return m_rotation.isActive(); } + DeviceOrientation* orientation() const { return m_orientation.get(); } + bool hasAlpha() const { return m_rotation.property("hasZ").toBool(); } + +Q_SIGNALS: + void deviceOrientationChanged(DeviceOrientation*); + +private: + RefPtr<DeviceOrientation> m_orientation; + QRotationSensor m_rotation; +}; + +} + +#endif // DeviceOrientationProviderQt_h diff --git a/WebKit/qt/WebCoreSupport/DragClientQt.cpp b/WebKit/qt/WebCoreSupport/DragClientQt.cpp index e48c3e3..52229dc 100644 --- a/WebKit/qt/WebCoreSupport/DragClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/DragClientQt.cpp @@ -93,7 +93,7 @@ void DragClientQt::startDrag(DragImageRef, const IntPoint&, const IntPoint&, Cli static_cast<ClipboardQt*>(clipboard)->invalidateWritableData(); QWidget* view = m_webPage->view(); if (view) { - QDrag *drag = new QDrag(view); + QDrag* drag = new QDrag(view); if (clipboardData && clipboardData->hasImage()) drag->setPixmap(qvariant_cast<QPixmap>(clipboardData->imageData())); DragOperation dragOperationMask = clipboard->sourceOperation(); diff --git a/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp new file mode 100644 index 0000000..f5fa06b --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp @@ -0,0 +1,905 @@ +/* + Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> + Copyright (C) 2008,2009,2010 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + Copyright (C) 2007 Apple Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "DumpRenderTreeSupportQt.h" + +#include "CSSComputedStyleDeclaration.h" +#include "ChromeClientQt.h" +#include "ContextMenu.h" +#include "ContextMenuClientQt.h" +#include "ContextMenuController.h" +#include "Editor.h" +#include "EditorClientQt.h" +#include "Element.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoaderClientQt.h" +#include "FrameView.h" +#if USE(JSC) +#include "GCController.h" +#elif USE(V8) +#include "V8GCController.h" +#include "V8Proxy.h" +#endif +#include "Geolocation.h" +#include "GeolocationServiceMock.h" +#include "Geoposition.h" +#include "HistoryItem.h" +#include "HTMLInputElement.h" +#include "InspectorController.h" +#include "NodeList.h" +#include "NotificationPresenterClientQt.h" +#include "Page.h" +#include "PageGroup.h" +#include "PluginDatabase.h" +#include "PositionError.h" +#include "PrintContext.h" +#include "RenderListItem.h" +#include "RenderTreeAsText.h" +#include "ScriptController.h" +#include "SecurityOrigin.h" +#include "Settings.h" +#if ENABLE(SVG) +#include "SVGSMILElement.h" +#endif +#include "TextIterator.h" +#include "WorkerThread.h" +#include <wtf/CurrentTime.h> + +#include "qwebelement.h" +#include "qwebframe.h" +#include "qwebframe_p.h" +#include "qwebhistory.h" +#include "qwebhistory_p.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include "qwebscriptworld.h" + +using namespace WebCore; + +QMap<int, QWebScriptWorld*> m_worldMap; + +DumpRenderTreeSupportQt::DumpRenderTreeSupportQt() +{ +} + +DumpRenderTreeSupportQt::~DumpRenderTreeSupportQt() +{ +} + +void DumpRenderTreeSupportQt::overwritePluginDirectories() +{ + PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false); + + Vector<String> paths; + String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data()); + qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths); + + db->setPluginDirectories(paths); + db->refresh(); +} + +int DumpRenderTreeSupportQt::workerThreadCount() +{ +#if ENABLE(WORKERS) + return WebCore::WorkerThread::workerThreadCount(); +#else + return 0; +#endif +} + +void DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(bool b) +{ + QWebPagePrivate::drtRun = b; +} + +void DumpRenderTreeSupportQt::setFrameFlatteningEnabled(QWebPage* page, bool enabled) +{ + QWebPagePrivate::core(page)->settings()->setFrameFlatteningEnabled(enabled); +} + +void DumpRenderTreeSupportQt::webPageSetGroupName(QWebPage* page, const QString& groupName) +{ + page->handle()->page->setGroupName(groupName); +} + +QString DumpRenderTreeSupportQt::webPageGroupName(QWebPage* page) +{ + return page->handle()->page->groupName(); +} + +void DumpRenderTreeSupportQt::webInspectorExecuteScript(QWebPage* page, long callId, const QString& script) +{ +#if ENABLE(INSPECTOR) + if (!page->handle()->page->inspectorController()) + return; + page->handle()->page->inspectorController()->evaluateForTestInFrontend(callId, script); +#endif +} + +void DumpRenderTreeSupportQt::webInspectorClose(QWebPage* page) +{ +#if ENABLE(INSPECTOR) + if (!page->handle()->page->inspectorController()) + return; + page->handle()->page->inspectorController()->close(); +#endif +} + +void DumpRenderTreeSupportQt::webInspectorShow(QWebPage* page) +{ +#if ENABLE(INSPECTOR) + if (!page->handle()->page->inspectorController()) + return; + page->handle()->page->inspectorController()->show(); +#endif +} + +void DumpRenderTreeSupportQt::setTimelineProfilingEnabled(QWebPage* page, bool enabled) +{ +#if ENABLE(INSPECTOR) + InspectorController* controller = page->handle()->page->inspectorController(); + if (!controller) + return; + if (enabled) + controller->startTimelineProfiler(); + else + controller->stopTimelineProfiler(); +#endif +} + +bool DumpRenderTreeSupportQt::hasDocumentElement(QWebFrame* frame) +{ + return QWebFramePrivate::core(frame)->document()->documentElement(); +} + +void DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + Frame* coreFrame = QWebFramePrivate::core(frame); + InspectorController* controller = coreFrame->page()->inspectorController(); + if (!controller) + return; + if (enabled) + controller->enableProfiler(); + else + controller->disableProfiler(); +#endif +} + +// Pause a given CSS animation or transition on the target node at a specific time. +// If the animation or transition is already paused, it will update its pause time. +// This method is only intended to be used for testing the CSS animation and transition system. +bool DumpRenderTreeSupportQt::pauseAnimation(QWebFrame *frame, const QString &animationName, double time, const QString &elementId) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return false; + + AnimationController* controller = coreFrame->animation(); + if (!controller) + return false; + + Document* doc = coreFrame->document(); + Q_ASSERT(doc); + + Node* coreNode = doc->getElementById(elementId); + if (!coreNode || !coreNode->renderer()) + return false; + + return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time); +} + +bool DumpRenderTreeSupportQt::pauseTransitionOfProperty(QWebFrame *frame, const QString &propertyName, double time, const QString &elementId) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return false; + + AnimationController* controller = coreFrame->animation(); + if (!controller) + return false; + + Document* doc = coreFrame->document(); + Q_ASSERT(doc); + + Node* coreNode = doc->getElementById(elementId); + if (!coreNode || !coreNode->renderer()) + return false; + + return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time); +} + +// Pause a given SVG animation on the target node at a specific time. +// This method is only intended to be used for testing the SVG animation system. +bool DumpRenderTreeSupportQt::pauseSVGAnimation(QWebFrame *frame, const QString &animationId, double time, const QString &elementId) +{ +#if !ENABLE(SVG) + return false; +#else + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return false; + + Document* doc = coreFrame->document(); + Q_ASSERT(doc); + + if (!doc->svgExtensions()) + return false; + + Node* coreNode = doc->getElementById(animationId); + if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) + return false; + + return doc->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time); +#endif +} + +// Returns the total number of currently running animations (includes both CSS transitions and CSS animations). +int DumpRenderTreeSupportQt::numberOfActiveAnimations(QWebFrame *frame) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return false; + + AnimationController* controller = coreFrame->animation(); + if (!controller) + return false; + + return controller->numberOfActiveAnimations(); +} + +void DumpRenderTreeSupportQt::suspendAnimations(QWebFrame *frame) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return; + + AnimationController* controller = coreFrame->animation(); + if (!controller) + return; + + controller->suspendAnimations(); +} + +void DumpRenderTreeSupportQt::resumeAnimations(QWebFrame *frame) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return; + + AnimationController* controller = coreFrame->animation(); + if (!controller) + return; + + controller->resumeAnimations(); +} + +void DumpRenderTreeSupportQt::clearFrameName(QWebFrame* frame) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + coreFrame->tree()->clearName(); +} + +int DumpRenderTreeSupportQt::javaScriptObjectsCount() +{ +#if USE(JSC) + return JSDOMWindowBase::commonJSGlobalData()->heap.globalObjectCount(); +#elif USE(V8) + // FIXME: Find a way to do this using V8. + return 1; +#endif +} + +void DumpRenderTreeSupportQt::garbageCollectorCollect() +{ +#if USE(JSC) + gcController().garbageCollectNow(); +#elif USE(V8) + v8::V8::LowMemoryNotification(); +#endif +} + +void DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(bool waitUntilDone) +{ +#if USE(JSC) + gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); +#elif USE(V8) + // FIXME: Find a way to do this using V8. + garbageCollectorCollect(); +#endif +} + +// Returns the value of counter in the element specified by \a id. +QString DumpRenderTreeSupportQt::counterValueForElementById(QWebFrame* frame, const QString& id) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (Document* document = coreFrame->document()) { + if (Element* element = document->getElementById(id)) + return WebCore::counterValueForElement(element); + } + return QString(); +} + +int DumpRenderTreeSupportQt::pageNumberForElementById(QWebFrame* frame, const QString& id, float width, float height) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return -1; + + Element* element = coreFrame->document()->getElementById(AtomicString(id)); + if (!element) + return -1; + + return PrintContext::pageNumberForElement(element, FloatSize(width, height)); +} + +int DumpRenderTreeSupportQt::numberOfPages(QWebFrame* frame, float width, float height) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return -1; + + return PrintContext::numberOfPages(coreFrame, FloatSize(width, height)); +} + +// Suspend active DOM objects in this frame. +void DumpRenderTreeSupportQt::suspendActiveDOMObjects(QWebFrame* frame) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (coreFrame->document()) + // FIXME: This function should be changed take a ReasonForSuspension parameter + // https://bugs.webkit.org/show_bug.cgi?id=45732 + coreFrame->document()->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); +} + +// Resume active DOM objects in this frame. +void DumpRenderTreeSupportQt::resumeActiveDOMObjects(QWebFrame* frame) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (coreFrame->document()) + coreFrame->document()->resumeActiveDOMObjects(); +} + +void DumpRenderTreeSupportQt::whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) +{ + SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); +} + +void DumpRenderTreeSupportQt::removeWhiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) +{ + SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); +} + +void DumpRenderTreeSupportQt::resetOriginAccessWhiteLists() +{ + SecurityOrigin::resetOriginAccessWhitelists(); +} + +void DumpRenderTreeSupportQt::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme) +{ + SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); +} + +void DumpRenderTreeSupportQt::setCaretBrowsingEnabled(QWebPage* page, bool value) +{ + page->handle()->page->settings()->setCaretBrowsingEnabled(value); +} + +void DumpRenderTreeSupportQt::setMediaType(QWebFrame* frame, const QString& type) +{ + WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); + WebCore::FrameView* view = coreFrame->view(); + view->setMediaType(type); + coreFrame->document()->styleSelectorChanged(RecalcStyleImmediately); + view->layout(); +} + +void DumpRenderTreeSupportQt::setSmartInsertDeleteEnabled(QWebPage* page, bool enabled) +{ + page->d->smartInsertDeleteEnabled = enabled; +} + + +void DumpRenderTreeSupportQt::setSelectTrailingWhitespaceEnabled(QWebPage* page, bool enabled) +{ + page->d->selectTrailingWhitespaceEnabled = enabled; +} + + +void DumpRenderTreeSupportQt::executeCoreCommandByName(QWebPage* page, const QString& name, const QString& value) +{ + page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value); +} + +bool DumpRenderTreeSupportQt::isCommandEnabled(QWebPage* page, const QString& name) +{ + return page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled(); +} + +QString DumpRenderTreeSupportQt::markerTextForListItem(const QWebElement& listItem) +{ + return WebCore::markerTextForListItem(listItem.m_element); +} + +static QString convertToPropertyName(const QString& name) +{ + QStringList parts = name.split('-'); + QString camelCaseName; + for (int j = 0; j < parts.count(); ++j) { + QString part = parts.at(j); + if (j) + camelCaseName.append(part.replace(0, 1, part.left(1).toUpper())); + else + camelCaseName.append(part); + } + return camelCaseName; +} + +QVariantMap DumpRenderTreeSupportQt::computedStyleIncludingVisitedInfo(const QWebElement& element) +{ + QVariantMap res; + + WebCore::Element* webElement = element.m_element; + if (!webElement) + return res; + + RefPtr<WebCore::CSSComputedStyleDeclaration> style = computedStyle(webElement, true); + for (int i = 0; i < style->length(); i++) { + QString name = style->item(i); + QString value = (static_cast<WebCore::CSSStyleDeclaration*>(style.get()))->getPropertyValue(name); + res[convertToPropertyName(name)] = QVariant(value); + } + return res; +} + +QVariantList DumpRenderTreeSupportQt::selectedRange(QWebPage* page) +{ + WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); + QVariantList selectedRange; + RefPtr<Range> range = frame->selection()->toNormalizedRange().get(); + + Element* selectionRoot = frame->selection()->rootEditableElement(); + Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); + + RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); + ASSERT(testRange->startContainer() == scope); + int startPosition = TextIterator::rangeLength(testRange.get()); + + ExceptionCode ec; + testRange->setEnd(range->endContainer(), range->endOffset(), ec); + ASSERT(testRange->startContainer() == scope); + int endPosition = TextIterator::rangeLength(testRange.get()); + + selectedRange << startPosition << (endPosition - startPosition); + + return selectedRange; + +} + +QVariantList DumpRenderTreeSupportQt::firstRectForCharacterRange(QWebPage* page, int location, int length) +{ + WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); + QVariantList rect; + + if ((location + length < location) && (location + length)) + length = 0; + + Element* selectionRoot = frame->selection()->rootEditableElement(); + Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); + RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(scope, location, length); + + if (!range) + return QVariantList(); + + QRect resultRect = frame->editor()->firstRectForRange(range.get()); + rect << resultRect.x() << resultRect.y() << resultRect.width() << resultRect.height(); + return rect; +} + +bool DumpRenderTreeSupportQt::elementDoesAutoCompleteForElementWithId(QWebFrame* frame, const QString& elementId) +{ + Frame* coreFrame = QWebFramePrivate::core(frame); + if (!coreFrame) + return false; + + Document* doc = coreFrame->document(); + Q_ASSERT(doc); + + Node* coreNode = doc->getElementById(elementId); + if (!coreNode || !coreNode->renderer()) + return false; + + HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(coreNode); + if (!inputElement) + return false; + + return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->autoComplete(); +} + +void DumpRenderTreeSupportQt::setEditingBehavior(QWebPage* page, const QString& editingBehavior) +{ + WebCore::EditingBehaviorType coreEditingBehavior; + + if (editingBehavior == "win") + coreEditingBehavior = EditingWindowsBehavior; + else if (editingBehavior == "mac") + coreEditingBehavior = EditingMacBehavior; + else if (editingBehavior == "unix") + coreEditingBehavior = EditingUnixBehavior; + else { + ASSERT_NOT_REACHED(); + return; + } + + Page* corePage = QWebPagePrivate::core(page); + if (!corePage) + return; + + corePage->settings()->setEditingBehaviorType(coreEditingBehavior); +} + +void DumpRenderTreeSupportQt::dumpFrameLoader(bool b) +{ + FrameLoaderClientQt::dumpFrameLoaderCallbacks = b; +} + +void DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(bool b) +{ + FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = b; +} + +void DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(bool b) +{ + FrameLoaderClientQt::dumpResourceLoadCallbacks = b; +} + +void DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(const QString& path) +{ + FrameLoaderClientQt::dumpResourceLoadCallbacksPath = path; +} + +void DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(bool b) +{ + FrameLoaderClientQt::dumpResourceResponseMIMETypes = b; +} + +void DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(bool b) +{ + FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = b; +} + +void DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(bool b) +{ + FrameLoaderClientQt::sendRequestReturnsNull = b; +} + +void DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(const QStringList& headers) +{ + FrameLoaderClientQt::sendRequestClearHeaders = headers; +} + +void DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(bool b) +{ + FrameLoaderClientQt::deferMainResourceDataLoad = b; +} + +void DumpRenderTreeSupportQt::setCustomPolicyDelegate(bool enabled, bool permissive) +{ + FrameLoaderClientQt::policyDelegateEnabled = enabled; + FrameLoaderClientQt::policyDelegatePermissive = permissive; +} + +void DumpRenderTreeSupportQt::dumpHistoryCallbacks(bool b) +{ + FrameLoaderClientQt::dumpHistoryCallbacks = b; +} + +void DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(bool b) +{ + ChromeClientQt::dumpVisitedLinksCallbacks = b; +} + +void DumpRenderTreeSupportQt::dumpEditingCallbacks(bool b) +{ + EditorClientQt::dumpEditingCallbacks = b; +} + +void DumpRenderTreeSupportQt::dumpSetAcceptsEditing(bool b) +{ + EditorClientQt::acceptsEditing = b; +} + +void DumpRenderTreeSupportQt::dumpNotification(bool b) +{ +#if ENABLE(NOTIFICATIONS) + NotificationPresenterClientQt::dumpNotification = b; +#endif +} + +QString DumpRenderTreeSupportQt::viewportAsText(QWebPage* page, const QSize& availableSize) +{ + WebCore::ViewportArguments args = page->d->viewportArguments(); + WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(args, + /* desktop-width */ 980, + /* device-width */ 320, + /* device-height */ 480, + /* device-dpi */ 160, + availableSize); + + QString res; + res = res.sprintf("viewport size %dx%d scale %f with limits [%f, %f]\n", + conf.layoutSize.width(), + conf.layoutSize.height(), + conf.initialScale, + conf.minimumScale, + conf.maximumScale); + + return res; +} + +void DumpRenderTreeSupportQt::setMockGeolocationPosition(double latitude, double longitude, double accuracy) +{ +#if ENABLE(GEOLOCATION) + RefPtr<Geoposition> geoposition = Geoposition::create(Coordinates::create(latitude, longitude, false, 0, accuracy, true, 0, false, 0, false, 0), currentTime() * 1000.0); + GeolocationServiceMock::setPosition(geoposition); +#endif +} + +void DumpRenderTreeSupportQt::setMockGeolocationError(int errorCode, const QString& message) +{ +#if ENABLE(GEOLOCATION) + RefPtr<PositionError> positionError = PositionError::create(static_cast<PositionError::ErrorCode>(errorCode), message); + GeolocationServiceMock::setError(positionError); +#endif +} + +bool DumpRenderTreeSupportQt::isTargetItem(const QWebHistoryItem& historyItem) +{ + QWebHistoryItem it = historyItem; + if (QWebHistoryItemPrivate::core(&it)->isTargetItem()) + return true; + return false; +} + +QString DumpRenderTreeSupportQt::historyItemTarget(const QWebHistoryItem& historyItem) +{ + QWebHistoryItem it = historyItem; + return (QWebHistoryItemPrivate::core(&it)->target()); +} + +QMap<QString, QWebHistoryItem> DumpRenderTreeSupportQt::getChildHistoryItems(const QWebHistoryItem& historyItem) +{ + QWebHistoryItem it = historyItem; + HistoryItem* item = QWebHistoryItemPrivate::core(&it); + const WebCore::HistoryItemVector& children = item->children(); + + unsigned size = children.size(); + QMap<QString, QWebHistoryItem> kids; + for (unsigned i = 0; i < size; ++i) { + QWebHistoryItem kid(new QWebHistoryItemPrivate(children[i].get())); + kids.insert(DumpRenderTreeSupportQt::historyItemTarget(kid), kid); + } + return kids; +} + +bool DumpRenderTreeSupportQt::shouldClose(QWebFrame* frame) +{ + WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); + return coreFrame->loader()->shouldClose(); +} + +void DumpRenderTreeSupportQt::clearScriptWorlds() +{ + m_worldMap.clear(); +} + +void DumpRenderTreeSupportQt::evaluateScriptInIsolatedWorld(QWebFrame* frame, int worldID, const QString& script) +{ + QWebScriptWorld* scriptWorld; + if (!worldID) { + scriptWorld = new QWebScriptWorld(); + } else if (!m_worldMap.contains(worldID)) { + scriptWorld = new QWebScriptWorld(); + m_worldMap.insert(worldID, scriptWorld); + } else + scriptWorld = m_worldMap.value(worldID); + + WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); + + ScriptController* proxy = coreFrame->script(); + + if (!proxy) + return; +#if USE(JSC) + proxy->executeScriptInWorld(scriptWorld->world(), script, true); +#elif USE(V8) + ScriptSourceCode source(script); + Vector<ScriptSourceCode> sources; + sources.append(source); + proxy->evaluateInIsolatedWorld(0, sources, true); +#endif +} + +bool DumpRenderTreeSupportQt::isPageBoxVisible(QWebFrame* frame, int pageIndex) +{ + WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); + return coreFrame->document()->isPageBoxVisible(pageIndex); +} + +QString DumpRenderTreeSupportQt::pageSizeAndMarginsInPixels(QWebFrame* frame, int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) +{ + WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); + return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageIndex, width, height, + marginTop, marginRight, marginBottom, marginLeft); +} + +QString DumpRenderTreeSupportQt::pageProperty(QWebFrame* frame, const QString& propertyName, int pageNumber) +{ + WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); + return PrintContext::pageProperty(coreFrame, propertyName.toUtf8().constData(), pageNumber); +} + +void DumpRenderTreeSupportQt::addUserStyleSheet(QWebPage* page, const QString& sourceCode) +{ + page->handle()->page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, QUrl(), 0, 0, WebCore::InjectInAllFrames); +} + +void DumpRenderTreeSupportQt::simulateDesktopNotificationClick(const QString& title) +{ +#if ENABLE(NOTIFICATIONS) + NotificationPresenterClientQt::notificationPresenter()->notificationClicked(title); +#endif +} + +QString DumpRenderTreeSupportQt::plainText(const QVariant& range) +{ + QMap<QString, QVariant> map = range.toMap(); + QVariant startContainer = map.value("startContainer"); + map = startContainer.toMap(); + + return map.value("innerText").toString(); +} + +QVariantList DumpRenderTreeSupportQt::nodesFromRect(const QWebElement& document, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) +{ + QVariantList res; + WebCore::Element* webElement = document.m_element; + if (!webElement) + return res; + + Document* doc = webElement->document(); + if (!doc) + return res; + RefPtr<NodeList> nodes = doc->nodesFromRect(x, y, top, right, bottom, left, ignoreClipping); + for (int i = 0; i < nodes->length(); i++) { + QVariant v; + // QWebElement will be null if the Node is not an HTML Element + v.setValue(QWebElement(nodes->item(i))); + res << v; + } + return res; +} + +// Provide a backward compatibility with previously exported private symbols as of QtWebKit 4.6 release + +void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* frame) +{ + DumpRenderTreeSupportQt::resumeActiveDOMObjects(frame); +} + +void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* frame) +{ + DumpRenderTreeSupportQt::suspendActiveDOMObjects(frame); +} + +void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* frame) +{ + DumpRenderTreeSupportQt::clearFrameName(frame); +} + +void QWEBKIT_EXPORT qt_drt_garbageCollector_collect() +{ + DumpRenderTreeSupportQt::garbageCollectorCollect(); +} + +void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone) +{ + DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(waitUntilDone); +} + +int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount() +{ + return DumpRenderTreeSupportQt::javaScriptObjectsCount(); +} + +int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame* frame) +{ + return DumpRenderTreeSupportQt::numberOfActiveAnimations(frame); +} + +void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories() +{ + DumpRenderTreeSupportQt::overwritePluginDirectories(); +} + +bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame* frame, const QString& animationName, double time, const QString& elementId) +{ + return DumpRenderTreeSupportQt::pauseAnimation(frame, animationName, time, elementId); +} + +bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame* frame, const QString& propertyName, double time, const QString &elementId) +{ + return DumpRenderTreeSupportQt::pauseTransitionOfProperty(frame, propertyName, time, elementId); +} + +void QWEBKIT_EXPORT qt_drt_resetOriginAccessWhiteLists() +{ + DumpRenderTreeSupportQt::resetOriginAccessWhiteLists(); +} + +void QWEBKIT_EXPORT qt_drt_run(bool b) +{ + DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(b); +} + +void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) +{ + DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(frame, enabled); +} + +void QWEBKIT_EXPORT qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) +{ + DumpRenderTreeSupportQt::whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains); +} + +QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page) +{ + return DumpRenderTreeSupportQt::webPageGroupName(page); +} + +void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName) +{ + DumpRenderTreeSupportQt::webPageSetGroupName(page, groupName); +} + +void QWEBKIT_EXPORT qt_dump_frame_loader(bool b) +{ + DumpRenderTreeSupportQt::dumpFrameLoader(b); +} + +void QWEBKIT_EXPORT qt_dump_resource_load_callbacks(bool b) +{ + DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(b); +} + +void QWEBKIT_EXPORT qt_dump_editing_callbacks(bool b) +{ + DumpRenderTreeSupportQt::dumpEditingCallbacks(b); +} + +void QWEBKIT_EXPORT qt_dump_set_accepts_editing(bool b) +{ + DumpRenderTreeSupportQt::dumpSetAcceptsEditing(b); +} + diff --git a/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h new file mode 100644 index 0000000..82d9319 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h @@ -0,0 +1,140 @@ +/* + Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> + Copyright (C) 2008,2009,2010 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + Copyright (C) 2007 Apple Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef DumpRenderTreeSupportQt_h +#define DumpRenderTreeSupportQt_h + +#include "qwebkitglobal.h" +#include <QVariant> + +class QWebElement; +class QWebFrame; +class QWebPage; +class QWebHistoryItem; +class QWebScriptWorld; + +extern QMap<int, QWebScriptWorld*> m_worldMap; + +class QWEBKIT_EXPORT DumpRenderTreeSupportQt { + +public: + + DumpRenderTreeSupportQt(); + ~DumpRenderTreeSupportQt(); + + + static void executeCoreCommandByName(QWebPage* page, const QString& name, const QString& value); + static bool isCommandEnabled(QWebPage* page, const QString& name); + static void setSmartInsertDeleteEnabled(QWebPage* page, bool enabled); + static void setSelectTrailingWhitespaceEnabled(QWebPage* page, bool enabled); + static QVariantList selectedRange(QWebPage* page); + static QVariantList firstRectForCharacterRange(QWebPage* page, int location, int length); + + static bool pauseAnimation(QWebFrame*, const QString& name, double time, const QString& elementId); + static bool pauseTransitionOfProperty(QWebFrame*, const QString& name, double time, const QString& elementId); + static bool pauseSVGAnimation(QWebFrame*, const QString& animationId, double time, const QString& elementId); + static void suspendActiveDOMObjects(QWebFrame* frame); + static void resumeActiveDOMObjects(QWebFrame* frame); + + static void setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme); + static void setFrameFlatteningEnabled(QWebPage*, bool); + static void setCaretBrowsingEnabled(QWebPage* page, bool value); + static void setMediaType(QWebFrame* qframe, const QString& type); + static void setDumpRenderTreeModeEnabled(bool b); + + static void garbageCollectorCollect(); + static void garbageCollectorCollectOnAlternateThread(bool waitUntilDone); + static void setJavaScriptProfilingEnabled(QWebFrame*, bool enabled); + static int javaScriptObjectsCount(); + static void clearScriptWorlds(); + static void evaluateScriptInIsolatedWorld(QWebFrame* frame, int worldID, const QString& script); + + static void setTimelineProfilingEnabled(QWebPage*, bool enabled); + static void webInspectorExecuteScript(QWebPage* page, long callId, const QString& script); + static void webInspectorShow(QWebPage* page); + static void webInspectorClose(QWebPage* page); + + static QString webPageGroupName(QWebPage *page); + static QString counterValueForElementById(QWebFrame* frame, const QString& id); + static void webPageSetGroupName(QWebPage* page, const QString& groupName); + static void clearFrameName(QWebFrame* frame); + static void overwritePluginDirectories(); + static int numberOfActiveAnimations(QWebFrame*); + static void suspendAnimations(QWebFrame*); + static void resumeAnimations(QWebFrame*); + static int numberOfPages(QWebFrame* frame, float width, float height); + static int pageNumberForElementById(QWebFrame* frame, const QString& id, float width, float height); + static bool hasDocumentElement(QWebFrame* frame); + static bool elementDoesAutoCompleteForElementWithId(QWebFrame* frame, const QString& elementId); + static void setEditingBehavior(QWebPage* page, const QString& editingBehavior); + + static void whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains); + static void removeWhiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains); + static void resetOriginAccessWhiteLists(); + + static void setMockGeolocationPosition(double latitude, double longitude, double accuracy); + static void setMockGeolocationError(int errorCode, const QString& message); + + static int workerThreadCount(); + + static QString markerTextForListItem(const QWebElement& listItem); + static QVariantMap computedStyleIncludingVisitedInfo(const QWebElement& element); + static QString plainText(const QVariant& rng); + + static void dumpFrameLoader(bool b); + static void dumpUserGestureInFrameLoader(bool b); + static void dumpResourceLoadCallbacks(bool b); + static void dumpResourceResponseMIMETypes(bool b); + static void dumpResourceLoadCallbacksPath(const QString& path); + static void setWillSendRequestReturnsNullOnRedirect(bool b); + static void setWillSendRequestReturnsNull(bool b); + static void setWillSendRequestClearHeaders(const QStringList& headers); + static void dumpHistoryCallbacks(bool b); + static void dumpVisitedLinksCallbacks(bool b); + + static void setDeferMainResourceDataLoad(bool b); + + static void dumpEditingCallbacks(bool b); + static void dumpSetAcceptsEditing(bool b); + + static void dumpNotification(bool b); + + static QMap<QString, QWebHistoryItem> getChildHistoryItems(const QWebHistoryItem& historyItem); + static bool isTargetItem(const QWebHistoryItem& historyItem); + static QString historyItemTarget(const QWebHistoryItem& historyItem); + + static bool shouldClose(QWebFrame* frame); + + static void setCustomPolicyDelegate(bool enabled, bool permissive); + + static bool isPageBoxVisible(QWebFrame* frame, int pageIndex); + + static QString pageSizeAndMarginsInPixels(QWebFrame* frame, int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft); + static QString pageProperty(QWebFrame* frame, const QString& propertyName, int pageNumber); + static void addUserStyleSheet(QWebPage* page, const QString& sourceCode); + static void simulateDesktopNotificationClick(const QString& title); + static QString viewportAsText(QWebPage*, const QSize&); + + static QVariantList nodesFromRect(const QWebElement& document, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping); +}; + +#endif diff --git a/WebKit/qt/WebCoreSupport/EditCommandQt.cpp b/WebKit/qt/WebCoreSupport/EditCommandQt.cpp index a166840..9c4ff87 100644 --- a/WebKit/qt/WebCoreSupport/EditCommandQt.cpp +++ b/WebKit/qt/WebCoreSupport/EditCommandQt.cpp @@ -18,7 +18,6 @@ */ #include "config.h" -#include <wtf/Platform.h> #include "EditCommandQt.h" using namespace WebCore; @@ -28,30 +27,31 @@ EditCommandQt::EditCommandQt(WTF::RefPtr<EditCommand> cmd, QUndoCommand *parent) #ifndef QT_NO_UNDOCOMMAND QUndoCommand(parent), #endif - _cmd(cmd), _first(true) + m_cmd(cmd), m_first(true) { } -EditCommandQt::~EditCommandQt() { +EditCommandQt::~EditCommandQt() +{ } -void EditCommandQt::redo() { - if (_first) { - _first = false; +void EditCommandQt::redo() +{ + if (m_first) { + m_first = false; return; } - if (_cmd) { - _cmd->reapply(); - } + if (m_cmd) + m_cmd->reapply(); } -void EditCommandQt::undo() { - if (_cmd) { - _cmd->unapply(); - } +void EditCommandQt::undo() +{ + if (m_cmd) + m_cmd->unapply(); } diff --git a/WebKit/qt/WebCoreSupport/EditCommandQt.h b/WebKit/qt/WebCoreSupport/EditCommandQt.h index ae6ea51..e03b9b2 100644 --- a/WebKit/qt/WebCoreSupport/EditCommandQt.h +++ b/WebKit/qt/WebCoreSupport/EditCommandQt.h @@ -17,16 +17,12 @@ Boston, MA 02110-1301, USA. */ -#ifndef EDITCOMMANDQT_H -#define EDITCOMMANDQT_H +#ifndef EditCommandQt_h +#define EditCommandQt_h -#include <qglobal.h> -QT_BEGIN_NAMESPACE -class QUndoCommand; -QT_END_NAMESPACE - -#include <QUndoCommand> #include <EditCommand.h> +#include <QUndoCommand> +#include <qglobal.h> class EditCommandQt #ifndef QT_NO_UNDOCOMMAND @@ -41,8 +37,8 @@ class EditCommandQt void undo(); private: - WTF::RefPtr<WebCore::EditCommand> _cmd; - bool _first; + WTF::RefPtr<WebCore::EditCommand> m_cmd; + bool m_first; }; #endif diff --git a/WebKit/qt/WebCoreSupport/EditorClientQt.cpp b/WebKit/qt/WebCoreSupport/EditorClientQt.cpp index 90ebb1d..91a0cc6 100644 --- a/WebKit/qt/WebCoreSupport/EditorClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/EditorClientQt.cpp @@ -31,9 +31,6 @@ #include "config.h" #include "EditorClientQt.h" -#include "qwebpage.h" -#include "qwebpage_p.h" - #include "CSSStyleDeclaration.h" #include "Document.h" #include "EditCommandQt.h" @@ -43,33 +40,22 @@ #include "HTMLElement.h" #include "HTMLInputElement.h" #include "HTMLNames.h" -#include "KeyboardCodes.h" #include "KeyboardEvent.h" #include "NotImplemented.h" #include "Page.h" -#include "Page.h" #include "PlatformKeyboardEvent.h" #include "QWebPageClient.h" #include "Range.h" +#include "Settings.h" +#include "WindowsKeyboardCodes.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include <QUndoStack> #include <stdio.h> -#include <QUndoStack> #define methodDebug() qDebug("EditorClientQt: %s", __FUNCTION__); -static bool dumpEditingCallbacks = false; -static bool acceptsEditing = true; -void QWEBKIT_EXPORT qt_dump_editing_callbacks(bool b) -{ - dumpEditingCallbacks = b; -} - -void QWEBKIT_EXPORT qt_dump_set_accepts_editing(bool b) -{ - acceptsEditing = b; -} - - static QString dumpPath(WebCore::Node *node) { QString str = node->nodeName(); @@ -99,6 +85,9 @@ static QString dumpRange(WebCore::Range *range) namespace WebCore { +bool EditorClientQt::dumpEditingCallbacks = false; +bool EditorClientQt::acceptsEditing = true; + using namespace HTMLNames; bool EditorClientQt::shouldDeleteRange(Range* range) @@ -257,9 +246,8 @@ void EditorClientQt::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand { #ifndef QT_NO_UNDOSTACK Frame* frame = m_page->d->page->focusController()->focusedOrMainFrame(); - if (m_inUndoRedo || (frame && !frame->editor()->lastEditCommand() /* HACK!! Don't recreate undos */)) { + if (m_inUndoRedo || (frame && !frame->editor()->lastEditCommand() /* HACK!! Don't recreate undos */)) return; - } m_page->undoStack()->push(new EditCommandQt(cmd)); #endif // QT_NO_UNDOSTACK } @@ -333,14 +321,18 @@ void EditorClientQt::pageDestroyed() bool EditorClientQt::smartInsertDeleteEnabled() { - notImplemented(); - return false; + return m_page->d->smartInsertDeleteEnabled; +} + +void EditorClientQt::toggleSmartInsertDelete() +{ + bool current = m_page->d->smartInsertDeleteEnabled; + m_page->d->smartInsertDeleteEnabled = !current; } bool EditorClientQt::isSelectTrailingWhitespaceEnabled() { - notImplemented(); - return false; + return m_page->d->selectTrailingWhitespaceEnabled; } void EditorClientQt::toggleContinuousSpellChecking() @@ -369,9 +361,21 @@ void EditorClientQt::handleKeyboardEvent(KeyboardEvent* event) // FIXME: refactor all of this to use Actions or something like them if (start->isContentEditable()) { + bool doSpatialNavigation = false; + if (isSpatialNavigationEnabled(frame)) { + if (!kevent->modifiers()) { + switch (kevent->windowsVirtualKeyCode()) { + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + doSpatialNavigation = true; + } + } + } #ifndef QT_NO_SHORTCUT QWebPage::WebAction action = QWebPagePrivate::editorActionForKeyEvent(kevent->qtEvent()); - if (action != QWebPage::NoWebAction) { + if (action != QWebPage::NoWebAction && !doSpatialNavigation) { const char* cmd = QWebPagePrivate::editorCommandForWebActions(action); // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated, // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated @@ -384,131 +388,89 @@ void EditorClientQt::handleKeyboardEvent(KeyboardEvent* event) } else #endif // QT_NO_SHORTCUT switch (kevent->windowsVirtualKeyCode()) { -#if QT_VERSION < 0x040500 - case VK_RETURN: -#ifdef QT_WS_MAC - if (kevent->shiftKey() || kevent->metaKey()) -#else - if (kevent->shiftKey()) -#endif - frame->editor()->command("InsertLineBreak").execute(); - else - frame->editor()->command("InsertNewline").execute(); - break; -#endif - case VK_BACK: - frame->editor()->deleteWithDirection(SelectionController::BACKWARD, - CharacterGranularity, false, true); - break; - case VK_DELETE: - frame->editor()->deleteWithDirection(SelectionController::FORWARD, - CharacterGranularity, false, true); - break; - case VK_LEFT: - if (kevent->shiftKey()) - frame->editor()->command("MoveLeftAndModifySelection").execute(); - else - frame->editor()->command("MoveLeft").execute(); - break; - case VK_RIGHT: - if (kevent->shiftKey()) - frame->editor()->command("MoveRightAndModifySelection").execute(); - else - frame->editor()->command("MoveRight").execute(); - break; - case VK_UP: - if (kevent->shiftKey()) - frame->editor()->command("MoveUpAndModifySelection").execute(); - else - frame->editor()->command("MoveUp").execute(); - break; - case VK_DOWN: - if (kevent->shiftKey()) - frame->editor()->command("MoveDownAndModifySelection").execute(); - else - frame->editor()->command("MoveDown").execute(); - break; - case VK_PRIOR: // PageUp - if (kevent->shiftKey()) - frame->editor()->command("MovePageUpAndModifySelection").execute(); - else - frame->editor()->command("MovePageUp").execute(); - break; - case VK_NEXT: // PageDown - if (kevent->shiftKey()) - frame->editor()->command("MovePageDownAndModifySelection").execute(); - else - frame->editor()->command("MovePageDown").execute(); - break; - case VK_TAB: + case VK_BACK: + frame->editor()->deleteWithDirection(SelectionController::DirectionBackward, + CharacterGranularity, false, true); + break; + case VK_DELETE: + frame->editor()->deleteWithDirection(SelectionController::DirectionForward, + CharacterGranularity, false, true); + break; + case VK_LEFT: + if (kevent->shiftKey()) + frame->editor()->command("MoveLeftAndModifySelection").execute(); + else if (!frame->editor()->command("MoveLeft").execute()) return; - default: - if (kevent->type() != PlatformKeyboardEvent::KeyDown && !kevent->ctrlKey() + break; + case VK_RIGHT: + if (kevent->shiftKey()) + frame->editor()->command("MoveRightAndModifySelection").execute(); + else if (!frame->editor()->command("MoveRight").execute()) + return; + break; + case VK_UP: + if (kevent->shiftKey()) + frame->editor()->command("MoveUpAndModifySelection").execute(); + else if (!frame->editor()->command("MoveUp").execute()) + return; + break; + case VK_DOWN: + if (kevent->shiftKey()) + frame->editor()->command("MoveDownAndModifySelection").execute(); + else if (!frame->editor()->command("MoveDown").execute()) + return; + break; + case VK_PRIOR: // PageUp + if (kevent->shiftKey()) + frame->editor()->command("MovePageUpAndModifySelection").execute(); + else + frame->editor()->command("MovePageUp").execute(); + break; + case VK_NEXT: // PageDown + if (kevent->shiftKey()) + frame->editor()->command("MovePageDownAndModifySelection").execute(); + else + frame->editor()->command("MovePageDown").execute(); + break; + case VK_TAB: + return; + default: + if (kevent->type() != PlatformKeyboardEvent::KeyDown && !kevent->ctrlKey() #ifndef Q_WS_MAC - // We need to exclude checking for Alt because it is just a different Shift - && !kevent->altKey() + // We need to exclude checking for Alt because it is just a different Shift + && !kevent->altKey() #endif - && !kevent->text().isEmpty()) { - frame->editor()->insertText(kevent->text(), event); - } else if (kevent->ctrlKey()) { - switch (kevent->windowsVirtualKeyCode()) { - case VK_A: - frame->editor()->command("SelectAll").execute(); - break; - case VK_B: - frame->editor()->command("ToggleBold").execute(); - break; - case VK_I: - frame->editor()->command("ToggleItalic").execute(); - break; - default: - // catch combination AltGr+key or Ctrl+Alt+key - if (kevent->type() != PlatformKeyboardEvent::KeyDown && kevent->altKey() && !kevent->text().isEmpty()) { - frame->editor()->insertText(kevent->text(), event); - break; - } - return; + && !kevent->text().isEmpty()) { + frame->editor()->insertText(kevent->text(), event); + } else if (kevent->ctrlKey()) { + switch (kevent->windowsVirtualKeyCode()) { + case VK_A: + frame->editor()->command("SelectAll").execute(); + break; + case VK_B: + frame->editor()->command("ToggleBold").execute(); + break; + case VK_I: + frame->editor()->command("ToggleItalic").execute(); + break; + default: + // catch combination AltGr+key or Ctrl+Alt+key + if (kevent->type() != PlatformKeyboardEvent::KeyDown && kevent->altKey() && !kevent->text().isEmpty()) { + frame->editor()->insertText(kevent->text(), event); + break; } - } else return; + return; + } + } else + return; } } else { #ifndef QT_NO_SHORTCUT - if (kevent->qtEvent() == QKeySequence::Copy) { + if (kevent->qtEvent() == QKeySequence::Copy) m_page->triggerAction(QWebPage::Copy); - } else + else #endif // QT_NO_SHORTCUT - switch (kevent->windowsVirtualKeyCode()) { - case VK_UP: - frame->editor()->command("MoveUp").execute(); - break; - case VK_DOWN: - frame->editor()->command("MoveDown").execute(); - break; - case VK_PRIOR: // PageUp - frame->editor()->command("MovePageUp").execute(); - break; - case VK_NEXT: // PageDown - frame->editor()->command("MovePageDown").execute(); - break; - case VK_HOME: - if (kevent->ctrlKey()) - frame->editor()->command("MoveToBeginningOfDocument").execute(); - break; - case VK_END: - if (kevent->ctrlKey()) - frame->editor()->command("MoveToEndOfDocument").execute(); - break; - default: - if (kevent->ctrlKey()) { - switch (kevent->windowsVirtualKeyCode()) { - case VK_A: - frame->editor()->command("SelectAll").execute(); - break; - default: - return; - } - } else return; - } + return; } event->setDefaultHandled(); } @@ -606,31 +568,47 @@ bool EditorClientQt::isEditing() const return m_editing; } +void EditorClientQt::willSetInputMethodState() +{ +} + void EditorClientQt::setInputMethodState(bool active) { QWebPageClient* webPageClient = m_page->d->client; if (webPageClient) { -#if QT_VERSION >= 0x040600 - bool isPasswordField = false; - if (!active) { + Qt::InputMethodHints hints; + + HTMLInputElement* inputElement = 0; + Frame* frame = m_page->d->page->focusController()->focusedOrMainFrame(); + if (frame && frame->document() && frame->document()->focusedNode()) + if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) + inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode()); + + if (inputElement) { + // Set input method hints for "number", "tel", "email", "url" and "password" input elements. + if (inputElement->isTelephoneField()) + hints |= Qt::ImhDialableCharactersOnly; + if (inputElement->isNumberField()) + hints |= Qt::ImhDigitsOnly; + if (inputElement->isEmailField()) + hints |= Qt::ImhEmailCharactersOnly; + if (inputElement->isURLField()) + hints |= Qt::ImhUrlCharactersOnly; // Setting the Qt::WA_InputMethodEnabled attribute true and Qt::ImhHiddenText flag - // for password fields. The Qt platform is responsible for determining which widget + // for password fields. The Qt platform is responsible for determining which widget // will receive input method events for password fields. - Frame* frame = m_page->d->page->focusController()->focusedOrMainFrame(); - if (frame && frame->document() && frame->document()->focusedNode()) { - if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) { - HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode()); - active = isPasswordField = inputElement->isPasswordField(); - } + if (inputElement->isPasswordField()) { + active = true; + hints |= Qt::ImhHiddenText; } } - webPageClient->setInputMethodHint(Qt::ImhHiddenText, isPasswordField); -#ifdef Q_WS_MAEMO_5 - // Maemo 5 MicroB Browser disables auto-uppercase and predictive text, thus, so do we. - webPageClient->setInputMethodHint(Qt::ImhNoAutoUppercase, true); - webPageClient->setInputMethodHint(Qt::ImhNoPredictiveText, true); -#endif // Q_WS_MAEMO_5 -#endif // QT_VERSION check + +#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || defined(Q_OS_SYMBIAN) + // disables auto-uppercase and predictive text for mobile devices + hints |= Qt::ImhNoAutoUppercase; + hints |= Qt::ImhNoPredictiveText; +#endif // Q_WS_MAEMO_5 || Q_WS_MAEMO_6 || Q_OS_SYMBIAN + webPageClient->setInputMethodHints(hints); webPageClient->setInputMethodEnabled(active); } emit m_page->microFocusChanged(); diff --git a/WebKit/qt/WebCoreSupport/EditorClientQt.h b/WebKit/qt/WebCoreSupport/EditorClientQt.h index 42a402f..7d99d22 100644 --- a/WebKit/qt/WebCoreSupport/EditorClientQt.h +++ b/WebKit/qt/WebCoreSupport/EditorClientQt.h @@ -27,8 +27,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EditorClientQt_H -#define EditorClientQt_H +#ifndef EditorClientQt_h +#define EditorClientQt_h #include "EditorClient.h" #include "RefCounted.h" @@ -48,13 +48,13 @@ public: virtual bool shouldDeleteRange(Range*); virtual bool shouldShowDeleteInterface(HTMLElement*); virtual bool smartInsertDeleteEnabled(); + virtual void toggleSmartInsertDelete(); virtual bool isSelectTrailingWhitespaceEnabled(); virtual bool isContinuousSpellCheckingEnabled(); virtual void toggleContinuousSpellChecking(); virtual bool isGrammarCheckingEnabled(); virtual void toggleGrammarChecking(); virtual int spellCheckerDocumentTag(); - virtual bool selectWordBeforeMenuEvent(); virtual bool isEditable(); @@ -105,10 +105,14 @@ public: virtual void showSpellingUI(bool show); virtual bool spellingUIIsShowing(); virtual void getGuessesForWord(const String&, Vector<String>& guesses); + virtual void willSetInputMethodState(); virtual void setInputMethodState(bool enabled); bool isEditing() const; + static bool dumpEditingCallbacks; + static bool acceptsEditing; + private: QWebPage* m_page; bool m_editing; diff --git a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp index 16a6faa..1b57138 100644 --- a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008 Collabora Ltd. All rights reserved. * Coypright (C) 2008 Holger Hans Peter Freyther - * Coypright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> + * Coypright (C) 2009, 2010 Girish Ramakrishnan <girish@forwardbias.in> * * All rights reserved. * @@ -35,10 +35,18 @@ #include "CSSPropertyNames.h" #include "FormState.h" #include "FrameLoaderClientQt.h" +#include "FrameNetworkingContextQt.h" #include "FrameTree.h" #include "FrameView.h" #include "DocumentLoader.h" +#include "HitTestResult.h" +#if USE(JSC) +#include "JSDOMWindowBase.h" +#elif USE(V8) +#include "V8DOMWindow.h" +#endif #include "MIMETypeRegistry.h" +#include "MouseEvent.h" #include "ResourceResponse.h" #include "Page.h" #include "PluginData.h" @@ -50,14 +58,15 @@ #include "HTMLAppletElement.h" #include "HTMLFormElement.h" #include "HTMLPlugInElement.h" +#include "HTTPParsers.h" #include "NotImplemented.h" #include "QNetworkReplyHandler.h" #include "ResourceHandleInternal.h" #include "ResourceHandle.h" #include "ScriptController.h" -#include "ScriptString.h" #include "Settings.h" #include "QWebPageClient.h" +#include "ViewportArguments.h" #include "qwebpage.h" #include "qwebpage_p.h" @@ -74,23 +83,11 @@ #include <QGraphicsWidget> #include <QNetworkRequest> #include <QNetworkReply> +#include <QStringList> #include "qwebhistory_p.h" -static bool dumpFrameLoaderCallbacks = false; -static bool dumpResourceLoadCallbacks = false; - static QMap<unsigned long, QString> dumpAssignedUrls; -void QWEBKIT_EXPORT qt_dump_frame_loader(bool b) -{ - dumpFrameLoaderCallbacks = b; -} - -void QWEBKIT_EXPORT qt_dump_resource_load_callbacks(bool b) -{ - dumpResourceLoadCallbacks = b; -} - // Compare with WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm static QString drtDescriptionSuitableForTestResult(WebCore::Frame* _frame) { @@ -109,10 +106,19 @@ static QString drtDescriptionSuitableForTestResult(WebCore::Frame* _frame) } } +static QString drtPrintFrameUserGestureStatus(WebCore::Frame* frame) +{ + if (frame->loader()->isProcessingUserGesture()) + return QString::fromLatin1("Frame with user gesture \"%1\"").arg(QLatin1String("true")); + return QString::fromLatin1("Frame with user gesture \"%1\"").arg(QLatin1String("false")); +} + static QString drtDescriptionSuitableForTestResult(const WebCore::KURL& _url) { - QUrl url = _url; - return url.toString(); + if (_url.isEmpty() || !_url.isLocalFile()) + return _url.string(); + // Remove the leading path from file urls + return QString(_url.string()).replace(WebCore::FrameLoaderClientQt::dumpResourceLoadCallbacksPath, "").mid(1); } static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceError& error) @@ -123,30 +129,83 @@ static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceError& static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceRequest& request) { - QString url = request.url().string(); - return QString::fromLatin1("<NSURLRequest %1>").arg(url); + QString url = drtDescriptionSuitableForTestResult(request.url()); + QString httpMethod = request.httpMethod(); + QString mainDocumentUrl = drtDescriptionSuitableForTestResult(request.firstPartyForCookies()); + return QString::fromLatin1("<NSURLRequest URL %1, main document URL %2, http method %3>").arg(url).arg(mainDocumentUrl).arg(httpMethod); } static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceResponse& response) { - QString text = response.httpStatusText(); - if (text.isEmpty()) - return QLatin1String("(null)"); - - return text; + QString url = drtDescriptionSuitableForTestResult(response.url()); + int httpStatusCode = response.httpStatusCode(); + return QString::fromLatin1("<NSURLResponse %1, http status code %2>").arg(url).arg(httpStatusCode); } +static QString drtDescriptionSuitableForTestResult(const RefPtr<WebCore::Node> node, int exception) +{ + QString result; + if (exception) { + result.append("ERROR"); + return result; + } + if (!node) { + result.append("NULL"); + return result; + } + result.append(node->nodeName()); + RefPtr<WebCore::Node> parent = node->parentNode(); + if (parent) { + result.append(" > "); + result.append(drtDescriptionSuitableForTestResult(parent, 0)); + } + return result; +} namespace WebCore { +bool FrameLoaderClientQt::dumpFrameLoaderCallbacks = false; +bool FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = false; +bool FrameLoaderClientQt::dumpResourceLoadCallbacks = false; +bool FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = false; +bool FrameLoaderClientQt::sendRequestReturnsNull = false; +bool FrameLoaderClientQt::dumpResourceResponseMIMETypes = false; +bool FrameLoaderClientQt::deferMainResourceDataLoad = true; +bool FrameLoaderClientQt::dumpHistoryCallbacks = false; + +QStringList FrameLoaderClientQt::sendRequestClearHeaders; +QString FrameLoaderClientQt::dumpResourceLoadCallbacksPath; +bool FrameLoaderClientQt::policyDelegateEnabled = false; +bool FrameLoaderClientQt::policyDelegatePermissive = false; + +// Taken from DumpRenderTree/chromium/WebViewHost.cpp +static const char* navigationTypeToString(NavigationType type) +{ + switch (type) { + case NavigationTypeLinkClicked: + return "link clicked"; + case NavigationTypeFormSubmitted: + return "form submitted"; + case NavigationTypeBackForward: + return "back/forward"; + case NavigationTypeReload: + return "reload"; + case NavigationTypeFormResubmitted: + return "form resubmitted"; + case NavigationTypeOther: + return "other"; + } + return "illegal value"; +} + FrameLoaderClientQt::FrameLoaderClientQt() : m_frame(0) , m_webFrame(0) - , m_firstData(false) , m_pluginView(0) , m_hasSentResponseToPlugin(false) - , m_loadError (ResourceError()) + , m_hasRepresentation(false) + , m_loadError(ResourceError()) { } @@ -159,6 +218,7 @@ void FrameLoaderClientQt::setFrame(QWebFrame* webFrame, Frame* frame) { m_webFrame = webFrame; m_frame = frame; + if (!m_webFrame || !m_webFrame->page()) { qWarning("FrameLoaderClientQt::setFrame frame without Page!"); return; @@ -178,11 +238,6 @@ void FrameLoaderClientQt::setFrame(QWebFrame* webFrame, Frame* frame) m_webFrame, SIGNAL(titleChanged(QString))); } -QWebFrame* FrameLoaderClientQt::webFrame() const -{ - return m_webFrame; -} - void FrameLoaderClientQt::callPolicyFunction(FramePolicyFunction function, PolicyAction action) { (m_frame->loader()->policyChecker()->*function)(action); @@ -214,18 +269,26 @@ void FrameLoaderClientQt::transitionToCommittedForNewPage() QWebPage* page = m_webFrame->page(); const QSize preferredLayoutSize = page->preferredContentsSize(); + ScrollbarMode hScrollbar = (ScrollbarMode) m_webFrame->scrollBarPolicy(Qt::Horizontal); + ScrollbarMode vScrollbar = (ScrollbarMode) m_webFrame->scrollBarPolicy(Qt::Vertical); + bool hLock = hScrollbar != ScrollbarAuto; + bool vLock = vScrollbar != ScrollbarAuto; + m_frame->createView(m_webFrame->page()->viewportSize(), backgroundColor, !backgroundColor.alpha(), preferredLayoutSize.isValid() ? IntSize(preferredLayoutSize) : IntSize(), preferredLayoutSize.isValid(), - (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Horizontal), - (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Vertical)); + hScrollbar, hLock, + vScrollbar, vLock); } +void FrameLoaderClientQt::dispatchDidBecomeFrameset(bool) +{ +} void FrameLoaderClientQt::makeRepresentation(DocumentLoader*) { - // don't need this for now I think. + m_hasRepresentation = true; } @@ -233,7 +296,7 @@ void FrameLoaderClientQt::forceLayout() { FrameView* view = m_frame->view(); if (view) - view->forceLayout(true); + view->layout(true); } @@ -262,7 +325,6 @@ void FrameLoaderClientQt::dispatchDidHandleOnloadEvents() // don't need this one if (dumpFrameLoaderCallbacks) printf("%s - didHandleOnloadEventsForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); - } @@ -305,11 +367,23 @@ void FrameLoaderClientQt::dispatchDidChangeLocationWithinPage() m_webFrame->page()->d->updateNavigationActions(); } +#if USE(V8) +void FrameLoaderClientQt::didCreateScriptContextForFrame() +{ +} +void FrameLoaderClientQt::didDestroyScriptContextForFrame() +{ +} +void FrameLoaderClientQt::didCreateIsolatedScriptContext() +{ +} +#endif + void FrameLoaderClientQt::dispatchDidPushStateWithinPage() { if (dumpFrameLoaderCallbacks) printf("%s - dispatchDidPushStateWithinPage\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); - + notImplemented(); } @@ -317,7 +391,7 @@ void FrameLoaderClientQt::dispatchDidReplaceStateWithinPage() { if (dumpFrameLoaderCallbacks) printf("%s - dispatchDidReplaceStateWithinPage\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); - + notImplemented(); } @@ -325,7 +399,7 @@ void FrameLoaderClientQt::dispatchDidPopStateWithinPage() { if (dumpFrameLoaderCallbacks) printf("%s - dispatchDidPopStateWithinPage\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); - + notImplemented(); } @@ -339,6 +413,9 @@ void FrameLoaderClientQt::dispatchDidStartProvisionalLoad() if (dumpFrameLoaderCallbacks) printf("%s - didStartProvisionalLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); + if (dumpUserGestureInFrameLoaderCallbacks) + printf("%s - in didStartProvisionalLoadForFrame\n", qPrintable(drtPrintFrameUserGestureStatus(m_frame))); + if (m_webFrame) emit m_webFrame->provisionalLoad(); } @@ -356,6 +433,19 @@ void FrameLoaderClientQt::dispatchDidReceiveTitle(const String& title) } +void FrameLoaderClientQt::dispatchDidChangeIcons() +{ + if (dumpFrameLoaderCallbacks) + printf("%s - didChangeIcons\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); + + if (!m_webFrame) + return; + + // FIXME: To be notified of changing icon URLS add notification + // emit iconsChanged(); +} + + void FrameLoaderClientQt::dispatchDidCommitLoad() { if (dumpFrameLoaderCallbacks) @@ -371,6 +461,12 @@ void FrameLoaderClientQt::dispatchDidCommitLoad() // will be called very soon with the correct title. // This properly resets the title when we navigate to a URI without a title. emit titleChanged(String()); + + bool isMainFrame = (m_frame == m_frame->page()->mainFrame()); + if (!isMainFrame) + return; + + emit m_webFrame->page()->viewportChangeRequested(); } @@ -408,13 +504,12 @@ void FrameLoaderClientQt::dispatchDidFinishLoad() void FrameLoaderClientQt::dispatchDidFirstLayout() { - if (m_webFrame) - emit m_webFrame->initialLayoutCompleted(); } void FrameLoaderClientQt::dispatchDidFirstVisuallyNonEmptyLayout() { - notImplemented(); + if (m_webFrame) + emit m_webFrame->initialLayoutCompleted(); } void FrameLoaderClientQt::dispatchShow() @@ -445,7 +540,7 @@ void FrameLoaderClientQt::dispatchDidLoadMainResource(DocumentLoader*) void FrameLoaderClientQt::revertToProvisionalState(DocumentLoader*) { - notImplemented(); + m_hasRepresentation = true; } @@ -500,7 +595,7 @@ void FrameLoaderClientQt::willChangeTitle(DocumentLoader*) } -void FrameLoaderClientQt::didChangeTitle(DocumentLoader *) +void FrameLoaderClientQt::didChangeTitle(DocumentLoader*) { // no need for, dispatchDidReceiveTitle is the right callback } @@ -509,30 +604,37 @@ void FrameLoaderClientQt::didChangeTitle(DocumentLoader *) void FrameLoaderClientQt::finishedLoading(DocumentLoader* loader) { if (!m_pluginView) { - if(m_firstData) { - FrameLoader *fl = loader->frameLoader(); - fl->setEncoding(m_response.textEncodingName(), false); - m_firstData = false; - } + // This is necessary to create an empty document. See bug 634004. + // However, we only want to do this if makeRepresentation has been called, to + // match the behavior on the Mac. + if (m_hasRepresentation) + loader->frameLoader()->writer()->setEncoding("", false); + return; } - else { + if (m_pluginView->isPluginView()) m_pluginView->didFinishLoading(); - m_pluginView = 0; - m_hasSentResponseToPlugin = false; - } + m_pluginView = 0; + m_hasSentResponseToPlugin = false; } - +bool FrameLoaderClientQt::canShowMIMETypeAsHTML(const String& MIMEType) const +{ + notImplemented(); + return false; +} + bool FrameLoaderClientQt::canShowMIMEType(const String& MIMEType) const { - if (MIMETypeRegistry::isSupportedImageMIMEType(MIMEType)) + String type = MIMEType; + type.makeLower(); + if (MIMETypeRegistry::isSupportedImageMIMEType(type)) return true; - if (MIMETypeRegistry::isSupportedNonImageMIMEType(MIMEType)) + if (MIMETypeRegistry::isSupportedNonImageMIMEType(type)) return true; if (m_frame && m_frame->settings() && m_frame->settings()->arePluginsEnabled() - && PluginDatabase::installedPlugins()->isMIMETypeRegistered(MIMEType)) + && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type)) return true; return false; @@ -581,9 +683,17 @@ void FrameLoaderClientQt::prepareForDataSourceReplacement() { } -void FrameLoaderClientQt::setTitle(const String&, const KURL&) +void FrameLoaderClientQt::setTitle(const String& title, const KURL& url) { - // no need for, dispatchDidReceiveTitle is the right callback + // Used by Apple WebKit to update the title of an existing history item. + // QtWebKit doesn't accomodate this on history items. If it ever does, + // it should be privateBrowsing-aware.For now, we are just passing + // globalhistory layout tests. + if (dumpHistoryCallbacks) { + printf("WebView updated the title for history URL \"%s\" to \"%s\".\n", + qPrintable(drtDescriptionSuitableForTestResult(url)), + qPrintable(QString(title))); + } } @@ -621,8 +731,9 @@ void FrameLoaderClientQt::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* w if (world != mainThreadNormalWorld()) return; - if (m_webFrame) + if (m_webFrame) { emit m_webFrame->javaScriptWindowObjectCleared(); + } } void FrameLoaderClientQt::documentElementAvailable() @@ -645,12 +756,48 @@ void FrameLoaderClientQt::registerForIconNotification(bool) void FrameLoaderClientQt::updateGlobalHistory() { QWebHistoryInterface *history = QWebHistoryInterface::defaultInterface(); + WebCore::DocumentLoader* loader = m_frame->loader()->documentLoader(); if (history) - history->addHistoryEntry(m_frame->loader()->documentLoader()->urlForHistory().prettyURL()); + history->addHistoryEntry(loader->urlForHistory().prettyURL()); + + if (dumpHistoryCallbacks) { + printf("WebView navigated to url \"%s\" with title \"%s\" with HTTP equivalent method \"%s\". The navigation was %s and was %s%s.\n", + qPrintable(drtDescriptionSuitableForTestResult(loader->urlForHistory())), + qPrintable(QString(loader->title())), + qPrintable(QString(loader->request().httpMethod())), + ((loader->substituteData().isValid() || (loader->response().httpStatusCode() >= 400)) ? "a failure" : "successful"), + ((!loader->clientRedirectSourceForHistory().isEmpty()) ? "a client redirect from " : "not a client redirect"), + (!loader->clientRedirectSourceForHistory().isEmpty()) ? qPrintable(drtDescriptionSuitableForTestResult(loader->clientRedirectSourceForHistory())) : ""); + } } void FrameLoaderClientQt::updateGlobalHistoryRedirectLinks() { + // Apple WebKit is the only port that makes use of this callback. It calls + // WebCore::HistoryItem::addRedirectURL() with the contents of + // loader->[server|client]RedirectDestinationForHistory(). + // WebCore can associate a bunch of redirect URLs with a particular + // item in the history, presumably this allows Safari to skip the redirections + // when navigating to that history item. That might be a feature Qt wants to + // offer through QWebHistoryInterface in the future. For now, we're just + // passing tests in LayoutTests/http/tests/globalhistory. + WebCore::DocumentLoader* loader = m_frame->loader()->documentLoader(); + + if (!loader->clientRedirectSourceForHistory().isNull()) { + if (dumpHistoryCallbacks) { + printf("WebView performed a client redirect from \"%s\" to \"%s\".\n", + qPrintable(QString(loader->clientRedirectSourceForHistory())), + qPrintable(QString(loader->clientRedirectDestinationForHistory()))); + } + } + + if (!loader->serverRedirectSourceForHistory().isNull()) { + if (dumpHistoryCallbacks) { + printf("WebView performed a server redirect from \"%s\" to \"%s\".\n", + qPrintable(QString(loader->serverRedirectSourceForHistory())), + qPrintable(QString(loader->serverRedirectDestinationForHistory()))); + } + } } bool FrameLoaderClientQt::shouldGoToHistoryItem(WebCore::HistoryItem *) const @@ -699,33 +846,22 @@ bool FrameLoaderClientQt::canCachePage() const void FrameLoaderClientQt::setMainDocumentError(WebCore::DocumentLoader* loader, const WebCore::ResourceError& error) { - if (!m_pluginView) { - if (m_firstData) { - loader->frameLoader()->setEncoding(m_response.textEncodingName(), false); - m_firstData = false; - } - } else { + if (!m_pluginView) + return; + if (m_pluginView->isPluginView()) m_pluginView->didFail(error); - m_pluginView = 0; - m_hasSentResponseToPlugin = false; - } + m_pluginView = 0; + m_hasSentResponseToPlugin = false; } +// FIXME: This function should be moved into WebCore. void FrameLoaderClientQt::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length) { - if (!m_pluginView) { - if (!m_frame) - return; - FrameLoader *fl = loader->frameLoader(); - if (m_firstData) { - fl->setEncoding(m_response.textEncodingName(), false); - m_firstData = false; - } - fl->addData(data, length); - } + if (!m_pluginView) + loader->commitData(data, length); // We re-check here as the plugin can have been created - if (m_pluginView) { + if (m_pluginView && m_pluginView->isPluginView()) { if (!m_hasSentResponseToPlugin) { m_pluginView->didReceiveResponse(loader->response()); // didReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in @@ -760,26 +896,26 @@ enum { WebCore::ResourceError FrameLoaderClientQt::blockedError(const WebCore::ResourceRequest& request) { - return ResourceError("WebKit", WebKitErrorCannotUseRestrictedPort, request.url().prettyURL(), + return ResourceError("WebKitErrorDomain", WebKitErrorCannotUseRestrictedPort, request.url().prettyURL(), QCoreApplication::translate("QWebFrame", "Request blocked", 0, QCoreApplication::UnicodeUTF8)); } WebCore::ResourceError FrameLoaderClientQt::cannotShowURLError(const WebCore::ResourceRequest& request) { - return ResourceError("WebKit", WebKitErrorCannotShowURL, request.url().string(), + return ResourceError("WebKitErrorDomain", WebKitErrorCannotShowURL, request.url().string(), QCoreApplication::translate("QWebFrame", "Cannot show URL", 0, QCoreApplication::UnicodeUTF8)); } WebCore::ResourceError FrameLoaderClientQt::interruptForPolicyChangeError(const WebCore::ResourceRequest& request) { - return ResourceError("WebKit", WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(), + return ResourceError("WebKitErrorDomain", WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(), QCoreApplication::translate("QWebFrame", "Frame load interrupted by policy change", 0, QCoreApplication::UnicodeUTF8)); } WebCore::ResourceError FrameLoaderClientQt::cannotShowMIMETypeError(const WebCore::ResourceResponse& response) { - return ResourceError("WebKit", WebKitErrorCannotShowMIMEType, response.url().string(), + return ResourceError("WebKitErrorDomain", WebKitErrorCannotShowMIMEType, response.url().string(), QCoreApplication::translate("QWebFrame", "Cannot show mimetype", 0, QCoreApplication::UnicodeUTF8)); } @@ -804,8 +940,20 @@ bool FrameLoaderClientQt::shouldFallBack(const WebCore::ResourceError&) WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClientQt::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData) { RefPtr<DocumentLoader> loader = DocumentLoader::create(request, substituteData); - if (substituteData.isValid()) + if (!deferMainResourceDataLoad || substituteData.isValid()) { loader->setDeferMainResourceDataLoad(false); + // Use the default timeout interval for JS as the HTML tokenizer delay. This ensures + // that long-running JavaScript will still allow setHtml() to be synchronous, while + // still giving a reasonable timeout to prevent deadlock. +#if USE(JSC) + double delay = JSDOMWindowBase::commonJSGlobalData()->timeoutChecker.timeoutInterval() / 1000.0f; +#elif USE(V8) + // FIXME: Hard coded for now. + double delay = 10000 / 1000.0f; +#endif + m_frame->page()->setCustomHTMLTokenizerTimeDelay(delay); + } else + m_frame->page()->setCustomHTMLTokenizerTimeDelay(-1); return loader.release(); } @@ -819,7 +967,7 @@ void FrameLoaderClientQt::download(WebCore::ResourceHandle* handle, const WebCor if (reply) { QWebPage *page = m_webFrame->page(); if (page->forwardUnsupportedContent()) - emit m_webFrame->page()->unsupportedContent(reply); + emit page->unsupportedContent(reply); else reply->abort(); } @@ -833,11 +981,23 @@ void FrameLoaderClientQt::assignIdentifierToInitialRequest(unsigned long identif void FrameLoaderClientQt::dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long identifier, WebCore::ResourceRequest& newRequest, const WebCore::ResourceResponse& redirectResponse) { + if (dumpResourceLoadCallbacks) printf("%s - willSendRequest %s redirectResponse %s\n", qPrintable(dumpAssignedUrls[identifier]), qPrintable(drtDescriptionSuitableForTestResult(newRequest)), - qPrintable(drtDescriptionSuitableForTestResult(redirectResponse))); + (redirectResponse.isNull()) ? "(null)" : qPrintable(drtDescriptionSuitableForTestResult(redirectResponse))); + + if (sendRequestReturnsNull) + newRequest.setURL(QUrl()); + + if (sendRequestReturnsNullOnRedirect && !redirectResponse.isNull()) { + printf("Returning null for this redirect\n"); + newRequest.setURL(QUrl()); + } + + for (int i = 0; i < sendRequestClearHeaders.size(); ++i) + newRequest.setHTTPHeaderField(sendRequestClearHeaders.at(i).toLocal8Bit().constData(), QString()); // seems like the Mac code doesn't do anything here by default neither //qDebug() << "FrameLoaderClientQt::dispatchWillSendRequest" << request.isNull() << request.url().string`(); @@ -860,32 +1020,39 @@ void FrameLoaderClientQt::dispatchDidCancelAuthenticationChallenge(DocumentLoade notImplemented(); } -void FrameLoaderClientQt::dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long, const WebCore::ResourceResponse& response) +void FrameLoaderClientQt::dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse& response) { m_response = response; - m_firstData = true; - //qDebug() << " got response from" << response.url().string(); + if (dumpResourceLoadCallbacks) + printf("%s - didReceiveResponse %s\n", + qPrintable(dumpAssignedUrls[identifier]), + qPrintable(drtDescriptionSuitableForTestResult(response))); + + if (dumpResourceResponseMIMETypes) { + printf("%s has MIME type %s\n", + qPrintable(QFileInfo(drtDescriptionSuitableForTestResult(response.url())).fileName()), + qPrintable(QString(response.mimeType()))); + } } void FrameLoaderClientQt::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long, int) { } -void FrameLoaderClientQt::dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long) +void FrameLoaderClientQt::dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long identifier) { + if (dumpResourceLoadCallbacks) + printf("%s - didFinishLoading\n", + (dumpAssignedUrls.contains(identifier) ? qPrintable(dumpAssignedUrls[identifier]) : "<unknown>")); } void FrameLoaderClientQt::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const WebCore::ResourceError& error) { if (dumpResourceLoadCallbacks) - printf("%s - didFailLoadingWithError: %s\n", qPrintable(dumpAssignedUrls[identifier]), qPrintable(drtDescriptionSuitableForTestResult(error))); - - if (m_firstData) { - FrameLoader *fl = loader->frameLoader(); - fl->setEncoding(m_response.textEncodingName(), false); - m_firstData = false; - } + printf("%s - didFailLoadingWithError: %s\n", + (dumpAssignedUrls.contains(identifier) ? qPrintable(dumpAssignedUrls[identifier]) : "<unknown>"), + qPrintable(drtDescriptionSuitableForTestResult(error))); } bool FrameLoaderClientQt::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int) @@ -894,11 +1061,6 @@ bool FrameLoaderClientQt::dispatchDidLoadResourceFromMemoryCache(WebCore::Docume return false; } -void FrameLoaderClientQt::dispatchDidLoadResourceByXMLHttpRequest(unsigned long, const WebCore::ScriptString&) -{ - notImplemented(); -} - void FrameLoaderClientQt::callErrorPageExtension(const WebCore::ResourceError& error) { QWebPage* page = m_webFrame->page(); @@ -953,7 +1115,7 @@ void FrameLoaderClientQt::dispatchDidFailLoad(const WebCore::ResourceError& erro callErrorPageExtension(error); } -WebCore::Frame* FrameLoaderClientQt::dispatchCreatePage() +WebCore::Frame* FrameLoaderClientQt::dispatchCreatePage(const WebCore::NavigationAction&) { if (!m_webFrame) return 0; @@ -963,16 +1125,19 @@ WebCore::Frame* FrameLoaderClientQt::dispatchCreatePage() return newPage->mainFrame()->d->frame; } -void FrameLoaderClientQt::dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const WebCore::String& MIMEType, const WebCore::ResourceRequest&) +void FrameLoaderClientQt::dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const WTF::String& MIMEType, const WebCore::ResourceRequest&) { // we need to call directly here - if (canShowMIMEType(MIMEType)) + const ResourceResponse& response = m_frame->loader()->activeDocumentLoader()->response(); + if (WebCore::contentDispositionType(response.httpHeaderField("Content-Disposition")) == WebCore::ContentDispositionAttachment) + callPolicyFunction(function, PolicyDownload); + else if (canShowMIMEType(MIMEType)) callPolicyFunction(function, PolicyUse); else callPolicyFunction(function, PolicyDownload); } -void FrameLoaderClientQt::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState>, const WebCore::String&) +void FrameLoaderClientQt::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState>, const WTF::String&) { Q_ASSERT(m_webFrame); QNetworkRequest r(request.toNetworkRequest(m_webFrame)); @@ -998,6 +1163,32 @@ void FrameLoaderClientQt::dispatchDecidePolicyForNavigationAction(FramePolicyFun Q_ASSERT(m_webFrame); QNetworkRequest r(request.toNetworkRequest(m_webFrame)); QWebPage*page = m_webFrame->page(); + PolicyAction result; + + // Currently, this is only enabled by DRT + if (policyDelegateEnabled) { + RefPtr<Node> node; + for (const Event* event = action.event(); event; event = event->underlyingEvent()) { + if (event->isMouseEvent()) { + const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event); + node = QWebFramePrivate::core(m_webFrame)->eventHandler()->hitTestResultAtPoint( + mouseEvent->absoluteLocation(), false).innerNonSharedNode(); + break; + } + } + + printf("Policy delegate: attempt to load %s with navigation type '%s'%s\n", + qPrintable(drtDescriptionSuitableForTestResult(request.url())), navigationTypeToString(action.type()), + (node) ? qPrintable(QString(" originating from " + drtDescriptionSuitableForTestResult(node, 0))) : ""); + + if (policyDelegatePermissive) + result = PolicyUse; + else + result = PolicyIgnore; + + callPolicyFunction(function, result); + return; + } if (!page->d->acceptNavigationRequest(m_webFrame, r, QWebPage::NavigationType(action.type()))) { if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted) @@ -1057,7 +1248,7 @@ PassRefPtr<Frame> FrameLoaderClientQt::createFrame(const KURL& url, const String // ### set override encoding if we have one - frameData.frame->loader()->loadURLIntoChildFrame(frameData.url, frameData.referrer, frameData.frame.get()); + m_frame->loader()->loadURLIntoChildFrame(frameData.url, frameData.referrer, frameData.frame.get()); // The frame's onload handler may have removed it from the document. if (!frameData.frame->tree()->parent()) @@ -1066,6 +1257,28 @@ PassRefPtr<Frame> FrameLoaderClientQt::createFrame(const KURL& url, const String return frameData.frame.release(); } +void FrameLoaderClientQt::didTransferChildFrameToNewDocument(Page*) +{ + ASSERT(m_frame->ownerElement()); + + if (!m_webFrame) + return; + + Frame* parentFrame = m_webFrame->d->frame->tree()->parent(); + ASSERT(parentFrame); + + if (QWebFrame* parent = QWebFramePrivate::kit(parentFrame)) { + m_webFrame->d->setPage(parent->page()); + + if (m_webFrame->parent() != qobject_cast<QObject*>(parent)) + m_webFrame->setParent(parent); + } +} + +void FrameLoaderClientQt::transferLoadingResourceFromPage(unsigned long, DocumentLoader*, const ResourceRequest&, Page*) +{ +} + ObjectContentType FrameLoaderClientQt::objectContentType(const KURL& url, const String& _mimeType) { // qDebug()<<" ++++++++++++++++ url is "<<url.prettyURL()<<", mime = "<<_mimeType; @@ -1147,6 +1360,8 @@ public: platformWidget()->setMask(clipRegion); handleVisibility(); + + platformWidget()->update(); } virtual void show() @@ -1168,7 +1383,6 @@ private: } }; -#if QT_VERSION >= 0x040600 class QtPluginGraphicsWidget: public Widget { public: @@ -1213,7 +1427,6 @@ private: QGraphicsWidget* graphicsWidget; }; -#endif PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) @@ -1254,7 +1467,7 @@ PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, for (unsigned i = 0; i < numqStyleSheetProperties; ++i) { CSSPropertyID property = qstyleSheetProperties[i]; - styleSheet += QString::fromLatin1(::getPropertyName(property)); + styleSheet += QString::fromLatin1(getPropertyName(property)); styleSheet += QLatin1Char(':'); styleSheet += computedStyle(element)->getPropertyValue(property); styleSheet += QLatin1Char(';'); @@ -1286,7 +1499,7 @@ PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, w->setFrameRect(IntRect(0, 0, 0, 0)); return w; } -#if QT_VERSION >= 0x040600 + QGraphicsWidget* graphicsWidget = qobject_cast<QGraphicsWidget*>(object); if (graphicsWidget) { QGraphicsObject* parentWidget = 0; @@ -1300,15 +1513,30 @@ PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, w->setFrameRect(IntRect(0, 0, 0, 0)); return w; } -#endif + // FIXME: make things work for widgetless plugins as well delete object; - } else { // NPAPI Plugins + } +#if ENABLE(NETSCAPE_PLUGIN_API) + else { // NPAPI Plugins Vector<String> params = paramNames; Vector<String> values = paramValues; +#if !OS(SYMBIAN) if (mimeType == "application/x-shockwave-flash") { QWebPageClient* client = m_webFrame->page()->d->client; - if (!client || !qobject_cast<QWidget*>(client->pluginParent())) { + const bool isQWebView = client && qobject_cast<QWidget*>(client->pluginParent()); +#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5) + size_t wmodeIndex = params.find("wmode"); + if (wmodeIndex == -1) { + // Disable XEmbed mode and force it to opaque mode + params.append("wmode"); + values.append("opaque"); + } else if (!isQWebView) { + // Disable transparency if client is not a QWebView + values[wmodeIndex] = "opaque"; + } +#else + if (!isQWebView) { // inject wmode=opaque when there is no client or the client is not a QWebView size_t wmodeIndex = params.find("wmode"); if (wmodeIndex == -1) { @@ -1317,12 +1545,15 @@ PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, } else values[wmodeIndex] = "opaque"; } +#endif } +#endif RefPtr<PluginView> pluginView = PluginView::create(m_frame, pluginSize, element, url, params, values, mimeType, loadManually); return pluginView; } +#endif // ENABLE(NETSCAPE_PLUGIN_API) return 0; } @@ -1334,11 +1565,10 @@ void FrameLoaderClientQt::redirectDataToPlugin(Widget* pluginWidget) m_hasSentResponseToPlugin = false; } -PassRefPtr<Widget> FrameLoaderClientQt::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL&, - const Vector<String>&, const Vector<String>&) +PassRefPtr<Widget> FrameLoaderClientQt::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& url, + const Vector<String>& paramNames, const Vector<String>& paramValues) { - notImplemented(); - return 0; + return createPlugin(pluginSize, element, url, paramNames, paramValues, "application/x-java-applet", true); } String FrameLoaderClientQt::overrideMediaType() const @@ -1348,7 +1578,12 @@ String FrameLoaderClientQt::overrideMediaType() const QString FrameLoaderClientQt::chooseFile(const QString& oldFile) { - return webFrame()->page()->chooseFile(webFrame(), oldFile); + return m_webFrame->page()->chooseFile(m_webFrame, oldFile); +} + +PassRefPtr<FrameNetworkingContext> FrameLoaderClientQt::createNetworkingContext() +{ + return FrameNetworkingContextQt::create(m_frame, m_webFrame, m_webFrame->page()->networkAccessManager()); } } diff --git a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h index 32b9caa..275b0e8 100644 --- a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h +++ b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h @@ -27,201 +27,243 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef FrameLoaderClientQt_H -#define FrameLoaderClientQt_H +#ifndef FrameLoaderClientQt_h +#define FrameLoaderClientQt_h -#include <qobject.h> -#include <QUrl> -#include "FrameLoaderClient.h" -#include "KURL.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameLoaderClient.h" +#include "KURL.h" +#include <wtf/OwnPtr.h> +#include "PluginView.h" #include "RefCounted.h" +#include "ResourceError.h" #include "ResourceResponse.h" -#include "PluginView.h" +#include <QUrl> +#include <qobject.h> +#include <wtf/Forward.h> class QWebFrame; namespace WebCore { - class AuthenticationChallenge; - class DocumentLoader; - class Element; - class FormState; - class NavigationAction; - class String; - class ResourceLoader; - - struct LoadErrorResetToken; - - class FrameLoaderClientQt : public QObject, public FrameLoaderClient { - Q_OBJECT - - friend class ::QWebFrame; - void callPolicyFunction(FramePolicyFunction function, PolicyAction action); - void callErrorPageExtension(const ResourceError&); - signals: - void loadStarted(); - void loadProgress(int d); - void loadFinished(bool); - void titleChanged(const QString& title); - - public: - FrameLoaderClientQt(); - ~FrameLoaderClientQt(); - virtual void frameLoaderDestroyed(); - - void setFrame(QWebFrame* webFrame, Frame* frame); - QWebFrame* webFrame() const; - - virtual bool hasWebView() const; // mainly for assertions - - virtual void makeRepresentation(DocumentLoader*); - virtual void forceLayout(); - virtual void forceLayoutForNonHTML(); - - virtual void setCopiesOnScroll(); - - virtual void detachedFromParent2(); - virtual void detachedFromParent3(); - - virtual void assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader*, const WebCore::ResourceRequest&); - - virtual void dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long, WebCore::ResourceRequest&, const WebCore::ResourceResponse&); - virtual bool shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier); - virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); - virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); - virtual void dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long, const WebCore::ResourceResponse&); - virtual void dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long, int); - virtual void dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long); - virtual void dispatchDidFailLoading(WebCore::DocumentLoader*, unsigned long, const WebCore::ResourceError&); - virtual bool dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int); - virtual void dispatchDidLoadResourceByXMLHttpRequest(unsigned long identifier, const WebCore::ScriptString& sourceString); - - virtual void dispatchDidHandleOnloadEvents(); - virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); - virtual void dispatchDidCancelClientRedirect(); - virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate); - virtual void dispatchDidChangeLocationWithinPage(); - virtual void dispatchDidPushStateWithinPage(); - virtual void dispatchDidReplaceStateWithinPage(); - virtual void dispatchDidPopStateWithinPage(); - virtual void dispatchWillClose(); - virtual void dispatchDidReceiveIcon(); - virtual void dispatchDidStartProvisionalLoad(); - virtual void dispatchDidReceiveTitle(const String& title); - virtual void dispatchDidCommitLoad(); - virtual void dispatchDidFailProvisionalLoad(const ResourceError&); - virtual void dispatchDidFailLoad(const WebCore::ResourceError&); - virtual void dispatchDidFinishDocumentLoad(); - virtual void dispatchDidFinishLoad(); - virtual void dispatchDidFirstLayout(); - virtual void dispatchDidFirstVisuallyNonEmptyLayout(); - - virtual WebCore::Frame* dispatchCreatePage(); - virtual void dispatchShow(); - - virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const WebCore::String&, const WebCore::ResourceRequest&); - virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const WebCore::NavigationAction&, const WebCore::ResourceRequest&, PassRefPtr<FormState>, const WebCore::String&); - virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const WebCore::NavigationAction&, const WebCore::ResourceRequest&, PassRefPtr<FormState>); - virtual void cancelPolicyCheck(); - - virtual void dispatchUnableToImplementPolicy(const WebCore::ResourceError&); - - virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>); - - virtual void dispatchDidLoadMainResource(DocumentLoader*); - virtual void revertToProvisionalState(DocumentLoader*); - virtual void setMainDocumentError(DocumentLoader*, const ResourceError&); - - virtual void postProgressStartedNotification(); - virtual void postProgressEstimateChangedNotification(); - virtual void postProgressFinishedNotification(); - - virtual void setMainFrameDocumentReady(bool); - - virtual void startDownload(const WebCore::ResourceRequest&); - - virtual void willChangeTitle(DocumentLoader*); - virtual void didChangeTitle(DocumentLoader*); - - virtual void committedLoad(WebCore::DocumentLoader*, const char*, int); - virtual void finishedLoading(DocumentLoader*); - - virtual void updateGlobalHistory(); - virtual void updateGlobalHistoryRedirectLinks(); - virtual bool shouldGoToHistoryItem(HistoryItem*) const; - virtual void dispatchDidAddBackForwardItem(HistoryItem*) const; - virtual void dispatchDidRemoveBackForwardItem(HistoryItem*) const; - virtual void dispatchDidChangeBackForwardIndex() const; - virtual void didDisplayInsecureContent(); - virtual void didRunInsecureContent(SecurityOrigin*); - - virtual ResourceError cancelledError(const ResourceRequest&); - virtual ResourceError blockedError(const ResourceRequest&); - virtual ResourceError cannotShowURLError(const ResourceRequest&); - virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&); - - virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&); - virtual ResourceError fileDoesNotExistError(const ResourceResponse&); - virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&); - - virtual bool shouldFallBack(const ResourceError&); - - virtual bool canHandleRequest(const WebCore::ResourceRequest&) const; - virtual bool canShowMIMEType(const String& MIMEType) const; - virtual bool representationExistsForURLScheme(const String& URLScheme) const; - virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const; - - virtual void frameLoadCompleted(); - virtual void saveViewStateToItem(WebCore::HistoryItem*); - virtual void restoreViewState(); - virtual void provisionalLoadStarted(); - virtual void didFinishLoad(); - virtual void prepareForDataSourceReplacement(); - - virtual WTF::PassRefPtr<WebCore::DocumentLoader> createDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&); - virtual void setTitle(const String& title, const KURL&); - - virtual String userAgent(const WebCore::KURL&); - - virtual void savePlatformDataToCachedFrame(WebCore::CachedFrame*); - virtual void transitionToCommittedFromCachedFrame(WebCore::CachedFrame*); - virtual void transitionToCommittedForNewPage(); - - virtual bool canCachePage() const; - virtual void download(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); - - virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, - const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) ; - virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool); - virtual void redirectDataToPlugin(Widget* pluginWidget); - - virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues); - - virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType); - virtual String overrideMediaType() const; - - virtual void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*); - virtual void documentElementAvailable(); - virtual void didPerformFirstNavigation() const; - - virtual void registerForIconNotification(bool); +class AuthenticationChallenge; +class DocumentLoader; +class Element; +class FormState; +class NavigationAction; +class FrameNetworkingContext; +class ResourceLoader; + +struct LoadErrorResetToken; + +class FrameLoaderClientQt : public QObject, public FrameLoaderClient { + Q_OBJECT + + friend class ::QWebFrame; + void callPolicyFunction(FramePolicyFunction function, PolicyAction action); + void callErrorPageExtension(const ResourceError&); +signals: + void loadStarted(); + void loadProgress(int d); + void loadFinished(bool); + void titleChanged(const QString& title); + +public: + FrameLoaderClientQt(); + ~FrameLoaderClientQt(); + virtual void frameLoaderDestroyed(); + + void setFrame(QWebFrame* webFrame, Frame* frame); + + virtual bool hasWebView() const; // mainly for assertions + + virtual void makeRepresentation(DocumentLoader*); + virtual void forceLayout(); + virtual void forceLayoutForNonHTML(); + + virtual void setCopiesOnScroll(); + + virtual void detachedFromParent2(); + virtual void detachedFromParent3(); + + virtual void assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader*, const WebCore::ResourceRequest&); + + virtual void dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long, WebCore::ResourceRequest&, const WebCore::ResourceResponse&); + virtual bool shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier); + virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); + virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); + virtual void dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long, const WebCore::ResourceResponse&); + virtual void dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long, int); + virtual void dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long); + virtual void dispatchDidFailLoading(WebCore::DocumentLoader*, unsigned long, const WebCore::ResourceError&); + virtual bool dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int); + + virtual void dispatchDidHandleOnloadEvents(); + virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); + virtual void dispatchDidCancelClientRedirect(); + virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate); + virtual void dispatchDidChangeLocationWithinPage(); + virtual void dispatchDidPushStateWithinPage(); + virtual void dispatchDidReplaceStateWithinPage(); + virtual void dispatchDidPopStateWithinPage(); + virtual void dispatchWillClose(); + virtual void dispatchDidReceiveIcon(); + virtual void dispatchDidStartProvisionalLoad(); + virtual void dispatchDidReceiveTitle(const String& title); + virtual void dispatchDidChangeIcons(); + virtual void dispatchDidCommitLoad(); + virtual void dispatchDidFailProvisionalLoad(const ResourceError&); + virtual void dispatchDidFailLoad(const WebCore::ResourceError&); + virtual void dispatchDidFinishDocumentLoad(); + virtual void dispatchDidFinishLoad(); + virtual void dispatchDidFirstLayout(); + virtual void dispatchDidFirstVisuallyNonEmptyLayout(); + + virtual WebCore::Frame* dispatchCreatePage(const WebCore::NavigationAction&); + virtual void dispatchShow(); + + virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const WTF::String&, const WebCore::ResourceRequest&); + virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const WebCore::NavigationAction&, const WebCore::ResourceRequest&, PassRefPtr<FormState>, const WTF::String&); + virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const WebCore::NavigationAction&, const WebCore::ResourceRequest&, PassRefPtr<FormState>); + virtual void cancelPolicyCheck(); + + virtual void dispatchUnableToImplementPolicy(const WebCore::ResourceError&); + + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { } + virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>); + + virtual void dispatchDidLoadMainResource(DocumentLoader*); + virtual void revertToProvisionalState(DocumentLoader*); + virtual void setMainDocumentError(DocumentLoader*, const ResourceError&); + + virtual void postProgressStartedNotification(); + virtual void postProgressEstimateChangedNotification(); + virtual void postProgressFinishedNotification(); + + virtual void setMainFrameDocumentReady(bool); + + virtual void startDownload(const WebCore::ResourceRequest&); + + virtual void willChangeTitle(DocumentLoader*); + virtual void didChangeTitle(DocumentLoader*); + + virtual void committedLoad(WebCore::DocumentLoader*, const char*, int); + virtual void finishedLoading(DocumentLoader*); + + virtual void updateGlobalHistory(); + virtual void updateGlobalHistoryRedirectLinks(); + virtual bool shouldGoToHistoryItem(HistoryItem*) const; + virtual void dispatchDidAddBackForwardItem(HistoryItem*) const; + virtual void dispatchDidRemoveBackForwardItem(HistoryItem*) const; + virtual void dispatchDidChangeBackForwardIndex() const; + virtual void didDisplayInsecureContent(); + virtual void didRunInsecureContent(SecurityOrigin*); + + virtual ResourceError cancelledError(const ResourceRequest&); + virtual ResourceError blockedError(const ResourceRequest&); + virtual ResourceError cannotShowURLError(const ResourceRequest&); + virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&); + + virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&); + virtual ResourceError fileDoesNotExistError(const ResourceResponse&); + virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&); + + virtual bool shouldFallBack(const ResourceError&); + + virtual bool canHandleRequest(const WebCore::ResourceRequest&) const; + virtual bool canShowMIMEType(const String& MIMEType) const; + virtual bool canShowMIMETypeAsHTML(const String& MIMEType) const; + virtual bool representationExistsForURLScheme(const String& URLScheme) const; + virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const; + + virtual void frameLoadCompleted(); + virtual void saveViewStateToItem(WebCore::HistoryItem*); + virtual void restoreViewState(); + virtual void provisionalLoadStarted(); + virtual void didFinishLoad(); + virtual void prepareForDataSourceReplacement(); + + virtual WTF::PassRefPtr<WebCore::DocumentLoader> createDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&); + virtual void setTitle(const String& title, const KURL&); + + virtual String userAgent(const WebCore::KURL&); + + virtual void savePlatformDataToCachedFrame(WebCore::CachedFrame*); + virtual void transitionToCommittedFromCachedFrame(WebCore::CachedFrame*); + virtual void transitionToCommittedForNewPage(); + + virtual void dispatchDidBecomeFrameset(bool); + + virtual bool canCachePage() const; + virtual void download(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); + + virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, + const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); + virtual void didTransferChildFrameToNewDocument(WebCore::Page*); + virtual void transferLoadingResourceFromPage(unsigned long, WebCore::DocumentLoader*, const WebCore::ResourceRequest&, WebCore::Page*); + virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool); + virtual void redirectDataToPlugin(Widget* pluginWidget); + + virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues); + + virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType); + virtual String overrideMediaType() const; + + virtual void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*); + virtual void documentElementAvailable(); + virtual void didPerformFirstNavigation() const; - QString chooseFile(const QString& oldFile); +#if USE(V8) + // A frame's V8 context was created or destroyed. + virtual void didCreateScriptContextForFrame(); + virtual void didDestroyScriptContextForFrame(); - private: - Frame *m_frame; - QWebFrame *m_webFrame; - ResourceResponse m_response; - bool m_firstData; + // A context untied to a frame was created (through evaluateInIsolatedWorld). + // This context is not tied to the lifetime of its frame, and is destroyed + // in garbage collection. + virtual void didCreateIsolatedScriptContext(); - // Plugin view to redirect data to - WebCore::PluginView* m_pluginView; - bool m_hasSentResponseToPlugin; + // Returns true if we should allow the given V8 extension to be added to + // the script context at the currently loading page and given extension group. + virtual bool allowScriptExtension(const String& extensionName, int extensionGroup) { return false; } +#endif - ResourceError m_loadError; - }; + virtual void registerForIconNotification(bool); + + QString chooseFile(const QString& oldFile); + + virtual PassRefPtr<FrameNetworkingContext> createNetworkingContext(); + + static bool dumpFrameLoaderCallbacks; + static bool dumpUserGestureInFrameLoaderCallbacks; + static bool dumpResourceLoadCallbacks; + static bool dumpResourceResponseMIMETypes; + static QString dumpResourceLoadCallbacksPath; + static bool sendRequestReturnsNullOnRedirect; + static bool sendRequestReturnsNull; + static QStringList sendRequestClearHeaders; + static bool policyDelegateEnabled; + static bool policyDelegatePermissive; + static bool deferMainResourceDataLoad; + static bool dumpHistoryCallbacks; + +private: + Frame *m_frame; + QWebFrame *m_webFrame; + ResourceResponse m_response; + + // Plugin view to redirect data to + WebCore::PluginView* m_pluginView; + bool m_hasSentResponseToPlugin; + + // True if makeRepresentation was called. We don't actually have a concept + // of a "representation", but we need to know when we're expected to have one. + // See finishedLoading(). + bool m_hasRepresentation; + + ResourceError m_loadError; +}; } diff --git a/WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.cpp b/WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.cpp new file mode 100644 index 0000000..b3b0f00 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.cpp @@ -0,0 +1,53 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#include "FrameNetworkingContextQt.h" + +#include <QNetworkAccessManager> +#include <QObject> +#include <QWebFrame> +#include <QWebPage> + +namespace WebCore { + +FrameNetworkingContextQt::FrameNetworkingContextQt(Frame* frame, QObject* originatingObject, QNetworkAccessManager* networkAccessManager) + : FrameNetworkingContext(frame) + , m_originatingObject(originatingObject) + , m_networkAccessManager(networkAccessManager) +{ +} + +PassRefPtr<FrameNetworkingContextQt> FrameNetworkingContextQt::create(Frame* frame, QObject* originatingObject, QNetworkAccessManager* networkAccessManager) +{ + return adoptRef(new FrameNetworkingContextQt(frame, originatingObject, networkAccessManager)); +} + +QObject* FrameNetworkingContextQt::originatingObject() const +{ + return m_originatingObject; +} + +QNetworkAccessManager* FrameNetworkingContextQt::networkAccessManager() const +{ + return (qobject_cast<QWebFrame*>(m_originatingObject))->page()->networkAccessManager(); +} + +} diff --git a/WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.h b/WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.h new file mode 100644 index 0000000..461023e --- /dev/null +++ b/WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef FrameNetworkingContextQt_h +#define FrameNetworkingContextQt_h + +#include "FrameNetworkingContext.h" + +namespace WebCore { + +class FrameNetworkingContextQt : public FrameNetworkingContext { +public: + static PassRefPtr<FrameNetworkingContextQt> create(Frame*, QObject* originatingObject, QNetworkAccessManager*); + +private: + FrameNetworkingContextQt(Frame*, QObject* originatingObject, QNetworkAccessManager*); + + virtual QObject* originatingObject() const; + virtual QNetworkAccessManager* networkAccessManager() const; + + QObject* m_originatingObject; + QNetworkAccessManager* m_networkAccessManager; +}; + +} + +#endif // FrameNetworkingContextQt_h diff --git a/WebKit/qt/WebCoreSupport/GeolocationPermissionClientQt.cpp b/WebKit/qt/WebCoreSupport/GeolocationPermissionClientQt.cpp new file mode 100644 index 0000000..5fb9ab7 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/GeolocationPermissionClientQt.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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 "GeolocationPermissionClientQt.h" + +#include "Geolocation.h" + +#include "qwebframe.h" +#include "qwebkitglobal.h" +#include "qwebpage.h" + +namespace WebCore { + +#if ENABLE(GEOLOCATION) + +static GeolocationPermissionClientQt* s_geolocationPermission; + +GeolocationPermissionClientQt* GeolocationPermissionClientQt::geolocationPermissionClient() +{ + if (s_geolocationPermission) + return s_geolocationPermission; + + s_geolocationPermission = new GeolocationPermissionClientQt(); + return s_geolocationPermission; +} + +GeolocationPermissionClientQt::GeolocationPermissionClientQt() +{ +} + +GeolocationPermissionClientQt::~GeolocationPermissionClientQt() +{ +} + +void GeolocationPermissionClientQt::requestGeolocationPermissionForFrame(QWebFrame* webFrame, Geolocation* listener) +{ + m_pendingPermissionRequests.insert(webFrame, listener); + + QWebPage* page = webFrame->page(); + emit page->requestPermissionFromUser(webFrame, QWebPage::GeolocationPermissionDomain); +} + + +void GeolocationPermissionClientQt::cancelGeolocationPermissionRequestForFrame(QWebFrame* webFrame, Geolocation* listener) +{ + m_pendingPermissionRequests.remove(webFrame); + + QWebPage* page = webFrame->page(); + emit page->cancelRequestsForPermission(webFrame, QWebPage::GeolocationPermissionDomain); +} + +void GeolocationPermissionClientQt::setPermission(QWebFrame* webFrame, QWebPage::PermissionPolicy permission) +{ + if (!m_pendingPermissionRequests.contains(webFrame)) + return; + + Geolocation* listener = m_pendingPermissionRequests.value(webFrame); + + if (permission == QWebPage::PermissionGranted) + listener->setIsAllowed(true); + else if (permission == QWebPage::PermissionDenied) + listener->setIsAllowed(false); + else + return; + + m_pendingPermissionRequests.remove(webFrame); +} + +#endif // ENABLE(GEOLOCATION) +} diff --git a/WebKit/qt/WebCoreSupport/GeolocationPermissionClientQt.h b/WebKit/qt/WebCoreSupport/GeolocationPermissionClientQt.h new file mode 100644 index 0000000..abe9c76 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/GeolocationPermissionClientQt.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ + +#ifndef GeolocationPermissionClientQt_h +#define GeolocationPermissionClientQt_h + +#include "Geolocation.h" +#include "qwebpage.h" + +#include <QHash> + +class QWebFrame; +class QWebPage; + +namespace WebCore { + +class GeolocationPermissionClientQt { +public: + GeolocationPermissionClientQt(); + ~GeolocationPermissionClientQt(); + + void requestGeolocationPermissionForFrame(QWebFrame*, Geolocation*); + void cancelGeolocationPermissionRequestForFrame(QWebFrame*, Geolocation*); + void setPermission(QWebFrame*, QWebPage::PermissionPolicy); + + static GeolocationPermissionClientQt* geolocationPermissionClient(); +private: + QHash<QWebFrame*, Geolocation*> m_pendingPermissionRequests; +}; + +} + +#endif diff --git a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp index 4927ea8..e596870 100644 --- a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp @@ -31,19 +31,24 @@ #include "config.h" #include "InspectorClientQt.h" +#include "Frame.h" +#include "InspectorBackendDispatcher.h" +#include "InspectorController.h" +#include "InspectorFrontend.h" +#include "InspectorServerQt.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PlatformString.h" +#include "ScriptDebugServer.h" #include "qwebinspector.h" #include "qwebinspector_p.h" #include "qwebpage.h" #include "qwebpage_p.h" #include "qwebview.h" - -#include <QtCore/QSettings> #include <QtCore/QCoreApplication> - -#include "InspectorController.h" -#include "NotImplemented.h" -#include "Page.h" -#include "PlatformString.h" +#include <QtCore/QFile> +#include <QtCore/QSettings> +#include <QtCore/QVariant> namespace WebCore { @@ -60,6 +65,7 @@ public: InspectorClientWebPage(QObject* parent = 0) : QWebPage(parent) { + connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), SLOT(javaScriptWindowObjectCleared())); } QWebPage* createWindow(QWebPage::WebWindowType) @@ -70,74 +76,129 @@ public: view->setAttribute(Qt::WA_DeleteOnClose); return page; } + +public slots: + void javaScriptWindowObjectCleared() + { +#ifndef QT_NO_PROPERTIES + QVariant inspectorJavaScriptWindowObjects = property("_q_inspectorJavaScriptWindowObjects"); + if (!inspectorJavaScriptWindowObjects.isValid()) + return; + QMap<QString, QVariant> javaScriptNameObjectMap = inspectorJavaScriptWindowObjects.toMap(); + QWebFrame* frame = mainFrame(); + QMap<QString, QVariant>::const_iterator it = javaScriptNameObjectMap.constBegin(); + for ( ; it != javaScriptNameObjectMap.constEnd(); ++it) { + QString name = it.key(); + QVariant value = it.value(); + QObject* obj = value.value<QObject*>(); + frame->addToJavaScriptWindowObject(name, obj); + } +#endif + } }; +#if USE(V8) +static void ensureDebuggerScriptLoaded() +{ + static bool scriptLoaded = false; + if (scriptLoaded) + return; + + QFile debuggerScriptFile(":/webkit/inspector/DebuggerScript.js"); + if (debuggerScriptFile.open(QIODevice::ReadOnly)) { + QByteArray ba = debuggerScriptFile.readAll(); + ScriptDebugServer::shared().setDebuggerScriptSource(String(ba.constData(), ba.length())); + scriptLoaded = true; + } +} +#endif + InspectorClientQt::InspectorClientQt(QWebPage* page) : m_inspectedWebPage(page) -{} + , m_frontendWebPage(0) + , m_frontendClient(0) +{ + InspectorServerQt* webInspectorServer = InspectorServerQt::server(); + if (webInspectorServer) + webInspectorServer->registerClient(this); +} void InspectorClientQt::inspectorDestroyed() { + if (m_frontendClient) + m_frontendClient->inspectorClientDestroyed(); + + InspectorServerQt* webInspectorServer = InspectorServerQt::server(); + if (webInspectorServer) + webInspectorServer->unregisterClient(this); + delete this; } -Page* InspectorClientQt::createPage() + +void InspectorClientQt::openInspectorFrontend(WebCore::InspectorController* inspectorController) { +#if USE(V8) + ensureDebuggerScriptLoaded(); +#endif + QWebView* inspectorView = new QWebView; InspectorClientWebPage* inspectorPage = new InspectorClientWebPage(inspectorView); inspectorView->setPage(inspectorPage); - m_inspectorView.set(inspectorView); - inspectorPage->mainFrame()->load(QString::fromLatin1("qrc:/webkit/inspector/inspector.html")); - m_inspectedWebPage->d->inspectorFrontend = inspectorView; - m_inspectedWebPage->d->getOrCreateInspector()->d->setFrontend(inspectorView); + QWebInspector* inspector = m_inspectedWebPage->d->getOrCreateInspector(); + // Remote frontend was attached. + if (m_inspectedWebPage->d->inspector->d->remoteFrontend) + return; - return m_inspectorView->page()->d->page; -} + // This is a known hook that allows changing the default URL for the + // Web inspector. This is used for SDK purposes. Please keep this hook + // around and don't remove it. + // https://bugs.webkit.org/show_bug.cgi?id=35340 + QUrl inspectorUrl; +#ifndef QT_NO_PROPERTIES + inspectorUrl = inspector->property("_q_inspectorUrl").toUrl(); +#endif + if (!inspectorUrl.isValid()) + inspectorUrl = QUrl("qrc:/webkit/inspector/inspector.html"); -String InspectorClientQt::localizedStringsURL() -{ - notImplemented(); - return String(); +#ifndef QT_NO_PROPERTIES + QVariant inspectorJavaScriptWindowObjects = inspector->property("_q_inspectorJavaScriptWindowObjects"); + if (inspectorJavaScriptWindowObjects.isValid()) + inspectorPage->setProperty("_q_inspectorJavaScriptWindowObjects", inspectorJavaScriptWindowObjects); +#endif + inspectorView->page()->mainFrame()->load(inspectorUrl); + m_inspectedWebPage->d->inspectorFrontend = inspectorView; + inspector->d->setFrontend(inspectorView); + + m_frontendClient = new InspectorFrontendClientQt(m_inspectedWebPage, inspectorView, this); + inspectorView->page()->d->page->inspectorController()->setInspectorFrontendClient(m_frontendClient); + m_frontendWebPage = inspectorPage; } -String InspectorClientQt::hiddenPanels() +void InspectorClientQt::releaseFrontendPage() { - notImplemented(); - return String(); + m_frontendWebPage = 0; + m_frontendClient = 0; } -void InspectorClientQt::showWindow() +void InspectorClientQt::attachAndReplaceRemoteFrontend(RemoteFrontendChannel* channel) { - updateWindowTitle(); - #if ENABLE(INSPECTOR) - m_inspectedWebPage->d->inspectorController()->setWindowVisible(true, true); + // Channel was allocated by InspectorServerQt. Here we transfer ownership to inspector. + m_inspectedWebPage->d->inspector->d->attachAndReplaceRemoteFrontend(channel); + m_inspectedWebPage->d->inspectorController()->connectFrontend(); #endif } -void InspectorClientQt::closeWindow() +void InspectorClientQt::detachRemoteFrontend() { #if ENABLE(INSPECTOR) - m_inspectedWebPage->d->inspectorController()->setWindowVisible(false); + m_inspectedWebPage->d->inspector->d->detachRemoteFrontend(); + m_inspectedWebPage->d->inspectorController()->disconnectFrontend(); #endif } -void InspectorClientQt::attachWindow() -{ - notImplemented(); -} - -void InspectorClientQt::detachWindow() -{ - notImplemented(); -} - -void InspectorClientQt::setAttachedWindowHeight(unsigned) -{ - notImplemented(); -} - void InspectorClientQt::highlight(Node*) { notImplemented(); @@ -148,27 +209,13 @@ void InspectorClientQt::hideHighlight() notImplemented(); } -void InspectorClientQt::inspectedURLChanged(const String& newURL) -{ - m_inspectedURL = newURL; - updateWindowTitle(); -} - -void InspectorClientQt::inspectorWindowObjectCleared() -{ - notImplemented(); -} - -void InspectorClientQt::updateWindowTitle() -{ - if (m_inspectedWebPage->d->inspector) { - QString caption = QCoreApplication::translate("QWebPage", "Web Inspector - %2").arg(m_inspectedURL); - m_inspectedWebPage->d->inspector->setWindowTitle(caption); - } -} - void InspectorClientQt::populateSetting(const String& key, String* setting) { +#ifdef QT_NO_SETTINGS + Q_UNUSED(key) + Q_UNUSED(setting) + qWarning("QWebInspector: QSettings is not supported by Qt."); +#else QSettings qsettings; if (qsettings.status() == QSettings::AccessError) { // QCoreApplication::setOrganizationName and QCoreApplication::setApplicationName haven't been called @@ -177,15 +224,21 @@ void InspectorClientQt::populateSetting(const String& key, String* setting) return; } - QString settingKey(settingStoragePrefix + key); + QString settingKey(settingStoragePrefix + QString(key)); QString storedValueType = qsettings.value(settingKey + settingStorageTypeSuffix).toString(); QVariant storedValue = qsettings.value(settingKey); storedValue.convert(QVariant::nameToType(storedValueType.toAscii().data())); *setting = variantToSetting(storedValue); +#endif // QT_NO_SETTINGS } void InspectorClientQt::storeSetting(const String& key, const String& setting) { +#ifdef QT_NO_SETTINGS + Q_UNUSED(key) + Q_UNUSED(setting) + qWarning("QWebInspector: QSettings is not supported by Qt."); +#else QSettings qsettings; if (qsettings.status() == QSettings::AccessError) { qWarning("QWebInspector: QSettings couldn't persist configuration setting [%s].", @@ -194,9 +247,25 @@ void InspectorClientQt::storeSetting(const String& key, const String& setting) } QVariant valueToStore = settingToVariant(setting); - QString settingKey(settingStoragePrefix + key); + QString settingKey(settingStoragePrefix + QString(key)); qsettings.setValue(settingKey, valueToStore); qsettings.setValue(settingKey + settingStorageTypeSuffix, QVariant::typeToName(valueToStore.type())); +#endif // QT_NO_SETTINGS +} + +bool InspectorClientQt::sendMessageToFrontend(const String& message) +{ + if (m_inspectedWebPage->d->inspector->d->remoteFrontend) { + RemoteFrontendChannel* session = qobject_cast<RemoteFrontendChannel*>(m_inspectedWebPage->d->inspector->d->remoteFrontend); + if (session) + session->sendMessageToFrontend(message); + return true; + } + if (!m_frontendWebPage) + return false; + + Page* frontendPage = QWebPagePrivate::core(m_frontendWebPage); + return doDispatchMessageOnFrontendPage(frontendPage, message); } static String variantToSetting(const QVariant& qvariant) @@ -208,6 +277,8 @@ static String variantToSetting(const QVariant& qvariant) retVal = qvariant.toBool() ? "true" : "false"; case QVariant::String: retVal = qvariant.toString(); + default: + break; } return retVal; @@ -220,6 +291,113 @@ static QVariant settingToVariant(const String& setting) return retVal; } +InspectorFrontendClientQt::InspectorFrontendClientQt(QWebPage* inspectedWebPage, PassOwnPtr<QWebView> inspectorView, InspectorClientQt* inspectorClient) + : InspectorFrontendClientLocal(inspectedWebPage->d->page->inspectorController(), inspectorView->page()->d->page) + , m_inspectedWebPage(inspectedWebPage) + , m_inspectorView(inspectorView) + , m_destroyingInspectorView(false) + , m_inspectorClient(inspectorClient) +{ +} + +InspectorFrontendClientQt::~InspectorFrontendClientQt() +{ + ASSERT(m_destroyingInspectorView); + if (m_inspectorClient) + m_inspectorClient->releaseFrontendPage(); +} + +void InspectorFrontendClientQt::frontendLoaded() +{ + InspectorFrontendClientLocal::frontendLoaded(); + setAttachedWindow(true); +} + +String InspectorFrontendClientQt::localizedStringsURL() +{ + notImplemented(); + return String(); +} + +String InspectorFrontendClientQt::hiddenPanels() +{ + notImplemented(); + return String(); +} + +void InspectorFrontendClientQt::bringToFront() +{ + updateWindowTitle(); +} + +void InspectorFrontendClientQt::closeWindow() +{ + destroyInspectorView(true); +} + +void InspectorFrontendClientQt::disconnectFromBackend() +{ + destroyInspectorView(false); +} + +void InspectorFrontendClientQt::attachWindow() +{ + notImplemented(); +} + +void InspectorFrontendClientQt::detachWindow() +{ + notImplemented(); +} + +void InspectorFrontendClientQt::setAttachedWindowHeight(unsigned) +{ + notImplemented(); +} + +void InspectorFrontendClientQt::inspectedURLChanged(const String& newURL) +{ + m_inspectedURL = newURL; + updateWindowTitle(); +} + +void InspectorFrontendClientQt::updateWindowTitle() +{ + if (m_inspectedWebPage->d->inspector) { + QString caption = QCoreApplication::translate("QWebPage", "Web Inspector - %2").arg(m_inspectedURL); + m_inspectedWebPage->d->inspector->setWindowTitle(caption); + } +} + +void InspectorFrontendClientQt::destroyInspectorView(bool notifyInspectorController) +{ + if (m_destroyingInspectorView) + return; + m_destroyingInspectorView = true; + + // Inspected page may have already been destroyed. + if (m_inspectedWebPage) { + // Clear reference from QWebInspector to the frontend view. + m_inspectedWebPage->d->getOrCreateInspector()->d->setFrontend(0); + } + +#if ENABLE(INSPECTOR) + if (notifyInspectorController) + m_inspectedWebPage->d->inspectorController()->disconnectFrontend(); +#endif + if (m_inspectorClient) + m_inspectorClient->releaseFrontendPage(); + + // Clear pointer before deleting WebView to avoid recursive calls to its destructor. + OwnPtr<QWebView> inspectorView = m_inspectorView.release(); +} + +void InspectorFrontendClientQt::inspectorClientDestroyed() +{ + m_inspectorClient = 0; + m_inspectedWebPage = 0; +} + } #include "InspectorClientQt.moc" diff --git a/WebKit/qt/WebCoreSupport/InspectorClientQt.h b/WebKit/qt/WebCoreSupport/InspectorClientQt.h index 923bab4..64a2d0c 100644 --- a/WebKit/qt/WebCoreSupport/InspectorClientQt.h +++ b/WebKit/qt/WebCoreSupport/InspectorClientQt.h @@ -31,52 +31,85 @@ #define InspectorClientQt_h #include "InspectorClient.h" +#include "InspectorFrontendClientLocal.h" #include "OwnPtr.h" +#include "PassOwnPtr.h" #include <QtCore/QString> +#include <wtf/Forward.h> class QWebPage; class QWebView; namespace WebCore { - class Node; - class Page; - class String; +class InspectorFrontendClientQt; +class InspectorServerRequestHandlerQt; +class Node; +class Page; +class RemoteFrontendChannel; - class InspectorClientQt : public InspectorClient { - public: - InspectorClientQt(QWebPage*); +class InspectorClientQt : public InspectorClient { +public: + InspectorClientQt(QWebPage*); - virtual void inspectorDestroyed(); + virtual void inspectorDestroyed(); - virtual Page* createPage(); + virtual void openInspectorFrontend(WebCore::InspectorController*); - virtual String localizedStringsURL(); + virtual void highlight(Node*); + virtual void hideHighlight(); - virtual String hiddenPanels(); + virtual void populateSetting(const String& key, String* value); + virtual void storeSetting(const String& key, const String& value); - virtual void showWindow(); - virtual void closeWindow(); + virtual bool sendMessageToFrontend(const String&); - virtual void attachWindow(); - virtual void detachWindow(); + void releaseFrontendPage(); - virtual void setAttachedWindowHeight(unsigned height); + void attachAndReplaceRemoteFrontend(RemoteFrontendChannel *channel); + void detachRemoteFrontend(); - virtual void highlight(Node*); - virtual void hideHighlight(); - virtual void inspectedURLChanged(const String& newURL); +private: + QWebPage* m_inspectedWebPage; + QWebPage* m_frontendWebPage; + InspectorFrontendClientQt* m_frontendClient; + bool m_remoteInspector; - virtual void populateSetting(const String& key, String* value); - virtual void storeSetting(const String& key, const String& value); + friend class InspectorServerRequestHandlerQt; +}; - virtual void inspectorWindowObjectCleared(); +class InspectorFrontendClientQt : public InspectorFrontendClientLocal { +public: + InspectorFrontendClientQt(QWebPage* inspectedWebPage, PassOwnPtr<QWebView> inspectorView, InspectorClientQt* inspectorClient); + virtual ~InspectorFrontendClientQt(); - private: - void updateWindowTitle(); - QWebPage* m_inspectedWebPage; - OwnPtr<QWebView> m_inspectorView; - QString m_inspectedURL; - }; + virtual void frontendLoaded(); + + virtual String localizedStringsURL(); + + virtual String hiddenPanels(); + + virtual void bringToFront(); + virtual void closeWindow(); + virtual void disconnectFromBackend(); + + virtual void attachWindow(); + virtual void detachWindow(); + + virtual void setAttachedWindowHeight(unsigned height); + + virtual void inspectedURLChanged(const String& newURL); + + void inspectorClientDestroyed(); + +private: + void updateWindowTitle(); + void destroyInspectorView(bool notifyInspectorController); + QWebPage* m_inspectedWebPage; + OwnPtr<QWebView> m_inspectorView; + QString m_inspectedURL; + bool m_destroyingInspectorView; + InspectorClientQt* m_inspectorClient; +}; } #endif diff --git a/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp b/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp new file mode 100644 index 0000000..a6dda58 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp @@ -0,0 +1,387 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "InspectorServerQt.h" + +#include "InspectorBackendDispatcher.h" +#include "InspectorClientQt.h" +#include "MD5.h" +#include "Page.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include <QFile> +#include <QHttpHeader> +#include <QHttpRequestHeader> +#include <QHttpResponseHeader> +#include <QString> +#include <QStringList> +#include <QTcpServer> +#include <QTcpSocket> +#include <QUrl> +#include <QWidget> +#include <qendian.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +/*! + Computes the WebSocket handshake response given the two challenge numbers and key3. + */ +static void generateWebSocketChallengeResponse(uint32_t number1, uint32_t number2, const unsigned char key3[8], unsigned char response[16]) +{ + uint8_t challenge[16]; + qToBigEndian<qint32>(number1, &challenge[0]); + qToBigEndian<qint32>(number2, &challenge[4]); + memcpy(&challenge[8], key3, 8); + MD5 md5; + md5.addBytes(challenge, sizeof(challenge)); + Vector<uint8_t, 16> digest; + md5.checksum(digest); + memcpy(response, digest.data(), 16); +} + +/*! + Parses and returns a WebSocket challenge number according to the + method specified in the WebSocket protocol. + + The field contains numeric digits interspersed with spaces and + non-numeric digits. The protocol ignores the characters that are + neither digits nor spaces. The digits are concatenated and + interpreted as a long int. The result is this number divided by + the number of spaces. + */ +static quint32 parseWebSocketChallengeNumber(QString field) +{ + QString nString; + int numSpaces = 0; + for (int i = 0; i < field.size(); i++) { + QChar c = field[i]; + if (c == (QChar)' ') { + numSpaces++; + } else if ((c >= (QChar)'0') && (c <= (QChar)'9')) { + nString.append((QChar)c); + } + } + quint32 num = nString.toLong(); + quint32 result = (numSpaces ? (num / numSpaces) : num); + return result; +} + +static InspectorServerQt* s_inspectorServer; + +InspectorServerQt* InspectorServerQt::server() +{ + // s_inspectorServer is deleted in unregisterClient() when the last client is unregistered. + if (!s_inspectorServer) + s_inspectorServer = new InspectorServerQt(); + + return s_inspectorServer; +} + +InspectorServerQt::InspectorServerQt() + : QObject() + , m_tcpServer(0) + , m_pageNumber(1) +{ +} + +InspectorServerQt::~InspectorServerQt() +{ + close(); +} + +void InspectorServerQt::listen(quint16 port) +{ + if (m_tcpServer) + return; + + m_tcpServer = new QTcpServer(); + m_tcpServer->listen(QHostAddress::Any, port); + connect(m_tcpServer, SIGNAL(newConnection()), SLOT(newConnection())); +} + +void InspectorServerQt::close() +{ + if (m_tcpServer) { + m_tcpServer->close(); + delete m_tcpServer; + } + m_tcpServer = 0; +} + +InspectorClientQt* InspectorServerQt::inspectorClientForPage(int pageNum) +{ + InspectorClientQt* client = m_inspectorClients.value(pageNum); + return client; +} + +void InspectorServerQt::registerClient(InspectorClientQt* client) +{ + if (!m_inspectorClients.key(client)) + m_inspectorClients.insert(m_pageNumber++, client); +} + +void InspectorServerQt::unregisterClient(InspectorClientQt* client) +{ + int pageNum = m_inspectorClients.key(client, -1); + if (pageNum >= 0) + m_inspectorClients.remove(pageNum); + if (!m_inspectorClients.size()) { + // s_inspectorServer points to this. + s_inspectorServer = 0; + close(); + deleteLater(); + } +} + +void InspectorServerQt::newConnection() +{ + QTcpSocket* tcpConnection = m_tcpServer->nextPendingConnection(); + InspectorServerRequestHandlerQt* handler = new InspectorServerRequestHandlerQt(tcpConnection, this); + handler->setParent(this); +} + +InspectorServerRequestHandlerQt::InspectorServerRequestHandlerQt(QTcpSocket* tcpConnection, InspectorServerQt* server) + : QObject(server) + , m_tcpConnection(tcpConnection) + , m_server(server) + , m_inspectorClient(0) +{ + m_endOfHeaders = false; + m_contentLength = 0; + + connect(m_tcpConnection, SIGNAL(readyRead()), SLOT(tcpReadyRead())); + connect(m_tcpConnection, SIGNAL(disconnected()), SLOT(tcpConnectionDisconnected())); +} + +InspectorServerRequestHandlerQt::~InspectorServerRequestHandlerQt() +{ +} + +void InspectorServerRequestHandlerQt::tcpReadyRead() +{ + QHttpRequestHeader header; + bool isWebSocket = false; + if (!m_tcpConnection) + return; + + if (!m_endOfHeaders) { + while (m_tcpConnection->bytesAvailable() && !m_endOfHeaders) { + QByteArray line = m_tcpConnection->readLine(); + m_data.append(line); + if (line == "\r\n") + m_endOfHeaders = true; + } + if (m_endOfHeaders) { + header = QHttpRequestHeader(QString::fromLatin1(m_data)); + if (header.isValid()) { + m_path = header.path(); + m_contentType = header.contentType().toLatin1(); + m_contentLength = header.contentLength(); + if (header.hasKey("Upgrade") && (header.value("Upgrade") == QLatin1String("WebSocket"))) + isWebSocket = true; + + m_data.clear(); + } + } + } + + if (m_endOfHeaders) { + QStringList pathAndQuery = m_path.split("?"); + m_path = pathAndQuery[0]; + QStringList words = m_path.split(QString::fromLatin1("/")); + + if (isWebSocket) { + // switch to websocket-style WebSocketService messaging + if (m_tcpConnection) { + m_tcpConnection->disconnect(SIGNAL(readyRead())); + connect(m_tcpConnection, SIGNAL(readyRead()), SLOT(webSocketReadyRead())); + + QByteArray key3 = m_tcpConnection->read(8); + + quint32 number1 = parseWebSocketChallengeNumber(header.value("Sec-WebSocket-Key1")); + quint32 number2 = parseWebSocketChallengeNumber(header.value("Sec-WebSocket-Key2")); + + char responseData[16]; + generateWebSocketChallengeResponse(number1, number2, (unsigned char*)key3.data(), (unsigned char*)responseData); + QByteArray response(responseData, sizeof(responseData)); + + QHttpResponseHeader responseHeader(101, "WebSocket Protocol Handshake", 1, 1); + responseHeader.setValue("Upgrade", header.value("Upgrade")); + responseHeader.setValue("Connection", header.value("Connection")); + responseHeader.setValue("Sec-WebSocket-Origin", header.value("Origin")); + responseHeader.setValue("Sec-WebSocket-Location", ("ws://" + header.value("Host") + m_path)); + responseHeader.setContentLength(response.size()); + m_tcpConnection->write(responseHeader.toString().toLatin1()); + m_tcpConnection->write(response); + m_tcpConnection->flush(); + + if ((words.size() == 4) + && (words[1] == QString::fromLatin1("devtools")) + && (words[2] == QString::fromLatin1("page"))) { + int pageNum = words[3].toInt(); + + m_inspectorClient = m_server->inspectorClientForPage(pageNum); + // Attach remoteFrontendChannel to inspector, also transferring ownership. + if (m_inspectorClient) + m_inspectorClient->attachAndReplaceRemoteFrontend(new RemoteFrontendChannel(this)); + } + + } + + return; + } + if (m_contentLength && (m_tcpConnection->bytesAvailable() < m_contentLength)) + return; + + QByteArray content = m_tcpConnection->read(m_contentLength); + m_endOfHeaders = false; + + QByteArray response; + int code = 200; + QString text = QString::fromLatin1("OK"); + + // If no path is specified, generate an index page. + if ((m_path == "") || (m_path == "/")) { + QString indexHtml = "<html><head><title>Remote Web Inspector</title></head><body><ul>\n"; + for (QMap<int, InspectorClientQt* >::const_iterator it = m_server->m_inspectorClients.begin(); + it != m_server->m_inspectorClients.end(); + ++it) { + indexHtml.append(QString("<li><a href=\"/webkit/inspector/inspector.html?page=%1\">%2</li>\n") + .arg(it.key()) + .arg(it.value()->m_inspectedWebPage->mainFrame()->url().toString())); + } + indexHtml.append("</ul></body></html>"); + response = indexHtml.toLatin1(); + } else { + QString path = QString(":%1").arg(m_path); + QFile file(path); + // It seems that there should be an enum or define for these status codes somewhere in Qt or WebKit, + // but grep fails to turn one up. + // QNetwork uses the numeric values directly. + if (file.exists()) { + file.open(QIODevice::ReadOnly); + response = file.readAll(); + } else { + code = 404; + text = QString::fromLatin1("Not OK"); + } + } + + QHttpResponseHeader responseHeader(code, text, 1, 0); + responseHeader.setContentLength(response.size()); + if (!m_contentType.isEmpty()) + responseHeader.setContentType(QString::fromLatin1(m_contentType)); + + QByteArray asciiHeader = responseHeader.toString().toAscii(); + m_tcpConnection->write(asciiHeader); + + m_tcpConnection->write(response); + m_tcpConnection->flush(); + m_tcpConnection->close(); + + return; + } +} + +void InspectorServerRequestHandlerQt::tcpConnectionDisconnected() +{ + if (m_inspectorClient) + m_inspectorClient->detachRemoteFrontend(); + m_tcpConnection->deleteLater(); + m_tcpConnection = 0; +} + +int InspectorServerRequestHandlerQt::webSocketSend(QByteArray payload) +{ + Q_ASSERT(m_tcpConnection); + m_tcpConnection->putChar(0x00); + int nBytes = m_tcpConnection->write(payload); + m_tcpConnection->putChar(0xFF); + m_tcpConnection->flush(); + return nBytes; +} + +int InspectorServerRequestHandlerQt::webSocketSend(const char* data, size_t length) +{ + Q_ASSERT(m_tcpConnection); + m_tcpConnection->putChar(0x00); + int nBytes = m_tcpConnection->write(data, length); + m_tcpConnection->putChar(0xFF); + m_tcpConnection->flush(); + return nBytes; +} + +void InspectorServerRequestHandlerQt::webSocketReadyRead() +{ + Q_ASSERT(m_tcpConnection); + if (!m_tcpConnection->bytesAvailable()) + return; + QByteArray content = m_tcpConnection->read(m_tcpConnection->bytesAvailable()); + m_data.append(content); + while (m_data.size() > 0) { + // first byte in websocket frame should be 0 + Q_ASSERT(!m_data[0]); + + // Start of WebSocket frame is indicated by 0 + if (m_data[0]) { + qCritical() << "webSocketReadyRead: unknown frame type" << m_data[0]; + m_data.clear(); + m_tcpConnection->close(); + return; + } + + // End of WebSocket frame indicated by 0xff. + int pos = m_data.indexOf(0xff, 1); + if (pos < 1) + return; + + // After above checks, length will be >= 0. + size_t length = pos - 1; + if (length <= 0) + return; + + QByteArray payload = m_data.mid(1, length); + + if (m_inspectorClient) { + InspectorController* inspectorController = m_inspectorClient->m_inspectedWebPage->d->page->inspectorController(); + inspectorController->inspectorBackendDispatcher()->dispatch(QString::fromUtf8(payload)); + } + + // Remove this WebSocket message from m_data (payload, start-of-frame byte, end-of-frame byte). + m_data = m_data.mid(length + 2); + } +} + +RemoteFrontendChannel::RemoteFrontendChannel(InspectorServerRequestHandlerQt* requestHandler) + : QObject(requestHandler) + , m_requestHandler(requestHandler) +{ +} + +bool RemoteFrontendChannel::sendMessageToFrontend(const String& message) +{ + if (!m_requestHandler) + return false; + CString cstr = message.utf8(); + return m_requestHandler->webSocketSend(cstr.data(), cstr.length()); +} + +} diff --git a/WebKit/qt/WebCoreSupport/InspectorServerQt.h b/WebKit/qt/WebCoreSupport/InspectorServerQt.h new file mode 100644 index 0000000..74e8c2f --- /dev/null +++ b/WebKit/qt/WebCoreSupport/InspectorServerQt.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef InspectorServerQt_h +#define InspectorServerQt_h + +#include <QList> +#include <QMap> +#include <QObject> +#include <QPair> +#include <QString> +#include <wtf/Forward.h> + +class QTcpServer; +class QTcpSocket; +class QWebPage; + +namespace WebCore { +class InspectorServerRequestHandlerQt; +class InspectorClientQt; + +class InspectorServerQt : public QObject { + Q_OBJECT +public: + + static InspectorServerQt* server(); + + void listen(quint16 port); + + void registerClient(InspectorClientQt* client); + void unregisterClient(InspectorClientQt* client); + + void close(); + InspectorClientQt* inspectorClientForPage(int pageNum); + +protected: + InspectorServerQt(); + virtual ~InspectorServerQt(); + +private slots: + void newConnection(); + +private: + QTcpServer* m_tcpServer; + QMap<int, InspectorClientQt*> m_inspectorClients; + int m_pageNumber; + + friend class InspectorServerRequestHandlerQt; +}; + +class RemoteFrontendChannel : public QObject { + Q_OBJECT +public: + + RemoteFrontendChannel(InspectorServerRequestHandlerQt* requestHandler); + bool sendMessageToFrontend(const String& message); + +private: + InspectorServerRequestHandlerQt* m_requestHandler; +}; + +class InspectorServerRequestHandlerQt : public QObject { + Q_OBJECT +public: + + InspectorServerRequestHandlerQt(QTcpSocket *tcpConnection, InspectorServerQt *server); + virtual ~InspectorServerRequestHandlerQt(); + virtual int webSocketSend(QByteArray payload); + virtual int webSocketSend(const char *payload, size_t length); + +private slots: + void tcpReadyRead(); + void tcpConnectionDisconnected(); + void webSocketReadyRead(); + +private: + QTcpSocket* m_tcpConnection; + InspectorServerQt* m_server; + + QString m_path; + QByteArray m_contentType; + int m_contentLength; + bool m_endOfHeaders; + QByteArray m_data; + InspectorClientQt* m_inspectorClient; + + void handleInspectorRequest(QStringList words); + void handleFromFrontendRequest(); + void handleResourceRequest(QStringList words); + +}; + +} +#endif diff --git a/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.cpp b/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.cpp new file mode 100644 index 0000000..0324c0d --- /dev/null +++ b/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.cpp @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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 "NotificationPresenterClientQt.h" + +#include "Document.h" +#include "DumpRenderTreeSupportQt.h" +#include "EventNames.h" +#include "KURL.h" +#include "Page.h" +#include "QtPlatformPlugin.h" +#include "ScriptExecutionContext.h" +#include "SecurityOrigin.h" +#include "UserGestureIndicator.h" + +#include "qwebframe_p.h" +#include "qwebkitglobal.h" +#include "qwebpage.h" + +namespace WebCore { + +#if ENABLE(NOTIFICATIONS) + +const double notificationTimeout = 10.0; + +bool NotificationPresenterClientQt::dumpNotification = false; + +NotificationPresenterClientQt* s_notificationPresenter = 0; + +NotificationPresenterClientQt* NotificationPresenterClientQt::notificationPresenter() +{ + if (s_notificationPresenter) + return s_notificationPresenter; + + s_notificationPresenter = new NotificationPresenterClientQt(); + return s_notificationPresenter; +} + +#endif + +NotificationWrapper::NotificationWrapper() + : m_closeTimer(this, &NotificationWrapper::close) +{ +#if ENABLE(NOTIFICATIONS) + +#ifndef QT_NO_SYSTEMTRAYICON + m_notificationIcon = 0; +#endif + m_presenter = 0; +#endif +} + +void NotificationWrapper::close(Timer<NotificationWrapper>*) +{ +#if ENABLE(NOTIFICATIONS) + NotificationPresenterClientQt::notificationPresenter()->cancel(this); +#endif +} + +const QString NotificationWrapper::title() const +{ +#if ENABLE(NOTIFICATIONS) + Notification* notification = NotificationPresenterClientQt::notificationPresenter()->notificationForWrapper(this); + if (notification) + return notification->contents().title(); +#endif + return QString(); +} + +const QString NotificationWrapper::message() const +{ +#if ENABLE(NOTIFICATIONS) + Notification* notification = NotificationPresenterClientQt::notificationPresenter()->notificationForWrapper(this); + if (notification) + return notification->contents().body(); +#endif + return QString(); +} + +const QByteArray NotificationWrapper::iconData() const +{ + QByteArray iconData; +#if ENABLE(NOTIFICATIONS) + Notification* notification = NotificationPresenterClientQt::notificationPresenter()->notificationForWrapper(this); + if (notification) { + if (notification->iconData()) + iconData = QByteArray::fromRawData(notification->iconData()->data(), notification->iconData()->size()); + } +#endif + return iconData; +} + +const QUrl NotificationWrapper::openerPageUrl() const +{ + QUrl url; +#if ENABLE(NOTIFICATIONS) + Notification* notification = NotificationPresenterClientQt::notificationPresenter()->notificationForWrapper(this); + if (notification) { + if (notification->scriptExecutionContext()) + url = static_cast<Document*>(notification->scriptExecutionContext())->page()->mainFrame()->document()->url(); + } +#endif + return url; +} + +void NotificationWrapper::notificationClicked() +{ +#if ENABLE(NOTIFICATIONS) + NotificationPresenterClientQt::notificationPresenter()->notificationClicked(this); +#endif +} + +void NotificationWrapper::notificationClosed() +{ +#if ENABLE(NOTIFICATIONS) + NotificationPresenterClientQt::notificationPresenter()->cancel(this); +#endif +} + +#if ENABLE(NOTIFICATIONS) + +NotificationPresenterClientQt::NotificationPresenterClientQt() : m_clientCount(0) +{ +} + +NotificationPresenterClientQt::~NotificationPresenterClientQt() +{ + while (!m_notifications.isEmpty()) { + NotificationsQueue::Iterator iter = m_notifications.begin(); + detachNotification(iter.key()); + } +} + +void NotificationPresenterClientQt::removeClient() +{ + m_clientCount--; + if (!m_clientCount) { + s_notificationPresenter = 0; + delete this; + } +} + +bool NotificationPresenterClientQt::show(Notification* notification) +{ + // FIXME: workers based notifications are not supported yet. + if (notification->scriptExecutionContext()->isWorkerContext()) + return false; + notification->setPendingActivity(notification); + if (!notification->replaceId().isEmpty()) + removeReplacedNotificationFromQueue(notification); + if (dumpNotification) + dumpShowText(notification); + QByteArray iconData; + if (notification->iconData()) + iconData = QByteArray::fromRawData(notification->iconData()->data(), notification->iconData()->size()); + displayNotification(notification, iconData); + notification->releaseIconData(); + return true; +} + +void NotificationPresenterClientQt::displayNotification(Notification* notification, const QByteArray& bytes) +{ + NotificationWrapper* wrapper = new NotificationWrapper(); + m_notifications.insert(notification, wrapper); + QString title; + QString message; + // FIXME: download & display HTML notifications + if (notification->isHTML()) + message = notification->url().string(); + else { + title = notification->contents().title(); + message = notification->contents().body(); + } + + if (m_platformPlugin.plugin() && m_platformPlugin.plugin()->supportsExtension(QWebKitPlatformPlugin::Notifications)) + wrapper->m_presenter = m_platformPlugin.createNotificationPresenter(); + + if (!wrapper->m_presenter) { +#ifndef QT_NO_SYSTEMTRAYICON + if (!dumpNotification) + wrapper->m_closeTimer.startOneShot(notificationTimeout); + QPixmap pixmap; + if (bytes.length() && pixmap.loadFromData(bytes)) { + QIcon icon(pixmap); + wrapper->m_notificationIcon = new QSystemTrayIcon(icon); + } else + wrapper->m_notificationIcon = new QSystemTrayIcon(); +#endif + } + + sendEvent(notification, "display"); + + // Make sure the notification was not cancelled during handling the display event + if (m_notifications.find(notification) == m_notifications.end()) + return; + + if (wrapper->m_presenter) { + wrapper->connect(wrapper->m_presenter.get(), SIGNAL(notificationClosed()), wrapper, SLOT(notificationClosed()), Qt::QueuedConnection); + wrapper->connect(wrapper->m_presenter.get(), SIGNAL(notificationClicked()), wrapper, SLOT(notificationClicked())); + wrapper->m_presenter->showNotification(wrapper); + return; + } + +#ifndef QT_NO_SYSTEMTRAYICON + wrapper->connect(wrapper->m_notificationIcon.get(), SIGNAL(messageClicked()), wrapper, SLOT(notificationClicked())); + wrapper->m_notificationIcon->show(); + wrapper->m_notificationIcon->showMessage(notification->contents().title(), notification->contents().body()); +#endif +} + +void NotificationPresenterClientQt::cancel(Notification* notification) +{ + if (dumpNotification && notification->scriptExecutionContext()) { + if (notification->isHTML()) + printf("DESKTOP NOTIFICATION CLOSED: %s\n", QString(notification->url().string()).toUtf8().constData()); + else + printf("DESKTOP NOTIFICATION CLOSED: %s\n", QString(notification->contents().title()).toUtf8().constData()); + } + + NotificationsQueue::Iterator iter = m_notifications.find(notification); + if (iter != m_notifications.end()) { + sendEvent(notification, eventNames().closeEvent); + detachNotification(notification); + } +} + +void NotificationPresenterClientQt::cancel(NotificationWrapper* wrapper) +{ + Notification* notification = notificationForWrapper(wrapper); + if (notification) + cancel(notification); +} + +void NotificationPresenterClientQt::notificationClicked(NotificationWrapper* wrapper) +{ + Notification* notification = notificationForWrapper(wrapper); + if (notification) { + // Make sure clicks on notifications are treated as user gestures. + UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); + sendEvent(notification, eventNames().clickEvent); + } +} + +void NotificationPresenterClientQt::notificationClicked(const QString& title) +{ + if (!dumpNotification) + return; + NotificationsQueue::ConstIterator end = m_notifications.end(); + NotificationsQueue::ConstIterator iter = m_notifications.begin(); + Notification* notification = 0; + while (iter != end) { + notification = iter.key(); + QString notificationTitle; + if (notification->isHTML()) + notificationTitle = notification->url().string(); + else + notificationTitle = notification->contents().title(); + if (notificationTitle == title) + break; + iter++; + } + if (notification) + sendEvent(notification, eventNames().clickEvent); +} + +Notification* NotificationPresenterClientQt::notificationForWrapper(const NotificationWrapper* wrapper) const +{ + NotificationsQueue::ConstIterator end = m_notifications.end(); + NotificationsQueue::ConstIterator iter = m_notifications.begin(); + while (iter != end && iter.value() != wrapper) + iter++; + if (iter != end) + return iter.key(); + return 0; +} + +void NotificationPresenterClientQt::notificationObjectDestroyed(Notification* notification) +{ + // Called from ~Notification(), Remove the entry from the notifications list and delete the icon. + NotificationsQueue::Iterator iter = m_notifications.find(notification); + if (iter != m_notifications.end()) + delete m_notifications.take(notification); +} + +void NotificationPresenterClientQt::requestPermission(ScriptExecutionContext* context, PassRefPtr<VoidCallback> callback) +{ + if (dumpNotification) + printf("DESKTOP NOTIFICATION PERMISSION REQUESTED: %s\n", QString(context->securityOrigin()->toString()).toUtf8().constData()); + + QHash<ScriptExecutionContext*, CallbacksInfo >::iterator iter = m_pendingPermissionRequests.find(context); + if (iter != m_pendingPermissionRequests.end()) + iter.value().m_callbacks.append(callback); + else { + RefPtr<VoidCallback> cb = callback; + CallbacksInfo info; + info.m_frame = toFrame(context); + info.m_callbacks.append(cb); + m_pendingPermissionRequests.insert(context, info); + + if (toPage(context) && toFrame(context)) { + m_pendingPermissionRequests.insert(context, info); + emit toPage(context)->requestPermissionFromUser(toFrame(context), QWebPage::NotificationsPermissionDomain); + } + } +} + +NotificationPresenter::Permission NotificationPresenterClientQt::checkPermission(ScriptExecutionContext* context) +{ + QWebPage::PermissionPolicy policy = QWebPage::PermissionUnknown; + if (toPage(context) && toFrame(context)) + emit toPage(context)->checkPermissionFromUser(toFrame(context), QWebPage::NotificationsPermissionDomain, policy); + + switch (policy) { + case QWebPage::PermissionGranted: + return NotificationPresenter::PermissionAllowed; + case QWebPage::PermissionUnknown: + return NotificationPresenter::PermissionNotAllowed; + case QWebPage::PermissionDenied: + return NotificationPresenter::PermissionDenied; + } + ASSERT_NOT_REACHED(); + return NotificationPresenter::PermissionNotAllowed; +} + +void NotificationPresenterClientQt::cancelRequestsForPermission(ScriptExecutionContext* context) +{ + QHash<ScriptExecutionContext*, CallbacksInfo >::iterator iter = m_pendingPermissionRequests.find(context); + if (iter == m_pendingPermissionRequests.end()) + return; + + QWebFrame* frame = iter.value().m_frame; + if (!frame) + return; + QWebPage* page = frame->page(); + m_pendingPermissionRequests.erase(iter); + + if (!page) + return; + + if (dumpNotification) + printf("DESKTOP NOTIFICATION PERMISSION REQUEST CANCELLED: %s\n", QString(context->securityOrigin()->toString()).toUtf8().constData()); + + emit page->cancelRequestsForPermission(frame, QWebPage::NotificationsPermissionDomain); +} + +void NotificationPresenterClientQt::allowNotificationForFrame(QWebFrame* frame) +{ + QHash<ScriptExecutionContext*, CallbacksInfo>::iterator iter = m_pendingPermissionRequests.begin(); + while (iter != m_pendingPermissionRequests.end()) { + if (toFrame(iter.key()) == frame) + break; + } + + if (iter == m_pendingPermissionRequests.end()) + return; + + QList<RefPtr<VoidCallback> >& callbacks = iter.value().m_callbacks; + for (int i = 0; i < callbacks.size(); i++) + callbacks.at(i)->handleEvent(); + m_pendingPermissionRequests.remove(iter.key()); +} + +void NotificationPresenterClientQt::sendEvent(Notification* notification, const AtomicString& eventName) +{ + if (notification->scriptExecutionContext()) + notification->dispatchEvent(Event::create(eventName, false, true)); +} + +void NotificationPresenterClientQt::removeReplacedNotificationFromQueue(Notification* notification) +{ + Notification* oldNotification = 0; + NotificationsQueue::Iterator end = m_notifications.end(); + NotificationsQueue::Iterator iter = m_notifications.begin(); + + while (iter != end) { + Notification* existingNotification = iter.key(); + if (existingNotification->replaceId() == notification->replaceId() && existingNotification->url().protocol() == notification->url().protocol() && existingNotification->url().host() == notification->url().host()) { + oldNotification = iter.key(); + break; + } + iter++; + } + + if (oldNotification) { + if (dumpNotification) + dumpReplacedIdText(oldNotification); + sendEvent(oldNotification, eventNames().closeEvent); + detachNotification(oldNotification); + } +} + +void NotificationPresenterClientQt::detachNotification(Notification* notification) +{ + delete m_notifications.take(notification); + notification->detachPresenter(); + notification->unsetPendingActivity(notification); +} + +void NotificationPresenterClientQt::dumpReplacedIdText(Notification* notification) +{ + if (notification) + printf("REPLACING NOTIFICATION %s\n", notification->isHTML() ? QString(notification->url().string()).toUtf8().constData() : QString(notification->contents().title()).toUtf8().constData()); +} + +void NotificationPresenterClientQt::dumpShowText(Notification* notification) +{ + if (notification->isHTML()) + printf("DESKTOP NOTIFICATION: contents at %s\n", QString(notification->url().string()).toUtf8().constData()); + else { + printf("DESKTOP NOTIFICATION:%s icon %s, title %s, text %s\n", + notification->dir() == "rtl" ? "(RTL)" : "", + QString(notification->contents().icon().string()).toUtf8().constData(), QString(notification->contents().title()).toUtf8().constData(), + QString(notification->contents().body()).toUtf8().constData()); + } +} + +QWebPage* NotificationPresenterClientQt::toPage(ScriptExecutionContext* context) +{ + if (!context || context->isWorkerContext()) + return 0; + + Document* document = static_cast<Document*>(context); + if (!document) + return 0; + + Page* page = document->page(); + if (!page || !page->mainFrame()) + return 0; + + return QWebFramePrivate::kit(page->mainFrame())->page(); +} + +QWebFrame* NotificationPresenterClientQt::toFrame(ScriptExecutionContext* context) +{ + if (!context || context->isWorkerContext()) + return 0; + + Document* document = static_cast<Document*>(context); + if (!document || !document->frame()) + return 0; + + return QWebFramePrivate::kit(document->frame()); +} + +#endif // ENABLE(NOTIFICATIONS) +} + +#include "moc_NotificationPresenterClientQt.cpp" diff --git a/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.h b/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.h new file mode 100644 index 0000000..2520f6c --- /dev/null +++ b/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ + +#ifndef NotificationPresenterClientQt_h +#define NotificationPresenterClientQt_h + +#include "Notification.h" +#include "NotificationPresenter.h" +#include "QtPlatformPlugin.h" +#include "Timer.h" + +#include "qwebkitplatformplugin.h" + +#include <QMultiHash> +#include <QSystemTrayIcon> + +class QWebFrame; +class QWebPage; + +namespace WebCore { + +class Document; +class ScriptExecutionContext; + +class NotificationWrapper : public QObject, public QWebNotificationData { + Q_OBJECT +public: + NotificationWrapper(); + ~NotificationWrapper() {} + + void close(); + void close(Timer<NotificationWrapper>*); + const QString title() const; + const QString message() const; + const QByteArray iconData() const; + const QUrl openerPageUrl() const; + +public Q_SLOTS: + void notificationClosed(); + void notificationClicked(); + +public: +#ifndef QT_NO_SYSTEMTRAYICON + OwnPtr<QSystemTrayIcon> m_notificationIcon; +#endif + + OwnPtr<QWebNotificationPresenter> m_presenter; + Timer<NotificationWrapper> m_closeTimer; +}; + +#if ENABLE(NOTIFICATIONS) + +typedef QHash <Notification*, NotificationWrapper*> NotificationsQueue; + +class NotificationPresenterClientQt : public NotificationPresenter { +public: + NotificationPresenterClientQt(); + ~NotificationPresenterClientQt(); + + /* WebCore::NotificationPresenter interface */ + virtual bool show(Notification*); + virtual void cancel(Notification*); + virtual void notificationObjectDestroyed(Notification*); + virtual void requestPermission(ScriptExecutionContext*, PassRefPtr<VoidCallback>); + virtual NotificationPresenter::Permission checkPermission(ScriptExecutionContext*); + virtual void cancelRequestsForPermission(ScriptExecutionContext*); + + void cancel(NotificationWrapper*); + + void allowNotificationForFrame(QWebFrame*); + + static bool dumpNotification; + + void addClient() { m_clientCount++; } + void removeClient(); + static NotificationPresenterClientQt* notificationPresenter(); + + Notification* notificationForWrapper(const NotificationWrapper*) const; + void notificationClicked(NotificationWrapper*); + void notificationClicked(const QString& title); + +private: + void sendEvent(Notification*, const AtomicString& eventName); + void displayNotification(Notification*, const QByteArray&); + void removeReplacedNotificationFromQueue(Notification*); + void detachNotification(Notification*); + void dumpReplacedIdText(Notification*); + void dumpShowText(Notification*); + QWebPage* toPage(ScriptExecutionContext*); + QWebFrame* toFrame(ScriptExecutionContext*); + + int m_clientCount; + struct CallbacksInfo { + QWebFrame* m_frame; + QList<RefPtr<VoidCallback> > m_callbacks; + }; + QHash<ScriptExecutionContext*, CallbacksInfo > m_pendingPermissionRequests; + + NotificationsQueue m_notifications; + QtPlatformPlugin m_platformPlugin; +}; + +#endif + +} + +#endif diff --git a/WebKit/qt/WebCoreSupport/PageClientQt.cpp b/WebKit/qt/WebCoreSupport/PageClientQt.cpp new file mode 100644 index 0000000..9fa5bf7 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/PageClientQt.cpp @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#include "PageClientQt.h" +#include "TextureMapperQt.h" +#include "texmap/TextureMapperPlatformLayer.h" +#include <QGraphicsScene> +#include <QGraphicsView> +#if defined(Q_WS_X11) +#include <QX11Info> +#endif + +#ifdef QT_OPENGL_LIB +#include "opengl/TextureMapperGL.h" +#include <QGLWidget> +#endif + +namespace WebCore { + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +class PlatformLayerProxyQt : public QObject, public virtual TextureMapperLayerClient { +public: + PlatformLayerProxyQt(QWebFrame* frame, TextureMapperContentLayer* layer, QObject* object) + : QObject(object) + , m_frame(frame) + , m_layer(layer) + { + if (m_layer) + m_layer->setPlatformLayerClient(this); + m_frame->d->rootGraphicsLayer = m_layer; + } + + void setTextureMapper(PassOwnPtr<TextureMapper> textureMapper) + { + m_frame->d->textureMapper = textureMapper; + } + + virtual ~PlatformLayerProxyQt() + { + if (m_layer) + m_layer->setPlatformLayerClient(0); + if (m_frame->d) + m_frame->d->rootGraphicsLayer = 0; + } + + virtual TextureMapper* textureMapper() + { + return m_frame->d->textureMapper.get(); + } + + // Since we just paint the composited tree and never create a special item for it, we don't have to handle its size changes. + void setSizeChanged(const IntSize&) { } + +private: + QWebFrame* m_frame; + TextureMapperContentLayer* m_layer; +}; + +class PlatformLayerProxyQWidget : public PlatformLayerProxyQt { +public: + PlatformLayerProxyQWidget(QWebFrame* frame, TextureMapperContentLayer* layer, QWidget* widget) + : PlatformLayerProxyQt(frame, layer, widget) + , m_widget(widget) + { + if (m_widget) + m_widget->installEventFilter(this); + + if (textureMapper()) + return; + + setTextureMapper(TextureMapperQt::create()); + } + + // We don't want a huge region-clip on the compositing layers; instead we unite the rectangles together + // and clear them when the paint actually occurs. + bool eventFilter(QObject* object, QEvent* event) + { + if (object == m_widget && event->type() == QEvent::Paint) + m_dirtyRect = QRect(); + return QObject::eventFilter(object, event); + } + + void setNeedsDisplay() + { + if (m_widget) + m_widget->update(); + } + + void setNeedsDisplayInRect(const IntRect& rect) + { + m_dirtyRect |= rect; + m_widget->update(m_dirtyRect); + } + +private: + QRect m_dirtyRect; + QWidget* m_widget; +}; + +class PlatformLayerProxyQGraphicsObject : public PlatformLayerProxyQt { +public: + PlatformLayerProxyQGraphicsObject(QWebFrame* frame, TextureMapperContentLayer* layer, QGraphicsObject* object) + : PlatformLayerProxyQt(frame, layer, object) + , m_graphicsItem(object) + { + if (textureMapper()) + return; + +#ifdef QT_OPENGL_LIB + QGraphicsView* view = object->scene()->views()[0]; + if (view && view->viewport() && view->viewport()->inherits("QGLWidget")) { + setTextureMapper(TextureMapperGL::create()); + return; + } +#endif + setTextureMapper(TextureMapperQt::create()); + } + + void setNeedsDisplay() + { + if (m_graphicsItem) + m_graphicsItem->update(); + } + + void setNeedsDisplayInRect(const IntRect& rect) + { + if (m_graphicsItem) + m_graphicsItem->update(QRectF(rect)); + } + +private: + QGraphicsItem* m_graphicsItem; +}; + +void PageClientQWidget::setRootGraphicsLayer(TextureMapperPlatformLayer* layer) +{ + if (layer) { + platformLayerProxy = new PlatformLayerProxyQWidget(page->mainFrame(), static_cast<TextureMapperContentLayer*>(layer), view); + return; + } + delete platformLayerProxy; + platformLayerProxy = 0; +} + +void PageClientQWidget::markForSync(bool scheduleSync) +{ + syncTimer.startOneShot(0); +} + +void PageClientQWidget::syncLayers(Timer<PageClientQWidget>*) +{ + QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateRecursive(); +} +#endif + +void PageClientQWidget::scroll(int dx, int dy, const QRect& rectToScroll) +{ + view->scroll(qreal(dx), qreal(dy), rectToScroll); +} + +void PageClientQWidget::update(const QRect & dirtyRect) +{ + view->update(dirtyRect); +} + +void PageClientQWidget::setInputMethodEnabled(bool enable) +{ + view->setAttribute(Qt::WA_InputMethodEnabled, enable); +} + +bool PageClientQWidget::inputMethodEnabled() const +{ + return view->testAttribute(Qt::WA_InputMethodEnabled); +} + +void PageClientQWidget::setInputMethodHints(Qt::InputMethodHints hints) +{ + view->setInputMethodHints(hints); +} + +PageClientQWidget::~PageClientQWidget() +{ +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + delete platformLayerProxy; +#endif +} + +#ifndef QT_NO_CURSOR +QCursor PageClientQWidget::cursor() const +{ + return view->cursor(); +} + +void PageClientQWidget::updateCursor(const QCursor& cursor) +{ + view->setCursor(cursor); +} +#endif + +QPalette PageClientQWidget::palette() const +{ + return view->palette(); +} + +int PageClientQWidget::screenNumber() const +{ +#if defined(Q_WS_X11) + return view->x11Info().screen(); +#endif + return 0; +} + +QWidget* PageClientQWidget::ownerWidget() const +{ + return view; +} + +QRect PageClientQWidget::geometryRelativeToOwnerWidget() const +{ + return view->geometry(); +} + +QObject* PageClientQWidget::pluginParent() const +{ + return view; +} + +QStyle* PageClientQWidget::style() const +{ + return view->style(); +} + +QRectF PageClientQWidget::windowRect() const +{ + return QRectF(view->window()->geometry()); +} + +PageClientQGraphicsWidget::~PageClientQGraphicsWidget() +{ + delete overlay; +#if USE(ACCELERATED_COMPOSITING) +#if USE(TEXTURE_MAPPER) + delete platformLayerProxy; +#else + if (!rootGraphicsLayer) + return; + // we don't need to delete the root graphics layer. The lifecycle is managed in GraphicsLayerQt.cpp. + rootGraphicsLayer.data()->setParentItem(0); + view->scene()->removeItem(rootGraphicsLayer.data()); +#endif +#endif +} + +void PageClientQGraphicsWidget::scroll(int dx, int dy, const QRect& rectToScroll) +{ + view->scroll(qreal(dx), qreal(dy), rectToScroll); +} + +void PageClientQGraphicsWidget::update(const QRect& dirtyRect) +{ + view->update(dirtyRect); + + createOrDeleteOverlay(); + if (overlay) + overlay->update(QRectF(dirtyRect)); +#if USE(ACCELERATED_COMPOSITING) + syncLayers(); +#endif +} + +void PageClientQGraphicsWidget::createOrDeleteOverlay() +{ + // We don't use an overlay with TextureMapper. Instead, the overlay is drawn inside QWebFrame. +#if !USE(TEXTURE_MAPPER) + bool useOverlay = false; + if (!viewResizesToContents) { +#if USE(ACCELERATED_COMPOSITING) + useOverlay = useOverlay || rootGraphicsLayer; +#endif +#if ENABLE(TILED_BACKING_STORE) + useOverlay = useOverlay || QWebFramePrivate::core(page->mainFrame())->tiledBackingStore(); +#endif + } + if (useOverlay == !!overlay) + return; + + if (useOverlay) { + overlay = new QGraphicsItemOverlay(view, page); + overlay->setZValue(OverlayZValue); + } else { + // Changing the overlay might be done inside paint events. + overlay->deleteLater(); + overlay = 0; + } +#endif // !USE(TEXTURE_MAPPER) +} + +#if USE(ACCELERATED_COMPOSITING) +void PageClientQGraphicsWidget::syncLayers() +{ + if (shouldSync) { + QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateRecursive(); + shouldSync = false; + } +} + +#if USE(TEXTURE_MAPPER) +void PageClientQGraphicsWidget::setRootGraphicsLayer(TextureMapperPlatformLayer* layer) +{ + if (layer) { + platformLayerProxy = new PlatformLayerProxyQGraphicsObject(page->mainFrame(), static_cast<TextureMapperContentLayer*>(layer), view); + return; + } + delete platformLayerProxy; + platformLayerProxy = 0; +} +#else +void PageClientQGraphicsWidget::setRootGraphicsLayer(QGraphicsObject* layer) +{ + if (rootGraphicsLayer) { + rootGraphicsLayer.data()->setParentItem(0); + view->scene()->removeItem(rootGraphicsLayer.data()); + QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateRecursive(); + } + + rootGraphicsLayer = layer; + + if (layer) { + layer->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); + layer->setParentItem(view); + layer->setZValue(RootGraphicsLayerZValue); + } + createOrDeleteOverlay(); +} +#endif + +void PageClientQGraphicsWidget::markForSync(bool scheduleSync) +{ + shouldSync = true; + if (scheduleSync) + syncMetaMethod.invoke(view, Qt::QueuedConnection); +} + +#endif + +#if ENABLE(TILED_BACKING_STORE) +void PageClientQGraphicsWidget::updateTiledBackingStoreScale() +{ + WebCore::TiledBackingStore* backingStore = QWebFramePrivate::core(page->mainFrame())->tiledBackingStore(); + if (!backingStore) + return; + backingStore->setContentsScale(view->scale()); +} +#endif + +void PageClientQGraphicsWidget::setInputMethodEnabled(bool enable) +{ + view->setFlag(QGraphicsItem::ItemAcceptsInputMethod, enable); +} + +bool PageClientQGraphicsWidget::inputMethodEnabled() const +{ + return view->flags() & QGraphicsItem::ItemAcceptsInputMethod; +} + +void PageClientQGraphicsWidget::setInputMethodHints(Qt::InputMethodHints hints) +{ + view->setInputMethodHints(hints); +} + +#ifndef QT_NO_CURSOR +QCursor PageClientQGraphicsWidget::cursor() const +{ + return view->cursor(); +} + +void PageClientQGraphicsWidget::updateCursor(const QCursor& cursor) +{ + view->setCursor(cursor); +} +#endif + +QPalette PageClientQGraphicsWidget::palette() const +{ + return view->palette(); +} + +int PageClientQGraphicsWidget::screenNumber() const +{ +#if defined(Q_WS_X11) + if (QGraphicsScene* scene = view->scene()) { + const QList<QGraphicsView*> views = scene->views(); + + if (!views.isEmpty()) + return views.at(0)->x11Info().screen(); + } +#endif + + return 0; +} + +QWidget* PageClientQGraphicsWidget::ownerWidget() const +{ + if (QGraphicsScene* scene = view->scene()) { + const QList<QGraphicsView*> views = scene->views(); + return views.value(0); + } + return 0; +} + +QRect PageClientQGraphicsWidget::geometryRelativeToOwnerWidget() const +{ + if (!view->scene()) + return QRect(); + + QList<QGraphicsView*> views = view->scene()->views(); + if (views.isEmpty()) + return QRect(); + + QGraphicsView* graphicsView = views.at(0); + return graphicsView->mapFromScene(view->boundingRect()).boundingRect(); +} + +#if ENABLE(TILED_BACKING_STORE) +QRectF PageClientQGraphicsWidget::graphicsItemVisibleRect() const +{ + if (!view->scene()) + return QRectF(); + + QList<QGraphicsView*> views = view->scene()->views(); + if (views.isEmpty()) + return QRectF(); + + QGraphicsView* graphicsView = views.at(0); + int xOffset = graphicsView->horizontalScrollBar()->value(); + int yOffset = graphicsView->verticalScrollBar()->value(); + return view->mapRectFromScene(QRectF(QPointF(xOffset, yOffset), graphicsView->viewport()->size())); +} +#endif + +QObject* PageClientQGraphicsWidget::pluginParent() const +{ + return view; +} + +QStyle* PageClientQGraphicsWidget::style() const +{ + return view->style(); +} + +QRectF PageClientQGraphicsWidget::windowRect() const +{ + if (!view->scene()) + return QRectF(); + + // The sceneRect is a good approximation of the size of the application, independent of the view. + return view->scene()->sceneRect(); +} + +} // namespace WebCore diff --git a/WebKit/qt/WebCoreSupport/PageClientQt.h b/WebKit/qt/WebCoreSupport/PageClientQt.h new file mode 100644 index 0000000..924d2a7 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/PageClientQt.h @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef PageClientQt_h +#define PageClientQt_h + +#include "FrameView.h" +#include "GraphicsContext.h" +#include "IntRect.h" +#include "QWebPageClient.h" +#include "TiledBackingStore.h" +#include "qgraphicswebview.h" +#include "qwebframe.h" +#include "qwebframe_p.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include <QtCore/qmetaobject.h> +#include <QtGui/qgraphicsscene.h> +#include <QtGui/qgraphicsview.h> +#include <QtGui/qgraphicswidget.h> +#include <QtGui/qscrollbar.h> +#include <QtGui/qstyleoption.h> +#include <QtGui/qwidget.h> + +#include <Settings.h> + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#include "texmap/TextureMapperPlatformLayer.h" +#endif + +namespace WebCore { + +class PageClientQWidget : public QWebPageClient { +public: + PageClientQWidget(QWidget* newView, QWebPage* newPage) + : view(newView) + , page(newPage) +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + , syncTimer(this, &PageClientQWidget::syncLayers) + , platformLayerProxy(0) +#endif + { + Q_ASSERT(view); + } + virtual ~PageClientQWidget(); + + virtual bool isQWidgetClient() const { return true; } + + virtual void scroll(int dx, int dy, const QRect&); + virtual void update(const QRect& dirtyRect); + virtual void setInputMethodEnabled(bool enable); + virtual bool inputMethodEnabled() const; + virtual void setInputMethodHints(Qt::InputMethodHints hints); + +#ifndef QT_NO_CURSOR + virtual QCursor cursor() const; + virtual void updateCursor(const QCursor& cursor); +#endif + + virtual QPalette palette() const; + virtual int screenNumber() const; + virtual QWidget* ownerWidget() const; + virtual QRect geometryRelativeToOwnerWidget() const; + + virtual QObject* pluginParent() const; + + virtual QStyle* style() const; + + virtual bool viewResizesToContentsEnabled() const { return false; } + + virtual QRectF windowRect() const; + + QWidget* view; + QWebPage* page; + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + virtual void setRootGraphicsLayer(TextureMapperPlatformLayer* layer); + virtual void markForSync(bool scheduleSync); + void syncLayers(Timer<PageClientQWidget>*); +#endif + + // QGraphicsWebView can render composited layers + virtual bool allowsAcceleratedCompositing() const { return true; } + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + Timer<PageClientQWidget> syncTimer; + PlatformLayerProxyQt* platformLayerProxy; +#endif +}; + +// the overlay is here for one reason only: to have the scroll-bars and other +// extra UI elements appear on top of any QGraphicsItems created by CSS compositing layers +class QGraphicsItemOverlay : public QGraphicsObject { + public: + QGraphicsItemOverlay(QGraphicsWidget* view, QWebPage* p) + :QGraphicsObject(view) + , q(view) + , page(p) + { + setPos(0, 0); + setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); + setCacheMode(QGraphicsItem::DeviceCoordinateCache); + } + + QRectF boundingRect() const + { + return q->boundingRect(); + } + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* options, QWidget*) + { + page->mainFrame()->render(painter, static_cast<QWebFrame::RenderLayer>(QWebFrame::AllLayers&(~QWebFrame::ContentsLayer)), options->exposedRect.toRect()); + } + + void prepareGraphicsItemGeometryChange() + { + prepareGeometryChange(); + } + + QGraphicsWidget* q; + QWebPage* page; +}; + + +class PageClientQGraphicsWidget : public QWebPageClient { +public: + PageClientQGraphicsWidget(QGraphicsWebView* newView, QWebPage* newPage) + : view(newView) + , page(newPage) + , viewResizesToContents(false) +#if USE(ACCELERATED_COMPOSITING) +#if USE(TEXTURE_MAPPER) + , platformLayerProxy(0) +#endif + , shouldSync(false) +#endif + , overlay(0) + { + Q_ASSERT(view); +#if USE(ACCELERATED_COMPOSITING) + // the overlay and stays alive for the lifetime of + // this QGraphicsWebView as the scrollbars are needed when there's no compositing + view->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); + syncMetaMethod = view->metaObject()->method(view->metaObject()->indexOfMethod("syncLayers()")); +#endif + } + + virtual ~PageClientQGraphicsWidget(); + + virtual bool isQWidgetClient() const { return false; } + + virtual void scroll(int dx, int dy, const QRect&); + virtual void update(const QRect& dirtyRect); + virtual void setInputMethodEnabled(bool enable); + virtual bool inputMethodEnabled() const; + virtual void setInputMethodHints(Qt::InputMethodHints hints); + +#ifndef QT_NO_CURSOR + virtual QCursor cursor() const; + virtual void updateCursor(const QCursor& cursor); +#endif + + virtual QPalette palette() const; + virtual int screenNumber() const; + virtual QWidget* ownerWidget() const; + virtual QRect geometryRelativeToOwnerWidget() const; + + virtual QObject* pluginParent() const; + + virtual QStyle* style() const; + + virtual bool viewResizesToContentsEnabled() const { return viewResizesToContents; } + + void createOrDeleteOverlay(); + +#if ENABLE(TILED_BACKING_STORE) + void updateTiledBackingStoreScale(); + virtual QRectF graphicsItemVisibleRect() const; +#endif + +#if USE(ACCELERATED_COMPOSITING) + virtual void setRootGraphicsLayer(PlatformLayer* layer); + virtual void markForSync(bool scheduleSync); + void syncLayers(); + + // QGraphicsWebView can render composited layers + virtual bool allowsAcceleratedCompositing() const { return true; } +#endif + + virtual QRectF windowRect() const; + + QGraphicsWebView* view; + QWebPage* page; + bool viewResizesToContents; + +#if USE(ACCELERATED_COMPOSITING) +#if USE(TEXTURE_MAPPER) + PlatformLayerProxyQt* platformLayerProxy; +#else + QWeakPointer<QGraphicsObject> rootGraphicsLayer; +#endif + // we have to flush quite often, so we use a meta-method instead of QTimer::singleShot for putting the event in the queue + QMetaMethod syncMetaMethod; + + // we need to sync the layers if we get a special call from the WebCore + // compositor telling us to do so. We'll get that call from ChromeClientQt + bool shouldSync; +#endif + // the overlay gets instantiated when the root layer is attached, and get deleted when it's detached + QGraphicsItemOverlay* overlay; + + // we need to put the root graphics layer behind the overlay (which contains the scrollbar) + enum { RootGraphicsLayerZValue, OverlayZValue }; +}; + +} +#endif // PageClientQt diff --git a/WebKit/qt/WebCoreSupport/PopupMenuQt.cpp b/WebKit/qt/WebCoreSupport/PopupMenuQt.cpp new file mode 100644 index 0000000..9b34955 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/PopupMenuQt.cpp @@ -0,0 +1,158 @@ +/* + * This file is part of the popup menu implementation for <select> elements in WebCore. + * + * Copyright (C) 2008, 2009, 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Coypright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "PopupMenuQt.h" + +#include "ChromeClientQt.h" +#include "FrameView.h" +#include "PopupMenuClient.h" +#include "QtFallbackWebPopup.h" + +#include "qwebkitplatformplugin.h" + +class SelectData : public QWebSelectData { +public: + SelectData(WebCore::PopupMenuClient*& data) : d(data) {} + + virtual ItemType itemType(int) const; + virtual QString itemText(int idx) const { return QString(d ? d->itemText(idx) : ""); } + virtual QString itemToolTip(int idx) const { return QString(d ? d->itemToolTip(idx) : ""); } + virtual bool itemIsEnabled(int idx) const { return d ? d->itemIsEnabled(idx) : false; } + virtual int itemCount() const { return d ? d->listSize() : 0; } + virtual bool itemIsSelected(int idx) const { return d ? d->itemIsSelected(idx) : false; } + virtual bool multiple() const; + +private: + WebCore::PopupMenuClient*& d; +}; + +bool SelectData::multiple() const +{ + if (!d) + return false; + +#if ENABLE(NO_LISTBOX_RENDERING) + WebCore::ListPopupMenuClient* client = static_cast<WebCore::ListPopupMenuClient*>(d); + return client && client->multiple(); +#else + return false; +#endif +} + +SelectData::ItemType SelectData::itemType(int idx) const +{ + if (!d) + return SelectData::Option; + + if (d->itemIsSeparator(idx)) + return SelectData::Separator; + if (d->itemIsLabel(idx)) + return SelectData::Group; + return SelectData::Option; +} + +namespace WebCore { + +PopupMenuQt::PopupMenuQt(PopupMenuClient* client, const ChromeClientQt* chromeClient) + : m_popupClient(client) + , m_popup(0) + , m_selectData(0) + , m_chromeClient(chromeClient) +{ +} + +PopupMenuQt::~PopupMenuQt() +{ + delete m_selectData; + delete m_popup; +} + +void PopupMenuQt::disconnectClient() +{ + m_popupClient = 0; +} + +void PopupMenuQt::show(const IntRect& rect, FrameView* view, int index) +{ + if (!m_popupClient) + return; + + if (!m_popup) { + m_popup = m_chromeClient->createSelectPopup(); + connect(m_popup, SIGNAL(didHide()), this, SLOT(didHide())); + connect(m_popup, SIGNAL(selectItem(int, bool, bool)), this, SLOT(selectItem(int, bool, bool))); + } + + if (QtFallbackWebPopup* fallback = qobject_cast<QtFallbackWebPopup*>(m_popup)) { + QRect geometry(rect); + geometry.moveTopLeft(view->contentsToWindow(rect.topLeft())); + fallback->setGeometry(geometry); + fallback->setFont(m_popupClient->menuStyle().font().font()); + } + + if (m_selectData) + delete m_selectData; + m_selectData = new SelectData(m_popupClient); + m_popup->show(*m_selectData); +} + +void PopupMenuQt::didHide() +{ + if (m_popupClient) + m_popupClient->popupDidHide(); +} + +void PopupMenuQt::hide() +{ + if (m_popup) + m_popup->hide(); +} + +void PopupMenuQt::updateFromElement() +{ + if (m_popupClient) + m_popupClient->setTextFromItem(m_popupClient->selectedIndex()); +} + +void PopupMenuQt::selectItem(int index, bool ctrl, bool shift) +{ + if (!m_popupClient) + return; + +#if ENABLE(NO_LISTBOX_RENDERING) + ListPopupMenuClient* client = static_cast<ListPopupMenuClient*>(m_popupClient); + if (client) { + client->listBoxSelectItem(index, ctrl, shift); + return; + } +#endif + + m_popupClient->valueChanged(index); +} + +} + +// vim: ts=4 sw=4 et diff --git a/WebKit/qt/WebCoreSupport/PopupMenuQt.h b/WebKit/qt/WebCoreSupport/PopupMenuQt.h new file mode 100644 index 0000000..837f323 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/PopupMenuQt.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef PopupMenuQt_h +#define PopupMenuQt_h + +#include "PopupMenu.h" +#include <QObject> + +class QWebSelectData; +class QWebSelectMethod; + +namespace WebCore { + +class ChromeClientQt; +class FrameView; +class PopupMenuClient; + +class PopupMenuQt : public QObject, public PopupMenu { + Q_OBJECT +public: + PopupMenuQt(PopupMenuClient*, const ChromeClientQt*); + ~PopupMenuQt(); + + virtual void show(const IntRect&, FrameView*, int index); + virtual void hide(); + virtual void updateFromElement(); + virtual void disconnectClient(); + +private slots: + void didHide(); + void selectItem(int index, bool ctrl, bool shift); + +private: + PopupMenuClient* m_popupClient; + QWebSelectMethod* m_popup; + QWebSelectData* m_selectData; + const ChromeClientQt* m_chromeClient; +}; + +} + +#endif // PopupMenuQt_h diff --git a/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.cpp b/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.cpp index c553c45..3f69a47 100644 --- a/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.cpp +++ b/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.cpp @@ -21,10 +21,11 @@ #include "config.h" #include "QtFallbackWebPopup.h" -#include "HostWindow.h" -#include "PopupMenuClient.h" -#include "qgraphicswebview.h" +#ifndef QT_NO_COMBOBOX + +#include "ChromeClientQt.h" #include "QWebPageClient.h" +#include "qgraphicswebview.h" #include <QAbstractItemView> #include <QApplication> #include <QGraphicsProxyWidget> @@ -34,11 +35,21 @@ #include <QMouseEvent> #include <QStandardItemModel> +#if ENABLE(SYMBIAN_DIALOG_PROVIDERS) +#include <BrCtlDialogsProvider.h> +#include <BrowserDialogsProvider.h> // S60 platform private header file +#include <e32base.h> +#endif + namespace WebCore { QtFallbackWebPopupCombo::QtFallbackWebPopupCombo(QtFallbackWebPopup& ownerPopup) : m_ownerPopup(ownerPopup) { + // Install an event filter on the view inside the combo box popup to make sure we know + // when the popup got closed. E.g. QComboBox::hidePopup() won't be called when the popup + // is closed by a mouse wheel event outside its window. + view()->installEventFilter(this); } void QtFallbackWebPopupCombo::showPopup() @@ -49,6 +60,7 @@ void QtFallbackWebPopupCombo::showPopup() void QtFallbackWebPopupCombo::hidePopup() { +#ifndef QT_NO_IM QWidget* activeFocus = QApplication::focusWidget(); if (activeFocus && activeFocus == QComboBox::view() && activeFocus->testAttribute(Qt::WA_InputMethodEnabled)) { @@ -58,60 +70,65 @@ void QtFallbackWebPopupCombo::hidePopup() qic->setFocusWidget(0); } } +#endif // QT_NO_IM QComboBox::hidePopup(); - if (QGraphicsProxyWidget* proxy = graphicsProxyWidget()) - proxy->setVisible(false); - if (!m_ownerPopup.m_popupVisible) return; m_ownerPopup.m_popupVisible = false; - m_ownerPopup.popupDidHide(); + emit m_ownerPopup.didHide(); + m_ownerPopup.destroyPopup(); +} + +bool QtFallbackWebPopupCombo::eventFilter(QObject* watched, QEvent* event) +{ + Q_ASSERT(watched == view()); + + if (event->type() == QEvent::Show && !m_ownerPopup.m_popupVisible) + showPopup(); + else if (event->type() == QEvent::Hide && m_ownerPopup.m_popupVisible) + hidePopup(); + + return false; } // QtFallbackWebPopup -QtFallbackWebPopup::QtFallbackWebPopup() - : QtAbstractWebPopup() - , m_popupVisible(false) - , m_combo(new QtFallbackWebPopupCombo(*this)) - , m_proxy(0) +QtFallbackWebPopup::QtFallbackWebPopup(const ChromeClientQt* chromeClient) + : m_popupVisible(false) + , m_combo(0) + , m_chromeClient(chromeClient) { - connect(m_combo, SIGNAL(activated(int)), - SLOT(activeChanged(int)), Qt::QueuedConnection); } QtFallbackWebPopup::~QtFallbackWebPopup() { - // If we create a proxy, then the deletion of the proxy and the - // combo will be done by the proxy's parent (QGraphicsWebView) - if (!m_proxy) - delete m_combo; + destroyPopup(); } -void QtFallbackWebPopup::show() +void QtFallbackWebPopup::show(const QWebSelectData& data) { - populate(); - m_combo->setCurrentIndex(currentIndex()); - -#if defined(Q_WS_MAEMO_5) - // Comboboxes with Qt on Maemo 5 come up in their full width on the screen, so neither - // the proxy widget, nor the coordinates are needed. - m_combo->setParent(pageClient()->ownerWidget()); - m_combo->showPopup(); - return; -#endif + if (!pageClient()) + return; + +#if ENABLE(SYMBIAN_DIALOG_PROVIDERS) + TRAP_IGNORE(showS60BrowserDialog()); +#else + + destroyPopup(); + m_combo = new QtFallbackWebPopupCombo(*this); + connect(m_combo, SIGNAL(activated(int)), + SLOT(activeChanged(int)), Qt::QueuedConnection); + + populate(data); QRect rect = geometry(); if (QGraphicsWebView *webView = qobject_cast<QGraphicsWebView*>(pageClient()->pluginParent())) { - if (!m_proxy) { - m_proxy = new QGraphicsProxyWidget(webView); - m_proxy->setWidget(m_combo); - } else - m_proxy->setVisible(true); - m_proxy->setGeometry(rect); + QGraphicsProxyWidget* proxy = new QGraphicsProxyWidget(webView); + proxy->setWidget(m_combo); + proxy->setGeometry(rect); } else { m_combo->setParent(pageClient()->ownerWidget()); m_combo->setGeometry(QRect(rect.left(), rect.top(), @@ -119,43 +136,111 @@ void QtFallbackWebPopup::show() } - // QCursor::pos() is not a great idea for a touch screen, but as Maemo 5 is handled - // separately above, this should be okay. QMouseEvent event(QEvent::MouseButtonPress, QCursor::pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QCoreApplication::sendEvent(m_combo, &event); +#endif +} + +#if ENABLE(SYMBIAN_DIALOG_PROVIDERS) + +static void ResetAndDestroy(TAny* aPtr) +{ + RPointerArray<HBufC>* items = reinterpret_cast<RPointerArray<HBufC>* >(aPtr); + items->ResetAndDestroy(); +} + +void QtFallbackWebPopup::showS60BrowserDialog() +{ + static MBrCtlDialogsProvider* dialogs = CBrowserDialogsProvider::NewL(0); + if (!dialogs) + return; + + int size = itemCount(); + CArrayFix<TBrCtlSelectOptionData>* options = new CArrayFixFlat<TBrCtlSelectOptionData>(qMax(1, size)); + RPointerArray<HBufC> items(qMax(1, size)); + CleanupStack::PushL(TCleanupItem(&ResetAndDestroy, &items)); + + for (int i = 0; i < size; i++) { + if (itemType(i) == Separator) { + TBrCtlSelectOptionData data(_L("----------"), false, false, false); + options->AppendL(data); + } else { + HBufC16* itemStr = HBufC16::NewL(itemText(i).length()); + itemStr->Des().Copy((const TUint16*)itemText(i).utf16(), itemText(i).length()); + CleanupStack::PushL(itemStr); + TBrCtlSelectOptionData data(*itemStr, i == currentIndex(), false, itemIsEnabled(i)); + options->AppendL(data); + items.AppendL(itemStr); + CleanupStack::Pop(); + } + } + + dialogs->DialogSelectOptionL(KNullDesC(), (TBrCtlSelectOptionType)(ESelectTypeSingle | ESelectTypeWithFindPane), *options); + + CleanupStack::PopAndDestroy(&items); + + int newIndex; + for (newIndex = 0; newIndex < options->Count() && !options->At(newIndex).IsSelected(); newIndex++) {} + if (newIndex == options->Count()) + newIndex = currentIndex(); + + m_popupVisible = false; + popupDidHide(); + + if (currentIndex() != newIndex && newIndex >= 0) + valueChanged(newIndex); + + delete options; } +#endif void QtFallbackWebPopup::hide() { - m_combo->hidePopup(); + // Destroying the QComboBox here cause problems if the popup is in the + // middle of its show animation. Instead we rely on the fact that the + // Qt::Popup window will hide itself on mouse events outside its window. } -void QtFallbackWebPopup::populate() +void QtFallbackWebPopup::destroyPopup() { - m_combo->clear(); + if (m_combo) { + m_combo->deleteLater(); + m_combo = 0; + } +} +void QtFallbackWebPopup::populate(const QWebSelectData& data) +{ QStandardItemModel* model = qobject_cast<QStandardItemModel*>(m_combo->model()); Q_ASSERT(model); -#if !defined(Q_WS_S60) && !defined(Q_WS_MAEMO_5) +#if !defined(Q_OS_SYMBIAN) m_combo->setFont(font()); #endif - for (int i = 0; i < itemCount(); ++i) { - switch (itemType(i)) { - case Separator: + + int currentIndex = -1; + for (int i = 0; i < data.itemCount(); ++i) { + switch (data.itemType(i)) { + case QWebSelectData::Separator: m_combo->insertSeparator(i); break; - case Group: - m_combo->insertItem(i, itemText(i)); + case QWebSelectData::Group: + m_combo->insertItem(i, data.itemText(i)); model->item(i)->setEnabled(false); break; - case Option: - m_combo->insertItem(i, itemText(i)); - model->item(i)->setEnabled(itemIsEnabled(i)); + case QWebSelectData::Option: + m_combo->insertItem(i, data.itemText(i)); + model->item(i)->setEnabled(data.itemIsEnabled(i)); + model->item(i)->setToolTip(data.itemToolTip(i)); + if (data.itemIsSelected(i)) + currentIndex = i; break; } } + + if (currentIndex >= 0) + m_combo->setCurrentIndex(currentIndex); } void QtFallbackWebPopup::activeChanged(int index) @@ -163,7 +248,14 @@ void QtFallbackWebPopup::activeChanged(int index) if (index < 0) return; - valueChanged(index); + emit selectItem(index, false, false); +} + +QWebPageClient* QtFallbackWebPopup::pageClient() const +{ + return m_chromeClient->platformPageClient(); } } + +#endif // QT_NO_COMBOBOX diff --git a/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.h b/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.h index 3924bf6..7c98fb4 100644 --- a/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.h +++ b/WebKit/qt/WebCoreSupport/QtFallbackWebPopup.h @@ -20,24 +20,41 @@ #ifndef QtFallbackWebPopup_h #define QtFallbackWebPopup_h -#include "QtAbstractWebPopup.h" +#include "Platform.h" +#include "qwebkitplatformplugin.h" + #include <QComboBox> +#ifndef QT_NO_COMBOBOX + +QT_BEGIN_NAMESPACE class QGraphicsProxyWidget; +QT_END_NAMESPACE + +class QWebPageClient; namespace WebCore { +class ChromeClientQt; class QtFallbackWebPopupCombo; -class QtFallbackWebPopup : public QObject, public QtAbstractWebPopup { +class QtFallbackWebPopup : public QWebSelectMethod { Q_OBJECT public: - QtFallbackWebPopup(); + QtFallbackWebPopup(const ChromeClientQt*); ~QtFallbackWebPopup(); - virtual void show(); + virtual void show(const QWebSelectData&); virtual void hide(); + void destroyPopup(); + + void setGeometry(const QRect& rect) { m_geometry = rect; } + QRect geometry() const { return m_geometry; } + + void setFont(const QFont& font) { m_font = font; } + QFont font() const { return m_font; } + private slots: void activeChanged(int); @@ -45,9 +62,16 @@ private: friend class QtFallbackWebPopupCombo; bool m_popupVisible; QtFallbackWebPopupCombo* m_combo; - QGraphicsProxyWidget* m_proxy; + const ChromeClientQt* m_chromeClient; + QRect m_geometry; + QFont m_font; - void populate(); + QWebPageClient* pageClient() const; + + void populate(const QWebSelectData&); +#if ENABLE(SYMBIAN_DIALOG_PROVIDERS) + void showS60BrowserDialog(); +#endif }; class QtFallbackWebPopupCombo : public QComboBox { @@ -55,6 +79,7 @@ public: QtFallbackWebPopupCombo(QtFallbackWebPopup& ownerPopup); virtual void showPopup(); virtual void hidePopup(); + virtual bool eventFilter(QObject* watched, QEvent* event); private: QtFallbackWebPopup& m_ownerPopup; @@ -62,4 +87,6 @@ private: } +#endif // QT_NO_COMBOBOX + #endif // QtFallbackWebPopup_h diff --git a/WebKit/qt/WebCoreSupport/QtMaemoWebPopup.cpp b/WebKit/qt/WebCoreSupport/QtMaemoWebPopup.cpp new file mode 100644 index 0000000..90af0c6 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/QtMaemoWebPopup.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "QtMaemoWebPopup.h" + +#include <QHBoxLayout> +#include <QListWidget> +#include <QListWidgetItem> +#include <QPainter> +#include <QPushButton> +#include <QStyledItemDelegate> +#include <QVBoxLayout> + +#include <libintl.h> + + +namespace WebCore { + +static const int gMaemoListItemSize = 70; +static const int gMaemoListPadding = 38; +static const int gMaemoMaxVisibleItems = 5; + +void Maemo5Popup::populateList() +{ + QListWidgetItem* listItem; + for (int i = 0; i < m_data.itemCount(); ++i) { + if (m_data.itemType(i) == QWebSelectData::Option) { + listItem = new QListWidgetItem(m_data.itemText(i)); + m_list->addItem(listItem); + listItem->setSelected(m_data.itemIsSelected(i)); + } else if (m_data.itemType(i) == QWebSelectData::Group) { + listItem = new QListWidgetItem(m_data.itemText(i)); + m_list->addItem(listItem); + listItem->setSelected(false); + listItem->setFlags(Qt::NoItemFlags); + } + } + connect(m_list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemSelected(QListWidgetItem*))); +} + +void Maemo5Popup::onItemSelected(QListWidgetItem* item) +{ + if (item->flags() != Qt::NoItemFlags) + emit itemClicked(m_list->row(item)); +} + +QtMaemoWebPopup::QtMaemoWebPopup() + : m_popup(0) +{ +} + +QtMaemoWebPopup::~QtMaemoWebPopup() +{ + if (m_popup) + m_popup->deleteLater(); +} + +Maemo5Popup* QtMaemoWebPopup::createSingleSelectionPopup(const QWebSelectData& data) +{ + return new Maemo5SingleSelectionPopup(data); +} + +Maemo5Popup* QtMaemoWebPopup::createMultipleSelectionPopup(const QWebSelectData& data) +{ + return new Maemo5MultipleSelectionPopup(data); +} + +Maemo5Popup* QtMaemoWebPopup::createPopup(const QWebSelectData& data) +{ + Maemo5Popup* result = data.multiple() ? createMultipleSelectionPopup(data) : createSingleSelectionPopup(data); + connect(result, SIGNAL(finished(int)), this, SLOT(popupClosed())); + connect(result, SIGNAL(itemClicked(int)), this, SLOT(itemClicked(int))); + return result; +} + +void QtMaemoWebPopup::show(const QWebSelectData& data) +{ + if (m_popup) + return; + + m_popup = createPopup(data); + m_popup->show(); +} + +void QtMaemoWebPopup::hide() +{ + if (!m_popup) + return; + + m_popup->accept(); +} + +void QtMaemoWebPopup::popupClosed() +{ + if (!m_popup) + return; + + m_popup->deleteLater(); + m_popup = 0; + emit didHide(); +} + +void QtMaemoWebPopup::itemClicked(int idx) +{ + emit selectItem(idx, true, false); +} + +Maemo5SingleSelectionPopup::Maemo5SingleSelectionPopup(const QWebSelectData& data) + : Maemo5Popup(data) +{ + // we try to get the standard list title the web browser is using + const char* title = ::dgettext("osso-browser-ui", "weba_ti_texlist_single"); + if (qstrcmp(title, "weba_ti_texlist_single")) + setWindowTitle(QString::fromUtf8(title)); + else + setWindowTitle("Select item"); + + QHBoxLayout* hLayout = new QHBoxLayout(this); + hLayout->setContentsMargins(0, 0, 0, 0); + + m_list = new QListWidget(this); + populateList(); + + hLayout->addSpacing(gMaemoListPadding); + hLayout->addWidget(m_list); + hLayout->addSpacing(gMaemoListPadding); + + connect(m_list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(accept())); + + const int visibleItemCount = (m_list->count() > gMaemoMaxVisibleItems) ? gMaemoMaxVisibleItems : m_list->count(); + resize(size().width(), visibleItemCount * gMaemoListItemSize); +} + + +class MultipleItemListDelegate : public QStyledItemDelegate { +public: + MultipleItemListDelegate(QObject* parent = 0) + : QStyledItemDelegate(parent) + { + tickMark = QIcon::fromTheme("widgets_tickmark_list").pixmap(48, 48); + } + + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const + { + QStyledItemDelegate::paint(painter, option, index); + + if (option.state & QStyle::State_Selected) + painter->drawPixmap(option.rect.width() - tickMark.rect().width(), option.rect.y() + (option.rect.height() / 2 - tickMark.rect().height() / 2), tickMark); + } + +private: + QPixmap tickMark; +}; + +Maemo5MultipleSelectionPopup::Maemo5MultipleSelectionPopup(const QWebSelectData& data) + : Maemo5Popup(data) +{ + // we try to get the standard list title the web browser is using + const char* title = ::dgettext("osso-browser-ui", "weba_ti_textlist_multi"); + if (qstrcmp(title, "weba_ti_textlist_multi")) + setWindowTitle(QString::fromUtf8(title)); + else + setWindowTitle("Select items"); + + QHBoxLayout* hLayout = new QHBoxLayout(this); + hLayout->setContentsMargins(0, 0, 0, 0); + + m_list = new QListWidget(this); + m_list->setSelectionMode(QAbstractItemView::MultiSelection); + populateList(); + + MultipleItemListDelegate* delegate = new MultipleItemListDelegate(this); + m_list->setItemDelegate(delegate); + + hLayout->addSpacing(gMaemoListPadding); + hLayout->addWidget(m_list); + + QVBoxLayout* vLayout = new QVBoxLayout(); + + const int visibleItemCount = (m_list->count() > gMaemoMaxVisibleItems) ? gMaemoMaxVisibleItems : m_list->count(); + vLayout->addSpacing((visibleItemCount - 1) * gMaemoListItemSize); + + // we try to get the standard Done button title + QPushButton* done = new QPushButton(this); + title = ::dgettext("hildon-libs", "wdgt_bd_done"); + if (qstrcmp(title, "wdgt_bd_done")) + done->setText(QString::fromUtf8(title)); + else + done->setText("Done"); + + done->setMinimumWidth(178); + vLayout->addWidget(done); + + hLayout->addSpacing(8); + hLayout->addLayout(vLayout); + hLayout->addSpacing(18); + + connect(done, SIGNAL(clicked()), this, SLOT(accept())); + resize(size().width(), visibleItemCount * gMaemoListItemSize); +} + +} diff --git a/WebKit/qt/WebCoreSupport/QtMaemoWebPopup.h b/WebKit/qt/WebCoreSupport/QtMaemoWebPopup.h new file mode 100644 index 0000000..5433b75 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/QtMaemoWebPopup.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef QtMaemoWebPopup_h +#define QtMaemoWebPopup_h + +#include "qwebkitplatformplugin.h" + +#include <QDialog> + +class QListWidgetItem; +class QListWidget; + + +namespace WebCore { + +class Maemo5Popup : public QDialog { + Q_OBJECT +public: + Maemo5Popup(const QWebSelectData& data) : m_data(data) {} + +signals: + void itemClicked(int idx); + +protected slots: + void onItemSelected(QListWidgetItem* item); + +protected: + void populateList(); + + const QWebSelectData& m_data; + QListWidget* m_list; +}; + + +class QtMaemoWebPopup : public QWebSelectMethod { + Q_OBJECT +public: + QtMaemoWebPopup(); + ~QtMaemoWebPopup(); + + virtual void show(const QWebSelectData& data); + virtual void hide(); + +private slots: + void popupClosed(); + void itemClicked(int idx); + +private: + Maemo5Popup* m_popup; + + Maemo5Popup* createPopup(const QWebSelectData& data); + Maemo5Popup* createSingleSelectionPopup(const QWebSelectData& data); + Maemo5Popup* createMultipleSelectionPopup(const QWebSelectData& data); +}; + + +class Maemo5SingleSelectionPopup : public Maemo5Popup { + Q_OBJECT +public: + Maemo5SingleSelectionPopup(const QWebSelectData& data); +}; + + +class Maemo5MultipleSelectionPopup : public Maemo5Popup { + Q_OBJECT +public: + Maemo5MultipleSelectionPopup(const QWebSelectData& data); +}; + +} + +#endif // QtMaemoWebPopup_h diff --git a/WebKit/qt/WebCoreSupport/QtPlatformPlugin.cpp b/WebKit/qt/WebCoreSupport/QtPlatformPlugin.cpp new file mode 100644 index 0000000..ede8a73 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/QtPlatformPlugin.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "QtPlatformPlugin.h" + +#include "qwebkitplatformplugin.h" + +#include <QCoreApplication> +#include <QDir> +#include <QPluginLoader> + +namespace WebCore { + +bool QtPlatformPlugin::load(const QString& file) +{ + m_loader.setFileName(file); + if (!m_loader.load()) + return false; + + QObject* obj = m_loader.instance(); + if (obj) { + m_plugin = qobject_cast<QWebKitPlatformPlugin*>(obj); + if (m_plugin) + return true; + } + + m_loader.unload(); + return false; +} + +bool QtPlatformPlugin::load() +{ + const QLatin1String suffix("/webkit/"); + const QStringList paths = QCoreApplication::libraryPaths(); + + for (int i = 0; i < paths.count(); ++i) { + const QDir dir(paths[i] + suffix); + if (!dir.exists()) + continue; + const QStringList files = dir.entryList(QDir::Files); + for (int j = 0; j < files.count(); ++j) { + if (load(dir.absoluteFilePath(files.at(j)))) + return true; + } + } + return false; +} + +QtPlatformPlugin::~QtPlatformPlugin() +{ + m_loader.unload(); +} + +QWebKitPlatformPlugin* QtPlatformPlugin::plugin() +{ + if (m_loaded) + return m_plugin; + m_loaded = true; + + // Plugin path is stored in a static variable to avoid searching for the plugin + // more then once. + static QString pluginPath; + + if (pluginPath.isNull()) { + if (load()) + pluginPath = m_loader.fileName(); + } else + load(pluginPath); + + return m_plugin; +} + +QWebSelectMethod* QtPlatformPlugin::createSelectInputMethod() +{ + QWebKitPlatformPlugin* p = plugin(); + return p ? static_cast<QWebSelectMethod*>(p->createExtension(QWebKitPlatformPlugin::MultipleSelections)) : 0; +} + + +QWebNotificationPresenter* QtPlatformPlugin::createNotificationPresenter() +{ + QWebKitPlatformPlugin* p = plugin(); + return p ? static_cast<QWebNotificationPresenter*>(p->createExtension(QWebKitPlatformPlugin::Notifications)) : 0; +} + +QWebHapticFeedbackPlayer* QtPlatformPlugin::createHapticFeedbackPlayer() +{ + QWebKitPlatformPlugin* p = plugin(); + return p ? static_cast<QWebHapticFeedbackPlayer*>(p->createExtension(QWebKitPlatformPlugin::Haptics)) : 0; +} + +QWebTouchModifier* QtPlatformPlugin::createTouchModifier() +{ + QWebKitPlatformPlugin* p = plugin(); + return p ? static_cast<QWebTouchModifier*>(p->createExtension(QWebKitPlatformPlugin::TouchInteraction)) : 0; +} + +} diff --git a/WebKit/qt/WebCoreSupport/QtPlatformPlugin.h b/WebKit/qt/WebCoreSupport/QtPlatformPlugin.h new file mode 100644 index 0000000..ef14a1f --- /dev/null +++ b/WebKit/qt/WebCoreSupport/QtPlatformPlugin.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef QtPlatformPlugin_h +#define QtPlatformPlugin_h + +#include <QPluginLoader> + +class QWebSelectMethod; +class QWebKitPlatformPlugin; +class QWebNotificationPresenter; +class QWebHapticFeedbackPlayer; +class QWebSelectData; +class QWebTouchModifier; + +namespace WebCore { + +class QtPlatformPlugin { +public: + QtPlatformPlugin() : m_loaded(false), m_plugin(0) {} + ~QtPlatformPlugin(); + + QWebSelectMethod* createSelectInputMethod(); + QWebNotificationPresenter* createNotificationPresenter(); + QWebHapticFeedbackPlayer* createHapticFeedbackPlayer(); + QWebTouchModifier* createTouchModifier(); + + QWebKitPlatformPlugin* plugin(); + +private: + bool m_loaded; + QWebKitPlatformPlugin* m_plugin; + QPluginLoader m_loader; + bool load(); + bool load(const QString& file); +}; + +} + +#endif // QtPlatformPlugin_h diff --git a/WebKit/qt/WebCoreSupport/SearchPopupMenuQt.cpp b/WebKit/qt/WebCoreSupport/SearchPopupMenuQt.cpp new file mode 100644 index 0000000..63437cf --- /dev/null +++ b/WebKit/qt/WebCoreSupport/SearchPopupMenuQt.cpp @@ -0,0 +1,49 @@ +/* + * Copyright C 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "SearchPopupMenuQt.h" + +namespace WebCore { + +SearchPopupMenuQt::SearchPopupMenuQt(PassRefPtr<PopupMenu> popup) + : m_popup(popup) +{ +} + +PopupMenu* SearchPopupMenuQt::popupMenu() +{ + return m_popup.get(); +} + +void SearchPopupMenuQt::saveRecentSearches(const AtomicString&, const Vector<String>&) +{ +} + +void SearchPopupMenuQt::loadRecentSearches(const AtomicString&, Vector<String>&) +{ +} + +bool SearchPopupMenuQt::enabled() +{ + return true; +} + +} diff --git a/WebKit/qt/WebCoreSupport/SearchPopupMenuQt.h b/WebKit/qt/WebCoreSupport/SearchPopupMenuQt.h new file mode 100644 index 0000000..11a9641 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/SearchPopupMenuQt.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef SearchPopupMenuQt_h +#define SearchPopupMenuQt_h + +#include "SearchPopupMenu.h" + +namespace WebCore { + +class SearchPopupMenuQt : public SearchPopupMenu { +public: + SearchPopupMenuQt(PassRefPtr<PopupMenu> popup); + + virtual PopupMenu* popupMenu(); + virtual void saveRecentSearches(const AtomicString& name, const Vector<String>& searchItems); + virtual void loadRecentSearches(const AtomicString& name, Vector<String>& searchItems); + virtual bool enabled(); + +private: + RefPtr<PopupMenu> m_popup; +}; + +} + +#endif // SearchPopupMenuQt_h diff --git a/WebKit/qt/WebCoreSupport/WebPlatformStrategies.cpp b/WebKit/qt/WebCoreSupport/WebPlatformStrategies.cpp new file mode 100644 index 0000000..7cd255f --- /dev/null +++ b/WebKit/qt/WebCoreSupport/WebPlatformStrategies.cpp @@ -0,0 +1,727 @@ +/* + * Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008 Collabora Ltd. All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 INdT - Instituto Nokia de Tecnologia + * + * 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 INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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 "WebPlatformStrategies.h" + +#include "Chrome.h" +#include "ChromeClientQt.h" +#include <IntSize.h> +#include "NotImplemented.h" +#include <Page.h> +#include <PageGroup.h> +#include <PluginDatabase.h> +#include <QCoreApplication> +#include <QLocale> +#include <qwebpage.h> +#include <qwebpluginfactory.h> +#include <wtf/MathExtras.h> + +using namespace WebCore; + +void WebPlatformStrategies::initialize() +{ + DEFINE_STATIC_LOCAL(WebPlatformStrategies, platformStrategies, ()); + Q_UNUSED(platformStrategies); +} + +WebPlatformStrategies::WebPlatformStrategies() +{ + setPlatformStrategies(this); +} + + +// PluginStrategy + +PluginStrategy* WebPlatformStrategies::createPluginStrategy() +{ + return this; +} + +LocalizationStrategy* WebPlatformStrategies::createLocalizationStrategy() +{ + return this; +} + +VisitedLinkStrategy* WebPlatformStrategies::createVisitedLinkStrategy() +{ + return this; +} + +void WebPlatformStrategies::refreshPlugins() +{ + PluginDatabase::installedPlugins()->refresh(); +} + +void WebPlatformStrategies::getPluginInfo(const WebCore::Page* page, Vector<WebCore::PluginInfo>& outPlugins) +{ + QWebPage* qPage = static_cast<ChromeClientQt*>(page->chrome()->client())->m_webPage; + QWebPluginFactory* factory; + if (qPage && (factory = qPage->pluginFactory())) { + + QList<QWebPluginFactory::Plugin> qplugins = factory->plugins(); + for (int i = 0; i < qplugins.count(); ++i) { + const QWebPluginFactory::Plugin& qplugin = qplugins.at(i); + PluginInfo info; + info.name = qplugin.name; + info.desc = qplugin.description; + + for (int j = 0; j < qplugin.mimeTypes.count(); ++j) { + const QWebPluginFactory::MimeType& mimeType = qplugin.mimeTypes.at(j); + + MimeClassInfo mimeInfo; + mimeInfo.type = mimeType.name; + mimeInfo.desc = mimeType.description; + for (int k = 0; k < mimeType.fileExtensions.count(); ++k) + mimeInfo.extensions.append(mimeType.fileExtensions.at(k)); + + info.mimes.append(mimeInfo); + } + outPlugins.append(info); + } + } + + PluginDatabase* db = PluginDatabase::installedPlugins(); + const Vector<PluginPackage*> &plugins = db->plugins(); + + outPlugins.resize(plugins.size()); + + for (unsigned int i = 0; i < plugins.size(); ++i) { + PluginInfo info; + PluginPackage* package = plugins[i]; + + info.name = package->name(); + info.file = package->fileName(); + info.desc = package->description(); + + const MIMEToDescriptionsMap& mimeToDescriptions = package->mimeToDescriptions(); + MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end(); + for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) { + MimeClassInfo mime; + + mime.type = it->first; + mime.desc = it->second; + mime.extensions = package->mimeToExtensions().get(mime.type); + + info.mimes.append(mime); + } + + outPlugins.append(info); + } + +} + + +// LocalizationStrategy + +String WebPlatformStrategies::inputElementAltText() +{ + return QCoreApplication::translate("QWebPage", "Submit", "Submit (input element) alt text for <input> elements with no alt, title, or value"); +} + +String WebPlatformStrategies::resetButtonDefaultLabel() +{ + return QCoreApplication::translate("QWebPage", "Reset", "default label for Reset buttons in forms on web pages"); +} + +String WebPlatformStrategies::searchableIndexIntroduction() +{ + return QCoreApplication::translate("QWebPage", "This is a searchable index. Enter search keywords: ", "text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index'"); +} + +String WebPlatformStrategies::submitButtonDefaultLabel() +{ + return QCoreApplication::translate("QWebPage", "Submit", "default label for Submit buttons in forms on web pages"); +} + +String WebPlatformStrategies::fileButtonChooseFileLabel() +{ + return QCoreApplication::translate("QWebPage", "Choose File", "title for file button used in HTML forms"); +} + +String WebPlatformStrategies::fileButtonNoFileSelectedLabel() +{ + return QCoreApplication::translate("QWebPage", "No file selected", "text to display in file button used in HTML forms when no file is selected"); +} + +String WebPlatformStrategies::contextMenuItemTagOpenLinkInNewWindow() +{ + return QCoreApplication::translate("QWebPage", "Open in New Window", "Open in New Window context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagDownloadLinkToDisk() +{ + return QCoreApplication::translate("QWebPage", "Save Link...", "Download Linked File context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagCopyLinkToClipboard() +{ + return QCoreApplication::translate("QWebPage", "Copy Link", "Copy Link context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagOpenImageInNewWindow() +{ + return QCoreApplication::translate("QWebPage", "Open Image", "Open Image in New Window context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagDownloadImageToDisk() +{ + return QCoreApplication::translate("QWebPage", "Save Image", "Download Image context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagCopyImageToClipboard() +{ + return QCoreApplication::translate("QWebPage", "Copy Image", "Copy Link context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagOpenVideoInNewWindow() +{ + return QCoreApplication::translate("QWebPage", "Open Video", "Open Video in New Window"); +} + +String WebPlatformStrategies::contextMenuItemTagOpenAudioInNewWindow() +{ + return QCoreApplication::translate("QWebPage", "Open Audio", "Open Audio in New Window"); +} + +String WebPlatformStrategies::contextMenuItemTagCopyVideoLinkToClipboard() +{ + return QCoreApplication::translate("QWebPage", "Copy Video", "Copy Video Link Location"); +} + +String WebPlatformStrategies::contextMenuItemTagCopyAudioLinkToClipboard() +{ + return QCoreApplication::translate("QWebPage", "Copy Audio", "Copy Audio Link Location"); +} + +String WebPlatformStrategies::contextMenuItemTagToggleMediaControls() +{ + return QCoreApplication::translate("QWebPage", "Toggle Controls", "Toggle Media Controls"); +} + +String WebPlatformStrategies::contextMenuItemTagToggleMediaLoop() +{ + return QCoreApplication::translate("QWebPage", "Toggle Loop", "Toggle Media Loop Playback"); +} + +String WebPlatformStrategies::contextMenuItemTagEnterVideoFullscreen() +{ + return QCoreApplication::translate("QWebPage", "Enter Fullscreen", "Switch Video to Fullscreen"); +} + +String WebPlatformStrategies::contextMenuItemTagMediaPlay() +{ + return QCoreApplication::translate("QWebPage", "Play", "Play"); +} + +String WebPlatformStrategies::contextMenuItemTagMediaPause() +{ + return QCoreApplication::translate("QWebPage", "Pause", "Pause"); +} + +String WebPlatformStrategies::contextMenuItemTagMediaMute() +{ + return QCoreApplication::translate("QWebPage", "Mute", "Mute"); +} + +String WebPlatformStrategies::contextMenuItemTagOpenFrameInNewWindow() +{ + return QCoreApplication::translate("QWebPage", "Open Frame", "Open Frame in New Window context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagCopy() +{ + return QCoreApplication::translate("QWebPage", "Copy", "Copy context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagGoBack() +{ + return QCoreApplication::translate("QWebPage", "Go Back", "Back context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagGoForward() +{ + return QCoreApplication::translate("QWebPage", "Go Forward", "Forward context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagStop() +{ + return QCoreApplication::translate("QWebPage", "Stop", "Stop context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagReload() +{ + return QCoreApplication::translate("QWebPage", "Reload", "Reload context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagCut() +{ + return QCoreApplication::translate("QWebPage", "Cut", "Cut context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagPaste() +{ + return QCoreApplication::translate("QWebPage", "Paste", "Paste context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagNoGuessesFound() +{ + return QCoreApplication::translate("QWebPage", "No Guesses Found", "No Guesses Found context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagIgnoreSpelling() +{ + return QCoreApplication::translate("QWebPage", "Ignore", "Ignore Spelling context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagLearnSpelling() +{ + return QCoreApplication::translate("QWebPage", "Add To Dictionary", "Learn Spelling context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagSearchWeb() +{ + return QCoreApplication::translate("QWebPage", "Search The Web", "Search The Web context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagLookUpInDictionary() +{ + return QCoreApplication::translate("QWebPage", "Look Up In Dictionary", "Look Up in Dictionary context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagOpenLink() +{ + return QCoreApplication::translate("QWebPage", "Open Link", "Open Link context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagIgnoreGrammar() +{ + return QCoreApplication::translate("QWebPage", "Ignore", "Ignore Grammar context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagSpellingMenu() +{ + return QCoreApplication::translate("QWebPage", "Spelling", "Spelling and Grammar context sub-menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagShowSpellingPanel(bool show) +{ + return show ? QCoreApplication::translate("QWebPage", "Show Spelling and Grammar", "menu item title") : + QCoreApplication::translate("QWebPage", "Hide Spelling and Grammar", "menu item title"); +} + +String WebPlatformStrategies::contextMenuItemTagCheckSpelling() +{ + return QCoreApplication::translate("QWebPage", "Check Spelling", "Check spelling context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagCheckSpellingWhileTyping() +{ + return QCoreApplication::translate("QWebPage", "Check Spelling While Typing", "Check spelling while typing context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagCheckGrammarWithSpelling() +{ + return QCoreApplication::translate("QWebPage", "Check Grammar With Spelling", "Check grammar with spelling context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagFontMenu() +{ + return QCoreApplication::translate("QWebPage", "Fonts", "Font context sub-menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagBold() +{ + return QCoreApplication::translate("QWebPage", "Bold", "Bold context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagItalic() +{ + return QCoreApplication::translate("QWebPage", "Italic", "Italic context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagUnderline() +{ + return QCoreApplication::translate("QWebPage", "Underline", "Underline context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagOutline() +{ + return QCoreApplication::translate("QWebPage", "Outline", "Outline context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagWritingDirectionMenu() +{ + return QCoreApplication::translate("QWebPage", "Direction", "Writing direction context sub-menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagTextDirectionMenu() +{ + return QCoreApplication::translate("QWebPage", "Text Direction", "Text direction context sub-menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagDefaultDirection() +{ + return QCoreApplication::translate("QWebPage", "Default", "Default writing direction context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagLeftToRight() +{ + return QCoreApplication::translate("QWebPage", "Left to Right", "Left to Right context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagRightToLeft() +{ + return QCoreApplication::translate("QWebPage", "Right to Left", "Right to Left context menu item"); +} + +String WebPlatformStrategies::contextMenuItemTagInspectElement() +{ + return QCoreApplication::translate("QWebPage", "Inspect", "Inspect Element context menu item"); +} + +String WebPlatformStrategies::searchMenuNoRecentSearchesText() +{ + return QCoreApplication::translate("QWebPage", "No recent searches", "Label for only item in menu that appears when clicking on the search field image, when no searches have been performed"); +} + +String WebPlatformStrategies::searchMenuRecentSearchesText() +{ + return QCoreApplication::translate("QWebPage", "Recent searches", "label for first item in the menu that appears when clicking on the search field image, used as embedded menu title"); +} + +String WebPlatformStrategies::searchMenuClearRecentSearchesText() +{ + return QCoreApplication::translate("QWebPage", "Clear recent searches", "menu item in Recent Searches menu that empties menu's contents"); +} + +String WebPlatformStrategies::AXWebAreaText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXLinkText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXListMarkerText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXImageMapText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXHeadingText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXDefinitionListTermText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXDefinitionListDefinitionText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXButtonActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXRadioButtonActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXTextFieldActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXCheckedCheckBoxActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXUncheckedCheckBoxActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXMenuListActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXMenuListPopupActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::AXLinkActionVerb() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::missingPluginText() +{ + return QCoreApplication::translate("QWebPage", "Missing Plug-in", "Label text to be used when a plug-in is missing"); +} + +String WebPlatformStrategies::crashedPluginText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::multipleFileUploadText(unsigned) +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::unknownFileSizeText() +{ + return QCoreApplication::translate("QWebPage", "Unknown", "Unknown filesize FTP directory listing item"); +} + +String WebPlatformStrategies::imageTitle(const String& filename, const IntSize& size) +{ + return QCoreApplication::translate("QWebPage", "%1 (%2x%3 pixels)", "Title string for images").arg(filename).arg(size.width()).arg(size.height()); +} + +String WebPlatformStrategies::mediaElementLoadingStateText() +{ + return QCoreApplication::translate("QWebPage", "Loading...", "Media controller status message when the media is loading"); +} + +String WebPlatformStrategies::mediaElementLiveBroadcastStateText() +{ + return QCoreApplication::translate("QWebPage", "Live Broadcast", "Media controller status message when watching a live broadcast"); +} + +#if ENABLE(VIDEO) + +String WebPlatformStrategies::localizedMediaControlElementString(const String& name) +{ + if (name == "AudioElement") + return QCoreApplication::translate("QWebPage", "Audio Element", "Media controller element"); + if (name == "VideoElement") + return QCoreApplication::translate("QWebPage", "Video Element", "Media controller element"); + if (name == "MuteButton") + return QCoreApplication::translate("QWebPage", "Mute Button", "Media controller element"); + if (name == "UnMuteButton") + return QCoreApplication::translate("QWebPage", "Unmute Button", "Media controller element"); + if (name == "PlayButton") + return QCoreApplication::translate("QWebPage", "Play Button", "Media controller element"); + if (name == "PauseButton") + return QCoreApplication::translate("QWebPage", "Pause Button", "Media controller element"); + if (name == "Slider") + return QCoreApplication::translate("QWebPage", "Slider", "Media controller element"); + if (name == "SliderThumb") + return QCoreApplication::translate("QWebPage", "Slider Thumb", "Media controller element"); + if (name == "RewindButton") + return QCoreApplication::translate("QWebPage", "Rewind Button", "Media controller element"); + if (name == "ReturnToRealtimeButton") + return QCoreApplication::translate("QWebPage", "Return to Real-time Button", "Media controller element"); + if (name == "CurrentTimeDisplay") + return QCoreApplication::translate("QWebPage", "Elapsed Time", "Media controller element"); + if (name == "TimeRemainingDisplay") + return QCoreApplication::translate("QWebPage", "Remaining Time", "Media controller element"); + if (name == "StatusDisplay") + return QCoreApplication::translate("QWebPage", "Status Display", "Media controller element"); + if (name == "FullscreenButton") + return QCoreApplication::translate("QWebPage", "Fullscreen Button", "Media controller element"); + if (name == "SeekForwardButton") + return QCoreApplication::translate("QWebPage", "Seek Forward Button", "Media controller element"); + if (name == "SeekBackButton") + return QCoreApplication::translate("QWebPage", "Seek Back Button", "Media controller element"); + + return String(); +} + +String WebPlatformStrategies::localizedMediaControlElementHelpText(const String& name) +{ + if (name == "AudioElement") + return QCoreApplication::translate("QWebPage", "Audio element playback controls and status display", "Media controller element"); + if (name == "VideoElement") + return QCoreApplication::translate("QWebPage", "Video element playback controls and status display", "Media controller element"); + if (name == "MuteButton") + return QCoreApplication::translate("QWebPage", "Mute audio tracks", "Media controller element"); + if (name == "UnMuteButton") + return QCoreApplication::translate("QWebPage", "Unmute audio tracks", "Media controller element"); + if (name == "PlayButton") + return QCoreApplication::translate("QWebPage", "Begin playback", "Media controller element"); + if (name == "PauseButton") + return QCoreApplication::translate("QWebPage", "Pause playback", "Media controller element"); + if (name == "Slider") + return QCoreApplication::translate("QWebPage", "Movie time scrubber", "Media controller element"); + if (name == "SliderThumb") + return QCoreApplication::translate("QWebPage", "Movie time scrubber thumb", "Media controller element"); + if (name == "RewindButton") + return QCoreApplication::translate("QWebPage", "Rewind movie", "Media controller element"); + if (name == "ReturnToRealtimeButton") + return QCoreApplication::translate("QWebPage", "Return streaming movie to real-time", "Media controller element"); + if (name == "CurrentTimeDisplay") + return QCoreApplication::translate("QWebPage", "Current movie time", "Media controller element"); + if (name == "TimeRemainingDisplay") + return QCoreApplication::translate("QWebPage", "Remaining movie time", "Media controller element"); + if (name == "StatusDisplay") + return QCoreApplication::translate("QWebPage", "Current movie status", "Media controller element"); + if (name == "FullscreenButton") + return QCoreApplication::translate("QWebPage", "Play movie in full-screen mode", "Media controller element"); + if (name == "SeekForwardButton") + return QCoreApplication::translate("QWebPage", "Seek quickly back", "Media controller element"); + if (name == "SeekBackButton") + return QCoreApplication::translate("QWebPage", "Seek quickly forward", "Media controller element"); + + ASSERT_NOT_REACHED(); + return String(); +} + +String WebPlatformStrategies::localizedMediaTimeDescription(float time) +{ + if (!isfinite(time)) + return QCoreApplication::translate("QWebPage", "Indefinite time", "Media time description"); + + int seconds = (int)fabsf(time); + int days = seconds / (60 * 60 * 24); + int hours = seconds / (60 * 60); + int minutes = (seconds / 60) % 60; + seconds %= 60; + + if (days) + return QCoreApplication::translate("QWebPage", "%1 days %2 hours %3 minutes %4 seconds", "Media time description").arg(days).arg(hours).arg(minutes).arg(seconds); + + if (hours) + return QCoreApplication::translate("QWebPage", "%1 hours %2 minutes %3 seconds", "Media time description").arg(hours).arg(minutes).arg(seconds); + + if (minutes) + return QCoreApplication::translate("QWebPage", "%1 minutes %2 seconds", "Media time description").arg(minutes).arg(seconds); + + return QCoreApplication::translate("QWebPage", "%1 seconds", "Media time description").arg(seconds); +} + +#else // ENABLE(VIDEO) +// FIXME: #if ENABLE(VIDEO) should be in the base class + +String WebPlatformStrategies::localizedMediaControlElementString(const String& name) +{ + return String(); +} + +String WebPlatformStrategies::localizedMediaControlElementHelpText(const String& name) +{ + return String(); +} + +String WebPlatformStrategies::localizedMediaTimeDescription(float time) +{ + return String(); +} + +#endif // ENABLE(VIDEO) + + +String WebPlatformStrategies::validationMessageValueMissingText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::validationMessageTypeMismatchText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::validationMessagePatternMismatchText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::validationMessageTooLongText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::validationMessageRangeUnderflowText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::validationMessageRangeOverflowText() +{ + notImplemented(); + return String(); +} + +String WebPlatformStrategies::validationMessageStepMismatchText() +{ + notImplemented(); + return String(); +} + + +// VisitedLinkStrategy + +bool WebPlatformStrategies::isLinkVisited(Page* page, LinkHash hash) +{ + return page->group().isLinkVisited(hash); +} + +void WebPlatformStrategies::addVisitedLink(Page* page, LinkHash hash) +{ + page->group().addVisitedLinkHash(hash); +} diff --git a/WebKit/qt/WebCoreSupport/WebPlatformStrategies.h b/WebKit/qt/WebCoreSupport/WebPlatformStrategies.h new file mode 100644 index 0000000..ea366e0 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/WebPlatformStrategies.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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. + */ + +#ifndef WebPlatformStrategies_h +#define WebPlatformStrategies_h + +#include <LocalizationStrategy.h> +#include <PlatformStrategies.h> +#include <PluginStrategy.h> +#include <VisitedLinkStrategy.h> + +namespace WebCore { +class Page; +} + +class WebPlatformStrategies : public WebCore::PlatformStrategies, private WebCore::PluginStrategy, private WebCore::LocalizationStrategy, private WebCore::VisitedLinkStrategy { +public: + static void initialize(); + +private: + WebPlatformStrategies(); + + // WebCore::PlatformStrategies + virtual WebCore::PluginStrategy* createPluginStrategy(); + virtual WebCore::LocalizationStrategy* createLocalizationStrategy(); + virtual WebCore::VisitedLinkStrategy* createVisitedLinkStrategy(); + + // WebCore::PluginStrategy + virtual void refreshPlugins(); + virtual void getPluginInfo(const WebCore::Page*, Vector<WebCore::PluginInfo>&); + + // WebCore::LocalizationStrategy + virtual WTF::String inputElementAltText(); + virtual WTF::String resetButtonDefaultLabel(); + virtual WTF::String searchableIndexIntroduction(); + virtual WTF::String submitButtonDefaultLabel(); + virtual WTF::String fileButtonChooseFileLabel(); + virtual WTF::String fileButtonNoFileSelectedLabel(); + virtual WTF::String contextMenuItemTagOpenLinkInNewWindow(); + virtual WTF::String contextMenuItemTagDownloadLinkToDisk(); + virtual WTF::String contextMenuItemTagCopyLinkToClipboard(); + virtual WTF::String contextMenuItemTagOpenImageInNewWindow(); + virtual WTF::String contextMenuItemTagDownloadImageToDisk(); + virtual WTF::String contextMenuItemTagCopyImageToClipboard(); + virtual WTF::String contextMenuItemTagOpenFrameInNewWindow(); + virtual WTF::String contextMenuItemTagCopy(); + virtual WTF::String contextMenuItemTagGoBack(); + virtual WTF::String contextMenuItemTagGoForward(); + virtual WTF::String contextMenuItemTagStop(); + virtual WTF::String contextMenuItemTagReload(); + virtual WTF::String contextMenuItemTagCut(); + virtual WTF::String contextMenuItemTagPaste(); + virtual WTF::String contextMenuItemTagNoGuessesFound(); + virtual WTF::String contextMenuItemTagIgnoreSpelling(); + virtual WTF::String contextMenuItemTagLearnSpelling(); + virtual WTF::String contextMenuItemTagSearchWeb(); + virtual WTF::String contextMenuItemTagLookUpInDictionary(); + virtual WTF::String contextMenuItemTagOpenLink(); + virtual WTF::String contextMenuItemTagIgnoreGrammar(); + virtual WTF::String contextMenuItemTagSpellingMenu(); + virtual WTF::String contextMenuItemTagShowSpellingPanel(bool show); + virtual WTF::String contextMenuItemTagCheckSpelling(); + virtual WTF::String contextMenuItemTagCheckSpellingWhileTyping(); + virtual WTF::String contextMenuItemTagCheckGrammarWithSpelling(); + virtual WTF::String contextMenuItemTagFontMenu(); + virtual WTF::String contextMenuItemTagBold(); + virtual WTF::String contextMenuItemTagItalic(); + virtual WTF::String contextMenuItemTagUnderline(); + virtual WTF::String contextMenuItemTagOutline(); + virtual WTF::String contextMenuItemTagWritingDirectionMenu(); + virtual WTF::String contextMenuItemTagTextDirectionMenu(); + virtual WTF::String contextMenuItemTagDefaultDirection(); + virtual WTF::String contextMenuItemTagLeftToRight(); + virtual WTF::String contextMenuItemTagRightToLeft(); + virtual WTF::String contextMenuItemTagInspectElement(); + virtual WTF::String contextMenuItemTagOpenVideoInNewWindow(); + virtual WTF::String contextMenuItemTagOpenAudioInNewWindow(); + virtual WTF::String contextMenuItemTagCopyVideoLinkToClipboard(); + virtual WTF::String contextMenuItemTagCopyAudioLinkToClipboard(); + virtual WTF::String contextMenuItemTagToggleMediaControls(); + virtual WTF::String contextMenuItemTagToggleMediaLoop(); + virtual WTF::String contextMenuItemTagEnterVideoFullscreen(); + virtual WTF::String contextMenuItemTagMediaPlay(); + virtual WTF::String contextMenuItemTagMediaPause(); + virtual WTF::String contextMenuItemTagMediaMute(); + virtual WTF::String searchMenuNoRecentSearchesText(); + virtual WTF::String searchMenuRecentSearchesText(); + virtual WTF::String searchMenuClearRecentSearchesText(); + virtual WTF::String AXWebAreaText(); + virtual WTF::String AXLinkText(); + virtual WTF::String AXListMarkerText(); + virtual WTF::String AXImageMapText(); + virtual WTF::String AXHeadingText(); + virtual WTF::String AXDefinitionListTermText(); + virtual WTF::String AXDefinitionListDefinitionText(); + virtual WTF::String AXButtonActionVerb(); + virtual WTF::String AXRadioButtonActionVerb(); + virtual WTF::String AXTextFieldActionVerb(); + virtual WTF::String AXCheckedCheckBoxActionVerb(); + virtual WTF::String AXUncheckedCheckBoxActionVerb(); + virtual WTF::String AXMenuListActionVerb(); + virtual WTF::String AXMenuListPopupActionVerb(); + virtual WTF::String AXLinkActionVerb(); + virtual WTF::String missingPluginText(); + virtual WTF::String crashedPluginText(); + virtual WTF::String multipleFileUploadText(unsigned numberOfFiles); + virtual WTF::String unknownFileSizeText(); + virtual WTF::String imageTitle(const WTF::String& filename, const WebCore::IntSize&); + virtual WTF::String mediaElementLoadingStateText(); + virtual WTF::String mediaElementLiveBroadcastStateText(); + virtual WTF::String localizedMediaControlElementString(const WTF::String&); + virtual WTF::String localizedMediaControlElementHelpText(const WTF::String&); + virtual WTF::String localizedMediaTimeDescription(float); + virtual WTF::String validationMessageValueMissingText(); + virtual WTF::String validationMessageTypeMismatchText(); + virtual WTF::String validationMessagePatternMismatchText(); + virtual WTF::String validationMessageTooLongText(); + virtual WTF::String validationMessageRangeUnderflowText(); + virtual WTF::String validationMessageRangeOverflowText(); + virtual WTF::String validationMessageStepMismatchText(); + + // WebCore::VisitedLinkStrategy + virtual bool isLinkVisited(WebCore::Page*, WebCore::LinkHash); + virtual void addVisitedLink(WebCore::Page*, WebCore::LinkHash); +}; + +#endif // WebPlatformStrategies_h |
