Skip to content
This repository was archived by the owner on Jul 28, 2023. It is now read-only.

Commit 3ac3d9c

Browse files
committed
Add network tab
1 parent 5a1b0e5 commit 3ac3d9c

File tree

5 files changed

+277
-31
lines changed

5 files changed

+277
-31
lines changed

front_end/ndb.json

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
{
2-
"modules" : [
3-
{ "name": "ndb_sdk", "type": "autostart" },
4-
{ "name": "ndb", "type": "autostart" },
5-
{ "name": "layer_viewer" },
6-
{ "name": "timeline_model" },
7-
{ "name": "timeline" },
8-
{ "name": "product_registry" },
9-
{ "name": "mobile_throttling" },
10-
{ "name": "ndb_ui" },
11-
{ "name": "xterm" }
12-
],
2+
"modules": [
3+
{ "name": "ndb_sdk", "type": "autostart" },
4+
{ "name": "ndb", "type": "autostart" },
5+
{ "name": "layer_viewer" },
6+
{ "name": "timeline_model" },
7+
{ "name": "timeline" },
8+
{ "name": "product_registry" },
9+
{ "name": "mobile_throttling" },
10+
{ "name": "ndb_ui" },
11+
{ "name": "xterm" },
12+
{ "name": "emulation", "type": "autostart" },
13+
{ "name": "inspector_main", "type": "autostart" },
14+
{ "name": "mobile_throttling", "type": "autostart" },
15+
{ "name": "cookie_table" },
16+
{ "name": "har_importer" },
17+
{ "name": "network" }
18+
],
1319
"extends": "shell",
1420
"has_html": true
1521
}

front_end/ndb/NdbMain.js

+79-17
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@
55
*/
66

77
Ndb.nodeExecPath = function() {
8-
if (!Ndb._nodeExecPathPromise)
9-
Ndb._nodeExecPathPromise = Ndb.backend.which('node').then(result => result.resolvedPath);
8+
if (!Ndb._nodeExecPathPromise) {
9+
Ndb._nodeExecPathPromise = Ndb.backend
10+
.which('node')
11+
.then(result => result.resolvedPath);
12+
}
1013
return Ndb._nodeExecPathPromise;
1114
};
1215

1316
Ndb.npmExecPath = function() {
14-
if (!Ndb._npmExecPathPromise)
15-
Ndb._npmExecPathPromise = Ndb.backend.which('npm').then(result => result.resolvedPath);
17+
if (!Ndb._npmExecPathPromise) {
18+
Ndb._npmExecPathPromise = Ndb.backend
19+
.which('npm')
20+
.then(result => result.resolvedPath);
21+
}
1622
return Ndb._npmExecPathPromise;
1723
};
1824

