Commit ed10e8d7 authored by allada's avatar allada Committed by Commit bot

[Devtools] Restructure network nodes for friendlier products/grouping

Restructures how NetworkNodes are managed to push more of the code into
the individual implementations of the NetworkGrouper. Grouper is now
more like a factory for a NetworkNode.

In the case here, we are setting up FrameGroupNode as an extension of
NetworkGroupNode which is a lightweight wrapper for groupable items.
When a cell is being rendered we are now able to intercept the calls and
render them with special content (like we do here with product and name
column).

R=pfeldman,dgozman
BUG=718236

Review-Url: https://codereview.chromium.org/2859063003
Cr-Commit-Position: refs/heads/master@{#469583}
parent 32a9e92e
......@@ -318,7 +318,7 @@ all_devtools_files = [
"front_end/network/networkLogView.css",
"front_end/network/NetworkLogView.js",
"front_end/network/NetworkLogViewColumns.js",
"front_end/network/NetworkGroupers.js",
"front_end/network/NetworkFrameGrouper.js",
"front_end/network/networkManageCustomHeadersView.css",
"front_end/network/NetworkManageCustomHeadersView.js",
"front_end/network/NetworkOverview.js",
......
......@@ -39,11 +39,10 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
super({});
this._parentView = parentView;
this._isHovered = false;
this._isProduct = false;
this._showingInitiatorChain = false;
/** @type {?SDK.NetworkRequest} */
this._requestOrFirstKnownChildRequest = null;
/** @type {?Common.Color} */
this._backgroundColor = null;
}
/**
......@@ -62,6 +61,39 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
return Network.NetworkNode._themedBackgroundColorsCache;
}
/**
* @return {string}
*/
displayName() {
return '';
}
/**
* @return {boolean}
*/
isFromFrame() {
return false;
}
/**
* @override
* @param {string} columnId
* @return {!Element}
*/
createCell(columnId) {
var cell = this.createTD(columnId);
this.renderCell(cell, columnId);
return cell;
}
/**
* @protected
* @param {!Element} cell
* @param {string} columnId
*/
renderCell(cell, columnId) {
}
/**
* @return {string}
*/
......@@ -72,8 +104,10 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
color = color.blendWith(bgColors.Navigation);
if (this.hovered())
color = color.blendWith(bgColors.Hovered);
if (this._backgroundColor)
color = color.blendWith(this._backgroundColor);
if (this.isFromFrame())
color = color.blendWith(bgColors.FromFrame);
else if (this._isProduct)
color = color.blendWith(bgColors.IsProduct);
if (this.isOnInitiatorPath())
color = color.blendWith(bgColors.InitiatorPath);
if (this.isOnInitiatedPath())
......@@ -184,20 +218,6 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
return false;
}
/**
* @return {?Network.NetworkRequestNode}
*/
asRequestNode() {
return null;
}
/**
* @return {?Network.NetworkGroupNode}
*/
asGroupNode() {
return null;
}
/**
* @override
*/
......@@ -239,7 +259,9 @@ Network.NetworkNode._backgroundColors = {
Hovered: [235, 242, 252, 0.7],
InitiatorPath: [58, 217, 58, 0.4],
InitiatedPath: [217, 58, 58, 0.4],
Selected: [63, 81, 181, .6]
Selected: [63, 81, 181, .6],
FromFrame: [224, 247, 250, .4],
IsProduct: [255, 252, 225, .6],
};
/** @typedef {!{
......@@ -249,7 +271,9 @@ Network.NetworkNode._backgroundColors = {
Hovered: !Common.Color,
InitiatorPath: !Common.Color,
InitiatedPath: !Common.Color,
Selected: !Common.Color
Selected: !Common.Color,
FromFrame: !Common.Color,
IsProduct: !Common.Color
}} */
Network.NetworkNode._SupportedBackgroundColors;
......@@ -277,36 +301,28 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
this.selectable = true;
this._isOnInitiatorPath = false;
this._isOnInitiatedPath = false;
this._isFromFrame = false;
if (!Runtime.experiments.isEnabled('networkGroupingRequests'))
return;
var frame = SDK.ResourceTreeModel.frameForRequest(request);
this._isFromFrame = frame ? !frame.isMainFrame() : false;
}
/**
* @param {!Network.NetworkNode} a
* @param {!Network.NetworkNode} b
* @return {number}
*/
static NameComparator(a, b) {
var aGroupNode = a.asGroupNode();
var bGroupNode = b.asGroupNode();
if ((!aGroupNode && bGroupNode) || (aGroupNode && !bGroupNode))
return aGroupNode ? 1 : -1;
var aName;
var bName;
if (aGroupNode && bGroupNode) {
aName = aGroupNode.displayName();
bName = bGroupNode.displayName();
if (aName === bName)
return Network.NetworkRequestNode.RequestPropertyComparator('startTime', a, b);
} else {
var aName = a.displayName().toLowerCase();
var bName = b.displayName().toLowerCase();
if (aName === bName) {
var aRequest = a.requestOrFirstKnownChildRequest();
var bRequest = b.requestOrFirstKnownChildRequest();
if (!aRequest || !bRequest)
return aRequest ? 1 : -1;
aName = aRequest.name();
bName = bRequest.name();
if (aName === bName)
if (aRequest && bRequest)
return aRequest.indentityCompare(bRequest);
return aRequest ? -1 : 1;
}
return aName < bName ? -1 : 1;
}
......@@ -376,8 +392,8 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
var bRequest = b.requestOrFirstKnownChildRequest();
if (!aRequest || !bRequest)
return !aRequest ? -1 : 1;
var aSimpleType = a.asRequestNode().displayType();
var bSimpleType = b.asRequestNode().displayType();
var aSimpleType = a.displayType();
var bSimpleType = b.displayType();
if (aSimpleType > bSimpleType)
return 1;
......@@ -623,6 +639,14 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
return this._isOnInitiatedPath;
}
/**
* @override
* @return {boolean}
*/
isFromFrame() {
return this._isFromFrame;
}
/**
* @return {string}
*/
......@@ -639,18 +663,18 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
/**
* @override
* @return {!SDK.NetworkRequest}
* @return {string}
*/
request() {
return this._request;
displayName() {
return this._request.name();
}
/**
* @override
* @return {!Network.NetworkRequestNode}
* @return {!SDK.NetworkRequest}
*/
asRequestNode() {
return this;
request() {
return this._request;
}
/**
......@@ -687,6 +711,17 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
element.classList.toggle('network-navigation-row', this._isNavigationRequest);
super.createCells(element);
this._updateBackgroundColor();
if (!Runtime.experiments.isEnabled('networkGroupingRequests'))
return;
ProductRegistry.instance().then(productRegistry => {
var frame = SDK.ResourceTreeModel.frameForRequest(this._request);
if (frame && frame.isMainFrame())
frame = null;
if (productRegistry.entryForUrl(this._request.parsedURL)) {
this._isProduct = true;
this._updateBackgroundColor();
}
});
}
/**
......@@ -700,22 +735,20 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
/**
* @override
* @param {string} columnIdentifier
* @return {!Element}
* @param {!Element} cell
* @param {string} columnId
*/
createCell(columnIdentifier) {
var cell = this.createTD(columnIdentifier);
switch (columnIdentifier) {
renderCell(cell, columnId) {
switch (columnId) {
case 'name':
this._renderNameCell(cell);
break;
case 'product':
if (!Runtime.experiments.isEnabled('networkGroupingRequests')) {
this._setTextAndTitle(cell, this._request.responseHeaderValue(columnIdentifier) || '');
this._setTextAndTitle(cell, this._request.responseHeaderValue(columnId) || '');
break;
}
if (this.request())
ProductRegistry.instance().then(this._renderProductCell.bind(this, cell));
ProductRegistry.instance().then(this._renderProductCell.bind(this, cell));
break;
case 'method':
this._setTextAndTitle(cell, this._request.requestMethod);
......@@ -764,11 +797,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
this._setTextAndTitle(cell, '');
break;
default:
this._setTextAndTitle(cell, this._request.responseHeaderValue(columnIdentifier) || '');
this._setTextAndTitle(cell, this._request.responseHeaderValue(columnId) || '');
break;
}
return cell;
}
/**
......@@ -869,35 +900,19 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
* @param {!ProductRegistry.Registry} productRegistry
*/
_renderProductCell(cell, productRegistry) {
var request = this.request();
if (!request)
var rowElement = this.existingElement();
if (!rowElement)
return;
var entry = productRegistry.entryForUrl(request.parsedURL);
var frame = SDK.ResourceTreeModel.frameForRequest(this._request);
if (frame && frame.isMainFrame())
frame = null;
var entry = frame ? productRegistry.entryForFrame(frame) : null;
if (!entry)
entry = productRegistry.entryForUrl(this._request.parsedURL);
if (!entry)
return;
this._setTextAndTitle(cell, entry.name);
if (entry.type !== null) {
var element = this.existingElement();
if (!element)
return;
switch (entry.type) {
case 0:
this._backgroundColor = Common.Color.fromRGBA([224, 247, 250, .6]);
cell.classList.add('product-ad');
break;
case 1:
this._backgroundColor = Common.Color.fromRGBA([255, 252, 225, .6]);
cell.classList.add('product-tracking');
break;
case 2:
this._backgroundColor = Common.Color.fromRGBA([211, 253, 211, .6]);
cell.classList.add('product-cdn');
break;
default:
this._backgroundColor = null;
}
this._updateBackgroundColor();
}
cell.textContent = entry.name;
cell.title = entry.name;
}
/**
......@@ -1056,59 +1071,18 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
}
};
/**
* @unrestricted
*/
Network.NetworkGroupNode = class extends Network.NetworkNode {
/**
* @param {!Network.NetworkLogView} parentView
* @param {string} displayName
* @param {string=} sortKey
*/
constructor(parentView, displayName, sortKey) {
super(parentView);
this._displayName = displayName;
this._name = sortKey;
}
/**
* @override
* @return {?Network.NetworkGroupNode}
*/
asGroupNode() {
return this;
}
/**
* @return {string}
*/
displayName() {
return this._displayName;
}
/**
* @param {!Element} element
* @param {string} text
*/
_setTextAndTitle(element, text) {
element.textContent = text;
element.title = text;
}
/**
* @override
* @param {string} columnIdentifier
* @return {!Element}
* @param {!Element} cell
* @param {string} columnId
*/
createCell(columnIdentifier) {
var cell = this.createTD(columnIdentifier);
if (columnIdentifier === 'name') {
renderCell(cell, columnId) {
if (columnId === 'name') {
var leftPadding = this.leftPadding ? this.leftPadding + 'px' : '';
cell.style.setProperty('padding-left', leftPadding);
cell.classList.add('disclosure');
this._setTextAndTitle(cell, this._displayName);
}
return cell;
}
/**
......
// 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.
/**
* @implements {Network.GroupLookupInterface}
*/
Network.FrameGrouper = class {
/**
* @param {!Network.NetworkLogView} parentView
*/
constructor(parentView) {
this._parentView = parentView;
/** @type {?ProductRegistry.Registry} */
this._productRegistry = null;
/** @type {!Map<!SDK.ResourceTreeFrame, !Network.FrameGroupNode>} */
this._activeGroups = new Map();
}
/**
* @override
* @return {!Promise}
*/
initialize() {
return ProductRegistry.instance().then(productRegistry => {
this._productRegistry = productRegistry;
this._activeGroups.forEach(node => node.refresh());
});
}
/**
* @override
* @param {!SDK.NetworkRequest} request
* @return {?Network.NetworkGroupNode}
*/
groupNodeForRequest(request) {
var frame = SDK.ResourceTreeModel.frameForRequest(request);
if (!frame || frame.isMainFrame())
return null;
var groupNode = this._activeGroups.get(frame);
if (groupNode)
return groupNode;
groupNode = new Network.FrameGroupNode(this._parentView, frame, this);
this._activeGroups.set(frame, groupNode);
return groupNode;
}
/**
* @override
*/
reset() {
this._activeGroups.clear();
}
};
Network.FrameGroupNode = class extends Network.NetworkGroupNode {
/**
* @param {!Network.NetworkLogView} parentView
* @param {!SDK.ResourceTreeFrame} frame
* @param {!Network.FrameGrouper} grouper
*/
constructor(parentView, frame, grouper) {
super(parentView);
this._frame = frame;
this._grouper = grouper;
/** @type {?ProductRegistry.Registry.ProductEntry|undefined} */
this._productEntryCache;
}
/**
* @override
* @return {boolean}
*/
isFromFrame() {
return true;
}
/**
* @override
*/
displayName() {
var entry = this._entry();
return entry ? entry.name : (new Common.ParsedURL(this._frame.url)).host || this._frame.name || '<iframe>';
}
/**
* @override
* @param {!Element} cell
* @param {string} columnId
*/
renderCell(cell, columnId) {
super.renderCell(cell, columnId);
if (columnId === 'name') {
var name = this.displayName();
cell.textContent = name;
cell.title = name;
}
if (columnId === 'product') {
var entry = this._entry();
if (!entry)
return;
cell.textContent = entry.name;
cell.title = entry.name;
}
}
/**
* @return {?ProductRegistry.Registry.ProductEntry}
*/
_entry() {
if (this._productEntryCache !== undefined)
return this._productEntryCache;
var productRegistry = this._grouper._productRegistry;
if (!productRegistry)
return null;
this._productEntryCache = productRegistry.entryForFrame(this._frame);
return this._productEntryCache;
}
};
// 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.
/**
* @implements {Network.GroupLookupInterface}
*/
Network.ProductGrouper = class {
constructor() {
/** @type {?ProductRegistry.Registry} */
this._productRegistry = null;
}
/**
* @override
* @return {!Promise}
*/
initialize() {
return ProductRegistry.instance().then(productRegistry => this._productRegistry = productRegistry);
}
/**
* @override
* @param {!SDK.NetworkRequest} request
* @return {?*}
*/
groupForRequest(request) {
if (!this._productRegistry)
return null;
var productName = this._productRegistry.nameForUrl(request.parsedURL);
if (!productName)
return null;
return productName;
}
/**
* @override
* @param {!*} key
* @return {string}
*/
groupName(key) {
return /** @type {string} */ (key);
}
};
/**
* @implements {Network.GroupLookupInterface}
*/
Network.FrameGrouper = class {
constructor() {
/** @type {?ProductRegistry.Registry} */
this._productRegistry = null;
}
/**
* @override
* @return {!Promise}
*/
initialize() {
return ProductRegistry.instance().then(productRegistry => this._productRegistry = productRegistry);
}
/**
* @override
* @param {!SDK.NetworkRequest} request
* @return {?*}
*/
groupForRequest(request) {
var resourceTreeModel = request.networkManager().target().model(SDK.ResourceTreeModel);
if (!resourceTreeModel)
return null;
var frame = resourceTreeModel.frameForId(request.frameId);
if (!frame || frame.isMainFrame())
return null;
return frame;
}
/**
* @override
* @param {!*} frameArg
* @return {string}
*/
groupName(frameArg) {
var frame = /** @type {!SDK.ResourceTreeFrame} */ (frameArg);
var entry = this._productRegistry ? this._productRegistry.entryForFrame(frame) : null;
if (entry)
return entry.name;
return (new Common.ParsedURL(frame.url)).host || frame.name || '<iframe>';
}
};
......@@ -71,8 +71,6 @@ Network.NetworkLogView = class extends UI.VBox {
/** @type {!Map.<string, !Network.NetworkRequestNode>} */
this._nodesByRequestId = new Map();
/** @type {!Map<*, !Network.NetworkGroupNode>} */
this._nodeGroups = new Map();
/** @type {!Object.<string, boolean>} */
this._staleRequestIds = {};
/** @type {number} */
......@@ -102,8 +100,7 @@ Network.NetworkLogView = class extends UI.VBox {
/** @type {!Map<string, !Network.GroupLookupInterface>} */
this._groupLookups = new Map();
this._groupLookups.set('Product', new Network.ProductGrouper());
this._groupLookups.set('Frame', new Network.FrameGrouper());
this._groupLookups.set('Frame', new Network.FrameGrouper(this));
/** @type {?Network.GroupLookupInterface} */
this._activeGroupLookup = null;
......@@ -367,14 +364,13 @@ Network.NetworkLogView = class extends UI.VBox {
var groupLookup = this._groupLookups.get(groupKey) || null;
this._activeGroupLookup = groupLookup;
if (!groupLookup) {
this._nodeGroups.clear();
this._invalidateAllItems();
return;
}
groupLookup.initialize().then(() => {
if (this._activeGroupLookup !== groupLookup)
return;
this._nodeGroups.clear();
this._activeGroupLookup.reset();
this._invalidateAllItems();
});
}
......@@ -899,16 +895,10 @@ Network.NetworkLogView = class extends UI.VBox {
if (!this._activeGroupLookup)
return this._dataGrid.rootNode();
var groupKey = this._activeGroupLookup.groupForRequest(node.request());
if (!groupKey)
var groupNode = this._activeGroupLookup.groupNodeForRequest(node.request());
if (!groupNode)
return this._dataGrid.rootNode();
var group = this._nodeGroups.get(groupKey);
if (group)
return group;
group = new Network.NetworkGroupNode(this, this._activeGroupLookup.groupName(groupKey));
this._nodeGroups.set(groupKey, group);
return group;
return groupNode;
}
reset() {
......@@ -929,7 +919,8 @@ Network.NetworkLogView = class extends UI.VBox {
for (var i = 0; i < nodes.length; ++i)
nodes[i].dispose();
this._nodeGroups.clear();
if (this._activeGroupLookup)
this._activeGroupLookup.reset();
this._nodesByRequestId.clear();
this._staleRequestIds = {};
this._resetSuggestionBuilder();
......@@ -1834,13 +1825,9 @@ Network.GroupLookupInterface.prototype = {
/**
* @param {!SDK.NetworkRequest} request
* @return {?*}
* @return {?Network.NetworkGroupNode}
*/
groupForRequest: function(request) {},
groupNodeForRequest: function(request) {},
/**
* @param {!*} key
* @return {string}
*/
groupName: function(key) {}
reset: function() {}
};
......@@ -92,20 +92,6 @@
"order": 40,
"className": "Network.NetworkConfigView",
"tags": "disk cache, network throttling, useragent, user agent"
},
{
"type": "@Network.GroupLookupInterface",
"className": "Network.ProductGrouper",
"experiment": "networkGroupingRequests",
"title": "Product",
"id": "product"
},
{
"type": "@Network.GroupLookupInterface",
"className": "Network.FrameGrouper",
"experiment": "networkGroupingRequests",
"title": "Frame",
"id": "frame"
}
],
"dependencies": [
......@@ -132,7 +118,7 @@
"NetworkTimeCalculator.js",
"NetworkLogView.js",
"NetworkLogViewColumns.js",
"NetworkGroupers.js",
"NetworkFrameGrouper.js",
"NetworkManageCustomHeadersView.js",
"NetworkOverview.js",
"NetworkWaterfallColumn.js",
......
......@@ -161,29 +161,6 @@
.network-header-subtitle {
color: gray;
}
.network-log-grid.data-grid .product-ad::before,
.network-log-grid.data-grid .product-tracking::before,
.network-log-grid.data-grid .product-cdn::before {
content: "";
border-radius: 5px;
height: 5px;
width: 5px;
margin-right: 3px;
display: inline-block;
vertical-align: middle;
}
.network-log-grid.data-grid .product-ad::before {
background-color: #00BCD4;
}
.network-log-grid.data-grid .product-tracking::before {
background-color: #FF9800;
}
.network-log-grid.data-grid .product-cdn::before {
background-color: #4CAF50;
}
.network-log-grid.data-grid.small .network-cell-subtitle,
.network-log-grid.data-grid.small .network-header-subtitle {
......
......@@ -58,6 +58,17 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
this._isInterstitialShowing = false;
}
/**
* @param {!SDK.NetworkRequest} request
* @return {?SDK.ResourceTreeFrame}
*/
static frameForRequest(request) {
var resourceTreeModel = request.networkManager().target().model(SDK.ResourceTreeModel);
if (!resourceTreeModel)
return null;
return resourceTreeModel.frameForId(request.frameId);
}
/**
* @return {!Array.<!SDK.ResourceTreeFrame>}
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment