diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/chrome/browser/resources/discards | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources/discards')
5 files changed, 244 insertions, 118 deletions
diff --git a/chromium/chrome/browser/resources/discards/OWNERS b/chromium/chrome/browser/resources/discards/OWNERS index dcd54320481..6ef4e6df1e5 100644 --- a/chromium/chrome/browser/resources/discards/OWNERS +++ b/chromium/chrome/browser/resources/discards/OWNERS @@ -1 +1 @@ -file://services/resource_coordinator/OWNERS +file://components/performance_manager/OWNERS diff --git a/chromium/chrome/browser/resources/discards/discards_tab.html b/chromium/chrome/browser/resources/discards/discards_tab.html index b91684d1b52..c4d1e25566a 100644 --- a/chromium/chrome/browser/resources/discards/discards_tab.html +++ b/chromium/chrome/browser/resources/discards/discards_tab.html @@ -206,11 +206,6 @@ </div> </div> </th> - <th data-sort-key="canFreeze" on-click="onSortClick"> - <div class="header-cell-container"> - Can freeze? - </div> - </th> <th data-sort-key="discardCount" on-click="onSortClick"> <div class="header-cell-container"> <div> @@ -258,19 +253,6 @@ <td>[[visibilityToString_(item.visibility)]]</td> <td>[[loadingStateToString_(item.loadingState)]]</td> <td>[[getLifeCycleState_(item)]]</td> - <td class="boolean-cell"> - <div>[[boolToString_(item.canFreeze)]]</div> - <div is="action-link" class="tooltip-container" - disabled$="[[!hasCannotFreezeReasons_(item)]]"> - [View Reason] - <div class="tooltip"> - <template is="dom-repeat" - items="[[item.cannotFreezeReasons]]"> - <div>[[item]]</div> - </template> - </div> - </div> - </td> <td>[[item.discardCount]]</td> <td class="boolean-cell"> <div>[[boolToString_(item.isAutoDiscardable)]]</div> @@ -286,8 +268,6 @@ <div is="action-link" on-click="loadTab_" disabled$="[[!canLoad_(item)]]"> [Load]</div> - <div is="action-link" on-click="freezeTab_" - disabled$="[[!canFreeze_(item)]]">[Freeze]</div> <div is="action-link" on-click="urgentDiscardTab_" disabled$="[[!canDiscard_(item)]]"> [Urgent Discard] diff --git a/chromium/chrome/browser/resources/discards/discards_tab.js b/chromium/chrome/browser/resources/discards/discards_tab.js index 2fef49056b5..963023218e5 100644 --- a/chromium/chrome/browser/resources/discards/discards_tab.js +++ b/chromium/chrome/browser/resources/discards/discards_tab.js @@ -37,7 +37,7 @@ export function compareTabDiscardsInfos(sortKey, a, b) { } // Compares boolean fields. - if (['canFreeze', 'isAutoDiscardable'].includes(sortKey)) { + if (['isAutoDiscardable'].includes(sortKey)) { if (val1 === val2) { return 0; } @@ -219,10 +219,6 @@ Polymer({ return pageLifecycleStateFromVisibilityAndFocus(); case mojom.LifecycleUnitState.THROTTLED: return pageLifecycleStateFromVisibilityAndFocus() + ' (throttled)'; - case mojom.LifecycleUnitState.PENDING_FREEZE: - return pageLifecycleStateFromVisibilityAndFocus() + ' (pending frozen)'; - case mojom.LifecycleUnitState.FROZEN: - return 'frozen'; case mojom.LifecycleUnitState.DISCARDED: return 'discarded (' + this.discardReasonToString_(reason) + ')' + ((reason === mojom.LifecycleUnitDiscardReason.URGENT) ? ' at ' + @@ -231,8 +227,6 @@ Polymer({ (new Date(stateChangeTime.microseconds / 1000)) .toLocaleString() : ''); - case mojom.LifecycleUnitState.PENDING_UNFREEZE: - return 'frozen (pending unfreeze)'; } assertNotReached('Unknown lifecycle state: ' + state); }, @@ -331,16 +325,6 @@ Polymer({ }, /** - * Tests whether an item has reasons why it cannot be frozen. - * @param {discards.mojom.TabDiscardsInfo} item The item in question. - * @return {boolean} true iff there are reasons why the item cannot be - * frozen. - * @private - */ - hasCannotFreezeReasons_(item) { - return item.cannotFreezeReasons.length !== 0; - }, - /** * Tests whether an item has reasons why it cannot be discarded. * @param {discards.mojom.TabDiscardsInfo} item The item in question. * @return {boolean} true iff there are reasons why the item cannot be @@ -362,27 +346,6 @@ Polymer({ }, /** - * Tests whether an item can be frozen. - * @param {discards.mojom.TabDiscardsInfo} item The item in question. - * @return {boolean} true iff the item can be frozen. - * @private - */ - canFreeze_(item) { - if (item.visibility === discards.mojom.LifecycleUnitVisibility.HIDDEN || - item.visibility === discards.mojom.LifecycleUnitVisibility.OCCLUDED) { - // Only tabs that aren't visible can be frozen for now. - switch (item.state) { - case mojom.LifecycleUnitState.DISCARDED: - case mojom.LifecycleUnitState.FROZEN: - case mojom.LifecycleUnitState.PENDING_FREEZE: - return false; - } - return true; - } - return false; - }, - - /** * Tests whether an item can be discarded. * @param {discards.mojom.TabDiscardsInfo} item The item in question. * @return {boolean} true iff the item can be discarded. @@ -423,15 +386,6 @@ Polymer({ }, /** - * Event handler that freezes a tab. - * @param {Event} e The event. - * @private - */ - freezeTab_(e) { - this.discardsDetailsProvider_.freezeById(e.model.item.id); - }, - - /** * Event handler that discards a given tab urgently. * @param {Event} e The event. * @private diff --git a/chromium/chrome/browser/resources/discards/graph_doc.js b/chromium/chrome/browser/resources/discards/graph_doc.js index 37b9bc7d46d..e3ce7e1d7f8 100644 --- a/chromium/chrome/browser/resources/discards/graph_doc.js +++ b/chromium/chrome/browser/resources/discards/graph_doc.js @@ -2,25 +2,42 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Radius of a node circle. +const /** number */ kNodeRadius = 6; + // Target y position for page nodes. -const kPageNodesTargetY = 20; +const /** number */ kPageNodesTargetY = 20; // Range occupied by page nodes at the top of the graph view. -const kPageNodesYRange = 100; +const /** number */ kPageNodesYRange = 100; // Range occupied by process nodes at the bottom of the graph view. -const kProcessNodesYRange = 100; +const /** number */ kProcessNodesYRange = 100; // Range occupied by worker nodes at the bottom of the graph view, above // process nodes. -const kWorkerNodesYRange = 200; +const /** number */ kWorkerNodesYRange = 200; // Target y position for frame nodes. -const kFrameNodesTargetY = kPageNodesYRange + 50; +const /** number */ kFrameNodesTargetY = kPageNodesYRange + 50; // Range that frame nodes cannot enter at the top/bottom of the graph view. -const kFrameNodesTopMargin = kPageNodesYRange; -const kFrameNodesBottomMargin = kWorkerNodesYRange + 50; +const /** number */ kFrameNodesTopMargin = kPageNodesYRange; +const /** number */ kFrameNodesBottomMargin = kWorkerNodesYRange + 50; + +// The maximum strength of a boundary force. +// According to https://github.com/d3/d3-force#positioning, strength values +// outside the range [0,1] are "not recommended". +const /** number */ kMaxBoundaryStrength = 1; + +// The strength of a high Y-force. This is appropriate for forces that +// strongly pull towards an attractor, but can still be overridden by the +// strongest force. +const /** number */ kHighYStrength = 0.9; + +// The strength of a weak Y-force. This is appropriate for forces that exert +// some influence but can be easily overridden. +const /** number */ kWeakYStrength = 0.1; class ToolTip { /** @@ -271,10 +288,18 @@ class GraphNode { /** * @return {number} The strength of the force that pulls the node towards - * its target y position. + * its target y position. + */ + get targetYPositionStrength() { + return kWeakYStrength; + } + + /** + * @return {number} A scaling factor applied to the strength of links to this + * node. */ - targetYPositionStrength() { - return 0.1; + get linkStrengthScalingFactor() { + return 1; } /** @@ -287,12 +312,23 @@ class GraphNode { } /** @return {number} The strength of the repulsion force with other nodes. */ - manyBodyStrength() { + get manyBodyStrength() { return -200; } - /** @return {!Array<number>} */ - linkTargets() { + /** @return {!Array<number>} an array of node ids. */ + get linkTargets() { + return []; + } + + /** + * Dashed links express ownership relationships. An object can own multiple + * things, but be owned by exactly one (per relationship type). As such, the + * relationship is expressed on the *owned* object. These links are drawn with + * an arrow at the beginning of the link, pointing to the owned object. + * @return {!Array<number>} an array of node ids. + */ + get dashedLinkTargets() { return []; } @@ -322,8 +358,18 @@ class PageNode extends GraphNode { } /** @override */ - targetYPositionStrength() { - return 10; + get targetYPositionStrength() { + // Gravitate strongly towards the top of the graph. Can be overridden by + // the bounding force which uses kMaxBoundaryStrength. + return kHighYStrength; + } + + /** @override */ + get linkStrengthScalingFactor() { + // Give links from frame nodes to page nodes less weight than links between + // frame nodes, so the that Y forces pulling page nodes into their area can + // dominate over link forces pulling them towards frame nodes. + return 0.5; } /** override */ @@ -332,9 +378,17 @@ class PageNode extends GraphNode { } /** override */ - manyBodyStrength() { + get manyBodyStrength() { return -600; } + + /** override */ + get dashedLinkTargets() { + if (this.page.openerFrameId) { + return [this.page.openerFrameId]; + } + return []; + } } class FrameNode extends GraphNode { @@ -362,7 +416,7 @@ class FrameNode extends GraphNode { } /** override */ - linkTargets() { + get linkTargets() { // Only link to the page if there isn't a parent frame. return [ this.frame.parentFrameId || this.frame.pageId, this.frame.processId @@ -386,8 +440,18 @@ class ProcessNode extends GraphNode { } /** @return {number} */ - targetYPositionStrength() { - return 10; + get targetYPositionStrength() { + // Gravitate strongly towards the bottom of the graph. Can be overridden by + // the bounding force which uses kMaxBoundaryStrength. + return kHighYStrength; + } + + /** @override */ + get linkStrengthScalingFactor() { + // Give links to process nodes less weight than links between frame nodes, + // so the that Y forces pulling process nodes into their area can dominate + // over link forces pulling them towards frame nodes. + return 0.5; } /** override */ @@ -396,7 +460,7 @@ class ProcessNode extends GraphNode { } /** override */ - manyBodyStrength() { + get manyBodyStrength() { return -600; } } @@ -417,8 +481,10 @@ class WorkerNode extends GraphNode { } /** @return {number} */ - targetYPositionStrength() { - return 10; + get targetYPositionStrength() { + // Gravitate strongly towards the worker area of the graph. Can be + // overridden by the bounding force which uses kMaxBoundaryStrength. + return kHighYStrength; } /** override */ @@ -429,12 +495,12 @@ class WorkerNode extends GraphNode { } /** override */ - manyBodyStrength() { + get manyBodyStrength() { return -600; } /** override */ - linkTargets() { + get linkTargets() { // Link the process, in addition to all the client and child workers. return [ this.worker.processId, ...this.worker.clientFrameIds, @@ -444,14 +510,19 @@ class WorkerNode extends GraphNode { } /** - * A force that bounds GraphNodes |allowedYRange| in Y. + * A force that bounds GraphNodes |allowedYRange| in Y, + * as well as bounding them to stay in page bounds in X. * @param {number} graphHeight + * @param {number} graphWidth */ -function boundingForce(graphHeight) { +function boundingForce(graphHeight, graphWidth) { /** @type {!Array<!GraphNode>} */ let nodes = []; /** @type {!Array<!Array>} */ let bounds = []; + const xBounds = [2 * kNodeRadius, graphWidth - 2 * kNodeRadius]; + const boundPosition = (pos, bound) => + Math.max(bound[0], Math.min(pos, bound[1])); /** @param {number} alpha */ function force(alpha) { @@ -459,12 +530,23 @@ function boundingForce(graphHeight) { for (let i = 0; i < n; ++i) { const bound = bounds[i]; const node = nodes[i]; - const yOld = node.y; - const yNew = Math.max(bound[0], Math.min(yOld, bound[1])); - if (yOld !== yNew) { - node.y = yNew; - // Zero the velocity of clamped nodes. - node.vy = 0; + + // Calculate where the node will end up after movement. If it will be out + // of bounds apply a counter-force to bring it back in. + const yNextPosition = node.y + node.vy; + const yBoundedPosition = boundPosition(yNextPosition, bound); + if (yNextPosition !== yBoundedPosition) { + // Do not include alpha because we want to be strongly repelled from + // the boundary even if alpha has decayed. + node.vy += (yBoundedPosition - yNextPosition) * kMaxBoundaryStrength; + } + + const xNextPosition = node.x + node.vx; + const xBoundedPosition = boundPosition(xNextPosition, xBounds); + if (xNextPosition !== xBoundedPosition) { + // Do not include alpha because we want to be strongly repelled from + // the boundary even if alpha has decayed. + node.vx += (xBoundedPosition - xNextPosition) * kMaxBoundaryStrength; } } } @@ -472,7 +554,13 @@ function boundingForce(graphHeight) { /** @param {!Array<!GraphNode>} n */ force.initialize = function(n) { nodes = n; - bounds = nodes.map(node => node.allowedYRange(graphHeight)); + bounds = nodes.map(node => { + const nodeBounds = node.allowedYRange(graphHeight); + // Leave space for the node circle plus a small border. + nodeBounds[0] += kNodeRadius * 2; + nodeBounds[1] -= kNodeRadius * 2; + return nodeBounds; + }); }; return force; @@ -533,6 +621,12 @@ class Graph { */ this.linkGroup_ = null; + /** + * A selection for the top-level <g> node that contains all dashed edges. + * @private {d3.selection} + */ + this.dashedLinkGroup_ = null; + /** @private {!Map<number, !GraphNode>} */ this.nodes_ = new Map(); @@ -543,6 +637,12 @@ class Graph { this.links_ = []; /** + * The dashed links. + * @private {!Array<!d3.ForceLink>} + */ + this.dashedLinks_ = []; + + /** * The host window. * @private {Window} */ @@ -575,7 +675,17 @@ class Graph { simulation.on('tick', this.onTick_.bind(this)); const linkForce = d3.forceLink().id(d => d.id); - simulation.force('link', linkForce); + const defaultStrength = linkForce.strength(); + + // Override the default link strength function to apply scaling factors + // from the source and target nodes to the link strength. This lets + // different node types balance link forces with other forces that act on + // them. + simulation.force( + 'link', + linkForce.strength( + l => defaultStrength(l) * l.source.linkStrengthScalingFactor * + l.target.linkStrengthScalingFactor)); // Sets the repulsion force between nodes (positive number is attraction, // negative number is repulsion). @@ -588,8 +698,9 @@ class Graph { // Create the <g> elements that host nodes and links. // The link groups are created first so that all links end up behind nodes. const svg = d3.select(this.svg_); - this.toolTipLinkGroup_ = svg.append('g').attr('class', 'toolTipLinks'); + this.toolTipLinkGroup_ = svg.append('g').attr('class', 'tool-tip-links'); this.linkGroup_ = svg.append('g').attr('class', 'links'); + this.dashedLinkGroup_ = svg.append('g').attr('class', 'dashed-links'); this.nodeGroup_ = svg.append('g').attr('class', 'nodes'); this.separatorGroup_ = svg.append('g').attr('class', 'separators'); @@ -630,7 +741,11 @@ class Graph { /** @override */ pageChanged(page) { const pageNode = /** @type {!PageNode} */ (this.nodes_.get(page.id)); + + // Page node dashed links may change dynamically, so account for that here. + this.removeDashedNodeLinks_(pageNode); pageNode.page = page; + this.addDashedNodeLinks_(pageNode); } /** @override */ @@ -665,6 +780,7 @@ class Graph { // Remove any links, and then the node itself. this.removeNodeLinks_(node); + this.removeDashedNodeLinks_(node); this.nodes_.delete(nodeId); } @@ -709,12 +825,22 @@ class Graph { * @private */ removeNodeLinks_(node) { - // Filter away any links to or from the deleted node. + // Filter away any links to or from the provided node. this.links_ = this.links_.filter( link => link.source !== node && link.target !== node); } /** + * @param {!GraphNode} node + * @private + */ + removeDashedNodeLinks_(node) { + // Filter away any dashed links to or from the provided node. + this.dashedLinks_ = this.dashedLinks_.filter( + link => link.source !== node && link.target !== node); + } + + /** * @param {!Object<string>} nodeDescriptions * @private */ @@ -848,10 +974,18 @@ class Graph { // Select the links. const link = this.linkGroup_.selectAll('line').data(this.links_); // Add new links. - link.enter().append('line').attr('stroke-width', 1); + link.enter().append('line'); // Remove dead links. link.exit().remove(); + // Select the dashed links. + const dashedLink = + this.dashedLinkGroup_.selectAll('line').data(this.dashedLinks_); + // Add new dashed links. + dashedLink.enter().append('line'); + // Remove dead dashed links. + dashedLink.exit().remove(); + // Select the nodes, except for any dead ones that are still transitioning. const nodes = Array.from(this.nodes_.values()); const node = @@ -863,8 +997,10 @@ class Graph { .append('g') .call(this.drag_) .on('click', this.onGraphNodeClick_.bind(this)); - const circles = newNodes.append('circle').attr('r', 9).attr( - 'fill', 'green'); // New nodes appear green. + const circles = newNodes.append('circle') + .attr('id', d => `circle-${d.id}`) + .attr('r', kNodeRadius * 1.5) + .attr('fill', 'green'); // New nodes appear green. newNodes.append('image') .attr('x', -8) @@ -877,7 +1013,7 @@ class Graph { circles.transition() .duration(2000) .attr('fill', d => d.color) - .attr('r', 6); + .attr('r', kNodeRadius); } if (!node.exit().empty()) { @@ -913,9 +1049,11 @@ class Graph { // Update and restart the simulation if the graph changed. if (!node.enter().empty() || !node.exit().empty() || - !link.enter().empty() || !link.exit().empty()) { + !link.enter().empty() || !link.exit().empty() || + !dashedLink.enter().empty() || !dashedLink.exit().empty()) { this.simulation_.nodes(nodes); - this.simulation_.force('link').links(this.links_); + const links = this.links_.concat(this.dashedLinks_); + this.simulation_.force('link').links(links); this.restartSimulation_(); } @@ -932,6 +1070,12 @@ class Graph { .attr('x2', d => d.target.x) .attr('y2', d => d.target.y); + const dashedLines = this.dashedLinkGroup_.selectAll('line'); + dashedLines.attr('x1', d => d.source.x) + .attr('y1', d => d.source.y) + .attr('x2', d => d.target.x) + .attr('y2', d => d.target.y); + this.updateToolTipLinks(); } @@ -945,6 +1089,7 @@ class Graph { addNode_(node) { this.nodes_.set(node.id, node); this.addNodeLinks_(node); + this.addDashedNodeLinks_(node); node.setInitialPosition(this.width_, this.height_); } @@ -955,8 +1100,7 @@ class Graph { * @private */ addNodeLinks_(node) { - const linkTargets = node.linkTargets(); - for (const linkTarget of linkTargets) { + for (const linkTarget of node.linkTargets) { const target = this.nodes_.get(linkTarget); if (target) { this.links_.push({source: node, target: target}); @@ -965,6 +1109,21 @@ class Graph { } /** + * Adds all the dashed links for a node to the graph. + * + * @param {!GraphNode} node + * @private + */ + addDashedNodeLinks_(node) { + for (const dashedLinkTarget of node.dashedLinkTargets) { + const target = this.nodes_.get(dashedLinkTarget); + if (target) { + this.dashedLinks_.push({source: node, target: target}); + } + } + } + + /** * @param {!GraphNode} d The dragged node. * @private */ @@ -993,8 +1152,16 @@ class Graph { if (!d3.event.active) { this.simulation_.alphaTarget(0); } - d.fx = null; - d.fy = null; + // Leave the node pinned where it was dropped. Return it to free + // positioning if it's dropped outside its designated area. + const bounds = d.allowedYRange(this.height_); + if (d3.event.y < bounds[0] || d3.event.y > bounds[1]) { + d.fx = null; + d.fy = null; + } + + // Toggle the pinned class as appropriate for the circle backing this node. + d3.select(`#circle-${d.id}`).classed('pinned', d.fx != null); } /** @@ -1010,7 +1177,7 @@ class Graph { * @private */ getTargetYPositionStrength_(d) { - return d.targetYPositionStrength(); + return d.targetYPositionStrength; } /** @@ -1018,7 +1185,7 @@ class Graph { * @private */ getManyBodyStrength_(d) { - return d.manyBodyStrength(); + return d.manyBodyStrength; } /** @@ -1093,7 +1260,7 @@ class Graph { .strength(this.getTargetYPositionStrength_.bind(this)); this.simulation_.force('x_pos', xForce); this.simulation_.force('y_pos', yForce); - this.simulation_.force('y_bound', boundingForce(this.height_)); + this.simulation_.force('y_bound', boundingForce(this.height_, this.width_)); if (!this.wasResized_) { this.wasResized_ = true; diff --git a/chromium/chrome/browser/resources/discards/graph_doc_template.html b/chromium/chrome/browser/resources/discards/graph_doc_template.html index b9fdfb27c8d..bcdb842d0c0 100644 --- a/chromium/chrome/browser/resources/discards/graph_doc_template.html +++ b/chromium/chrome/browser/resources/discards/graph_doc_template.html @@ -21,6 +21,20 @@ URL. As result, this document needs to be self-contained, hence inline scripts. .links line { stroke: #999; stroke-opacity: 0.6; + stroke-width: 1; + } + + .dashed-links line { + marker-start: url(#arrowToSource); + stroke: #999; + stroke-dasharray: 3; + stroke-opacity: 0.6; + stroke-width: 1; + } + + #arrowToSource { + fill: #999; + stroke: #999; } .nodes circle { @@ -28,6 +42,10 @@ URL. As result, this document needs to be self-contained, hence inline scripts. stroke-width: 1.5px; } + .nodes circle.pinned { + stroke: red; + } + .dead image { display: none; } @@ -70,6 +88,13 @@ ${javascript_file} </head> <body> <div id="toolTips" width="100%" height="100%"></div> - <svg id="graphBody" width="100%" height="100%"></svg> + <svg id="graphBody" width="100%" height="100%"> + <defs> + <marker id="arrowToSource" viewBox="0 -5 10 10" refX="-12" refY="0" + markerWidth="9" markerHeight="6" orient="auto"> + <path d="M15,-7 L0,0 L15,7" /> + </marker> + </defs> + </svg> </body> </html> |