@@ -27,39 +33,60 @@ Ndb.processInfo = function() {
2733
*/
2834
Ndb.NdbMain = class extends Common.Object {
2935
/**
30-
* @override
31-
*/
36+
* @override
37+
*/
3238
async run() {
3339
InspectorFrontendAPI.setUseSoftMenu(true);
3440
document.title = 'ndb';
35-
Common.moduleSetting('blackboxInternalScripts').addChangeListener(Ndb.NdbMain._calculateBlackboxState);
41+
Common.moduleSetting('blackboxInternalScripts').addChangeListener(
42+
Ndb.NdbMain._calculateBlackboxState
43+
);
3644
Ndb.NdbMain._calculateBlackboxState();
3745

3846
const setting = Persistence.isolatedFileSystemManager.workspaceFolderExcludePatternSetting();
3947
setting.set(Ndb.NdbMain._defaultExcludePattern().join('|'));
40-
Ndb.nodeProcessManager = await Ndb.NodeProcessManager.create(SDK.targetManager);
48+
Ndb.nodeProcessManager = await Ndb.NodeProcessManager.create(
49+
SDK.targetManager
50+
);
4151

42-
const {cwd} = await Ndb.processInfo();
52+
const { cwd } = await Ndb.processInfo();
4353
await Ndb.nodeProcessManager.addFileSystem(cwd);
4454

4555
// TODO(ak239): we do not want to create this model for workers, so we need a way to add custom capabilities.
46-
SDK.SDKModel.register(NdbSdk.NodeWorkerModel, SDK.Target.Capability.JS, true);
47-
SDK.SDKModel.register(NdbSdk.NodeRuntimeModel, SDK.Target.Capability.JS, true);
56+
SDK.SDKModel.register(
57+
NdbSdk.NodeWorkerModel,
58+
SDK.Target.Capability.JS,
59+
true
60+
);
61+
SDK.SDKModel.register(
62+
NdbSdk.NodeRuntimeModel,
63+
SDK.Target.Capability.JS,
64+
true
65+
);
4866

4967
await new Promise(resolve => SDK.initMainConnection(resolve));
50-
SDK.targetManager.createTarget('<root>', ls`Root`, SDK.Target.Type.Browser, null);
68+
SDK.targetManager.createTarget(
69+
'<root>',
70+
ls`Root`,
71+
SDK.Target.Type.Browser,
72+
null
73+
);
74+
5175
if (Common.moduleSetting('autoStartMain').get()) {
5276
const main = await Ndb.mainConfiguration();
5377
if (main) {
54-
if (main.prof)
55-
await Ndb.nodeProcessManager.profile(main.execPath, main.args);
56-
else
57-
Ndb.nodeProcessManager.debug(main.execPath, main.args);
78+
if (main.prof) {
79+
await Ndb.nodeProcessManager.profile(
80+
main.execPath,
81+
main.args
82+
);
83+
} else {Ndb.nodeProcessManager.debug(main.execPath, main.args);}
5884
}
5985
}
6086
Ndb.nodeProcessManager.startRepl();
6187
}
6288

89+
6390
static _defaultExcludePattern() {
6491
const defaultCommonExcludedFolders = [
6592
'/bower_components/', '/\\.devtools', '/\\.git/', '/\\.sass-cache/', '/\\.hg/', '/\\.idea/',
@@ -125,7 +152,6 @@ Ndb.mainConfiguration = async() => {
125152
prof
126153
};
127154
};
128-
129155
/**
130156
* @implements {UI.ContextMenu.Provider}
131157
* @unrestricted
@@ -172,9 +198,21 @@ Ndb.NodeProcessManager = class extends Common.Object {
172198
static async create(targetManager) {
173199
const manager = new Ndb.NodeProcessManager(targetManager);
174200
manager._service = await Ndb.backend.createService('ndd_service.js', rpc.handle(manager));
201+
InspectorFrontendHost.sendMessageToBackend = manager.sendMessageToBackend.bind(manager);
202+
175203
return manager;
176204
}
177205

206+
/**
207+
* @param {object} message
208+
*
209+
* @return {Promise} void
210+
*/
211+
async sendMessageToBackend(message) {
212+
if (this._service && this._service.sendMessage)
213+
return this._service.sendMessage(message);
214+
}
215+
178216
env() {
179217
return this._service.env();
180218
}
@@ -246,6 +284,30 @@ Ndb.NodeProcessManager = class extends Common.Object {
246284
}
247285
}
248286

287+
sendLoadingFinished({ type, payload }) {
288+
SDK._mainConnection._onMessage(JSON.stringify({
289+
method: 'Network.loadingFinished',
290+
params: payload
291+
}));
292+
}
293+
294+
responseToFrontEnd(id, result) {
295+
InspectorFrontendHost.events.dispatchEventToListeners(
296+
InspectorFrontendHostAPI.Events.DispatchMessage,
297+
{
298+
id,
299+
result
300+
}
301+
);
302+
}
303+
304+
sendNetworkData({ type, payload }) {
305+
SDK._mainConnection._onMessage(JSON.stringify({
306+
method: type,
307+
params: payload
308+
}));
309+
}
310+
249311
async terminalData(stream, data) {
250312
const content = await(await fetch(`data:application/octet-stream;base64,${data}`)).text();
251313
if (content.startsWith('Debugger listening on') || content.startsWith('Debugger attached.') || content.startsWith('Waiting for the debugger to disconnect...'))

front_end/ndb/module.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,14 @@
5252
"className": "Ndb.ContextMenuProvider"
5353
}
5454
],
55-
"dependencies": ["common", "sdk", "ndb_sdk", "bindings", "persistence", "components"],
55+
"dependencies": [
56+
"common",
57+
"sdk",
58+
"ndb_sdk",
59+
"bindings",
60+
"persistence",
61+
"components"
62+
],
5663
"scripts": [
5764
"InspectorFrontendHostOverrides.js",
5865
"Connection.js",

lib/preload/ndb/httpMonkeyPatching.js

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
const zlib = require('zlib');
2+
const http = require('http');
3+
const https = require('https');
4+
5+
const initTime = process.hrtime();
6+
7+
// DT requires us to use relative time in a strange format (xxx.xxx)
8+
const getTime = () => {
9+
const diff = process.hrtime(initTime);
10+
11+
return diff[0] + diff[1] / 1e9;
12+
};
13+
14+
const formatRequestHeaders = req => {
15+
if (!req.headers) return {};
16+
return Object.keys(req.headers).reduce((acc, k) => {
17+
if (typeof req.headers[k] === 'string') acc[k] = req.headers[k];
18+
return acc;
19+
}, {});
20+
};
21+
22+
const formatResponseHeaders = res => {
23+
if (!res.headers) return {};
24+
return Object.keys(res.headers).reduce((acc, k) => {
25+
if (typeof res.headers[k] === 'string') acc[k] = res.headers[k];
26+
return acc;
27+
}, {});
28+
};
29+
30+
const getMineType = mimeType => {
31+
// nasty hack for ASF
32+
if (mimeType === 'OPENJSON')
33+
return 'application/json;charset=UTF-8';
34+
35+
36+
return mimeType;
37+
};
38+
39+
const cacheRequests = {};
40+
let id = 1;
41+
const getId = () => id++;
42+
43+
const callbackWrapper = (callback, req) => res => {
44+
const requestId = getId();
45+
res.req.__requestId = requestId;
46+
47+
process.send({
48+
payload: {
49+
requestId: requestId,
50+
loaderId: requestId,
51+
documentURL: req.href,
52+
request: {
53+
url: req.href,
54+
method: req.method,
55+
headers: formatRequestHeaders(req),
56+
mixedContentType: 'none',
57+
initialPriority: 'VeryHigh',
58+
referrerPolicy: 'no-referrer-when-downgrade',
59+
postData: req.body
60+
},
61+
timestamp: getTime(),
62+
wallTime: Date.now(),
63+
initiator: {
64+
type: 'other'
65+
},
66+
type: 'Document'
67+
},
68+
type: 'Network.requestWillBeSent'
69+
});
70+
71+
const encoding = res.headers['content-encoding'];
72+
let rawData = [];
73+
74+
const onEnd = function() {
75+
rawData = Buffer.concat(rawData);
76+
rawData = rawData.toString('base64');
77+
78+
cacheRequests[res.req.__requestId] = {
79+
...res,
80+
__rawData: rawData,
81+
base64Encoded: true
82+
};
83+
const payload = {
84+
id: res.req.__requestId,
85+
requestId: res.req.__requestId,
86+
loaderId: res.req.__requestId,
87+
base64Encoded: true,
88+
data: cacheRequests[res.req.__requestId].__rawData,
89+
timestamp: getTime(),
90+
type: 'XHR',
91+
encodedDataLength: 100,
92+
response: {
93+
url: req.href,
94+
status: res.statusCode,
95+
statusText: res.statusText,
96+
// set-cookie prop in the header has value as an array
97+
// for example: ["__cfduid=dbfe006ef71658bf4dba321343c227f9a15449556…20:29 GMT; path=/; domain=.typicode.com; HttpOnly"]
98+
headers: formatResponseHeaders(res),
99+
mimeType: getMineType(
100+
res.headers['content-encoding'] ||
101+
res.headers['content-type']
102+
),
103+
requestHeaders: formatRequestHeaders(req)
104+
}
105+
};
106+
107+
// Send the response back.
108+
process.send({ payload: payload, type: 'Network.responseReceived' });
109+
process.send({ payload: payload, type: 'Network.loadingFinished' });
110+
};
111+
112+
if (encoding === 'gzip' || encoding === 'x-gzip') {
113+
const gunzip = zlib.createGunzip();
114+
res.pipe(gunzip);
115+
116+
gunzip.on('data', function(data) {
117+
rawData.push(data);
118+
});
119+
gunzip.on('end', onEnd);
120+
} else {
121+
res.on('data', chunk => {
122+
rawData.push(chunk);
123+
});
124+
res.on('end', onEnd);
125+
}
126+
127+
callback && callback(res);
128+
};
129+
130+
const originHTTPRequest = http.request;
131+
http.request = function wrapMethodRequest(req, callback) {
132+
const request = originHTTPRequest.call(
133+
this,
134+
req,
135+
callbackWrapper(callback, req)
136+
);
137+
return request;
138+
};
139+
140+
const originHTTPSRequest = https.request;
141+
https.request = function wrapMethodRequest(req, callback) {
142+
const request = originHTTPSRequest.call(
143+
this,
144+
req,
145+
callbackWrapper(callback, req)
146+
);
147+
const originWrite = request.write.bind(request);
148+
request.write = data => {
149+
req.body = data.toString();
150+
originWrite(data);
151+
};
152+
return request;
153+
};

0 commit comments

Comments
 (0)