[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

commit-queue at webkit.org commit-queue at webkit.org
Wed Dec 22 13:39:21 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 6bfc070a4ce15e9ecf6392bc4a21c6a7c5290228
Author: commit-queue at webkit.org <commit-queue at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Sep 22 17:33:56 2010 +0000

    2010-09-22  Jamey Hicks  <jamey.hicks at nokia.com>
    
            Reviewed by Kenneth Rohde Christiansen.
    
            [Qt] Web Inspector: Remote Web Inspector support for QtWebKit
            https://bugs.webkit.org/show_bug.cgi?id=43988
    
            Runs a web debug server on port specified by QtTestBrowser
            argument -remote-inspector-port. Property
            _q_webInspectorServerPort of the QWebPage instance will be set
            according to the argument. All pages with that property set will
            be remotely inspectable.
    
            URL for remote inspection of first QWebPage is
                http://localhost:9222/webkit/inspector/inspector.html?page=1
            where 1 is the number of the QWebPage instance.
    
            The base URL yields an index page with links to the individual inspectors:
                http://localhost:9222/
    
            * WebCore.pro
    2010-09-22  Jamey Hicks  <jamey.hicks at nokia.com>
    
            Reviewed by Kenneth Rohde Christiansen.
    
            [Qt] Web Inspector: Remote Web Inspector support for QtWebKit
            https://bugs.webkit.org/show_bug.cgi?id=43988
    
            Runs a web debug server on port specified by QtTestBrowser
            argument -remote-inspector-port. Property
            _q_webInspectorServerPort of the QWebPage instance will be set
            according to the argument. All pages with that property set will
            be remotely inspectable.
    
            URL for remote inspection of first QWebPage is
                http://localhost:9222/webkit/inspector/inspector.html?page=1
            where 1 is the number of the QWebPage instance.
    
            The base URL yields an index page with links to the individual inspectors:
                http://localhost:9222/
    
            * Api/qwebinspector.cpp:
            (QWebInspectorPrivate::attachAndReplaceRemoteFrontend):
            (QWebInspectorPrivate::detachRemoteFrontend):
            * Api/qwebinspector_p.h:
            (QWebInspectorPrivate::QWebInspectorPrivate):
            * Api/qwebpage.cpp:
            (QWebPagePrivate::dynamicPropertyChangeEvent):
            (QWebPagePrivate::inspectorServerPort):
            * Api/qwebpage.h:
            * Api/qwebpage_p.h:
            * WebCoreSupport/InspectorClientQt.cpp:
            (WebCore::InspectorClientQt::InspectorClientQt):
            (WebCore::InspectorClientQt::inspectorDestroyed):
            (WebCore::InspectorClientQt::openInspectorFrontend):
            (WebCore::InspectorClientQt::attachAndReplaceRemoteFrontend):
            (WebCore::InspectorClientQt::detachRemoteFrontend):
            (WebCore::InspectorClientQt::sendMessageToFrontend):
            * WebCoreSupport/InspectorClientQt.h:
            * WebCoreSupport/InspectorServerQt.cpp: Added.
            (WebCore::generateWebSocketChallengeResponse):
            (WebCore::parseWebSocketChallengeNumber):
            (WebCore::InspectorServerQt::server):
            (WebCore::InspectorServerQt::InspectorServerQt):
            (WebCore::InspectorServerQt::~InspectorServerQt):
            (WebCore::InspectorServerQt::listen):
            (WebCore::InspectorServerQt::close):
            (WebCore::InspectorServerQt::inspectorClientForPage):
            (WebCore::InspectorServerQt::registerClient):
            (WebCore::InspectorServerQt::unregisterClient):
            (WebCore::InspectorServerQt::newConnection):
            (WebCore::InspectorServerRequestHandlerQt::InspectorServerRequestHandlerQt):
            (WebCore::InspectorServerRequestHandlerQt::~InspectorServerRequestHandlerQt):
            (WebCore::InspectorServerRequestHandlerQt::tcpReadyRead):
            (WebCore::InspectorServerRequestHandlerQt::tcpConnectionDisconnected):
            (WebCore::InspectorServerRequestHandlerQt::webSocketSend):
            (WebCore::InspectorServerRequestHandlerQt::webSocketReadyRead):
            (WebCore::RemoteFrontendChannel::RemoteFrontendChannel):
            (WebCore::RemoteFrontendChannel::sendMessageToFrontend):
            * WebCoreSupport/InspectorServerQt.h: Added.
    2010-09-22  Jamey Hicks  <jamey.hicks at nokia.com>
    
            Reviewed by Kenneth Rohde Christiansen.
    
            [Qt] Web Inspector: Remote Web Inspector support for QtWebKit
            https://bugs.webkit.org/show_bug.cgi?id=43988
    
            Runs a web debug server on port specified by QtTestBrowser
            argument -remote-inspector-port. Property
            _q_webInspectorServerPort of the QWebPage instance will be set
            according to the argument. All pages with that property set will
            be remotely inspectable.
    
            URL for remote inspection of first QWebPage is
                http://localhost:9222/webkit/inspector/inspector.html?page=1
            where 1 is the number of the QWebPage instance.
    
            The base URL yields an index page with links to the individual inspectors:
                http://localhost:9222/
    
            * QtTestBrowser/launcherwindow.cpp:
            (LauncherWindow::init):
            * QtTestBrowser/launcherwindow.h:
            * QtTestBrowser/main.cpp:
            (LauncherApplication::handleUserOptions):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@68056 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 447ac9e..7715266 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,25 @@
+2010-09-22  Jamey Hicks  <jamey.hicks at nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        [Qt] Web Inspector: Remote Web Inspector support for QtWebKit
+        https://bugs.webkit.org/show_bug.cgi?id=43988
+
+        Runs a web debug server on port specified by QtTestBrowser
+        argument -remote-inspector-port. Property
+        _q_webInspectorServerPort of the QWebPage instance will be set
+        according to the argument. All pages with that property set will
+        be remotely inspectable.
+
+        URL for remote inspection of first QWebPage is
+            http://localhost:9222/webkit/inspector/inspector.html?page=1
+        where 1 is the number of the QWebPage instance.
+
+        The base URL yields an index page with links to the individual inspectors:
+            http://localhost:9222/
+
+        * WebCore.pro
+
 2010-09-21  Darin Adler  <darin at apple.com>
 
         Reviewed by Anders Carlsson.
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index 848556b..5d3650c 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -2503,6 +2503,7 @@ HEADERS += \
     xml/XSLTProcessor.h \
     xml/XSLTUnicodeSort.h \
     $$PWD/../WebKit/qt/Api/qwebplugindatabase_p.h \
+    $$PWD/../WebKit/qt/WebCoreSupport/InspectorServerQt.h \
     $$PWD/../WebKit/qt/WebCoreSupport/QtFallbackWebPopup.h \
     $$PWD/../WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h \
     $$PWD/../WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.h \
@@ -2609,6 +2610,7 @@ SOURCES += \
     ../WebKit/qt/WebCoreSupport/FrameNetworkingContextQt.cpp \
     ../WebKit/qt/WebCoreSupport/GeolocationPermissionClientQt.cpp \
     ../WebKit/qt/WebCoreSupport/InspectorClientQt.cpp \
+    ../WebKit/qt/WebCoreSupport/InspectorServerQt.cpp \
     ../WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.cpp \
     ../WebKit/qt/WebCoreSupport/PageClientQt.cpp \
     ../WebKit/qt/WebCoreSupport/PopupMenuQt.cpp \
diff --git a/WebKit/qt/Api/qwebinspector.cpp b/WebKit/qt/Api/qwebinspector.cpp
index 802ea98..27148f7 100644
--- a/WebKit/qt/Api/qwebinspector.cpp
+++ b/WebKit/qt/Api/qwebinspector.cpp
@@ -196,6 +196,31 @@ void QWebInspectorPrivate::setFrontend(QWidget* newFrontend)
     }
 }
 
