Skip to content

Commit 5324e50

Browse files
authored
feat(android): devtools for elements & network requests (#10506)
1 parent 7806cc4 commit 5324e50

19 files changed

+436
-115
lines changed

packages/core/debugger/InspectorBackendCommands.ios.ts renamed to packages/core/debugger/InspectorBackendCommands.ts

Lines changed: 57 additions & 57 deletions
Large diffs are not rendered by default.

packages/core/debugger/devtools-elements.android.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.
File renamed without changes.

packages/core/debugger/webinspector-css.ios.ts renamed to packages/core/debugger/webinspector-css.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as inspectorCommandTypes from './InspectorBackendCommands.ios';
1+
import * as inspectorCommandTypes from './InspectorBackendCommands';
22
const inspectorCommands: typeof inspectorCommandTypes = require('./InspectorBackendCommands');
33

44
import * as debuggerDomains from '.';

packages/core/debugger/webinspector-dom.ios.ts renamed to packages/core/debugger/webinspector-dom.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as inspectorCommandTypes from './InspectorBackendCommands.ios';
1+
import * as inspectorCommandTypes from './InspectorBackendCommands';
22
const inspectorCommands: typeof inspectorCommandTypes = require('./InspectorBackendCommands');
33

44
import * as debuggerDomains from '.';
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
import * as inspectorCommandTypes from './InspectorBackendCommands';
2+
const inspectorCommands: typeof inspectorCommandTypes = require('./InspectorBackendCommands');
3+
4+
import * as debuggerDomains from '.';
5+
const getApplicationContext = () => require('../utils/android').getApplicationContext();
6+
7+
declare let __inspectorSendEvent;
8+
9+
declare let __inspectorTimestamp;
10+
11+
const frameId = 'NativeScriptMainFrameIdentifier';
12+
const loaderId = 'Loader Identifier';
13+
14+
const resources_datas = [];
15+
16+
const documentTypeByMimeType = {
17+
'text/xml': 'Document',
18+
'text/plain': 'Document',
19+
'text/html': 'Document',
20+
'application/xml': 'Document',
21+
'application/xhtml+xml': 'Document',
22+
'text/css': 'Stylesheet',
23+
'text/javascript': 'Script',
24+
'text/ecmascript': 'Script',
25+
'application/javascript': 'Script',
26+
'application/ecmascript': 'Script',
27+
'application/x-javascript': 'Script',
28+
'application/json': 'Script',
29+
'application/x-json': 'Script',
30+
'text/x-javascript': 'Script',
31+
'text/x-json': 'Script',
32+
'text/typescript': 'Script',
33+
};
34+
35+
export class Request {
36+
private _resourceType: string;
37+
private _data: any;
38+
private _mimeType: string;
39+
40+
constructor(
41+
private _networkDomainDebugger: NetworkDomainDebugger,
42+
private _requestID: string,
43+
) {}
44+
45+
get mimeType(): string {
46+
return this._mimeType;
47+
}
48+
49+
set mimeType(value: string) {
50+
if (this._mimeType !== value) {
51+
if (!value) {
52+
this._mimeType = 'text/plain';
53+
this._resourceType = 'Other';
54+
55+
return;
56+
}
57+
58+
this._mimeType = value;
59+
60+
let resourceType = 'Other';
61+
62+
if (this._mimeType in documentTypeByMimeType) {
63+
resourceType = documentTypeByMimeType[this._mimeType];
64+
}
65+
66+
if (this._mimeType.indexOf('image/') !== -1) {
67+
resourceType = 'Image';
68+
}
69+
70+
if (this._mimeType.indexOf('font/') !== -1) {
71+
resourceType = 'Font';
72+
}
73+
74+
this._resourceType = resourceType;
75+
}
76+
}
77+
78+
get requestID(): string {
79+
return this._requestID;
80+
}
81+
82+
get hasTextContent(): boolean {
83+
return ['Document', 'Stylesheet', 'Script', 'XHR'].indexOf(this._resourceType) !== -1;
84+
}
85+
86+
get data(): any {
87+
return this._data;
88+
}
89+
90+
set data(value: any) {
91+
if (this._data !== value) {
92+
this._data = value;
93+
}
94+
}
95+
96+
get resourceType() {
97+
return this._resourceType;
98+
}
99+
100+
set resourceType(value: string) {
101+
if (this._resourceType !== value) {
102+
this._resourceType = value;
103+
}
104+
}
105+
106+
public responseReceived(response: inspectorCommandTypes.NetworkDomain.Response): void {
107+
if (this._networkDomainDebugger.enabled) {
108+
this._networkDomainDebugger.events.responseReceived(this.requestID, frameId, loaderId, __inspectorTimestamp(), <any>this.resourceType, response);
109+
}
110+
}
111+
112+
public loadingFinished(): void {
113+
if (this._networkDomainDebugger.enabled) {
114+
this._networkDomainDebugger.events.loadingFinished(this.requestID, __inspectorTimestamp());
115+
}
116+
}
117+
118+
public requestWillBeSent(request: inspectorCommandTypes.NetworkDomain.Request): void {
119+
if (this._networkDomainDebugger.enabled) {
120+
this._networkDomainDebugger.events.requestWillBeSent(this.requestID, frameId, loaderId, request.url, request, __inspectorTimestamp(), { type: 'Script' });
121+
}
122+
}
123+
}
124+
125+
@inspectorCommands.DomainDispatcher('Network')
126+
export class NetworkDomainDebugger implements inspectorCommandTypes.NetworkDomain.NetworkDomainDispatcher {
127+
private _enabled: boolean;
128+
public events: inspectorCommandTypes.NetworkDomain.NetworkFrontend;
129+
130+
constructor() {
131+
this.events = new inspectorCommands.NetworkDomain.NetworkFrontend();
132+
133+
// By default start enabled because we can miss the "enable" event when
134+
// running with `--debug-brk` -- the frontend will send it before we've been created
135+
this.enable();
136+
}
137+
138+
get enabled(): boolean {
139+
return this._enabled;
140+
}
141+
142+
/**
143+
* Enables network tracking, network events will now be delivered to the client.
144+
*/
145+
enable(): void {
146+
if (debuggerDomains.getNetwork()) {
147+
throw new Error('One NetworkDomainDebugger may be enabled at a time.');
148+
} else {
149+
debuggerDomains.setNetwork(this);
150+
}
151+
this._enabled = true;
152+
}
153+
154+
/**
155+
* Disables network tracking, prevents network events from being sent to the client.
156+
*/
157+
disable(): void {
158+
if (debuggerDomains.getNetwork() === this) {
159+
debuggerDomains.setNetwork(null);
160+
}
161+
this._enabled = false;
162+
}
163+
164+
/**
165+
* Specifies whether to always send extra HTTP headers with the requests from this page.
166+
*/
167+
setExtraHTTPHeaders(params: inspectorCommandTypes.NetworkDomain.SetExtraHTTPHeadersMethodArguments): void {
168+
//
169+
}
170+
171+
/**
172+
* Returns content served for the given request.
173+
*/
174+
getResponseBody(params: inspectorCommandTypes.NetworkDomain.GetResponseBodyMethodArguments): { body: string; base64Encoded: boolean } {
175+
const resource_data = resources_datas[params.requestId];
176+
// java.io.ByteArrayOutputStream
177+
const body = resource_data.hasTextContent ? resource_data.data.toString('UTF-8') : android.util.Base64.encodeToString(resource_data.data?.buf?.(), android.util.Base64.NO_WRAP);
178+
if (resource_data) {
179+
return {
180+
body: body,
181+
base64Encoded: !resource_data.hasTextContent,
182+
};
183+
}
184+
}
185+
186+
/**
187+
* Tells whether clearing browser cache is supported.
188+
*/
189+
canClearBrowserCache(): { result: boolean } {
190+
return {
191+
result: false,
192+
};
193+
}
194+
195+
/**
196+
* Clears browser cache.
197+
*/
198+
clearBrowserCache(): void {
199+
//
200+
}
201+
202+
/**
203+
* Tells whether clearing browser cookies is supported.
204+
*/
205+
canClearBrowserCookies(): { result: boolean } {
206+
return {
207+
result: false,
208+
};
209+
}
210+
211+
/**
212+
* Clears browser cookies.
213+
*/
214+
clearBrowserCookies(): void {
215+
//
216+
}
217+
218+
/**
219+
* Toggles ignoring cache for each request. If <code>true</code>, cache will not be used.
220+
*/
221+
setCacheDisabled(params: inspectorCommandTypes.NetworkDomain.SetCacheDisabledMethodArguments): void {
222+
//
223+
}
224+
225+
/**
226+
* Loads a resource in the context of a frame on the inspected page without cross origin checks.
227+
*/
228+
loadResource(params: inspectorCommandTypes.NetworkDomain.LoadResourceMethodArguments): { content: string; mimeType: string; status: number } {
229+
const appPath = getApplicationContext().getFilesDir().getCanonicalPath() + '/app';
230+
const pathUrl = params.url.replace('file://', appPath);
231+
const file = new java.io.File(pathUrl);
232+
const is = file.exists() ? new java.io.FileInputStream(file) : undefined;
233+
const data = is ? Array.create('bytes', file.length()) : undefined;
234+
const read = data ? is.read(data) : 0;
235+
const content = read ? new java.lang.String(data) : '';
236+
return {
237+
content: content.toString(), // Not sure why however we need to call toString() for NSString
238+
mimeType: 'application/octet-stream',
239+
status: 200,
240+
};
241+
}
242+
243+
public static idSequence = 0;
244+
create(): Request {
245+
const id = (++NetworkDomainDebugger.idSequence).toString();
246+
const resourceData = new Request(this, id);
247+
resources_datas[id] = resourceData;
248+
249+
return resourceData;
250+
}
251+
}

packages/core/debugger/webinspector-network.ios.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as inspectorCommandTypes from './InspectorBackendCommands.ios';
1+
import * as inspectorCommandTypes from './InspectorBackendCommands';
22
const inspectorCommands: typeof inspectorCommandTypes = require('./InspectorBackendCommands');
33

44
import * as debuggerDomains from '.';
@@ -36,7 +36,10 @@ export class Request {
3636
private _data: any;
3737
private _mimeType: string;
3838

39-
constructor(private _networkDomainDebugger: NetworkDomainDebugger, private _requestID: string) {}
39+
constructor(
40+
private _networkDomainDebugger: NetworkDomainDebugger,
41+
private _requestID: string,
42+
) {}
4043

4144
get mimeType(): string {
4245
return this._mimeType;

0 commit comments

Comments
 (0)