<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[213666] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/213666">213666</a></dd>
<dt>Author</dt> <dd>nvasilyev@apple.com</dd>
<dt>Date</dt> <dd>2017-03-09 13:56:33 -0800 (Thu, 09 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>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.

Source/JavaScriptCore:

Add walltime parameter and correct the description of Timestamp type.

* inspector/protocol/Network.json:

Source/WebCore:

Add walltime parameter.

No new tests. Tests will be added in a follow up patch.

* inspector/InspectorNetworkAgent.cpp:
(WebCore::InspectorNetworkAgent::willSendWebSocketHandshakeRequest):

Source/WebInspectorUI:

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 &gt; .data-grid):
(.web-socket.content-view &gt; .data-grid table.data):
(.web-socket.content-view &gt; .data-grid td.data-column,):
(body[dir=ltr] .web-socket.content-view &gt; .data-grid .data-column &gt; div):
(body[dir=rtl] .web-socket.content-view &gt; .data-grid .data-column &gt; 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):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolNetworkjson">trunk/Source/JavaScriptCore/inspector/protocol/Network.json</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorNetworkAgentcpp">trunk/Source/WebCore/inspector/InspectorNetworkAgent.cpp</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersFrameResourceManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsWebSocketResourcejs">trunk/Source/WebInspectorUI/UserInterface/Models/WebSocketResource.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceProtocolNetworkObserverjs">trunk/Source/WebInspectorUI/UserInterface/Protocol/NetworkObserver.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsResourceClusterContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/ResourceClusterContentView.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesArrowUpsvg">trunk/Source/WebInspectorUI/UserInterface/Images/ArrowUp.svg</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesgtkArrowUpsvg">trunk/Source/WebInspectorUI/UserInterface/Images/gtk/ArrowUp.svg</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsWebSocketContentViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsWebSocketContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-09 21:56:33 UTC (rev 213666)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2017-03-09  Nikita Vasilyev  &lt;nvasilyev@apple.com&gt;
+
+        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:
+
</ins><span class="cx"> 2017-03-09  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, fix weak external symbol error.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolNetworkjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Network.json (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Network.json        2017-03-09 21:42:04 UTC (rev 213665)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Network.json        2017-03-09 21:56:33 UTC (rev 213666)
</span><span class="lines">@@ -21,6 +21,11 @@
</span><span class="cx">         {
</span><span class="cx">             &quot;id&quot;: &quot;Timestamp&quot;,
</span><span class="cx">             &quot;type&quot;: &quot;number&quot;,
</span><ins>+            &quot;description&quot;: &quot;Elapsed seconds since frontend connected.&quot;
+        },
+        {
+            &quot;id&quot;: &quot;Walltime&quot;,
+            &quot;type&quot;: &quot;number&quot;,
</ins><span class="cx">             &quot;description&quot;: &quot;Number of seconds since epoch.&quot;
</span><span class="cx">         },
</span><span class="cx">         {
</span><span class="lines">@@ -255,7 +260,8 @@
</span><span class="cx">             &quot;description&quot;: &quot;Fired when WebSocket is about to initiate handshake.&quot;,
</span><span class="cx">             &quot;parameters&quot;: [
</span><span class="cx">                 { &quot;name&quot;: &quot;requestId&quot;, &quot;$ref&quot;: &quot;RequestId&quot;, &quot;description&quot;: &quot;Request identifier.&quot; },
</span><del>-                { &quot;name&quot;: &quot;timestamp&quot;, &quot;$ref&quot;: &quot;Timestamp&quot;, &quot;description&quot;: &quot;Timestamp.&quot; },
</del><ins>+                { &quot;name&quot;: &quot;timestamp&quot;, &quot;$ref&quot;: &quot;Timestamp&quot; },
+                { &quot;name&quot;: &quot;walltime&quot;, &quot;$ref&quot;: &quot;Walltime&quot; },
</ins><span class="cx">                 { &quot;name&quot;: &quot;request&quot;, &quot;$ref&quot;: &quot;WebSocketRequest&quot;, &quot;description&quot;: &quot;WebSocket request data.&quot; }
</span><span class="cx">             ]
</span><span class="cx">         },
</span><span class="lines">@@ -264,7 +270,7 @@
</span><span class="cx">             &quot;description&quot;: &quot;Fired when WebSocket handshake response becomes available.&quot;,
</span><span class="cx">             &quot;parameters&quot;: [
</span><span class="cx">                 { &quot;name&quot;: &quot;requestId&quot;, &quot;$ref&quot;: &quot;RequestId&quot;, &quot;description&quot;: &quot;Request identifier.&quot; },
</span><del>-                { &quot;name&quot;: &quot;timestamp&quot;, &quot;$ref&quot;: &quot;Timestamp&quot;, &quot;description&quot;: &quot;Timestamp.&quot; },
</del><ins>+                { &quot;name&quot;: &quot;timestamp&quot;, &quot;$ref&quot;: &quot;Timestamp&quot; },
</ins><span class="cx">                 { &quot;name&quot;: &quot;response&quot;, &quot;$ref&quot;: &quot;WebSocketResponse&quot;, &quot;description&quot;: &quot;WebSocket response data.&quot; }
</span><span class="cx">             ]
</span><span class="cx">         },
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2017-03-09  Nikita Vasilyev  &lt;nvasilyev@apple.com&gt;
+
+        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):
+
</ins><span class="cx"> 2017-03-09  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed build fix after r213628.
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorNetworkAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorNetworkAgent.cpp (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -557,7 +557,7 @@
</span><span class="cx">     auto requestObject = Inspector::Protocol::Network::WebSocketRequest::create()
</span><span class="cx">         .setHeaders(buildObjectForHeaders(request.httpHeaderFields()))
</span><span class="cx">         .release();
</span><del>-    m_frontendDispatcher-&gt;webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), timestamp(), WTFMove(requestObject));
</del><ins>+    m_frontendDispatcher-&gt;webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), timestamp(), currentTime(), WTFMove(requestObject));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InspectorNetworkAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const ResourceResponse&amp; response)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,69 @@
</span><ins>+2017-03-09  Nikita Vasilyev  &lt;nvasilyev@apple.com&gt;
+
+        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 &gt; .data-grid):
+        (.web-socket.content-view &gt; .data-grid table.data):
+        (.web-socket.content-view &gt; .data-grid td.data-column,):
+        (body[dir=ltr] .web-socket.content-view &gt; .data-grid .data-column &gt; div):
+        (body[dir=rtl] .web-socket.content-view &gt; .data-grid .data-column &gt; 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):
+
</ins><span class="cx"> 2017-03-09  Matt Baker  &lt;mattbaker@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: DOMTreeManager dispatches DocumentUpdated twice when the document is cleared
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -114,6 +114,7 @@
</span><span class="cx"> localizedStrings[&quot;Background&quot;] = &quot;Background&quot;;
</span><span class="cx"> localizedStrings[&quot;Basis&quot;] = &quot;Basis&quot;;
</span><span class="cx"> localizedStrings[&quot;Bezier&quot;] = &quot;Bezier&quot;;
</span><ins>+localizedStrings[&quot;Binary Frame&quot;] = &quot;Binary Frame&quot;;
</ins><span class="cx"> localizedStrings[&quot;Blend&quot;] = &quot;Blend&quot;;
</span><span class="cx"> localizedStrings[&quot;Block Variables&quot;] = &quot;Block Variables&quot;;
</span><span class="cx"> localizedStrings[&quot;Blur&quot;] = &quot;Blur&quot;;
</span><span class="lines">@@ -191,6 +192,7 @@
</span><span class="cx"> localizedStrings[&quot;Condition&quot;] = &quot;Condition&quot;;
</span><span class="cx"> localizedStrings[&quot;Conditional expression&quot;] = &quot;Conditional expression&quot;;
</span><span class="cx"> localizedStrings[&quot;Connection&quot;] = &quot;Connection&quot;;
</span><ins>+localizedStrings[&quot;Connection Close Frame&quot;] = &quot;Connection Close Frame&quot;;
</ins><span class="cx"> localizedStrings[&quot;Console&quot;] = &quot;Console&quot;;
</span><span class="cx"> localizedStrings[&quot;Console Evaluation&quot;] = &quot;Console Evaluation&quot;;
</span><span class="cx"> localizedStrings[&quot;Console Evaluation %d&quot;] = &quot;Console Evaluation %d&quot;;
</span><span class="lines">@@ -202,6 +204,7 @@
</span><span class="cx"> localizedStrings[&quot;Content&quot;] = &quot;Content&quot;;
</span><span class="cx"> localizedStrings[&quot;Content Flow&quot;] = &quot;Content Flow&quot;;
</span><span class="cx"> localizedStrings[&quot;Content Security Policy violation of directive: %s&quot;] = &quot;Content Security Policy violation of directive: %s&quot;;
</span><ins>+localizedStrings[&quot;Continuation Frame&quot;] = &quot;Continuation Frame&quot;;
</ins><span class="cx"> localizedStrings[&quot;Continue script execution (%s or %s)&quot;] = &quot;Continue script execution (%s or %s)&quot;;
</span><span class="cx"> localizedStrings[&quot;Continue to Here&quot;] = &quot;Continue to Here&quot;;
</span><span class="cx"> localizedStrings[&quot;Controls&quot;] = &quot;Controls&quot;;
</span><span class="lines">@@ -589,8 +592,10 @@
</span><span class="cx"> localizedStrings[&quot;Pause Playback&quot;] = &quot;Pause Playback&quot;;
</span><span class="cx"> localizedStrings[&quot;Pause Reason&quot;] = &quot;Pause Reason&quot;;
</span><span class="cx"> localizedStrings[&quot;Pause script execution (%s or %s)&quot;] = &quot;Pause script execution (%s or %s)&quot;;
</span><ins>+localizedStrings[&quot;Ping Frame&quot;] = &quot;Ping Frame&quot;;
</ins><span class="cx"> localizedStrings[&quot;Play Sound&quot;] = &quot;Play Sound&quot;;
</span><span class="cx"> localizedStrings[&quot;Polite&quot;] = &quot;Polite&quot;;
</span><ins>+localizedStrings[&quot;Pong Frame&quot;] = &quot;Pong Frame&quot;;
</ins><span class="cx"> localizedStrings[&quot;Port&quot;] = &quot;Port&quot;;
</span><span class="cx"> localizedStrings[&quot;Position&quot;] = &quot;Position&quot;;
</span><span class="cx"> localizedStrings[&quot;Position X&quot;] = &quot;Position X&quot;;
</span><span class="lines">@@ -783,6 +788,7 @@
</span><span class="cx"> localizedStrings[&quot;Take snapshot&quot;] = &quot;Take snapshot&quot;;
</span><span class="cx"> localizedStrings[&quot;Template Content&quot;] = &quot;Template Content&quot;;
</span><span class="cx"> localizedStrings[&quot;Text&quot;] = &quot;Text&quot;;
</span><ins>+localizedStrings[&quot;Text Frame&quot;] = &quot;Text Frame&quot;;
</ins><span class="cx"> localizedStrings[&quot;Text Node&quot;] = &quot;Text Node&quot;;
</span><span class="cx"> localizedStrings[&quot;Text Only&quot;] = &quot;Text Only&quot;;
</span><span class="cx"> localizedStrings[&quot;The selector “%s” is invalid.\nClick to revert to the previous selector.&quot;] = &quot;The selector “%s” is invalid.\nClick to revert to the previous selector.&quot;;
</span><span class="lines">@@ -854,6 +860,7 @@
</span><span class="cx"> localizedStrings[&quot;Warnings&quot;] = &quot;Warnings&quot;;
</span><span class="cx"> localizedStrings[&quot;Watch Expressions&quot;] = &quot;Watch Expressions&quot;;
</span><span class="cx"> localizedStrings[&quot;Web Inspector&quot;] = &quot;Web Inspector&quot;;
</span><ins>+localizedStrings[&quot;WebSocket Connection Established&quot;] = &quot;WebSocket Connection Established&quot;;
</ins><span class="cx"> localizedStrings[&quot;Weight&quot;] = &quot;Weight&quot;;
</span><span class="cx"> localizedStrings[&quot;Whitespace&quot;] = &quot;Whitespace&quot;;
</span><span class="cx"> localizedStrings[&quot;Whitespace Characters:&quot;] = &quot;Whitespace Characters:&quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersFrameResourceManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -206,7 +206,7 @@
</span><span class="cx">         this._webSocketIdentifierToURL.set(requestId, url);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    webSocketWillSendHandshakeRequest(requestId, timestamp, request)
</del><ins>+    webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request)
</ins><span class="cx">     {
</span><span class="cx">         let url = this._webSocketIdentifierToURL.get(requestId);
</span><span class="cx">         console.assert(url);
</span><span class="lines">@@ -213,6 +213,12 @@
</span><span class="cx">         if (!url)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><ins>+        // COMPATIBILITY(iOS 10.3): `walltime` did not exist in 10.3 and earlier.
+        if (!NetworkAgent.hasEventParameter(&quot;webSocketWillSendHandshakeRequest&quot;, &quot;walltime&quot;)) {
+            request = arguments[2];
+            walltime = NaN;
+        }
+
</ins><span class="cx">         // FIXME: &lt;webkit.org/b/168475&gt; Web Inspector: Correctly display iframe's and worker's WebSockets
</span><span class="cx">         let frameIdentifier = WebInspector.frameResourceManager.mainFrame.id;
</span><span class="cx">         let loaderIdentifier = WebInspector.frameResourceManager.mainFrame.id;
</span><span class="lines">@@ -223,7 +229,8 @@
</span><span class="cx">         let elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
</span><span class="cx">         let initiatorSourceCodeLocation = null;
</span><span class="cx"> 
</span><del>-        let resource = new WebInspector.WebSocketResource(url, loaderIdentifier, targetId, requestId, request.headers, requestData, elapsedTime, initiatorSourceCodeLocation);
</del><ins>+        let resource = new WebInspector.WebSocketResource(url, loaderIdentifier, targetId, requestId, request.headers, requestData, timestamp, walltime, elapsedTime, initiatorSourceCodeLocation);
+
</ins><span class="cx">         frame.addResource(resource);
</span><span class="cx"> 
</span><span class="cx">         this._resourceRequestIdentifierMap.set(requestId, resource);
</span><span class="lines">@@ -280,13 +287,15 @@
</span><span class="cx">         if (!resource)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        let isIncoming = !!response.mask;
</del><ins>+        // Data going from the client to the server is always masked.
+        let isOutgoing = !!response.mask;
+
</ins><span class="cx">         let data = response.payloadData;
</span><span class="cx">         let opcode = response.opcode;
</span><span class="cx"> 
</span><span class="cx">         let elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
</span><span class="cx"> 
</span><del>-        resource.addFrame(data, isIncoming, opcode, timestamp, elapsedTime);
</del><ins>+        resource.addFrame(data, isOutgoing, opcode, timestamp, elapsedTime);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     markResourceRequestAsServedFromMemoryCache(requestIdentifier)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesArrowUpsvg"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/ArrowUp.svg (0 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot;?&gt;
+&lt;!-- Copyright © 2017 Apple Inc. All rights reserved. --&gt;
+&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; id=&quot;root&quot; version=&quot;1.1&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot;&gt;
+    &lt;path fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1&quot; d=&quot;M 8 2 L 2 11 H 6 v 4 h 4 V 11 h 4 Z&quot;/&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesgtkArrowUpsvg"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/gtk/ArrowUp.svg (0 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot;?&gt;
+&lt;!-- Licensed under the Creative Commons Attribution-Share Alike 3.0 United States License (http://creativecommons.org/licenses/by-sa/3.0/) --&gt;
+&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; id=&quot;root&quot; version=&quot;1.1&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot;&gt;
+    &lt;path fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; d=&quot;M 8 2 L 2 11 H 6 v 4 h 4 V 11 h 4 Z&quot;/&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -202,6 +202,7 @@
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/VisualStyleTabbedPropertiesRow.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/VisualStyleTimingEditor.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/VisualStyleUnitSlider.css&quot;&gt;
</span><ins>+    &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/WebSocketContentView.css&quot;&gt;
</ins><span class="cx"> 
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Controllers/CodeMirrorCompletionController.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Controllers/CodeMirrorDragToAdjustNumberController.css&quot;&gt;
</span><span class="lines">@@ -678,6 +679,7 @@
</span><span class="cx">     &lt;script src=&quot;Views/TypeTokenView.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TypeTreeElement.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TypeTreeView.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Views/WebSocketContentView.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Views/WorkerTreeElement.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> 
</span><span class="cx">     &lt;script src=&quot;Views/VisualStyleDetailsPanel.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsWebSocketResourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/WebSocketResource.js (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> WebInspector.WebSocketResource = class WebSocketResource extends WebInspector.Resource
</span><span class="cx"> {
</span><del>-    constructor(url, loaderIdentifier, targetId, requestIdentifier, requestHeaders, requestData, requestSentTimestamp, initiatorSourceCodeLocation)
</del><ins>+    constructor(url, loaderIdentifier, targetId, requestIdentifier, requestHeaders, requestData, timestamp, walltime, requestSentTimestamp, initiatorSourceCodeLocation)
</ins><span class="cx">     {
</span><span class="cx">         const type = WebInspector.Resource.Type.WebSocket;
</span><span class="cx">         const mimeType = null;
</span><span class="lines">@@ -32,6 +32,8 @@
</span><span class="cx">         const requestMethod = &quot;GET&quot;;
</span><span class="cx">         super(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, requestSentTimestamp, initiatorSourceCodeLocation);
</span><span class="cx"> 
</span><ins>+        this._timestamp = timestamp;
+        this._walltime = walltime;
</ins><span class="cx">         this._readyState = WebInspector.WebSocketResource.ReadyState.Connecting;
</span><span class="cx">         this._frames = [];
</span><span class="cx">     }
</span><span class="lines">@@ -39,6 +41,7 @@
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get frames() { return this._frames; }
</span><ins>+    get walltime() { return this._walltime; }
</ins><span class="cx"> 
</span><span class="cx">     get readyState()
</span><span class="cx">     {
</span><span class="lines">@@ -56,13 +59,22 @@
</span><span class="cx">         this.dispatchEventToListeners(WebInspector.WebSocketResource.Event.ReadyStateChanged, {previousState, state});
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    addFrame(data, isIncoming, opcode, timestamp, elapsedTime)
</del><ins>+    addFrame(data, isOutgoing, opcode, timestamp, elapsedTime)
</ins><span class="cx">     {
</span><del>-        let frame = {data, isIncoming, opcode, timestamp, elapsedTime};
</del><ins>+        let frame = {data, isOutgoing, opcode, walltime: this._walltimeForWebSocketTimestamp(timestamp)};
</ins><span class="cx">         this._frames.push(frame);
</span><span class="cx"> 
</span><ins>+        this.increaseSize(data.length, elapsedTime);
+
</ins><span class="cx">         this.dispatchEventToListeners(WebInspector.WebSocketResource.Event.FrameAdded, frame);
</span><span class="cx">     }
</span><ins>+
+    // Private
+
+    _walltimeForWebSocketTimestamp(timestamp)
+    {
+        return this._walltime + (timestamp - this._timestamp);
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.WebSocketResource.Event = {
</span><span class="lines">@@ -75,3 +87,12 @@
</span><span class="cx">     Connecting: Symbol(&quot;web-socket-ready-state-connecting&quot;),
</span><span class="cx">     Open: Symbol(&quot;web-socket-ready-state-open&quot;),
</span><span class="cx"> };
</span><ins>+
+WebInspector.WebSocketResource.OpCodes = {
+    ContinuationFrame: 0,
+    TextFrame: 1,
+    BinaryFrame: 2,
+    ConnectionCloseFrame: 8,
+    PingFrame: 9,
+    PongFrame: 10,
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceProtocolNetworkObserverjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/NetworkObserver.js (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -68,9 +68,9 @@
</span><span class="cx">         WebInspector.frameResourceManager.webSocketCreated(requestId, url);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    webSocketWillSendHandshakeRequest(requestId, timestamp, request)
</del><ins>+    webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request)
</ins><span class="cx">     {
</span><del>-        WebInspector.frameResourceManager.webSocketWillSendHandshakeRequest(requestId, timestamp, request);
</del><ins>+        WebInspector.frameResourceManager.webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     webSocketHandshakeResponseReceived(requestId, timestamp, response)
</span><span class="lines">@@ -88,13 +88,13 @@
</span><span class="cx">         WebInspector.frameResourceManager.webSocketFrameReceived(requestId, timestamp, response);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    webSocketFrameError(requestId, timestamp, errorMessage)
</del><ins>+    webSocketFrameSent(requestId, timestamp, response)
</ins><span class="cx">     {
</span><del>-        // FIXME: Not implemented.
</del><ins>+        WebInspector.frameResourceManager.webSocketFrameSent(requestId, timestamp, response);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    webSocketFrameSent(requestId, timestamp, response)
</del><ins>+    webSocketFrameError(requestId, timestamp, errorMessage)
</ins><span class="cx">     {
</span><del>-        WebInspector.frameResourceManager.webSocketFrameSent(requestId, timestamp, response);
</del><ins>+        // FIXME: Not implemented.
</ins><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -168,13 +168,10 @@
</span><span class="cx">         closeButton.addEventListener(WebInspector.TreeElementStatusButton.Event.Clicked, this._treeElementCloseButtonClicked, this);
</span><span class="cx">         fragment.appendChild(closeButton.element);
</span><span class="cx"> 
</span><del>-        // FIXME: &lt;webkit.org/b/169011&gt; 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);
-        }
</del><ins>+        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);
</ins><span class="cx"> 
</span><span class="cx">         treeElement.status = fragment;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsResourceClusterContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceClusterContentView.js (213665 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case WebInspector.Resource.Type.WebSocket:
</span><del>-            // FIXME: &lt;webkit.org/b/169011&gt; Web Inspector: Show individual messages in the content pane for a WebSocket
</del><ins>+            this._responseContentView = new WebInspector.WebSocketContentView(this._resource);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         default:
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsWebSocketContentViewcss"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.css (0 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+/*
+ * 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 &gt; .data-grid {
+    height: 100%;
+}
+
+.web-socket.content-view &gt; .data-grid table.data {
+    height: auto;
+    background-image: none;
+}
+
+.web-socket.content-view &gt; .data-grid td.data-column,
+.web-socket.content-view .data-grid td.data-column &gt; div {
+    height: auto;
+    white-space: pre-wrap;
+}
+
+body[dir=ltr] .web-socket.content-view &gt; .data-grid .data-column &gt; div {
+    padding-left: 18px;
+}
+
+body[dir=rtl] .web-socket.content-view &gt; .data-grid .data-column &gt; 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(&quot;../Images/ArrowUp.svg&quot;);
+}
+
+.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%);
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsWebSocketContentViewjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketContentView.js (0 => 213666)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+/*
+ * 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(&quot;webSocketWillSendHandshakeRequest&quot;, &quot;walltime&quot;);
+
+        this.element.classList.add(&quot;web-socket&quot;, &quot;resource&quot;);
+
+        let columns = {data: {}};
+        columns.data.title = WebInspector.UIString(&quot;Data&quot;);
+        columns.data.sortable = false;
+        columns.data.icon = true;
+        columns.data.width = &quot;85%&quot;;
+
+        if (this._showTimeColumn)
+            columns.time = {title: WebInspector.UIString(&quot;Time&quot;), sortable: true};
+
+        this._dataGrid = new WebInspector.DataGrid(columns);
+        this._dataGrid.variableHeightRows = true;
+        this.addSubview(this._dataGrid);
+
+        this._addRow(WebInspector.UIString(&quot;WebSocket Connection Established&quot;), this._resource.walltime, [&quot;non-text-frame&quot;]);
+
+        this._dataGrid.updateLayout();
+    }
+
+    // Static
+
+    static textForOpcode(opcode)
+    {
+        switch (opcode) {
+        case WebInspector.WebSocketResource.OpCodes.ContinuationFrame:
+            return WebInspector.UIString(&quot;Continuation Frame&quot;);
+        case WebInspector.WebSocketResource.OpCodes.TextFrame:
+            return WebInspector.UIString(&quot;Text Frame&quot;);
+        case WebInspector.WebSocketResource.OpCodes.BinaryFrame:
+            return WebInspector.UIString(&quot;Binary Frame&quot;);
+        case WebInspector.WebSocketResource.OpCodes.ConnectionCloseFrame:
+            return WebInspector.UIString(&quot;Connection Close Frame&quot;);
+        case WebInspector.WebSocketResource.OpCodes.PingFrame:
+            return WebInspector.UIString(&quot;Ping Frame&quot;);
+        case WebInspector.WebSocketResource.OpCodes.PongFrame:
+            return WebInspector.UIString(&quot;Pong Frame&quot;);
+        }
+    }
+
+    // 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 ? &quot;outgoing&quot; : &quot;incoming&quot;,
+            opcode === WebInspector.WebSocketResource.OpCodes.TextFrame ? &quot;text-frame&quot; : &quot;non-text-frame&quot;
+        ];
+
+        this._addRow(nodeText, time, classNames);
+    }
+
+    // Private
+
+    _updateFrames()
+    {
+        let framesLength = this._resource.frames.length;
+        for (let index = this._framesRendered; index &lt; 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();
+    }
+};
</ins></span></pre>
</div>
</div>

</body>
</html>