+/*! 
+ * \internal 
+ */
+void QWebInspectorPrivate::attachAndReplaceRemoteFrontend(QObject* newRemoteFrontend)
+{
+    if (remoteFrontend)
+        remoteFrontend->setParent(0);
+
+    remoteFrontend = newRemoteFrontend;
+
+    if (remoteFrontend)
+        remoteFrontend->setParent(q);
+}
+
+/*! 
+ * \internal 
+ */
+void QWebInspectorPrivate::detachRemoteFrontend()
+{
+    if (remoteFrontend) {
+        remoteFrontend->deleteLater();
+        remoteFrontend = 0;
+    }
+}
+
 void QWebInspectorPrivate::adjustFrontendSize(const QSize& size)
 {
     if (frontend)
diff --git a/WebKit/qt/Api/qwebinspector_p.h b/WebKit/qt/Api/qwebinspector_p.h
index 4d327cc..3099eb1 100644
--- a/WebKit/qt/Api/qwebinspector_p.h
+++ b/WebKit/qt/Api/qwebinspector_p.h
@@ -33,14 +33,18 @@ public:
     : q(qq)
     , page(0)
     , frontend(0)
+    , remoteFrontend(0)
     {}
 
     void setFrontend(QWidget* newFrontend);
+    void attachAndReplaceRemoteFrontend(QObject* newRemoteFrontend);
+    void detachRemoteFrontend();
     void adjustFrontendSize(const QSize& size);
 
     QWebInspector* q;
     QWebPage* page;
     QWidget* frontend;
+    QObject* remoteFrontend;
 };
 
 #endif
