mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-06 20:11:38 +08:00
Bug: 1253323 Change-Id: I7a6d5eb0c67436814c434538df73397c89d2341d Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3467974 Reviewed-by: Eric Leese <leese@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Commit-Queue: Kateryna Prokopenko <kprokopenko@chromium.org>
404 lines
12 KiB
TypeScript
404 lines
12 KiB
TypeScript
// Copyright 2017 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import type * as Platform from '../../core/platform/platform.js';
|
|
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
|
|
class HARBase {
|
|
readonly custom: Map<string, any>;
|
|
constructor(data: any) {
|
|
if (!data || typeof data !== 'object') {
|
|
throw 'First parameter is expected to be an object';
|
|
}
|
|
this.custom = new Map();
|
|
}
|
|
|
|
static safeDate(data: any): Date {
|
|
const date = new Date(data);
|
|
if (!Number.isNaN(date.getTime())) {
|
|
return date;
|
|
}
|
|
throw 'Invalid date format';
|
|
}
|
|
|
|
static safeNumber(data: any): number {
|
|
const result = Number(data);
|
|
if (!Number.isNaN(result)) {
|
|
return result;
|
|
}
|
|
throw 'Casting to number results in NaN';
|
|
}
|
|
|
|
static optionalNumber(data: any): number|undefined {
|
|
return data !== undefined ? HARBase.safeNumber(data) : undefined;
|
|
}
|
|
|
|
static optionalString(data: any): string|undefined {
|
|
return data !== undefined ? String(data) : undefined;
|
|
}
|
|
|
|
customAsString(name: string): string|undefined {
|
|
const value = this.custom.get(name);
|
|
if (!value) {
|
|
return undefined;
|
|
}
|
|
return String(value);
|
|
}
|
|
|
|
customAsNumber(name: string): number|undefined {
|
|
const value = this.custom.get(name);
|
|
if (!value) {
|
|
return undefined;
|
|
}
|
|
const numberValue = Number(value);
|
|
if (Number.isNaN(numberValue)) {
|
|
return undefined;
|
|
}
|
|
return numberValue;
|
|
}
|
|
|
|
customAsArray(name: string): any[]|undefined {
|
|
const value = this.custom.get(name);
|
|
if (!value) {
|
|
return undefined;
|
|
}
|
|
return Array.isArray(value) ? value : undefined;
|
|
}
|
|
|
|
customInitiator(): HARInitiator|undefined {
|
|
return this.custom.get('initiator');
|
|
}
|
|
}
|
|
|
|
export class HARRoot extends HARBase {
|
|
log: HARLog;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.log = new HARLog(data['log']);
|
|
}
|
|
}
|
|
|
|
export class HARLog extends HARBase {
|
|
version: string;
|
|
creator: HARCreator;
|
|
browser: HARCreator|undefined;
|
|
pages: HARPage[];
|
|
entries: HAREntry[];
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.version = String(data['version']);
|
|
this.creator = new HARCreator(data['creator']);
|
|
this.browser = data['browser'] ? new HARCreator(data['browser']) : undefined;
|
|
this.pages = Array.isArray(data['pages']) ? data['pages'].map(page => new HARPage(page)) : [];
|
|
if (!Array.isArray(data['entries'])) {
|
|
throw 'log.entries is expected to be an array';
|
|
}
|
|
this.entries = data['entries'].map(entry => new HAREntry(entry));
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
class HARCreator extends HARBase {
|
|
name: string;
|
|
version: string;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.name = String(data['name']);
|
|
this.version = String(data['version']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
export class HARPage extends HARBase {
|
|
startedDateTime: Date;
|
|
id: string;
|
|
title: string;
|
|
pageTimings: HARPageTimings;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.startedDateTime = HARBase.safeDate(data['startedDateTime']);
|
|
this.id = String(data['id']);
|
|
this.title = String(data['title']);
|
|
this.pageTimings = new HARPageTimings(data['pageTimings']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
class HARPageTimings extends HARBase {
|
|
onContentLoad: number|undefined;
|
|
onLoad: number|undefined;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.onContentLoad = HARBase.optionalNumber(data['onContentLoad']);
|
|
this.onLoad = HARBase.optionalNumber(data['onLoad']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
export class HAREntry extends HARBase {
|
|
pageref: string|undefined;
|
|
startedDateTime: Date;
|
|
time: number;
|
|
request: HARRequest;
|
|
response: HARResponse;
|
|
cache: {};
|
|
timings: HARTimings;
|
|
serverIPAddress: string|undefined;
|
|
connection: string|undefined;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.pageref = HARBase.optionalString(data['pageref']);
|
|
this.startedDateTime = HARBase.safeDate(data['startedDateTime']);
|
|
this.time = HARBase.safeNumber(data['time']);
|
|
this.request = new HARRequest(data['request']);
|
|
this.response = new HARResponse(data['response']);
|
|
this.cache = {}; // Not yet implemented.
|
|
this.timings = new HARTimings(data['timings']);
|
|
this.serverIPAddress = HARBase.optionalString(data['serverIPAddress']);
|
|
this.connection = HARBase.optionalString(data['connection']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
|
|
// Chrome specific.
|
|
this.custom.set('fromCache', HARBase.optionalString(data['_fromCache']));
|
|
this.custom.set('initiator', this.importInitiator(data['_initiator']));
|
|
this.custom.set('priority', HARBase.optionalString(data['_priority']));
|
|
this.custom.set('resourceType', HARBase.optionalString(data['_resourceType']));
|
|
this.custom.set('webSocketMessages', this.importWebSocketMessages(data['_webSocketMessages']));
|
|
}
|
|
|
|
private importInitiator(initiator: any): HARInitiator|undefined {
|
|
if (typeof initiator !== 'object') {
|
|
return;
|
|
}
|
|
|
|
return new HARInitiator(initiator);
|
|
}
|
|
|
|
private importWebSocketMessages(inputMessages: any): HARWebSocketMessage[]|undefined {
|
|
if (!Array.isArray(inputMessages)) {
|
|
return;
|
|
}
|
|
|
|
const outputMessages = [];
|
|
for (const message of inputMessages) {
|
|
if (typeof message !== 'object') {
|
|
return;
|
|
}
|
|
outputMessages.push(new HARWebSocketMessage(message));
|
|
}
|
|
return outputMessages;
|
|
}
|
|
}
|
|
|
|
class HARRequest extends HARBase {
|
|
method: string;
|
|
url: Platform.DevToolsPath.UrlString;
|
|
httpVersion: string;
|
|
cookies: HARCookie[];
|
|
headers: HARHeader[];
|
|
queryString: HARQueryString[];
|
|
postData: HARPostData|undefined;
|
|
headersSize: number;
|
|
bodySize: number;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.method = String(data['method']);
|
|
this.url = String(data['url']) as Platform.DevToolsPath.UrlString;
|
|
this.httpVersion = String(data['httpVersion']);
|
|
this.cookies = Array.isArray(data['cookies']) ? data['cookies'].map(cookie => new HARCookie(cookie)) : [];
|
|
this.headers = Array.isArray(data['headers']) ? data['headers'].map(header => new HARHeader(header)) : [];
|
|
this.queryString = Array.isArray(data['queryString']) ? data['queryString'].map(qs => new HARQueryString(qs)) : [];
|
|
this.postData = data['postData'] ? new HARPostData(data['postData']) : undefined;
|
|
this.headersSize = HARBase.safeNumber(data['headersSize']);
|
|
this.bodySize = HARBase.safeNumber(data['bodySize']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
class HARResponse extends HARBase {
|
|
status: number;
|
|
statusText: string;
|
|
httpVersion: string;
|
|
cookies: HARCookie[];
|
|
headers: HARHeader[];
|
|
content: HARContent;
|
|
redirectURL: string;
|
|
headersSize: number;
|
|
bodySize: number;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.status = HARBase.safeNumber(data['status']);
|
|
this.statusText = String(data['statusText']);
|
|
this.httpVersion = String(data['httpVersion']);
|
|
this.cookies = Array.isArray(data['cookies']) ? data['cookies'].map(cookie => new HARCookie(cookie)) : [];
|
|
this.headers = Array.isArray(data['headers']) ? data['headers'].map(header => new HARHeader(header)) : [];
|
|
this.content = new HARContent(data['content']);
|
|
this.redirectURL = String(data['redirectURL']);
|
|
this.headersSize = HARBase.safeNumber(data['headersSize']);
|
|
this.bodySize = HARBase.safeNumber(data['bodySize']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
|
|
// Chrome specific.
|
|
this.custom.set('transferSize', HARBase.optionalNumber(data['_transferSize']));
|
|
this.custom.set('error', HARBase.optionalString(data['_error']));
|
|
}
|
|
}
|
|
|
|
class HARCookie extends HARBase {
|
|
name: string;
|
|
value: string;
|
|
path: string|undefined;
|
|
domain: string|undefined;
|
|
expires: Date|undefined;
|
|
httpOnly: boolean|undefined;
|
|
secure: boolean|undefined;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.name = String(data['name']);
|
|
this.value = String(data['value']);
|
|
this.path = HARBase.optionalString(data['path']);
|
|
this.domain = HARBase.optionalString(data['domain']);
|
|
this.expires = data['expires'] ? HARBase.safeDate(data['expires']) : undefined;
|
|
this.httpOnly = data['httpOnly'] !== undefined ? Boolean(data['httpOnly']) : undefined;
|
|
this.secure = data['secure'] !== undefined ? Boolean(data['secure']) : undefined;
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
class HARHeader extends HARBase {
|
|
name: string;
|
|
value: string;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.name = String(data['name']);
|
|
this.value = String(data['value']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
class HARQueryString extends HARBase {
|
|
name: string;
|
|
value: string;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.name = String(data['name']);
|
|
this.value = String(data['value']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
class HARPostData extends HARBase {
|
|
mimeType: string;
|
|
params: HARParam[];
|
|
text: string;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.mimeType = String(data['mimeType']);
|
|
this.params = Array.isArray(data['params']) ? data['params'].map(param => new HARParam(param)) : [];
|
|
this.text = String(data['text']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
export class HARParam extends HARBase {
|
|
name: string;
|
|
value: string|undefined;
|
|
fileName: string|undefined;
|
|
contentType: string|undefined;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.name = String(data['name']);
|
|
this.value = HARBase.optionalString(data['value']);
|
|
this.fileName = HARBase.optionalString(data['fileName']);
|
|
this.contentType = HARBase.optionalString(data['contentType']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
class HARContent extends HARBase {
|
|
size: number;
|
|
compression: number|undefined;
|
|
mimeType: string;
|
|
text: string|undefined;
|
|
encoding: string|undefined;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.size = HARBase.safeNumber(data['size']);
|
|
this.compression = HARBase.optionalNumber(data['compression']);
|
|
this.mimeType = String(data['mimeType']);
|
|
this.text = HARBase.optionalString(data['text']);
|
|
this.encoding = HARBase.optionalString(data['encoding']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
}
|
|
}
|
|
|
|
export class HARTimings extends HARBase {
|
|
blocked: number|undefined;
|
|
dns: number|undefined;
|
|
connect: number|undefined;
|
|
send: number;
|
|
wait: number;
|
|
receive: number;
|
|
ssl: number|undefined;
|
|
comment: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.blocked = HARBase.optionalNumber(data['blocked']);
|
|
this.dns = HARBase.optionalNumber(data['dns']);
|
|
this.connect = HARBase.optionalNumber(data['connect']);
|
|
this.send = HARBase.safeNumber(data['send']);
|
|
this.wait = HARBase.safeNumber(data['wait']);
|
|
this.receive = HARBase.safeNumber(data['receive']);
|
|
this.ssl = HARBase.optionalNumber(data['ssl']);
|
|
this.comment = HARBase.optionalString(data['comment']);
|
|
|
|
// Chrome specific.
|
|
this.custom.set('blocked_queueing', HARBase.optionalNumber(data['_blocked_queueing']));
|
|
this.custom.set('blocked_proxy', HARBase.optionalNumber(data['_blocked_proxy']));
|
|
}
|
|
}
|
|
|
|
export class HARInitiator extends HARBase {
|
|
type: string|undefined;
|
|
url: string|undefined;
|
|
lineNumber: number|undefined;
|
|
/**
|
|
* Based on Initiator defined in browser_protocol.pdl
|
|
*/
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.type = HARBase.optionalString(data['type']);
|
|
this.url = HARBase.optionalString(data['url']);
|
|
this.lineNumber = HARBase.optionalNumber(data['lineNumber']);
|
|
}
|
|
}
|
|
|
|
class HARWebSocketMessage extends HARBase {
|
|
time: number|undefined;
|
|
opcode: number|undefined;
|
|
data: string|undefined;
|
|
type: string|undefined;
|
|
constructor(data: any) {
|
|
super(data);
|
|
this.time = HARBase.optionalNumber(data['time']);
|
|
this.opcode = HARBase.optionalNumber(data['opcode']);
|
|
this.data = HARBase.optionalString(data['data']);
|
|
this.type = HARBase.optionalString(data['type']);
|
|
}
|
|
}
|