[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:23:58 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 44ca3efdb64c65d57aba2a6448d3804c77370b50
Author: commit-queue at webkit.org <commit-queue at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Sep 14 06:27:38 2010 +0000

    2010-09-13  Yuta Kitamura  <yutak at chromium.org>
    
            Reviewed by Pavel Feldman.
    
            Web Inspector: WebSocket in Resources tab
            https://bugs.webkit.org/show_bug.cgi?id=40768
    
            * inspector/extensions-api-expected.txt: Added a new resource type.
    2010-09-13  Yuta Kitamura  <yutak at chromium.org>
    
            Reviewed by Pavel Feldman.
    
            Add WebSocket resource type to Web Inspector.
    
            When a new WebSocket connection is established, a line for that connection
            will appear in Web Inspector's Resources tab. If the resource name is
            clicked, the details of handshake request and response will be shown.
    
            Web Inspector: WebSocket in Resources tab
            https://bugs.webkit.org/show_bug.cgi?id=40768
    
            * inspector/InspectorController.cpp:
            (WebCore::InspectorController::addResource): WebSocket resource does not
            have an associated loader, thus frame might be null. Need to check it.
            (WebCore::InspectorController::removeResource): Ditto.
            (WebCore::InspectorController::didCreateWebSocket):
            (WebCore::InspectorController::willSendWebSocketHandshakeRequest):
            (WebCore::InspectorController::didReceiveWebSocketHandshakeResponse):
            (WebCore::InspectorController::didCloseWebSocket):
            * inspector/InspectorController.h:
            * inspector/InspectorResource.cpp: Add null checks of m_loader and m_frame,
            because WebSocket does not have a loader and we need to allow null for
            these variables.
            (WebCore::createReadableStringFromBinary):
            (WebCore::InspectorResource::InspectorResource):
            (WebCore::InspectorResource::create): Factory function of
            regular (non-WebSocket) resources.
            (WebCore::InspectorResource::createWebSocket): Factory function of
            WebSocket resources.
            (WebCore::InspectorResource::updateWebSocketRequest):
            (WebCore::InspectorResource::updateWebSocketResponse):
            (WebCore::InspectorResource::updateScriptObject): m_frame->document() becomes
            available when Frame::setDocument() is called. We cannot obtain documentURL
            during the constructor or updateRequest() function, because m_frame->document()
            is not available yet at that point and documentURL will contain a wrong URL.
            As far as I know, updateScriptObject() is the only place where we can safely
            obtain documentURL.
            (WebCore::InspectorResource::cachedResource):
            (WebCore::InspectorResource::type):
            (WebCore::InspectorResource::resourceData):
            * inspector/InspectorResource.h:
            (WebCore::InspectorResource::):
            (WebCore::InspectorResource::markWebSocket):
            * inspector/front-end/Resource.js:
            (WebInspector.Resource.Type.toString):
            (WebInspector.Resource.prototype.set type):
            (WebInspector.Resource.prototype._mimeTypeIsConsistentWithType):
            * inspector/front-end/ResourceView.js:
            (WebInspector.ResourceView.prototype._refreshRequestHeaders):
            (WebInspector.ResourceView.prototype._refreshResponseHeaders):
            (WebInspector.ResourceView.prototype._refreshHeaders):
            * inspector/front-end/inspector.css:
            (.resources-category-websockets, .resources-category-other):
            (.resources-category-websockets .resources-graph-bar):
            (.resources-category-websockets.resource-cached .resources-graph-bar):
            * inspector/front-end/inspector.js:
            (WebInspector.loaded):
            (WebInspector.updateResource):
            * websockets/WebSocketChannel.cpp:
            (WebCore::WebSocketChannel::WebSocketChannel):
            (WebCore::WebSocketChannel::disconnect):
            (WebCore::WebSocketChannel::didOpen):
            (WebCore::WebSocketChannel::didClose):
            (WebCore::WebSocketChannel::processBuffer):
            (WebCore::WebSocketChannel::identifier):
            * websockets/WebSocketChannel.h:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@67447 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 8cc2f12..54e0cad 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,12 @@
+2010-09-13  Yuta Kitamura  <yutak at chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: WebSocket in Resources tab
+        https://bugs.webkit.org/show_bug.cgi?id=40768
+
+        * inspector/extensions-api-expected.txt: Added a new resource type.
+
 2010-09-13  Ryosuke Niwa  <rniwa at webkit.org>
 
         Reviewed by Darin Adler.
diff --git a/LayoutTests/inspector/extensions-api-expected.txt b/LayoutTests/inspector/extensions-api-expected.txt
index 3e66ab6..95d3a26 100644
--- a/LayoutTests/inspector/extensions-api-expected.txt
+++ b/LayoutTests/inspector/extensions-api-expected.txt
@@ -54,6 +54,7 @@ RUNNING TEST: extension_testAPI
             Script : "script"
             XHR : "XHR"
             Media : "media"
+            WebSocket : "WebSocket"
             Other : "other"
         }
         getAll : <function>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 48afca0..c03ca8d 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,72 @@