diff --git a/WebKit/qt/Api/qwebpage.cpp b/WebKit/qt/Api/qwebpage.cpp
index bc30bf5..9aa1a3b 100644
--- a/WebKit/qt/Api/qwebpage.cpp
+++ b/WebKit/qt/Api/qwebpage.cpp
@@ -77,6 +77,7 @@
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
 #include "HitTestResult.h"
+#include "InspectorServerQt.h"
 #include "WindowFeatures.h"
 #include "WebPlatformStrategies.h"
 #include "LocalizedStrings.h"
@@ -1302,6 +1303,10 @@ void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* ev
         frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
     }
 #endif
+    else if (event->propertyName() == "_q_webInspectorServerPort") {
+        InspectorServerQt* inspectorServer = InspectorServerQt::server();
+        inspectorServer->listen(inspectorServerPort());
+    }
 }
 #endif
 
@@ -1559,6 +1564,14 @@ InspectorController* QWebPagePrivate::inspectorController()
 #endif
 }
 
+quint16 QWebPagePrivate::inspectorServerPort()
+{
+#if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES)
+    if (q && q->property("_q_webInspectorServerPort").isValid())
+        return q->property("_q_webInspectorServerPort").toInt();
+#endif
+    return 0;
+}
 
 /*!
    \enum QWebPage::FindFlag
diff --git a/WebKit/qt/Api/qwebpage.h b/WebKit/qt/Api/qwebpage.h
index b1441ff..a20074f 100644
--- a/WebKit/qt/Api/qwebpage.h
+++ b/WebKit/qt/Api/qwebpage.h
@@ -55,6 +55,7 @@ namespace WebCore {
     class EditorClientQt;
     class FrameLoaderClientQt;
     class InspectorClientQt;
+    class InspectorServerRequestHandlerQt;
     class InspectorFrontendClientQt;
     class NotificationPresenterClientQt;
     class GeolocationPermissionClientQt;
@@ -425,6 +426,7 @@ private:
     friend class WebCore::EditorClientQt;
     friend class WebCore::FrameLoaderClientQt;
     friend class WebCore::InspectorClientQt;
+    friend class WebCore::InspectorServerRequestHandlerQt;
     friend class WebCore::InspectorFrontendClientQt;
     friend class WebCore::NotificationPresenterClientQt;
     friend class WebCore::GeolocationPermissionClientQt;
diff --git a/WebKit/qt/Api/qwebpage_p.h b/WebKit/qt/Api/qwebpage_p.h
index 82f5365..74e7ca1 100644
--- a/WebKit/qt/Api/qwebpage_p.h
+++ b/WebKit/qt/Api/qwebpage_p.h
@@ -139,6 +139,7 @@ public:
     void setInspector(QWebInspector*);
     QWebInspector* getOrCreateInspector();
     WebCore::InspectorController* inspectorController();
+    quint16 inspectorServerPort();
 
 #ifndef QT_NO_SHORTCUT
     static QWebPage::WebAction editorActionForKeyEvent(QKeyEvent* event);
diff --git a/WebKit/qt/ChangeLog b/WebKit/qt/ChangeLog
index 2c4cecb..4a4a069 100644
--- a/WebKit/qt/ChangeLog
+++ b/WebKit/qt/ChangeLog
@@ -1,3 +1,63 @@
+2010-09-22  Jamey Hicks  <jamey.hicks at nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        [Qt] Web Inspector: Remote Web Inspector support for QtWebKit
+        https://bugs.webkit.org/show_bug.cgi?id=43988
+
+        Runs a web debug server on port specified by QtTestBrowser
+        argument -remote-inspector-port. Property
+        _q_webInspectorServerPort of the QWebPage instance will be set
+        according to the argument. All pages with that property set will
+        be remotely inspectable.
+
+        URL for remote inspection of first QWebPage is
+            http://localhost:9222/webkit/inspector/inspector.html?page=1
+        where 1 is the number of the QWebPage instance.
+
+        The base URL yields an index page with links to the individual inspectors:
+            http://localhost:9222/
+
+        * Api/qwebinspector.cpp:
+        (QWebInspectorPrivate::attachAndReplaceRemoteFrontend):
+        (QWebInspectorPrivate::detachRemoteFrontend):
+        * Api/qwebinspector_p.h:
+        (QWebInspectorPrivate::QWebInspectorPrivate):
+        * Api/qwebpage.cpp:
+        (QWebPagePrivate::dynamicPropertyChangeEvent):
+        (QWebPagePrivate::inspectorServerPort):
+        * Api/qwebpage.h:
+        * Api/qwebpage_p.h:
+        * WebCoreSupport/InspectorClientQt.cpp:
+        (WebCore::InspectorClientQt::InspectorClientQt):
+        (WebCore::InspectorClientQt::inspectorDestroyed):
+        (WebCore::InspectorClientQt::openInspectorFrontend):
+        (WebCore::InspectorClientQt::attachAndReplaceRemoteFrontend):
+        (WebCore::InspectorClientQt::detachRemoteFrontend):
+        (WebCore::InspectorClientQt::sendMessageToFrontend):
+        * WebCoreSupport/InspectorClientQt.h:
+        * WebCoreSupport/InspectorServerQt.cpp: Added.
+        (WebCore::generateWebSocketChallengeResponse):
+        (WebCore::parseWebSocketChallengeNumber):
+        (WebCore::InspectorServerQt::server):
+        (WebCore::InspectorServerQt::InspectorServerQt):
+        (WebCore::InspectorServerQt::~InspectorServerQt):
+        (WebCore::InspectorServerQt::listen):
+        (WebCore::InspectorServerQt::close):
+        (WebCore::InspectorServerQt::inspectorClientForPage):
+        (WebCore::InspectorServerQt::registerClient):
+        (WebCore::InspectorServerQt::unregisterClient):
+        (WebCore::InspectorServerQt::newConnection):
+        (WebCore::InspectorServerRequestHandlerQt::InspectorServerRequestHandlerQt):
+        (WebCore::InspectorServerRequestHandlerQt::~InspectorServerRequestHandlerQt):
+        (WebCore::InspectorServerRequestHandlerQt::tcpReadyRead):
+        (WebCore::InspectorServerRequestHandlerQt::tcpConnectionDisconnected):
+        (WebCore::InspectorServerRequestHandlerQt::webSocketSend):
+        (WebCore::InspectorServerRequestHandlerQt::webSocketReadyRead):
+        (WebCore::RemoteFrontendChannel::RemoteFrontendChannel):
+        (WebCore::RemoteFrontendChannel::sendMessageToFrontend):
+        * WebCoreSupport/InspectorServerQt.h: Added.
+
 2010-09-22  Balazs Kelemen  <kb at inf.u-szeged.hu>
 
         Reviewed by Kenneth Rohde Christiansen.
diff --git a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp
index e6e6fde..b6673e6 100644
--- a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp
+++ b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp
@@ -32,7 +32,10 @@
 #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"
@@ -115,17 +118,26 @@ 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;
 }
 
     
-void InspectorClientQt::openInspectorFrontend(WebCore::InspectorController*)
+void InspectorClientQt::openInspectorFrontend(WebCore::InspectorController* inspectorController)
 {
 #if USE(V8)
     ensureDebuggerScriptLoaded();
@@ -136,6 +148,10 @@ void InspectorClientQt::openInspectorFrontend(WebCore::InspectorController*)
     inspectorView->setPage(inspectorPage);
 
     QWebInspector* inspector = m_inspectedWebPage->d->getOrCreateInspector();
+    // Remote frontend was attached.
+    if (m_inspectedWebPage->d->inspector->d->remoteFrontend)
+        return;
+
     // 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.
@@ -167,6 +183,23 @@ void InspectorClientQt::releaseFrontendPage()
     m_frontendClient = 0;
 }
 
+void InspectorClientQt::attachAndReplaceRemoteFrontend(RemoteFrontendChannel* channel)
+{
+#if ENABLE(INSPECTOR)
+    // 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::detachRemoteFrontend()
+{
+#if ENABLE(INSPECTOR)
+    m_inspectedWebPage->d->inspector->d->detachRemoteFrontend();
+    m_inspectedWebPage->d->inspectorController()->disconnectFrontend();
+#endif
+}
+
 void InspectorClientQt::highlight(Node*)
 {
     notImplemented();
@@ -223,6 +256,12 @@ void InspectorClientQt::storeSetting(const String& key, const String& setting)
 
 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;
 
diff --git a/WebKit/qt/WebCoreSupport/InspectorClientQt.h b/WebKit/qt/WebCoreSupport/InspectorClientQt.h
index 0074159..64a2d0c 100644
--- a/WebKit/qt/WebCoreSupport/InspectorClientQt.h
+++ b/WebKit/qt/WebCoreSupport/InspectorClientQt.h
@@ -42,8 +42,10 @@ class QWebView;
 
 namespace WebCore {
 class InspectorFrontendClientQt;
+class InspectorServerRequestHandlerQt;
 class Node;
 class Page;
+class RemoteFrontendChannel;
 
 class InspectorClientQt : public InspectorClient {
 public:
@@ -63,10 +65,16 @@ public:
 
     void releaseFrontendPage();
 
+    void attachAndReplaceRemoteFrontend(RemoteFrontendChannel *channel);
+    void detachRemoteFrontend();
+
 private:
     QWebPage* m_inspectedWebPage;
     QWebPage* m_frontendWebPage;
     InspectorFrontendClientQt* m_frontendClient;
+    bool m_remoteInspector;
+
+    friend class InspectorServerRequestHandlerQt;
 };
 
 class InspectorFrontendClientQt : public InspectorFrontendClientLocal {
diff --git a/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp b/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp
new file mode 100644
index 0000000..fad7247
--- /dev/null
+++ b/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp
@@ -0,0 +1,386 @@
+/*
+  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>
+
+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/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 149c549..086ed7d 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,29 @@
+2010-09-22  Jamey Hicks  <jamey.hicks at nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        [Qt] Web Inspector: Remote Web Inspector support for QtWebKit
+        https://bugs.webkit.org/show_bug.cgi?id=43988
+
+        Runs a web debug server on port specified by QtTestBrowser
+        argument -remote-inspector-port. Property
+        _q_webInspectorServerPort of the QWebPage instance will be set
+        according to the argument. All pages with that property set will
+        be remotely inspectable.
+
+        URL for remote inspection of first QWebPage is
+            http://localhost:9222/webkit/inspector/inspector.html?page=1
+        where 1 is the number of the QWebPage instance.
+
+        The base URL yields an index page with links to the individual inspectors:
+            http://localhost:9222/
+
+        * QtTestBrowser/launcherwindow.cpp:
+        (LauncherWindow::init):
+        * QtTestBrowser/launcherwindow.h:
+        * QtTestBrowser/main.cpp:
+        (LauncherApplication::handleUserOptions):
+
 2010-09-22  Adam Roben  <aroben at apple.com>
 
         Fix webkit-patch failure-reason now that build.webkit.org has been
diff --git a/WebKitTools/QtTestBrowser/launcherwindow.cpp b/WebKitTools/QtTestBrowser/launcherwindow.cpp
index 65bcee7..92dc9f2 100644
--- a/WebKitTools/QtTestBrowser/launcherwindow.cpp
+++ b/WebKitTools/QtTestBrowser/launcherwindow.cpp
@@ -91,6 +91,9 @@ void LauncherWindow::init()
     m_inspector->hide();
     connect(this, SIGNAL(destroyed()), m_inspector, SLOT(deleteLater()));
 
+    if (m_windowOptions.remoteInspectorPort)
+        page()->setProperty("_q_webInspectorServerPort", m_windowOptions.remoteInspectorPort);
+
     // the zoom values are chosen to be like in Mozilla Firefox 3
     if (!m_zoomLevels.count()) {
         m_zoomLevels << 30 << 50 << 67 << 80 << 90;
diff --git a/WebKitTools/QtTestBrowser/launcherwindow.h b/WebKitTools/QtTestBrowser/launcherwindow.h
index d3b7f8e..0e17a12 100644
--- a/WebKitTools/QtTestBrowser/launcherwindow.h
+++ b/WebKitTools/QtTestBrowser/launcherwindow.h
@@ -110,6 +110,7 @@ public:
     bool useQGLWidgetViewport;
 #endif
     QUrl inspectorUrl;
+    quint16 remoteInspectorPort;
 };
 
 class LauncherWindow : public MainWindow {
diff --git a/WebKitTools/QtTestBrowser/main.cpp b/WebKitTools/QtTestBrowser/main.cpp
index e0c6e7d..e7f9716 100644
--- a/WebKitTools/QtTestBrowser/main.cpp
+++ b/WebKitTools/QtTestBrowser/main.cpp
@@ -188,6 +188,11 @@ void LauncherApplication::handleUserOptions()
     if (inspectorUrlIndex != -1)
        windowOptions.inspectorUrl = takeOptionValue(&args, inspectorUrlIndex);
 
+    QString remoteInspectorPortArg("-remote-inspector-port");
+    int remoteInspectorPortIndex = args.indexOf(remoteInspectorPortArg);
+    if (remoteInspectorPortIndex != -1)
+        windowOptions.remoteInspectorPort = takeOptionValue(&args, remoteInspectorPortIndex).toInt();
+
     int robotIndex = args.indexOf("-r");
     if (robotIndex != -1) {
         QString listFile = takeOptionValue(&args, robotIndex);

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list