Continue with typechecking NetworkManager with TypeScript

Issues discovered:
- Introduced CONNECTION_TYPES as a Map, as we were using it as an
object before
- Introduce MIME_TYPE enum to specify all mimetypes and strongly
type the getter and setter in NetworkRequest. Sadly we use strings
in other places, so we have to cast these :(
- It turns out that Common.ResourceType.resourceTypes was not
in sync with the protocol mime types. Most notably, it was missing
the `Ping` and `CSPViolationReport` keys. Additionally, it erroneously
includes `SourceMapScript` and `SourceMapStyleSheet` which do not
exist in the protocol. I have kept them in for now, as there is
other code relying on it. However, we should look into removing
them later if they indeed turn out to be obsolete.

R=jacktfranklin@chromium.org,aerotwist@chromium.org

Bug: 1011811
Change-Id: I67b4bba47317fdfab3d724b913465e1be416c6d6
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2173370
Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
Reviewed-by: Paul Lewis <aerotwist@chromium.org>
This commit is contained in:
Tim van der Lippe
2020-05-01 13:49:41 +00:00
committed by Commit Bot
parent 7269d9d11f
commit aa800780e6
7 changed files with 87 additions and 49 deletions
+10 -8
View File
@@ -251,7 +251,7 @@ export const resourceCategories = {
Document: new ResourceCategory(ls`Documents`, ls`Doc`),
WebSocket: new ResourceCategory(ls`WebSockets`, ls`WS`),
Manifest: new ResourceCategory(ls`Manifest`, ls`Manifest`),
Other: new ResourceCategory(ls`Other`, ls`Other`)
Other: new ResourceCategory(ls`Other`, ls`Other`),
};
/**
@@ -259,22 +259,24 @@ export const resourceCategories = {
* @enum {!ResourceType}
*/
export const resourceTypes = {
XHR: new ResourceType('xhr', ls`XHR`, resourceCategories.XHR, true),
Fetch: new ResourceType('fetch', ls`Fetch`, resourceCategories.XHR, true),
EventSource: new ResourceType('eventsource', ls`EventSource`, resourceCategories.XHR, true),
Script: new ResourceType('script', ls`Script`, resourceCategories.Script, true),
Document: new ResourceType('document', ls`Document`, resourceCategories.Document, true),
Stylesheet: new ResourceType('stylesheet', ls`Stylesheet`, resourceCategories.Stylesheet, true),
Image: new ResourceType('image', ls`Image`, resourceCategories.Image, false),
Media: new ResourceType('media', ls`Media`, resourceCategories.Media, false),
Font: new ResourceType('font', ls`Font`, resourceCategories.Font, false),
Document: new ResourceType('document', ls`Document`, resourceCategories.Document, true),
Script: new ResourceType('script', ls`Script`, resourceCategories.Script, true),
TextTrack: new ResourceType('texttrack', ls`TextTrack`, resourceCategories.Other, true),
XHR: new ResourceType('xhr', ls`XHR`, resourceCategories.XHR, true),
Fetch: new ResourceType('fetch', ls`Fetch`, resourceCategories.XHR, true),
EventSource: new ResourceType('eventsource', ls`EventSource`, resourceCategories.XHR, true),
WebSocket: new ResourceType('websocket', ls`WebSocket`, resourceCategories.WebSocket, false),
Manifest: new ResourceType('manifest', ls`Manifest`, resourceCategories.Manifest, true),
SignedExchange: new ResourceType('signed-exchange', ls`SignedExchange`, resourceCategories.Other, false),
Ping: new ResourceType('ping', ls`Ping`, resourceCategories.Other, false),
CSPViolationReport: new ResourceType('csp-violation-report', ls`CSPViolationReport`, resourceCategories.Other, false),
Other: new ResourceType('other', ls`Other`, resourceCategories.Other, false),
SourceMapScript: new ResourceType('sm-script', ls`Script`, resourceCategories.Script, true),
SourceMapStyleSheet: new ResourceType('sm-stylesheet', ls`Stylesheet`, resourceCategories.Stylesheet, true),
Manifest: new ResourceType('manifest', ls`Manifest`, resourceCategories.Manifest, true),
SignedExchange: new ResourceType('signed-exchange', ls`SignedExchange`, resourceCategories.Other, false)
};
+6
View File
@@ -39,6 +39,9 @@
<message name="IDS_DEVTOOLS_a83f1ca5ad00b39773d9e6a26b0e70b2" desc="Text that appears in a tooltip for the JavaScript types filter.">
Scripts
</message>
<message name="IDS_DEVTOOLS_b85815d04cec053ce6deb8021f2df1b8" desc="Name of a network resource type">
Ping
</message>
<message name="IDS_DEVTOOLS_bef61d7d03206d267fdbab45fdca247d" desc="Name of a network resource type">
SignedExchange
</message>
@@ -48,6 +51,9 @@
<message name="IDS_DEVTOOLS_c350bb18c3cdfbd4e5444faa63be6586" desc="Name of a network resource type">
Stylesheet
</message>
<message name="IDS_DEVTOOLS_d4d96ef85bcd85156baa07069a5fcec8" desc="Name of a network resource type">
CSPViolationReport
</message>
<message name="IDS_DEVTOOLS_fff0d600f8a0b5e19e88bfb821dd1157" desc="Text that appears in a tooltip for the image types filter.">
Images
</message>
+1 -1
View File
@@ -85,7 +85,7 @@ export class Importer {
// Response data.
if (entry.response.content.mimeType && entry.response.content.mimeType !== 'x-unknown') {
request.mimeType = entry.response.content.mimeType;
request.mimeType = /** @type {!SDK.NetworkRequest.MIME_TYPE} */ (entry.response.content.mimeType);
}
request.responseHeaders = entry.response.headers;
request.statusCode = entry.response.status;
@@ -337,8 +337,8 @@ export class ServiceWorkerCacheView extends UI.View.SimpleView {
request.endTime = entry.responseTime;
let header = entry.responseHeaders.find(header => header.name.toLowerCase() === 'content-type');
const contentType = header ? header.value : 'text/plain';
request.mimeType = contentType;
const contentType = header ? header.value : SDK.NetworkRequest.MIME_TYPE.PLAIN;
request.mimeType = /** @type {!SDK.NetworkRequest.MIME_TYPE} */ (contentType);
header = entry.responseHeaders.find(header => header.name.toLowerCase() === 'content-length');
request.resourceSize = (header && header.value) | 0;
+23 -35
View File
@@ -38,12 +38,21 @@ import * as ProtocolClient from '../protocol_client/protocol_client.js';
import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars
import {Cookie} from './Cookie.js';
import {ContentData, Events as NetworkRequestEvents, ExtraRequestInfo, ExtraResponseInfo, NameValue, NetworkRequest} from './NetworkRequest.js'; // eslint-disable-line no-unused-vars
import {ContentData, Events as NetworkRequestEvents, ExtraRequestInfo, ExtraResponseInfo, MIME_TYPE, MIME_TYPE_TO_RESOURCE_TYPE, NameValue, NetworkRequest} from './NetworkRequest.js'; // eslint-disable-line no-unused-vars
import {Capability, SDKModel, SDKModelObserver, Target, TargetManager} from './SDKModel.js'; // eslint-disable-line no-unused-vars
/** @type {!WeakMap<!NetworkRequest, !NetworkManager>} */
const requestToManagerMap = new WeakMap();
const CONNECTION_TYPES = new Map([
['2g', Protocol.Network.ConnectionType.Cellular2g],
['3g', Protocol.Network.ConnectionType.Cellular3g],
['4g', Protocol.Network.ConnectionType.Cellular4g],
['bluetooth', Protocol.Network.ConnectionType.Bluetooth],
['wifi', Protocol.Network.ConnectionType.Wifi],
['wimax', Protocol.Network.ConnectionType.Wimax],
]);
/**
* @unrestricted
*/
@@ -165,30 +174,21 @@ export class NetworkManager extends SDKModel {
if (!conditions.download && !conditions.upload) {
return Protocol.Network.ConnectionType.None;
}
let types = NetworkManager._connectionTypes;
if (!types) {
NetworkManager._connectionTypes = [];
types = NetworkManager._connectionTypes;
types.push(['2g', Protocol.Network.ConnectionType.Cellular2g]);
types.push(['3g', Protocol.Network.ConnectionType.Cellular3g]);
types.push(['4g', Protocol.Network.ConnectionType.Cellular4g]);
types.push(['bluetooth', Protocol.Network.ConnectionType.Bluetooth]);
types.push(['wifi', Protocol.Network.ConnectionType.Wifi]);
types.push(['wimax', Protocol.Network.ConnectionType.Wimax]);
}
for (const type of types) {
if (conditions.title.toLowerCase().indexOf(type[0]) !== -1) {
return type[1];
const title = conditions.title.toLowerCase();
for (const [name, protocolType] of CONNECTION_TYPES) {
if (title.includes(name)) {
return protocolType;
}
}
return Protocol.Network.ConnectionType.Other;
}
/**
* @param {!Object} headers
* @param {!Object<string,string>} headers
* @return {!Object<string, string>}
*/
static lowercaseHeaders(headers) {
/** @type {!Object<string, string>} */
const newHeaders = {};
for (const headerName in headers) {
newHeaders[headerName.toLowerCase()] = headers[headerName];
@@ -209,7 +209,7 @@ export class NetworkManager extends SDKModel {
*/
_cacheDisabledSettingChanged(event) {
const enabled = /** @type {boolean} */ (event.data);
this._networkAgent.setCacheDisabled(enabled);
this._networkAgent.invoke_setCacheDisabled({cacheDisabled: enabled});
}
/**
@@ -222,7 +222,7 @@ export class NetworkManager extends SDKModel {
}
_bypassServiceWorkerChanged() {
this._networkAgent.setBypassServiceWorker(this._bypassServiceWorkerSetting.get());
this._networkAgent.invoke_setBypassServiceWorker({bypass: this._bypassServiceWorkerSetting.get()});
}
}
@@ -238,18 +238,6 @@ export const Events = {
LoadingFinished: Symbol('LoadingFinished'),
};
const _MIMETypes = {
'text/html': {'document': true},
'text/xml': {'document': true},
'text/plain': {'document': true},
'application/xhtml+xml': {'document': true},
'image/svg+xml': {'document': true},
'text/css': {'stylesheet': true},
'text/xsl': {'stylesheet': true},
'text/vtt': {'texttrack': true},
'application/pdf': {'document': true},
};
/** @type {!Conditions} */
export const NoThrottlingConditions = {
title: Common.UIString.UIString('Online'),
@@ -332,13 +320,13 @@ export class NetworkDispatcher {
/**
* @param {!NetworkRequest} networkRequest
* @param {!Protocol.Network.Response=} response
* @param {!Protocol.Network.Response} response
*/
_updateNetworkRequestWithResponse(networkRequest, response) {
if (response.url && networkRequest.url() !== response.url) {
networkRequest.setUrl(response.url);
}
networkRequest.mimeType = response.mimeType;
networkRequest.mimeType = /** @type {!MIME_TYPE} */ (response.mimeType);
networkRequest.statusCode = response.status;
networkRequest.statusText = response.statusText;
if (!networkRequest.hasExtraResponseInfo()) {
@@ -421,8 +409,8 @@ export class NetworkDispatcher {
return true;
} // Might be not known for cached resources with null responses.
if (networkRequest.mimeType in _MIMETypes) {
return resourceType.name() in _MIMETypes[networkRequest.mimeType];
if (MIME_TYPE_TO_RESOURCE_TYPE.has(networkRequest.mimeType)) {
return resourceType.name() in MIME_TYPE_TO_RESOURCE_TYPE.get(networkRequest.mimeType);
}
return false;
@@ -515,7 +503,7 @@ export class NetworkDispatcher {
this._updateNetworkRequestWithRequest(networkRequest, request);
networkRequest.setIssueTime(time, wallTime);
networkRequest.setResourceType(
resourceType ? Common.ResourceType.resourceTypes[resourceType] : Protocol.Network.ResourceType.Other);
resourceType ? Common.ResourceType.resourceTypes[resourceType] : Common.ResourceType.resourceTypes.Other);
this._getExtraInfoBuilder(requestId).addRequest(networkRequest);
+32 -2
View File
@@ -41,6 +41,32 @@ import {NetworkManager} from './NetworkManager.js';
import {Type} from './SDKModel.js';
import {ServerTiming} from './ServerTiming.js';
/** @enum {string} */
export const MIME_TYPE = {
HTML: 'text/html',
XML: 'text/xml',
PLAIN: 'text/plain',
XHTML: 'application/xhtml+xml',
SVG: 'image/svg+xml',
CSS: 'text/css',
XSL: 'text/xsl',
VTT: 'text/vtt',
PDF: 'application/pdf',
};
/** @type {!Map<!MIME_TYPE, *>} */
export const MIME_TYPE_TO_RESOURCE_TYPE = new Map([
[MIME_TYPE.HTML, {'document': true}],
[MIME_TYPE.XML, {'document': true}],
[MIME_TYPE.PLAIN, {'document': true}],
[MIME_TYPE.XHTML, {'document': true}],
[MIME_TYPE.SVG, {'document': true}],
[MIME_TYPE.CSS, {'stylesheet': true}],
[MIME_TYPE.XSL, {'stylesheet': true}],
[MIME_TYPE.VTT, {'texttrack': true}],
[MIME_TYPE.PDF, {'document': true}],
]);
/**
* @implements {TextUtils.ContentProvider.ContentProvider}
* @unrestricted
@@ -122,6 +148,10 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper {
/** @type {string} */
this.connectionId = '0';
/** @type {boolean} */
this.connectionReused = false;
/** @type {boolean} */
this.hasNetworkData = false;
/** @type {?Promise<?Array.<!NameValue>>} */
this._formParametersPromise = null;
// Assume no body initially
@@ -570,14 +600,14 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper {
}
/**
* @return {string}
* @return {!MIME_TYPE}
*/
get mimeType() {
return this._mimeType;
}
/**
* @param {string} x
* @param {!MIME_TYPE} x
*/
set mimeType(x) {
this._mimeType = x;
@@ -4,7 +4,7 @@
const {assert} = chai;
import {ResourceType, ResourceCategory} from '../../../../front_end/common/ResourceType.js';
import {ResourceType, ResourceCategory, resourceTypes} from '../../../../front_end/common/ResourceType.js';
describe('ResourceCategory class', () => {
it('is able to be instantiated successfully', () => {
@@ -322,4 +322,16 @@ describe('ResourceType class', () => {
const resourceType = new ResourceType('Type Test Name', 'Type Test Title', testResourceCategory, true);
assert.strictEqual(resourceType.canonicalMimeType(), '', 'the canonical mime type was not returned correctly');
});
it('treats a Ping as Other', () => {
const resourceType = resourceTypes.Ping;
assert.strictEqual(resourceType.isTextType(), false, 'A ping is not a text type');
assert.strictEqual(resourceType.canonicalMimeType(), '', 'A ping does not have an associated mime type');
});
it('treats a CSPViolationsReport as Other', () => {
const resourceType = resourceTypes.CSPViolationReport;
assert.strictEqual(resourceType.isTextType(), false, 'A ping is not a text type');
assert.strictEqual(resourceType.canonicalMimeType(), '', 'A ping does not have an associated mime type');
});
});