+2010-09-13  Yuta Kitamura  <yutak at chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Add WebSocket resource type to Web Inspector.
+
+        When a new WebSocket connection is established, a line for that connection
+        will appear in Web Inspector's Resources tab. If the resource name is
+        clicked, the details of handshake request and response will be shown.
+
+        Web Inspector: WebSocket in Resources tab
+        https://bugs.webkit.org/show_bug.cgi?id=40768
+
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::addResource): WebSocket resource does not
+        have an associated loader, thus frame might be null. Need to check it.
+        (WebCore::InspectorController::removeResource): Ditto.
+        (WebCore::InspectorController::didCreateWebSocket):
+        (WebCore::InspectorController::willSendWebSocketHandshakeRequest):
+        (WebCore::InspectorController::didReceiveWebSocketHandshakeResponse):
+        (WebCore::InspectorController::didCloseWebSocket):
+        * inspector/InspectorController.h:
+        * inspector/InspectorResource.cpp: Add null checks of m_loader and m_frame,
+        because WebSocket does not have a loader and we need to allow null for
+        these variables.
+        (WebCore::createReadableStringFromBinary):
+        (WebCore::InspectorResource::InspectorResource):
+        (WebCore::InspectorResource::create): Factory function of
+        regular (non-WebSocket) resources.
+        (WebCore::InspectorResource::createWebSocket): Factory function of
+        WebSocket resources.
+        (WebCore::InspectorResource::updateWebSocketRequest):
+        (WebCore::InspectorResource::updateWebSocketResponse):
+        (WebCore::InspectorResource::updateScriptObject): m_frame->document() becomes
+        available when Frame::setDocument() is called. We cannot obtain documentURL
+        during the constructor or updateRequest() function, because m_frame->document()
+        is not available yet at that point and documentURL will contain a wrong URL.
+        As far as I know, updateScriptObject() is the only place where we can safely
+        obtain documentURL.
+        (WebCore::InspectorResource::cachedResource):
+        (WebCore::InspectorResource::type):
+        (WebCore::InspectorResource::resourceData):
+        * inspector/InspectorResource.h:
+        (WebCore::InspectorResource::):
+        (WebCore::InspectorResource::markWebSocket):
+        * inspector/front-end/Resource.js:
+        (WebInspector.Resource.Type.toString):
+        (WebInspector.Resource.prototype.set type):
+        (WebInspector.Resource.prototype._mimeTypeIsConsistentWithType):
+        * inspector/front-end/ResourceView.js:
+        (WebInspector.ResourceView.prototype._refreshRequestHeaders):
+        (WebInspector.ResourceView.prototype._refreshResponseHeaders):
+        (WebInspector.ResourceView.prototype._refreshHeaders):
+        * inspector/front-end/inspector.css:
+        (.resources-category-websockets, .resources-category-other):
+        (.resources-category-websockets .resources-graph-bar):
+        (.resources-category-websockets.resource-cached .resources-graph-bar):
+        * inspector/front-end/inspector.js:
+        (WebInspector.loaded):
+        (WebInspector.updateResource):
+        * websockets/WebSocketChannel.cpp:
+        (WebCore::WebSocketChannel::WebSocketChannel):
+        (WebCore::WebSocketChannel::disconnect):
+        (WebCore::WebSocketChannel::didOpen):
+        (WebCore::WebSocketChannel::didClose):
+        (WebCore::WebSocketChannel::processBuffer):
+        (WebCore::WebSocketChannel::identifier):
+        * websockets/WebSocketChannel.h:
+
 2010-09-13  W. James MacLean  <wjmaclean at google.com>
 
         Reviewed by Darin Fisher.
diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp
index 8695758..90ef344 100644
--- a/WebCore/inspector/InspectorController.cpp
+++ b/WebCore/inspector/InspectorController.cpp
@@ -800,6 +800,8 @@ void InspectorController::addResource(InspectorResource* resource)
     m_knownResources.add(resource->requestURL());
 
     Frame* frame = resource->frame();
