1 /* 2 * Copyright (C) 2012 Research In Motion Limited. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /** 20 * @constructor 21 * @extends {WebInspector.VBox} 22 * @param {!WebInspector.NetworkRequest} request 23 */ 24 WebInspector.ResourceWebSocketFrameView = function(request) 25 { 26 WebInspector.VBox.call(this); 27 this.registerRequiredCSS("webSocketFrameView.css"); 28 this.element.classList.add("websocket-frame-view"); 29 this._request = request; 30 this.element.removeChildren(); 31 32 var columns = [ 33 {id: "data", title: WebInspector.UIString("Data"), sortable: false, weight: 88, longText: true}, 34 {id: "length", title: WebInspector.UIString("Length"), sortable: false, align: WebInspector.DataGrid.Align.Right, weight: 5}, 35 {id: "time", title: WebInspector.UIString("Time"), weight: 7} 36 ] 37 38 this._dataGrid = new WebInspector.SortableDataGrid(columns, undefined, undefined, undefined, this._onContextMenu.bind(this)); 39 this._dataGrid.setCellClass("websocket-frame-view-td"); 40 var comparator = /** @type {!WebInspector.SortableDataGrid.NodeComparator} */ (WebInspector.ResourceWebSocketFrameNodeTimeComparator); 41 this._dataGrid.sortNodes(comparator, true); 42 43 this.refresh(); 44 this._dataGrid.setName("ResourceWebSocketFrameView"); 45 this._dataGrid.show(this.element); 46 } 47 48 /** @enum {number} */ 49 WebInspector.ResourceWebSocketFrameView.OpCodes = { 50 ContinuationFrame: 0, 51 TextFrame: 1, 52 BinaryFrame: 2, 53 ConnectionCloseFrame: 8, 54 PingFrame: 9, 55 PongFrame: 10 56 }; 57 58 /** @type {!Array.<string> } */ 59 WebInspector.ResourceWebSocketFrameView.opCodeDescriptions = (function() 60 { 61 var opCodes = WebInspector.ResourceWebSocketFrameView.OpCodes; 62 var map = []; 63 map[opCodes.ContinuationFrame] = "Continuation Frame"; 64 map[opCodes.TextFrame] = "Text Frame"; 65 map[opCodes.BinaryFrame] = "Binary Frame"; 66 map[opCodes.ContinuationFrame] = "Connection Close Frame"; 67 map[opCodes.PingFrame] = "Ping Frame"; 68 map[opCodes.PongFrame] = "Pong Frame"; 69 return map; 70 })(); 71 72 /** 73 * @param {number} opCode 74 * @param {boolean} mask 75 * @return {string} 76 */ 77 WebInspector.ResourceWebSocketFrameView.opCodeDescription = function(opCode, mask) 78 { 79 var rawDescription = WebInspector.ResourceWebSocketFrameView.opCodeDescriptions[opCode] || ""; 80 var localizedDescription = WebInspector.UIString(rawDescription); 81 return WebInspector.UIString("%s (Opcode %d%s)", localizedDescription, opCode, (mask ? ", mask" : "")); 82 } 83 84 WebInspector.ResourceWebSocketFrameView.prototype = { 85 refresh: function() 86 { 87 this._dataGrid.rootNode().removeChildren(); 88 var frames = this._request.frames(); 89 for (var i = frames.length - 1; i >= 0; --i) 90 this._dataGrid.insertChild(new WebInspector.ResourceWebSocketFrameNode(frames[i])); 91 }, 92 93 show: function(parentElement, insertBefore) 94 { 95 this.refresh(); 96 WebInspector.View.prototype.show.call(this, parentElement, insertBefore); 97 }, 98 99 /** 100 * @param {!WebInspector.ContextMenu} contextMenu 101 * @param {!WebInspector.DataGridNode} node 102 */ 103 _onContextMenu: function(contextMenu, node) 104 { 105 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy message" : "Copy Message"), this._copyMessage.bind(this, node.data)); 106 }, 107 108 /** 109 * @param {!Object} row 110 */ 111 _copyMessage: function(row) 112 { 113 InspectorFrontendHost.copyText(row.data); 114 }, 115 116 __proto__: WebInspector.VBox.prototype 117 } 118 119 /** 120 * @constructor 121 * @extends {WebInspector.SortableDataGridNode} 122 * @param {!WebInspector.NetworkRequest.WebSocketFrame} frame 123 */ 124 WebInspector.ResourceWebSocketFrameNode = function(frame) 125 { 126 this._frame = frame; 127 this._dataText = frame.text; 128 this._length = frame.text.length; 129 this._timeText = (new Date(frame.time * 1000)).toLocaleTimeString(); 130 131 this._isTextFrame = frame.opCode === WebInspector.ResourceWebSocketFrameView.OpCodes.TextFrame; 132 if (!this._isTextFrame) 133 this._dataText = WebInspector.ResourceWebSocketFrameView.opCodeDescription(frame.opCode, frame.mask); 134 135 WebInspector.SortableDataGridNode.call(this, {data: this._dataText, length: this._length, time: this._timeText}); 136 } 137 138 WebInspector.ResourceWebSocketFrameNode.prototype = { 139 /** override */ 140 createCells: function() 141 { 142 var element = this._element; 143 element.classList.toggle("websocket-frame-view-row-error", this._frame.type === WebInspector.NetworkRequest.WebSocketFrameType.Error); 144 element.classList.toggle("websocket-frame-view-row-outcoming", this._frame.type === WebInspector.NetworkRequest.WebSocketFrameType.Send); 145 element.classList.toggle("websocket-frame-view-row-opcode", !this._isTextFrame); 146 WebInspector.SortableDataGridNode.prototype.createCells.call(this); 147 }, 148 149 __proto__: WebInspector.SortableDataGridNode.prototype 150 } 151 152 /** 153 * @param {!WebInspector.ResourceWebSocketFrameNode} a 154 * @param {!WebInspector.ResourceWebSocketFrameNode} b 155 * @return {number} 156 */ 157 WebInspector.ResourceWebSocketFrameNodeTimeComparator = function(a, b) 158 { 159 return a._frame.time - b._frame.time; 160 } 161