Skip to content
This repository was archived by the owner on Aug 13, 2018. It is now read-only.

Commit 244ea9f

Browse files
committed
Initial WebSocket monitoring
1 parent 7ed67e3 commit 244ea9f

37 files changed

+24702
-2
lines changed

.gitignore

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
# Junk that could exist anywhere:
3+
.DS_Store
4+
*.swp
5+
*.tmp
6+
.*.gz
7+
*.patch
8+
*~
9+
10+
# Temporary files created by Eclipse
11+
.tmp*
12+
13+
# Editor junk
14+
*.project
15+
/.pydevproject
16+
/.settings/
17+
/.settings.xml
18+
/.settings.xml.old
19+
/.idea/
20+
*.iws
21+
*.ids
22+
*.iml
23+
*.ipr
24+
25+
# Build Files
26+
/build/
27+
/release/
28+
*.graphml
29+
*.xpi
30+
31+
# Files from NPM
32+
node_modules/
33+
34+
# Extensions
35+
36+
37+
bootstrap.js
38+
install.rdf
39+
40+
# Bash
41+
*.sh
42+
*.bat

README.md

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,23 @@
1-
# websocket-monitor
2-
Monitor WebSocket connections
1+
WebSocket Monitor
2+
=================
3+
WebSocket monitor can be used to a web socket connection(s) on the current page.
4+
This extension requires platform API introduced in:
5+
[Bug 1203802](https://bugzilla.mozilla.org/show_bug.cgi?id=1203802) -
6+
Websocket Frame Listener API for devtool Network Inspector
7+
8+
Instructions
9+
------------
10+
1. Install the extension
11+
3. Open a browser tab and developer tools toolbox on it (F12)
12+
4. Select the `Web Sockets` toolbox panel
13+
5. Initiate WebSocket connection on the page and exchanges some messages.
14+
6. Check out content of the `Web Sockets` panel.
15+
16+
You might want to check out online [demo page](http://janodvarko.cz/test/websockets/)
17+
18+
Further Resources
19+
-----------------
20+
* RDP: https://wiki.mozilla.org/Remote_Debugging_Protocol
21+
* Add-on SDK: https://developer.mozilla.org/en-US/Add-ons/SDK
22+
* DevTools API: https://developer.mozilla.org/en-US/docs/Tools/DevToolsAPI
23+
* DevTools/Hacking: https://wiki.mozilla.org/DevTools/Hacking

chrome.manifest

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
skin websocketmonitor-firebug.sdk classic/1.0 node_modules/firebug.sdk/skin/classic/shared/
2+
3+
locale websocketmonitor en-US chrome/locale/en-US/
4+
5+
locale websocketmonitor-firebug.sdk en-US node_modules/firebug.sdk/locale/en-US/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
websocketmonitor.Clear=Clear
2+
websocketmonitor.SocketID=Socket ID
3+
websocketmonitor.Size=Size
4+
websocketmonitor.Payload=Payload
5+
websocketmonitor.OpCode=OpCode
6+
websocketmonitor.MaskBit=MaskBit
7+
websocketmonitor.FinBit=FinBit
8+
websocketmonitor.Details=Details
9+
websocketmonitor.Payload=Payload
10+
websocketmonitor.Time=Time
11+
websocketmonitor.SocketIO=Socket.IO

data/actions/frames.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* See license.txt for terms of usage */
2+
3+
define(function(require, exports/*, module*/) {
4+
5+
"use strict";
6+
7+
const types = {
8+
CLEAR: "CLEAR",
9+
ADD_FRAME: "ADD_FRAME",
10+
ADD_FRAMES: "ADD_FRAMES"
11+
}
12+
13+
function clear() {
14+
return { type: types.CLEAR };
15+
}
16+
17+
function addFrame(frame) {
18+
return { type: types.ADD_FRAME, frame: frame };
19+
}
20+
21+
function addFrames(frames) {
22+
return { type: types.ADD_FRAMES, frames: frames };
23+
}
24+
25+
// Exports from this module
26+
exports.clear = clear;
27+
exports.addFrame = addFrame;
28+
exports.addFrames = addFrames;
29+
exports.types = types;
30+
});
31+

data/actions/selection.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* See license.txt for terms of usage */
2+
3+
define(function(require, exports/*, module*/) {
4+
5+
"use strict";
6+
7+
const types = {
8+
SELECT_FRAME: "SELECT_FRAME",
9+
}
10+
11+
function selectFrame(frame) {
12+
return { type: types.SELECT_FRAME, frame: frame };
13+
}
14+
15+
// Exports from this module
16+
exports.selectFrame = selectFrame;
17+
exports.types = types;
18+
});
19+

data/components/details-tab.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* See license.txt for terms of usage */
2+
3+
define(function(require, exports/*, module*/) {
4+
5+
"use strict";
6+
7+
// Dependencies
8+
const React = require("react");
9+
10+
// Firebug SDK
11+
const { Reps } = require("reps/repository");
12+
const { TreeView } = require("reps/tree-view");
13+
14+
// Shortcuts
15+
const { DIV } = Reps.DOM;
16+
17+
/**
18+
* TODO: docs
19+
*/
20+
var DetailsTab = React.createClass({
21+
/** @lends DetailsTab */
22+
23+
displayName: "DetailsTab",
24+
25+
render: function() {
26+
var selectedFrame = this.props.selection || {};
27+
28+
return (
29+
DIV({className: "details"},
30+
TreeView({key: "detailsTabTree", data: selectedFrame})
31+
)
32+
);
33+
}
34+
});
35+
36+
// Exports from this module
37+
exports.DetailsTab = DetailsTab;
38+
});

data/components/frame-table.js

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/* See license.txt for terms of usage */
2+
3+
define(function(require, exports/*, module*/) {
4+
5+
"use strict";
6+
7+
// ReactJS
8+
const React = require("react");
9+
10+
// Firebug SDK
11+
const { Str } = require("reps/core/string");
12+
13+
// WebSockets Monitor
14+
const { selectFrame } = require("../actions/selection");
15+
16+
// Constants
17+
const { table, thead, th, tbody, tr, td, tfoot, div } = React.DOM;
18+
19+
/**
20+
* This components implements the main table layout for list of frames.
21+
*/
22+
var FrameTable = React.createClass({
23+
/** @lends FrameTable */
24+
25+
displayName: "FrameTable",
26+
27+
render: function() {
28+
var frames = this.props.frames.frames;
29+
30+
// Render list frames.
31+
var rows = frames.map(frame => FrameRow({
32+
selection: this.props.selection,
33+
frame: frame,
34+
dispatch: this.props.dispatch
35+
}));
36+
37+
return (
38+
table({className: "frameTable"},
39+
thead({className: "frameTHead"},
40+
tr({},
41+
th({className: "direction"}),
42+
th({className: "socketId"}, Locale.$STR("websocketmonitor.SocketID")),
43+
th({className: "payloadSize"}, Locale.$STR("websocketmonitor.Size")),
44+
th({className: "payload"}, Locale.$STR("websocketmonitor.Payload")),
45+
th({className: "opcode"}, Locale.$STR("websocketmonitor.OpCode")),
46+
th({className: "bit"}, Locale.$STR("websocketmonitor.MaskBit")),
47+
th({className: "bit"}, Locale.$STR("websocketmonitor.FinBit")),
48+
th({className: "time"}, Locale.$STR("websocketmonitor.Time"))
49+
)
50+
),
51+
tbody({className: "frameTBody"},
52+
rows
53+
)/*,
54+
tfoot({className: "frameTFoot"},
55+
tr({},
56+
td({colSpan: 5}, "Summary: ")
57+
)
58+
)*/
59+
)
60+
);
61+
}
62+
});
63+
64+
/**
65+
* Represents a row within the frame list.
66+
*/
67+
var FrameRow = React.createFactory(React.createClass({
68+
/** @lends FrameRow */
69+
70+
displayName: "FrameRow",
71+
72+
onClick: function() {
73+
if (this.props.frame != this.props.selection) {
74+
this.props.dispatch(selectFrame(this.props.frame));
75+
}
76+
},
77+
78+
getOpCode: function() {
79+
var frame = this.props.frame;
80+
var data = frame.header ? frame.header : frame.maskBit;
81+
var opCode = parseInt(data.opCode, 10);
82+
83+
switch (opCode) {
84+
case data.OPCODE_CONTINUATION:
85+
return "CONTINUATION";
86+
case data.OPCODE_TEXT:
87+
return "TEXT";
88+
case data.OPCODE_BINARY:
89+
return "BINARY";
90+
case data.OPCODE_CLOSE:
91+
return "CLOSE";
92+
case data.OPCODE_PING:
93+
return "PING";
94+
case data.OPCODE_PONG:
95+
return "PONG";
96+
}
97+
98+
return "(unknown)";
99+
},
100+
101+
render: function() {
102+
var frame = this.props.frame;
103+
var data = frame.header ? frame.header : frame.maskBit;
104+
var className = "frameRow " + (frame.header ? "send" : "receive");
105+
var tooltipText = frame.header ? "Sent" : "Received";
106+
107+
if (this.props.selection == frame) {
108+
className += " selected";
109+
}
110+
111+
var payload = Str.cropString(data.payload, 50);
112+
var size = Str.formatSize(data.payload.length);
113+
var onClick = this.onClick.bind(this);
114+
var time = new Date(data.timeStamp / 1000);
115+
var timeText = time.getHours() + ":" + time.getMinutes() +
116+
":" + time.getSeconds() + "." + time.getMilliseconds();
117+
118+
return (
119+
tr({className: className, onClick: onClick},
120+
td({className: "direction"},
121+
div({title: tooltipText})
122+
),
123+
td({className: "socketId"}, frame.webSocketSerialID),
124+
td({className: "payloadSize"}, size),
125+
td({className: "payload"}, payload),
126+
td({className: "opcode"}, this.getOpCode()),
127+
td({className: "bit"}, data.maskBit ? "true" : "false"),
128+
td({className: "bit"}, data.finBit ? "true" : "false"),
129+
td({className: "time"}, timeText)
130+
)
131+
);
132+
}
133+
}));
134+
135+
// Exports from this module
136+
exports.FrameTable = FrameTable;
137+
});

data/components/main-toolbar.js

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* See license.txt for terms of usage */
2+
3+
define(function(require, exports/*, module*/) {
4+
5+
"use strict";
6+
7+
// Dependencies
8+
const React = require("react");
9+
10+
// Firebug.SDK
11+
const { createFactories } = require("reps/rep-utils");
12+
const { Toolbar, ToolbarButton } = createFactories(require("reps/toolbar"));
13+
14+
// WebSockets Monitor
15+
const { clear } = require("../actions/frames");
16+
17+
/**
18+
* @template This object is responsible for rendering the toolbar
19+
* in Actors tab
20+
*/
21+
var MainToolbar = React.createClass({
22+
/** @lends MainToolbar */
23+
24+
displayName: "MainToolbar",
25+
26+
// Commands
27+
28+
onPause: function() {
29+
},
30+
31+
onClear: function() {
32+
this.props.dispatch(clear());
33+
},
34+
35+
// Render
36+
37+
render: function() {
38+
return (
39+
Toolbar({className: "toolbar"},
40+
/*ToolbarButton({bsSize: "xsmall", onClick: this.onPause},
41+
Locale.$STR("websocketmonitor.Pause")
42+
),*/
43+
ToolbarButton({bsSize: "xsmall", onClick: this.onClear},
44+
Locale.$STR("websocketmonitor.Clear")
45+
)
46+
)
47+
);
48+
},
49+
});
50+
51+
// Exports from this module
52+
exports.MainToolbar = MainToolbar;
53+
});

0 commit comments

Comments
 (0)