+    if (!frame)
+        return;
     ResourcesMap* resourceMap = m_frameResources.get(frame);
     if (resourceMap)
         resourceMap->set(resource->identifier(), resource);
@@ -818,6 +820,8 @@ void InspectorController::removeResource(InspectorResource* resource)
         m_knownResources.remove(requestURL);
 
     Frame* frame = resource->frame();
+    if (!frame)
+        return;
     ResourcesMap* resourceMap = m_frameResources.get(frame);
     if (!resourceMap) {
         ASSERT_NOT_REACHED();
@@ -1444,6 +1448,56 @@ InspectorDOMStorageResource* InspectorController::getDOMStorageResourceForId(lon
 }
 #endif
 
+#if ENABLE(WEB_SOCKETS)
+void InspectorController::didCreateWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL)
+{
+    if (!enabled())
+        return;
+    ASSERT(m_inspectedPage);
+
+    RefPtr<InspectorResource> resource = InspectorResource::createWebSocket(identifier, requestURL, documentURL);
+    addResource(resource.get());
+
+    if (m_frontend)
+        resource->updateScriptObject(m_frontend.get());
+}
+
+void InspectorController::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
+{
+    RefPtr<InspectorResource> resource = getTrackedResource(identifier);
+    if (!resource)
+        return;
+    resource->startTiming();
+    resource->updateWebSocketRequest(request);
+    if (m_frontend)
+        resource->updateScriptObject(m_frontend.get());
+}
+
+void InspectorController::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
+{
+    RefPtr<InspectorResource> resource = getTrackedResource(identifier);
+    if (!resource)
+        return;
+    // Calling resource->markResponseReceivedTime() here makes resources bar chart confusing, because
+    // we cannot apply the "latency + download" model of regular resources to WebSocket connections.
+    // FIXME: Design a new UI for bar charts of WebSocket resources, and record timing here.
+    resource->updateWebSocketResponse(response);
+    if (m_frontend)
+        resource->updateScriptObject(m_frontend.get());
+}
+
+void InspectorController::didCloseWebSocket(unsigned long identifier)
+{
+    RefPtr<InspectorResource> resource = getTrackedResource(identifier);
+    if (!resource)
+        return;
+
+    resource->endTiming();
+    if (m_frontend)
+        resource->updateScriptObject(m_frontend.get());
+}
+#endif // ENABLE(WEB_SOCKETS)
+
 #if ENABLE(JAVASCRIPT_DEBUGGER)
 void InspectorController::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
 {
diff --git a/WebCore/inspector/InspectorController.h b/WebCore/inspector/InspectorController.h
index 40099c6..079cf55 100644
--- a/WebCore/inspector/InspectorController.h
+++ b/WebCore/inspector/InspectorController.h
@@ -89,6 +89,11 @@ class StorageArea;
 class InspectorApplicationCacheAgent;
 #endif
 
+#if ENABLE(WEB_SOCKETS)
+class WebSocketHandshakeRequest;
+class WebSocketHandshakeResponse;
+#endif
+
 class InspectorController : public Noncopyable {
 public:
     typedef HashMap<unsigned long, RefPtr<InspectorResource> > ResourcesMap;
@@ -209,6 +214,12 @@ public:
     void setDOMStorageItem(long storageId, const String& key, const String& value, bool* success);
     void removeDOMStorageItem(long storageId, const String& key, bool* success);
 #endif
+#if ENABLE(WEB_SOCKETS)
+    void didCreateWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL);
+    void willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest&);
+    void didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse&);
+    void didCloseWebSocket(unsigned long identifier);
+#endif
 
     const ResourcesMap& resources() const { return m_resources; }
     InspectorResource* resourceForURL(const String& url);
diff --git a/WebCore/inspector/InspectorResource.cpp b/WebCore/inspector/InspectorResource.cpp
index be77827..0a4784d 100644
--- a/WebCore/inspector/InspectorResource.cpp
+++ b/WebCore/inspector/InspectorResource.cpp
@@ -43,14 +43,37 @@
 #include "ResourceLoadTiming.h"
 #include "ResourceRequest.h"
 #include "ResourceResponse.h"
+#include "StringBuffer.h"
 #include "TextEncoding.h"
