Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (213665 => 213666)
--- trunk/Source/_javascript_Core/ChangeLog 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-03-09 21:56:33 UTC (rev 213666)
@@ -1,3 +1,14 @@
+2017-03-09 Nikita Vasilyev <nvasil...@apple.com>
+
+ Web Inspector: Show individual messages in the content pane for a WebSocket
+ https://bugs.webkit.org/show_bug.cgi?id=169011
+
+ Reviewed by Joseph Pecoraro.
+
+ Add walltime parameter and correct the description of Timestamp type.
+
+ * inspector/protocol/Network.json:
+
2017-03-09 Filip Pizlo <fpi...@apple.com>
Unreviewed, fix weak external symbol error.
Modified: trunk/Source/_javascript_Core/inspector/protocol/Network.json (213665 => 213666)
--- trunk/Source/_javascript_Core/inspector/protocol/Network.json 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/_javascript_Core/inspector/protocol/Network.json 2017-03-09 21:56:33 UTC (rev 213666)
@@ -21,6 +21,11 @@
{
"id": "Timestamp",
"type": "number",
+ "description": "Elapsed seconds since frontend connected."
+ },
+ {
+ "id": "Walltime",
+ "type": "number",
"description": "Number of seconds since epoch."
},
{
@@ -255,7 +260,8 @@
"description": "Fired when WebSocket is about to initiate handshake.",
"parameters": [
{ "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
- { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "timestamp", "$ref": "Timestamp" },
+ { "name": "walltime", "$ref": "Walltime" },
{ "name": "request", "$ref": "WebSocketRequest", "description": "WebSocket request data." }
]
},
@@ -264,7 +270,7 @@
"description": "Fired when WebSocket handshake response becomes available.",
"parameters": [
{ "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
- { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "timestamp", "$ref": "Timestamp" },
{ "name": "response", "$ref": "WebSocketResponse", "description": "WebSocket response data." }
]
},
Modified: trunk/Source/WebCore/ChangeLog (213665 => 213666)
--- trunk/Source/WebCore/ChangeLog 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebCore/ChangeLog 2017-03-09 21:56:33 UTC (rev 213666)
@@ -1,3 +1,17 @@
+2017-03-09 Nikita Vasilyev <nvasil...@apple.com>
+
+ Web Inspector: Show individual messages in the content pane for a WebSocket
+ https://bugs.webkit.org/show_bug.cgi?id=169011
+
+ Reviewed by Joseph Pecoraro.
+
+ Add walltime parameter.
+
+ No new tests. Tests will be added in a follow up patch.
+
+ * inspector/InspectorNetworkAgent.cpp:
+ (WebCore::InspectorNetworkAgent::willSendWebSocketHandshakeRequest):
+
2017-03-09 Brent Fulgham <bfulg...@apple.com>
Unreviewed build fix after r213628.
Modified: trunk/Source/WebCore/inspector/InspectorNetworkAgent.cpp (213665 => 213666)
--- trunk/Source/WebCore/inspector/InspectorNetworkAgent.cpp 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebCore/inspector/InspectorNetworkAgent.cpp 2017-03-09 21:56:33 UTC (rev 213666)
@@ -557,7 +557,7 @@
auto requestObject = Inspector::Protocol::Network::WebSocketRequest::create()
.setHeaders(buildObjectForHeaders(request.httpHeaderFields()))
.release();
- m_frontendDispatcher->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), timestamp(), WTFMove(requestObject));
+ m_frontendDispatcher->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), timestamp(), currentTime(), WTFMove(requestObject));
}
void InspectorNetworkAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const ResourceResponse& response)
Modified: trunk/Source/WebInspectorUI/ChangeLog (213665 => 213666)
--- trunk/Source/WebInspectorUI/ChangeLog 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/ChangeLog 2017-03-09 21:56:33 UTC (rev 213666)
@@ -1,3 +1,69 @@
+2017-03-09 Nikita Vasilyev <nvasil...@apple.com>
+
+ Web Inspector: Show individual messages in the content pane for a WebSocket
+ https://bugs.webkit.org/show_bug.cgi?id=169011
+
+ Reviewed by Joseph Pecoraro.
+
+ When selecting a Web Socket in Network panel or Resources, display a table
+ of all messages that have been sent and received.
+
+ * Localizations/en.lproj/localizedStrings.js:
+ * UserInterface/Controllers/FrameResourceManager.js:
+ (WebInspector.FrameResourceManager.prototype.webSocketWillSendHandshakeRequest):
+ Add a walltime parameter.
+
+ (WebInspector.FrameResourceManager.prototype._webSocketFrameReceivedOrSent):
+ Fix a bug: masked messages are outgoing, not incoming.
+
+ * UserInterface/Images/ArrowUp.svg: Added.
+ * UserInterface/Images/gtk/ArrowUp.svg: Added.
+ Add an icon for outgoing messages.
+
+ * UserInterface/Main.html:
+ * UserInterface/Models/WebSocketResource.js:
+ (WebInspector.WebSocketResource):
+ (WebInspector.WebSocketResource.prototype.get walltime):
+ (WebInspector.WebSocketResource.prototype.addFrame):
+ (WebInspector.WebSocketResource.prototype._walltimeForWebSocketTimestamp):
+ * UserInterface/Protocol/NetworkObserver.js:
+ (WebInspector.NetworkObserver.prototype.webSocketWillSendHandshakeRequest):
+ (WebInspector.NetworkObserver.prototype.webSocketFrameSent):
+ (WebInspector.NetworkObserver.prototype.webSocketFrameError):
+ (WebInspector.NetworkObserver):
+ * UserInterface/Views/NetworkSidebarPanel.js:
+ (WebInspector.NetworkSidebarPanel.prototype.treeElementAddedOrChanged):
+ * UserInterface/Views/ResourceClusterContentView.js:
+ (WebInspector.ResourceClusterContentView.prototype.get responseContentView):
+ * UserInterface/Views/WebSocketContentView.css: Added.
+ (.web-socket.content-view > .data-grid):
+ (.web-socket.content-view > .data-grid table.data):
+ (.web-socket.content-view > .data-grid td.data-column,):
+ (body[dir=ltr] .web-socket.content-view > .data-grid .data-column > div):
+ (body[dir=rtl] .web-socket.content-view > .data-grid .data-column > div):
+ (.web-socket.content-view .icon):
+ (body[dir=ltr] .web-socket.content-view .icon):
+ (body[dir=rtl] .web-socket.content-view .icon):
+ (.web-socket.content-view .outgoing .icon):
+ (.web-socket.content-view .data-grid.variable-height-rows table.data tr:nth-child(odd)):
+ (.web-socket.content-view .data-grid table.data tr.revealed):
+ (.web-socket.content-view .data-grid.variable-height-rows table.data tr.outgoing):
+ (.web-socket.content-view .data-grid.variable-height-rows table.data tr.non-text-frame):
+
+ * UserInterface/Views/WebSocketContentView.js: Added.
+ (WebInspector.WebSocketContentView):
+ Only show Time column when walltime is available.
+
+ (WebInspector.WebSocketContentView.textForOpcode):
+ (WebInspector.WebSocketContentView.prototype.shown):
+ (WebInspector.WebSocketContentView.prototype.hidden):
+ (WebInspector.WebSocketContentView.prototype.addFrame):
+ (WebInspector.WebSocketContentView.prototype._updateFrames):
+ Only render frames that haven't been rendered yet.
+
+ (WebInspector.WebSocketContentView.prototype._addRow):
+ (WebInspector.WebSocketContentView.prototype._timeStringFromTimestamp):
+
2017-03-09 Matt Baker <mattba...@apple.com>
Web Inspector: DOMTreeManager dispatches DocumentUpdated twice when the document is cleared
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (213665 => 213666)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2017-03-09 21:56:33 UTC (rev 213666)
@@ -114,6 +114,7 @@
localizedStrings["Background"] = "Background";
localizedStrings["Basis"] = "Basis";
localizedStrings["Bezier"] = "Bezier";
+localizedStrings["Binary Frame"] = "Binary Frame";
localizedStrings["Blend"] = "Blend";
localizedStrings["Block Variables"] = "Block Variables";
localizedStrings["Blur"] = "Blur";
@@ -191,6 +192,7 @@
localizedStrings["Condition"] = "Condition";
localizedStrings["Conditional _expression_"] = "Conditional _expression_";
localizedStrings["Connection"] = "Connection";
+localizedStrings["Connection Close Frame"] = "Connection Close Frame";
localizedStrings["Console"] = "Console";
localizedStrings["Console Evaluation"] = "Console Evaluation";
localizedStrings["Console Evaluation %d"] = "Console Evaluation %d";
@@ -202,6 +204,7 @@
localizedStrings["Content"] = "Content";
localizedStrings["Content Flow"] = "Content Flow";
localizedStrings["Content Security Policy violation of directive: %s"] = "Content Security Policy violation of directive: %s";
+localizedStrings["Continuation Frame"] = "Continuation Frame";
localizedStrings["Continue script execution (%s or %s)"] = "Continue script execution (%s or %s)";
localizedStrings["Continue to Here"] = "Continue to Here";
localizedStrings["Controls"] = "Controls";
@@ -589,8 +592,10 @@
localizedStrings["Pause Playback"] = "Pause Playback";
localizedStrings["Pause Reason"] = "Pause Reason";
localizedStrings["Pause script execution (%s or %s)"] = "Pause script execution (%s or %s)";
+localizedStrings["Ping Frame"] = "Ping Frame";
localizedStrings["Play Sound"] = "Play Sound";
localizedStrings["Polite"] = "Polite";
+localizedStrings["Pong Frame"] = "Pong Frame";
localizedStrings["Port"] = "Port";
localizedStrings["Position"] = "Position";
localizedStrings["Position X"] = "Position X";
@@ -783,6 +788,7 @@
localizedStrings["Take snapshot"] = "Take snapshot";
localizedStrings["Template Content"] = "Template Content";
localizedStrings["Text"] = "Text";
+localizedStrings["Text Frame"] = "Text Frame";
localizedStrings["Text Node"] = "Text Node";
localizedStrings["Text Only"] = "Text Only";
localizedStrings["The selector “%s” is invalid.\nClick to revert to the previous selector."] = "The selector “%s” is invalid.\nClick to revert to the previous selector.";
@@ -854,6 +860,7 @@
localizedStrings["Warnings"] = "Warnings";
localizedStrings["Watch Expressions"] = "Watch Expressions";
localizedStrings["Web Inspector"] = "Web Inspector";
+localizedStrings["WebSocket Connection Established"] = "WebSocket Connection Established";
localizedStrings["Weight"] = "Weight";
localizedStrings["Whitespace"] = "Whitespace";
localizedStrings["Whitespace Characters:"] = "Whitespace Characters:";
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js (213665 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js 2017-03-09 21:56:33 UTC (rev 213666)
@@ -206,7 +206,7 @@
this._webSocketIdentifierToURL.set(requestId, url);
}
- webSocketWillSendHandshakeRequest(requestId, timestamp, request)
+ webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request)
{
let url = ""
console.assert(url);
@@ -213,6 +213,12 @@
if (!url)
return;
+ // COMPATIBILITY(iOS 10.3): `walltime` did not exist in 10.3 and earlier.
+ if (!NetworkAgent.hasEventParameter("webSocketWillSendHandshakeRequest", "walltime")) {
+ request = arguments[2];
+ walltime = NaN;
+ }
+
// FIXME: <webkit.org/b/168475> Web Inspector: Correctly display iframe's and worker's WebSockets
let frameIdentifier = WebInspector.frameResourceManager.mainFrame.id;
let loaderIdentifier = WebInspector.frameResourceManager.mainFrame.id;
@@ -223,7 +229,8 @@
let elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
let initiatorSourceCodeLocation = null;
- let resource = new WebInspector.WebSocketResource(url, loaderIdentifier, targetId, requestId, request.headers, requestData, elapsedTime, initiatorSourceCodeLocation);
+ let resource = new WebInspector.WebSocketResource(url, loaderIdentifier, targetId, requestId, request.headers, requestData, timestamp, walltime, elapsedTime, initiatorSourceCodeLocation);
+
frame.addResource(resource);
this._resourceRequestIdentifierMap.set(requestId, resource);
@@ -280,13 +287,15 @@
if (!resource)
return;
- let isIncoming = !!response.mask;
+ // Data going from the client to the server is always masked.
+ let isOutgoing = !!response.mask;
+
let data = ""
let opcode = response.opcode;
let elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
- resource.addFrame(data, isIncoming, opcode, timestamp, elapsedTime);
+ resource.addFrame(data, isOutgoing, opcode, timestamp, elapsedTime);
}
markResourceRequestAsServedFromMemoryCache(requestIdentifier)
Added: trunk/Source/WebInspectorUI/UserInterface/Images/ArrowUp.svg (0 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Images/ArrowUp.svg (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/ArrowUp.svg 2017-03-09 21:56:33 UTC (rev 213666)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!-- Copyright © 2017 Apple Inc. All rights reserved. -->
+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" width="16" height="16" viewBox="0 0 16 16">
+ <path fill="none" stroke="currentColor" stroke-width="1" d="M 8 2 L 2 11 H 6 v 4 h 4 V 11 h 4 Z"/>
+</svg>
Added: trunk/Source/WebInspectorUI/UserInterface/Images/gtk/ArrowUp.svg (0 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Images/gtk/ArrowUp.svg (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/gtk/ArrowUp.svg 2017-03-09 21:56:33 UTC (rev 213666)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!-- Licensed under the Creative Commons Attribution-Share Alike 3.0 United States License (http://creativecommons.org/licenses/by-sa/3.0/) -->
+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" width="16" height="16" viewBox="0 0 16 16">
+ <path fill="currentColor" stroke-width="0" d="M 8 2 L 2 11 H 6 v 4 h 4 V 11 h 4 Z"/>
+</svg>
Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (213665 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Main.html 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html 2017-03-09 21:56:33 UTC (rev 213666)
@@ -202,6 +202,7 @@
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
+ <link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
@@ -678,6 +679,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/WebSocketResource.js (213665 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Models/WebSocketResource.js 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/WebSocketResource.js 2017-03-09 21:56:33 UTC (rev 213666)
@@ -25,7 +25,7 @@
WebInspector.WebSocketResource = class WebSocketResource extends WebInspector.Resource
{
- constructor(url, loaderIdentifier, targetId, requestIdentifier, requestHeaders, requestData, requestSentTimestamp, initiatorSourceCodeLocation)
+ constructor(url, loaderIdentifier, targetId, requestIdentifier, requestHeaders, requestData, timestamp, walltime, requestSentTimestamp, initiatorSourceCodeLocation)
{
const type = WebInspector.Resource.Type.WebSocket;
const mimeType = null;
@@ -32,6 +32,8 @@
const requestMethod = "GET";
super(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, requestSentTimestamp, initiatorSourceCodeLocation);
+ this._timestamp = timestamp;
+ this._walltime = walltime;
this._readyState = WebInspector.WebSocketResource.ReadyState.Connecting;
this._frames = [];
}
@@ -39,6 +41,7 @@
// Public
get frames() { return this._frames; }
+ get walltime() { return this._walltime; }
get readyState()
{
@@ -56,13 +59,22 @@
this.dispatchEventToListeners(WebInspector.WebSocketResource.Event.ReadyStateChanged, {previousState, state});
}
- addFrame(data, isIncoming, opcode, timestamp, elapsedTime)
+ addFrame(data, isOutgoing, opcode, timestamp, elapsedTime)
{
- let frame = {data, isIncoming, opcode, timestamp, elapsedTime};
+ let frame = {data, isOutgoing, opcode, walltime: this._walltimeForWebSocketTimestamp(timestamp)};
this._frames.push(frame);
+ this.increaseSize(data.length, elapsedTime);
+
this.dispatchEventToListeners(WebInspector.WebSocketResource.Event.FrameAdded, frame);
}
+
+ // Private
+
+ _walltimeForWebSocketTimestamp(timestamp)
+ {
+ return this._walltime + (timestamp - this._timestamp);
+ }
};
WebInspector.WebSocketResource.Event = {
@@ -75,3 +87,12 @@
Connecting: Symbol("web-socket-ready-state-connecting"),
Open: Symbol("web-socket-ready-state-open"),
};
+
+WebInspector.WebSocketResource.OpCodes = {
+ ContinuationFrame: 0,
+ TextFrame: 1,
+ BinaryFrame: 2,
+ ConnectionCloseFrame: 8,
+ PingFrame: 9,
+ PongFrame: 10,
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/NetworkObserver.js (213665 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Protocol/NetworkObserver.js 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/NetworkObserver.js 2017-03-09 21:56:33 UTC (rev 213666)
@@ -68,9 +68,9 @@
WebInspector.frameResourceManager.webSocketCreated(requestId, url);
}
- webSocketWillSendHandshakeRequest(requestId, timestamp, request)
+ webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request)
{
- WebInspector.frameResourceManager.webSocketWillSendHandshakeRequest(requestId, timestamp, request);
+ WebInspector.frameResourceManager.webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request);
}
webSocketHandshakeResponseReceived(requestId, timestamp, response)
@@ -88,13 +88,13 @@
WebInspector.frameResourceManager.webSocketFrameReceived(requestId, timestamp, response);
}
- webSocketFrameError(requestId, timestamp, errorMessage)
+ webSocketFrameSent(requestId, timestamp, response)
{
- // FIXME: Not implemented.
+ WebInspector.frameResourceManager.webSocketFrameSent(requestId, timestamp, response);
}
- webSocketFrameSent(requestId, timestamp, response)
+ webSocketFrameError(requestId, timestamp, errorMessage)
{
- WebInspector.frameResourceManager.webSocketFrameSent(requestId, timestamp, response);
+ // FIXME: Not implemented.
}
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js (213665 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js 2017-03-09 21:56:33 UTC (rev 213666)
@@ -168,13 +168,10 @@
closeButton.addEventListener(WebInspector.TreeElementStatusButton.Event.Clicked, this._treeElementCloseButtonClicked, this);
fragment.appendChild(closeButton.element);
- // FIXME: <webkit.org/b/169011> Web Inspector: Show individual messages in the content pane for a WebSocket
- if (treeElement.resource.type !== WebInspector.Resource.Type.WebSocket) {
- let goToButton = new WebInspector.TreeElementStatusButton(WebInspector.createGoToArrowButton());
- goToButton[WebInspector.NetworkSidebarPanel.TreeElementSymbol] = treeElement;
- goToButton.addEventListener(WebInspector.TreeElementStatusButton.Event.Clicked, this._treeElementGoToArrowWasClicked, this);
- fragment.appendChild(goToButton.element);
- }
+ let goToButton = new WebInspector.TreeElementStatusButton(WebInspector.createGoToArrowButton());
+ goToButton[WebInspector.NetworkSidebarPanel.TreeElementSymbol] = treeElement;
+ goToButton.addEventListener(WebInspector.TreeElementStatusButton.Event.Clicked, this._treeElementGoToArrowWasClicked, this);
+ fragment.appendChild(goToButton.element);
treeElement.status = fragment;
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceClusterContentView.js (213665 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceClusterContentView.js 2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceClusterContentView.js 2017-03-09 21:56:33 UTC (rev 213666)
@@ -84,7 +84,7 @@
break;
case WebInspector.Resource.Type.WebSocket:
- // FIXME: <webkit.org/b/169011> Web Inspector: Show individual messages in the content pane for a WebSocket
+ this._responseContentView = new WebInspector.WebSocketContentView(this._resource);
break;
default:
Added: trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.css (0 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.css (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.css 2017-03-09 21:56:33 UTC (rev 213666)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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.
+ */
+
+.web-socket.content-view > .data-grid {
+ height: 100%;
+}
+
+.web-socket.content-view > .data-grid table.data {
+ height: auto;
+ background-image: none;
+}
+
+.web-socket.content-view > .data-grid td.data-column,
+.web-socket.content-view .data-grid td.data-column > div {
+ height: auto;
+ white-space: pre-wrap;
+}
+
+body[dir=ltr] .web-socket.content-view > .data-grid .data-column > div {
+ padding-left: 18px;
+}
+
+body[dir=rtl] .web-socket.content-view > .data-grid .data-column > div {
+ padding-right: 18px;
+}
+
+.web-socket.content-view .icon {
+ position: absolute;
+ margin-top: -1px;
+}
+
+body[dir=ltr] .web-socket.content-view .icon {
+ left: 4px;
+ margin-right: 2px;
+}
+
+body[dir=rtl] .web-socket.content-view .icon {
+ right: 4px;
+ margin-left: 2px;
+}
+
+.web-socket.content-view .outgoing .icon {
+ background-image: url("../Images/ArrowUp.svg");
+}
+
+.web-socket.content-view .data-grid.variable-height-rows table.data tr:nth-child(odd) {
+ background-color: unset;
+}
+
+.web-socket.content-view .data-grid table.data tr.revealed {
+ border-bottom: 0.5px solid hsla(0, 0%, 0%, 0.1);
+}
+
+.web-socket.content-view .data-grid.variable-height-rows table.data tr.outgoing {
+ background-color: hsl(80, 85%, 92%);
+ color: hsl(120, 100%, 16%);
+}
+
+.web-socket.content-view .data-grid.variable-height-rows table.data tr.non-text-frame {
+ background-color: hsl(50, 100%, 90%);
+ color: hsl(3, 96%, 27%);
+}
Added: trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.js (0 => 213666)
--- trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.js 2017-03-09 21:56:33 UTC (rev 213666)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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.
+ */
+
+WebInspector.WebSocketContentView = class WebSocketContentView extends WebInspector.ContentView
+{
+ constructor(resource)
+ {
+ console.assert(resource instanceof WebInspector.WebSocketResource, resource);
+
+ super(resource);
+
+ this._resource = resource;
+ this._framesRendered = 0;
+
+ // COMPATIBILITY (iOS 10.3): `walltime` did not exist in 10.3 and earlier.
+ this._showTimeColumn = NetworkAgent.hasEventParameter("webSocketWillSendHandshakeRequest", "walltime");
+
+ this.element.classList.add("web-socket", "resource");
+
+ let columns = {data: {}};
+ columns.data.title = WebInspector.UIString("Data");
+ columns.data.sortable = false;
+ columns.data.icon = true;
+ columns.data.width = "85%";
+
+ if (this._showTimeColumn)
+ columns.time = {title: WebInspector.UIString("Time"), sortable: true};
+
+ this._dataGrid = new WebInspector.DataGrid(columns);
+ this._dataGrid.variableHeightRows = true;
+ this.addSubview(this._dataGrid);
+
+ this._addRow(WebInspector.UIString("WebSocket Connection Established"), this._resource.walltime, ["non-text-frame"]);
+
+ this._dataGrid.updateLayout();
+ }
+
+ // Static
+
+ static textForOpcode(opcode)
+ {
+ switch (opcode) {
+ case WebInspector.WebSocketResource.OpCodes.ContinuationFrame:
+ return WebInspector.UIString("Continuation Frame");
+ case WebInspector.WebSocketResource.OpCodes.TextFrame:
+ return WebInspector.UIString("Text Frame");
+ case WebInspector.WebSocketResource.OpCodes.BinaryFrame:
+ return WebInspector.UIString("Binary Frame");
+ case WebInspector.WebSocketResource.OpCodes.ConnectionCloseFrame:
+ return WebInspector.UIString("Connection Close Frame");
+ case WebInspector.WebSocketResource.OpCodes.PingFrame:
+ return WebInspector.UIString("Ping Frame");
+ case WebInspector.WebSocketResource.OpCodes.PongFrame:
+ return WebInspector.UIString("Pong Frame");
+ }
+ }
+
+ // Public
+
+ shown()
+ {
+ this._updateFrames();
+ this._resource.addEventListener(WebInspector.WebSocketResource.Event.FrameAdded, this._updateFrames, this);
+ }
+
+ hidden()
+ {
+ this._resource.removeEventListener(WebInspector.WebSocketResource.Event.FrameAdded, this._updateFrames, this);
+ }
+
+ addFrame(data, isOutgoing, opcode, time)
+ {
+ let nodeText;
+ if (opcode === WebInspector.WebSocketResource.OpCodes.TextFrame)
+ nodeText = data;
+ else
+ nodeText = WebInspector.WebSocketContentView.textForOpcode(opcode);
+
+ let classNames = [
+ isOutgoing ? "outgoing" : "incoming",
+ opcode === WebInspector.WebSocketResource.OpCodes.TextFrame ? "text-frame" : "non-text-frame"
+ ];
+
+ this._addRow(nodeText, time, classNames);
+ }
+
+ // Private
+
+ _updateFrames()
+ {
+ let framesLength = this._resource.frames.length;
+ for (let index = this._framesRendered; index < framesLength; index++) {
+ let frame = this._resource.frames[index];
+ let {data, isOutgoing, opcode, walltime} = frame;
+ this.addFrame(data, isOutgoing, opcode, walltime);
+ }
+ this._framesRendered = framesLength;
+ }
+
+ _addRow(data, time, classNames)
+ {
+ let node;
+ if (this._showTimeColumn)
+ node = new WebInspector.DataGridNode({data, time: this._timeStringFromTimestamp(time)});
+ else
+ node = new WebInspector.DataGridNode({data});
+
+ this._dataGrid.appendChild(node);
+
+ node.element.classList.add(...classNames);
+ }
+
+ _timeStringFromTimestamp(timestamp)
+ {
+ return new Date(timestamp * 1000).toLocaleTimeString();
+ }
+};