+#include "WebSocketHandshakeRequest.h"
+#include "WebSocketHandshakeResponse.h"
+
+#include <wtf/Assertions.h>
 
 namespace WebCore {
 
+// Create human-readable binary representation, like "01:23:45:67:89:AB:CD:EF".
+static String createReadableStringFromBinary(const unsigned char* value, size_t length)
+{
+    ASSERT(length > 0);
+    static const char hexDigits[17] = "0123456789ABCDEF";
+    size_t bufferSize = length * 3 - 1;
+    StringBuffer buffer(bufferSize);
+    size_t index = 0;
+    for (size_t i = 0; i < length; ++i) {
+        if (i > 0)
+            buffer[index++] = ':';
+        buffer[index++] = hexDigits[value[i] >> 4];
+        buffer[index++] = hexDigits[value[i] & 0xF];
+    }
+    ASSERT(index == bufferSize);
+    return String::adopt(buffer);
+}
+
 InspectorResource::InspectorResource(unsigned long identifier, DocumentLoader* loader, const KURL& requestURL)
     : m_identifier(identifier)
     , m_loader(loader)
-    , m_frame(loader->frame())
+    , m_frame(loader ? loader->frame() : 0)
     , m_requestURL(requestURL)
     , m_expectedContentLength(0)
     , m_cached(false)
@@ -66,6 +89,9 @@ InspectorResource::InspectorResource(unsigned long identifier, DocumentLoader* l
     , m_connectionID(0)
     , m_connectionReused(false)
     , m_isMainResource(false)
+#if ENABLE(WEB_SOCKETS)
+    , m_isWebSocket(false)
+#endif
 {
 }
 
@@ -88,6 +114,12 @@ PassRefPtr<InspectorResource> InspectorResource::appendRedirect(unsigned long id
     return redirect;
 }
 
+PassRefPtr<InspectorResource> InspectorResource::create(unsigned long identifier, DocumentLoader* loader, const KURL& requestURL)
+{
+    ASSERT(loader);
+    return adoptRef(new InspectorResource(identifier, loader, requestURL));
+}
+
 PassRefPtr<InspectorResource> InspectorResource::createCached(unsigned long identifier, DocumentLoader* loader, const CachedResource* cachedResource)
 {
     PassRefPtr<InspectorResource> resource = create(identifier, loader, KURL(ParsedURLString, cachedResource->url()));
@@ -107,6 +139,16 @@ PassRefPtr<InspectorResource> InspectorResource::createCached(unsigned long iden
     return resource;
 }
 
+#if ENABLE(WEB_SOCKETS)
+PassRefPtr<InspectorResource> InspectorResource::createWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL)
+{
+    RefPtr<InspectorResource> resource = adoptRef(new InspectorResource(identifier, 0, requestURL));
+    resource->markWebSocket();
+    resource->m_documentURL = documentURL;
+    return resource.release();
+}
+#endif
+
 void InspectorResource::updateRequest(const ResourceRequest& request)
 {
     m_requestHeaderFields = request.httpHeaderFields();
@@ -146,6 +188,27 @@ void InspectorResource::updateResponse(const ResourceResponse& response)
     m_changes.set(TypeChange);
 }
 
+#if ENABLE(WEB_SOCKETS)
+void InspectorResource::updateWebSocketRequest(const WebSocketHandshakeRequest& request)
+{
+    m_requestHeaderFields = request.headerFields();
+    m_requestMethod = "GET"; // Currently we always use "GET" to request handshake.
+    m_webSocketRequestKey3.set(new WebSocketHandshakeRequest::Key3(request.key3()));
+    m_changes.set(RequestChange);
+    m_changes.set(TypeChange);
+}
+
+void InspectorResource::updateWebSocketResponse(const WebSocketHandshakeResponse& response)
+{
+    m_responseStatusCode = response.statusCode();
+    m_responseStatusText = response.statusText();
+    m_responseHeaderFields = response.headerFields();
+    m_webSocketChallengeResponse.set(new WebSocketHandshakeResponse::ChallengeResponse(response.challengeResponse()));
+    m_changes.set(ResponseChange);
+    m_changes.set(TypeChange);
+}
+#endif // ENABLE(WEB_SOCKETS)
+
 static PassRefPtr<InspectorObject> buildHeadersObject(const HTTPHeaderMap& headers)
 {
     RefPtr<InspectorObject> object = InspectorObject::create();
@@ -183,8 +246,10 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
     RefPtr<InspectorObject> jsonObject = InspectorObject::create();
     jsonObject->setNumber("id", m_identifier);
     if (m_changes.hasChange(RequestChange)) {
+        if (m_frame)
+            m_documentURL = m_frame->document()->url();
         jsonObject->setString("url", m_requestURL.string());
-        jsonObject->setString("documentURL", m_frame->document()->url().string());
+        jsonObject->setString("documentURL", m_documentURL.string());
         jsonObject->setString("host", m_requestURL.host());
         jsonObject->setString("path", m_requestURL.path());
         jsonObject->setString("lastPathComponent", m_requestURL.lastPathComponent());
@@ -194,6 +259,10 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
         jsonObject->setString("requestMethod", m_requestMethod);
         jsonObject->setString("requestFormData", m_requestFormData);
         jsonObject->setBoolean("didRequestChange", true);
+#if ENABLE(WEB_SOCKETS)
+        if (m_webSocketRequestKey3)
+            jsonObject->setString("webSocketRequestKey3", createReadableStringFromBinary(m_webSocketRequestKey3->value, sizeof(m_webSocketRequestKey3->value)));
+#endif
     }
 
     if (m_changes.hasChange(ResponseChange)) {
@@ -209,6 +278,10 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
         jsonObject->setBoolean("cached", m_cached);
         if (m_loadTiming && !m_cached)
             jsonObject->setObject("timing", buildObjectForTiming(m_loadTiming.get()));
+#if ENABLE(WEB_SOCKETS)
+        if (m_webSocketChallengeResponse)
+            jsonObject->setString("webSocketChallengeResponse", createReadableStringFromBinary(m_webSocketChallengeResponse->value, sizeof(m_webSocketChallengeResponse->value)));
+#endif
         jsonObject->setBoolean("didResponseChange", true);
     }
 
@@ -267,6 +340,8 @@ CachedResource* InspectorResource::cachedResource() const
     // Try hard to find a corresponding CachedResource. During preloading, CachedResourceLoader may not have the resource in document resources set yet,
     // but Inspector will already try to fetch data that is only available via CachedResource (and it won't update once the resource is added,
     // because m_changes will not have the appropriate bits set).
+    if (!m_frame)
+        return 0;
     const String& url = m_requestURL.string();
     CachedResource* cachedResource = m_frame->document()->cachedResourceLoader()->cachedResource(url);
     if (!cachedResource)
@@ -303,6 +378,12 @@ InspectorResource::Type InspectorResource::type() const
     if (!m_overrideContent.isNull())
         return m_overrideContentType;
 
+#if ENABLE(WEB_SOCKETS)
+    if (m_isWebSocket)
+        return WebSocket;
+#endif
+
+    ASSERT(m_loader);
     if (equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
         InspectorResource::Type resourceType = cachedResourceType();
         if (resourceType == Other)
@@ -342,7 +423,7 @@ String InspectorResource::sourceString() const
 
 PassRefPtr<SharedBuffer> InspectorResource::resourceData(String* textEncodingName) const
 {
-    if (equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
+    if (m_loader && equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
         *textEncodingName = m_frame->document()->inputEncoding();
         return m_loader->mainResourceData();
     }
diff --git a/WebCore/inspector/InspectorResource.h b/WebCore/inspector/InspectorResource.h
index 4004142..3fd5a69 100644
--- a/WebCore/inspector/InspectorResource.h
+++ b/WebCore/inspector/InspectorResource.h
@@ -34,6 +34,8 @@
 #include "HTTPHeaderMap.h"
 #include "KURL.h"
 #include "ScriptString.h"
+#include "WebSocketHandshakeRequest.h"
+#include "WebSocketHandshakeResponse.h"
 
 #include <wtf/CurrentTime.h>
 #include <wtf/OwnPtr.h>
@@ -51,6 +53,11 @@ namespace WebCore {
     class ResourceRequest;
     class ResourceResponse;
 
+#if ENABLE(WEB_SOCKETS)
+    class WebSocketHandshakeRequest;
+    class WebSocketHandshakeResponse;
+#endif
+
     class InspectorResource : public RefCounted<InspectorResource> {
     public:
 
@@ -63,16 +70,19 @@ namespace WebCore {
             Script,
             XHR,
             Media,
+            WebSocket,
             Other
         };
 
-        static PassRefPtr<InspectorResource> create(unsigned long identifier, DocumentLoader* loader, const KURL& requestURL)
-        {
-            return adoptRef(new InspectorResource(identifier, loader, requestURL));
-        }
+        static PassRefPtr<InspectorResource> create(unsigned long identifier, DocumentLoader* loader, const KURL& requestURL);
 
         static PassRefPtr<InspectorResource> createCached(unsigned long identifier, DocumentLoader*, const CachedResource*);
 
+#if ENABLE(WEB_SOCKETS)
+        // WebSocket resource doesn't have its loader. For WebSocket resources, m_loader and m_frame will become null.
+        static PassRefPtr<InspectorResource> createWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL);
+#endif
+
         ~InspectorResource();
 
         PassRefPtr<InspectorResource> appendRedirect(unsigned long identifier, const KURL& redirectURL);
@@ -82,6 +92,11 @@ namespace WebCore {
         void updateRequest(const ResourceRequest&);
         void updateResponse(const ResourceResponse&);
 
+#if ENABLE(WEB_SOCKETS)
+        void updateWebSocketRequest(const WebSocketHandshakeRequest&);
+        void updateWebSocketResponse(const WebSocketHandshakeResponse&);
+#endif
+
         void setOverrideContent(const ScriptString& data, Type);
 
         String sourceString() const;
@@ -149,10 +164,15 @@ namespace WebCore {
         Type cachedResourceType() const;
         CachedResource* cachedResource() const;
 
+#if ENABLE(WEB_SOCKETS)
+        void markWebSocket() { m_isWebSocket = true; }
+#endif
+
         unsigned long m_identifier;
         RefPtr<DocumentLoader> m_loader;
         RefPtr<Frame> m_frame;
         KURL m_requestURL;
+        KURL m_documentURL;
         HTTPHeaderMap m_requestHeaderFields;
         HTTPHeaderMap m_responseHeaderFields;
         String m_mimeType;
@@ -179,6 +199,15 @@ namespace WebCore {
         String m_requestMethod;
         String m_requestFormData;
         Vector<RefPtr<InspectorResource> > m_redirects;
+
+#if ENABLE(WEB_SOCKETS)
+        bool m_isWebSocket;
+
+        // The following fields are not used for resources other than WebSocket.
+        // We allocate them dynamically to reduce memory consumption for regular resources.
+        OwnPtr<WebSocketHandshakeRequest::Key3> m_webSocketRequestKey3;
+        OwnPtr<WebSocketHandshakeResponse::ChallengeResponse> m_webSocketChallengeResponse;
+#endif
     };
 
 } // namespace WebCore
diff --git a/WebCore/inspector/front-end/Resource.js b/WebCore/inspector/front-end/Resource.js
index de87047..ea9052d 100644
--- a/WebCore/inspector/front-end/Resource.js
+++ b/WebCore/inspector/front-end/Resource.js
@@ -45,7 +45,8 @@ WebInspector.Resource.Type = {
     Script:     4,
     XHR:        5,
     Media:      6,
-    Other:      7,
+    WebSocket:  7,
+    Other:      8,
 
     isTextType: function(type)
     {
@@ -76,6 +77,8 @@ WebInspector.Resource.Type = {
                 return "XHR";
             case this.Media:
                 return "media";
+            case this.WebSocket:
+                return "WebSocket";
             case this.Other:
             default:
                 return "other";
@@ -372,6 +375,9 @@ WebInspector.Resource.prototype = {
             case WebInspector.Resource.Type.XHR:
                 this.category = WebInspector.resourceCategories.xhr;
                 break;
+            case WebInspector.Resource.Type.WebSocket:
+                this.category = WebInspector.resourceCategories.websocket;
+                break;
             case WebInspector.Resource.Type.Other:
             default:
                 this.category = WebInspector.resourceCategories.other;
@@ -584,7 +590,8 @@ WebInspector.Resource.prototype = {
 
         if (typeof this.type === "undefined"
          || this.type === WebInspector.Resource.Type.Other
-         || this.type === WebInspector.Resource.Type.XHR)
+         || this.type === WebInspector.Resource.Type.XHR
+         || this.type === WebInspector.Resource.Type.WebSocket)
             return true;
 
         if (this.mimeType in WebInspector.MIMETypes)
diff --git a/WebCore/inspector/front-end/ResourceView.js b/WebCore/inspector/front-end/ResourceView.js
index 7ce09b6..1c2574f 100644
--- a/WebCore/inspector/front-end/ResourceView.js
+++ b/WebCore/inspector/front-end/ResourceView.js
@@ -279,13 +279,19 @@ WebInspector.ResourceView.prototype = {
 
     _refreshRequestHeaders: function()
     {
-        this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement);
+        var additionalRow = null;
+        if (typeof this.resource.webSocketRequestKey3 !== "undefined")
+            additionalRow = {header: "(Key3)", value: this.resource.webSocketRequestKey3};
+        this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, additionalRow, this.requestHeadersTreeElement);
         this._refreshFormData();
     },
 
     _refreshResponseHeaders: function()
     {
-        this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, this.responseHeadersTreeElement);
+        var additionalRow = null;
+        if (typeof this.resource.webSocketChallengeResponse !== "undefined")
+            additionalRow = {header: "(Challenge Response)", value: this.resource.webSocketChallengeResponse};
+        this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, additionalRow, this.responseHeadersTreeElement);
     },
 
     _refreshHTTPInformation: function()
@@ -316,7 +322,7 @@ WebInspector.ResourceView.prototype = {
         }
     },
     
-    _refreshHeaders: function(title, headers, headersTreeElement)
+    _refreshHeaders: function(title, headers, additionalRow, headersTreeElement)
     {
         headersTreeElement.removeChildren();
 
@@ -333,6 +339,15 @@ WebInspector.ResourceView.prototype = {
             headerTreeElement.selectable = false;
             headersTreeElement.appendChild(headerTreeElement);
         }
+
+        if (additionalRow) {
+            var title = "<div class=\"header-name\">" + additionalRow.header.escapeHTML() + ":</div>";
+            title += "<div class=\"header-value source-code\">" + additionalRow.value.escapeHTML() + "</div>"
+
+            var headerTreeElement = new TreeElement(title, null, false);
+            headerTreeElement.selectable = false;
+            headersTreeElement.appendChild(headerTreeElement);
+        }
     }
 }
 
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 4319816..2823418 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -2835,7 +2835,8 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
 }
 
 .resources-category-documents, .resources-category-stylesheets, .resources-category-images,
-.resources-category-scripts, .resources-category-xhr, .resources-category-fonts, .resources-category-other {
+.resources-category-scripts, .resources-category-xhr, .resources-category-fonts,
+.resources-category-websockets, .resources-category-other {
     display: none;
 }
 
@@ -2845,6 +2846,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
 .filter-all .resources-category-scripts, .filter-scripts .resources-category-scripts,
 .filter-all .resources-category-xhr, .filter-xhr .resources-category-xhr,
 .filter-all .resources-category-fonts, .filter-fonts .resources-category-fonts,
+.filter-all .resources-category-websockets, .filter-websockets .resources-category-websockets,
 .filter-all .resources-category-other, .filter-other .resources-category-other,
 .resource-sidebar-tree-item.selected {
     display: list-item;
@@ -2920,6 +2922,15 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
     -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7;
 }
 
+/* FIXME: Create bar images for WebSocket. */
+.resources-category-websockets .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.resources-category-websockets.resource-cached .resources-graph-bar {
+   -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
 #resource-views {
     position: absolute;
     top: 23px;
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index 4c38a5a..cb5c83c 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -517,6 +517,7 @@ WebInspector.doLoadedDone = function()
         scripts: new WebInspector.ResourceCategory("scripts", WebInspector.UIString("Scripts"), "rgb(255,121,0)"),
         xhr: new WebInspector.ResourceCategory("xhr", WebInspector.UIString("XHR"), "rgb(231,231,10)"),
         fonts: new WebInspector.ResourceCategory("fonts", WebInspector.UIString("Fonts"), "rgb(255,82,62)"),
+        websocket: new WebInspector.ResourceCategory("websockets", WebInspector.UIString("WebSocket"), "rgb(186,186,186)"), // FIXME: Decide the color.
         other: new WebInspector.ResourceCategory("other", WebInspector.UIString("Other"), "rgb(186,186,186)")
     };
 
@@ -1233,6 +1234,8 @@ WebInspector.updateResource = function(payload)
         resource.requestMethod = payload.requestMethod;
         resource.requestFormData = payload.requestFormData;
         resource.documentURL = payload.documentURL;
+        if (typeof payload.webSocketRequestKey3 !== "undefined")
+            resource.webSocketRequestKey3 = payload.webSocketRequestKey3;
 
         if (resource.mainResource)
             this.mainResource = resource;
@@ -1257,6 +1260,8 @@ WebInspector.updateResource = function(payload)
         resource.connectionReused = payload.connectionReused;
         resource.timing = payload.timing;
         resource.cached = payload.cached;
+        if (typeof payload.webSocketChallengeResponse !== "undefined")
+            resource.webSocketChallengeResponse = payload.webSocketChallengeResponse;
     }
 
     if (payload.didTypeChange) {
diff --git a/WebCore/websockets/WebSocketChannel.cpp b/WebCore/websockets/WebSocketChannel.cpp
index a09224d..5ce1cc3 100644
--- a/WebCore/websockets/WebSocketChannel.cpp
+++ b/WebCore/websockets/WebSocketChannel.cpp
@@ -36,8 +36,11 @@
 
 #include "CookieJar.h"
 #include "Document.h"
+#include "InspectorController.h"
 #include "Logging.h"
+#include "Page.h"
 #include "PlatformString.h"
+#include "ProgressTracker.h"
 #include "ScriptExecutionContext.h"
 #include "SocketStreamError.h"
 #include "SocketStreamHandle.h"
@@ -63,7 +66,14 @@ WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketCha
     , m_closed(false)
     , m_shouldDiscardReceivedData(false)
     , m_unhandledBufferedAmount(0)
+#if ENABLE(INSPECTOR)
+    , m_identifier(0)
+#endif
 {
+#if ENABLE(INSPECTOR)
+    if (InspectorController* controller = m_context->inspectorController())
+        controller->didCreateWebSocket(identifier(), url, m_context->url());
+#endif
 }
 
 WebSocketChannel::~WebSocketChannel()
@@ -113,6 +123,11 @@ void WebSocketChannel::close()
 void WebSocketChannel::disconnect()
 {
     LOG(Network, "WebSocketChannel %p disconnect", this);
+#if ENABLE(INSPECTOR)
+    if (m_context)
+        if (InspectorController* controller = m_context->inspectorController())
+            controller->didCloseWebSocket(identifier());
+#endif
     m_handshake.clearScriptExecutionContext();
     m_client = 0;
     m_context = 0;
@@ -138,6 +153,10 @@ void WebSocketChannel::didOpen(SocketStreamHandle* handle)
     ASSERT(handle == m_handle);
     if (!m_context)
         return;
+#if ENABLE(INSPECTOR)
+    if (InspectorController* controller = m_context->inspectorController())
+        controller->willSendWebSocketHandshakeRequest(identifier(), m_handshake.clientHandshakeRequest());
+#endif
     const CString& handshakeMessage = m_handshake.clientHandshakeMessage();
     if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) {
         m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Error sending handshake message.", 0, m_handshake.clientOrigin());
@@ -148,6 +167,11 @@ void WebSocketChannel::didOpen(SocketStreamHandle* handle)
 void WebSocketChannel::didClose(SocketStreamHandle* handle)
 {
     LOG(Network, "WebSocketChannel %p didClose", this);
+#if ENABLE(INSPECTOR)
+    if (m_context)
+        if (InspectorController* controller = m_context->inspectorController())
+            controller->didCloseWebSocket(identifier());
+#endif
     ASSERT_UNUSED(handle, handle == m_handle || !m_handle);
     m_closed = true;
     if (m_handle) {
@@ -251,6 +275,10 @@ bool WebSocketChannel::processBuffer()
         if (headerLength <= 0)
             return false;
         if (m_handshake.mode() == WebSocketHandshake::Connected) {
+#if ENABLE(INSPECTOR)
+            if (InspectorController* controller = m_context->inspectorController())
+                controller->didReceiveWebSocketHandshakeResponse(identifier(), m_handshake.serverHandshakeResponse());
+#endif
             if (!m_handshake.serverSetCookie().isEmpty()) {
                 if (m_context->isDocument()) {
                     Document* document = static_cast<Document*>(m_context);
@@ -368,6 +396,21 @@ void WebSocketChannel::resumeTimerFired(Timer<WebSocketChannel>* timer)
         didClose(m_handle.get());
 }
 
+#if ENABLE(INSPECTOR)
+unsigned long WebSocketChannel::identifier()
+{
+    if (m_identifier)
+        return m_identifier;
+
+    if (InspectorController* controller = m_context->inspectorController())
+        if (Page* page = controller->inspectedPage())
+            m_identifier = page->progress()->createUniqueIdentifier();
+
+    ASSERT(m_identifier);
+    return m_identifier;
+}
+#endif // ENABLE(INSPECTOR)
+
 }  // namespace WebCore
 
 #endif  // ENABLE(WEB_SOCKETS)
diff --git a/WebCore/websockets/WebSocketChannel.h b/WebCore/websockets/WebSocketChannel.h
index 43d431a..a08e6bb 100644
--- a/WebCore/websockets/WebSocketChannel.h
+++ b/WebCore/websockets/WebSocketChannel.h
@@ -84,6 +84,10 @@ namespace WebCore {
         bool processBuffer();
         void resumeTimerFired(Timer<WebSocketChannel>* timer);
 
+#if ENABLE(INSPECTOR)
+        unsigned long identifier();
+#endif
+
         ScriptExecutionContext* m_context;
         WebSocketChannelClient* m_client;
         WebSocketHandshake m_handshake;
@@ -96,6 +100,10 @@ namespace WebCore {
         bool m_closed;
         bool m_shouldDiscardReceivedData;
         unsigned long m_unhandledBufferedAmount;
+
+#if ENABLE(INSPECTOR)
+        unsigned long m_identifier;
+#endif
     };
 
 } // namespace WebCore

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list