Changeset 237669 in webkit


Ignore:
Timestamp:
Oct 31, 2018 9:12:59 PM (5 years ago)
Author:
Devin Rousso
Message:

Web Inspector: display low-power enter/exit events in Timelines and Network node waterfalls
https://bugs.webkit.org/show_bug.cgi?id=190641
<rdar://problem/45319049>

Reviewed by Joseph Pecoraro.

Source/JavaScriptCore:

  • inspector/protocol/DOM.json:

Add videoLowPowerChanged event that is fired when InspectorDOMAgent is able to determine
whether a video element's low power state has changed.

Source/WebCore:

No new tests, as low power mode is indeterminate. Should not affect functionality.

  • inspector/agents/InspectorDOMAgent.h:
  • inspector/agents/InspectorDOMAgent.cpp:

(WebCore::InspectorDOMAgent::InspectorDOMAgent):
(WebCore::InspectorDOMAgent::addEventListenersToNode):
(WebCore::InspectorDOMAgent::mediaMetricsTimerFired): Added.

Source/WebInspectorUI:

  • UserInterface/Protocol/DOMObserver.js:

(WI.DOMObserver.prototype.videoLowPowerChanged): Added.

  • UserInterface/Controllers/DOMManager.js:

(WI.DOMManager.prototype.videoLowPowerChanged): Added.

  • UserInterface/Models/DOMNode.js:

(WI.DOMNode):
(WI.DOMNode.prototype.get lowPowerRanges): Added.
(WI.DOMNode.prototype.videoLowPowerChanged): Added.
(WI.DOMNode.prototype.canEnterLowPowerMode): Added.

  • UserInterface/Views/NetworkTableContentView.js:

(WI.NetworkTableContentView.prototype._populateDomainCell):
(WI.NetworkTableContentView.prototype._tryLinkResourceToDOMNode):
(WI.NetworkTableContentView.prototype._handleNodeLowPowerChanged): Added.

  • UserInterface/Views/NetworkTableContentView.css:

(.network-table :not(.header) .cell.waterfall .waterfall-container > .area):
(.network-table :not(.header) .cell.waterfall .waterfall-container > .area.dom-fullscreen): Added.
(.network-table :not(.header) .cell.waterfall .waterfall-container > .area.low-power): Added.
(.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-fullscreen): Deleted.

  • UserInterface/Views/DOMNodeEventsContentView.js:

(WI.DOMNodeEventsContentView):
(WI.DOMNodeEventsContentView.prototype.initialLayout):
(WI.DOMNodeEventsContentView.prototype.closed): Deleted.
(WI.DOMNodeEventsContentView.prototype._handleDOMNodeDidFireEvent): Deleted.

  • UserInterface/Views/DOMEventsBreakdownView.js:

(WI.DOMEventsBreakdownView):
(WI.DOMEventsBreakdownView.prototype.initialLayout):
(WI.DOMEventsBreakdownView.prototype.layout): Added.
(WI.DOMEventsBreakdownView.prototype._handleDOMNodeDidFireEvent): Added.
(WI.DOMEventsBreakdownView.prototype._handleDOMNodeLowPowerChanged): Added.
(WI.DOMEventsBreakdownView.prototype.addEvent): Deleted.
(WI.DOMEventsBreakdownView.prototype._populateTable.percentOfTotalTime): Deleted.
(WI.DOMEventsBreakdownView.prototype._populateTable): Deleted.

  • UserInterface/Views/DOMEventsBreakdownView.css:

(.dom-events-breakdown .graph > .area): Added.
(.dom-events-breakdown .graph > .area.fullscreen):
(.dom-events-breakdown .graph > .area.low-power): Added.

  • Localizations/en.lproj/localizedStrings.js:
Location:
trunk/Source
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r237645 r237669  
     12018-10-31  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: display low-power enter/exit events in Timelines and Network node waterfalls
     4        https://bugs.webkit.org/show_bug.cgi?id=190641
     5        <rdar://problem/45319049>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        * inspector/protocol/DOM.json:
     10        Add `videoLowPowerChanged` event that is fired when `InspectorDOMAgent` is able to determine
     11        whether a video element's low power state has changed.
     12
    1132018-10-31  Tadeu Zagallo  <tzagallo@apple.com>
    214
  • trunk/Source/JavaScriptCore/inspector/protocol/DOM.json

    r237431 r237669  
    670670                { "name": "data", "type": "object", "optional": true, "description": "Holds ancillary information about the event or its target." }
    671671            ]
     672        },
     673        {
     674            "name": "videoLowPowerChanged",
     675            "description": "Called when a video element enters/exits low power mode.",
     676            "parameters": [
     677                { "name": "nodeId", "$ref": "NodeId" },
     678                { "name": "timestamp", "$ref": "Network.Timestamp", "description": "Time when the video element entered/exited low power mode" },
     679                { "name": "isLowPower", "type": "boolean" }
     680            ]
    672681        }
    673682    ]
  • trunk/Source/WebCore/ChangeLog

    r237657 r237669  
     12018-10-31  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: display low-power enter/exit events in Timelines and Network node waterfalls
     4        https://bugs.webkit.org/show_bug.cgi?id=190641
     5        <rdar://problem/45319049>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        No new tests, as low power mode is indeterminate. Should not affect functionality.
     10
     11        * inspector/agents/InspectorDOMAgent.h:
     12        * inspector/agents/InspectorDOMAgent.cpp:
     13        (WebCore::InspectorDOMAgent::InspectorDOMAgent):
     14        (WebCore::InspectorDOMAgent::addEventListenersToNode):
     15        (WebCore::InspectorDOMAgent::mediaMetricsTimerFired): Added.
     16
    1172018-10-31  Alicia Boya García  <aboya@igalia.com>
    218
  • trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp

    r237441 r237669  
    6868#include "HTMLStyleElement.h"
    6969#include "HTMLTemplateElement.h"
     70#include "HTMLVideoElement.h"
    7071#include "HitTestResult.h"
    7172#include "InspectorClient.h"
     
    9798#include "TextNodeTraversal.h"
    9899#include "Timer.h"
     100#include "VideoPlaybackQuality.h"
    99101#include "WebInjectedScriptManager.h"
    100102#include "XPathResult.h"
     
    283285    , m_pageAgent(pageAgent)
    284286    , m_overlay(overlay)
     287    , m_mediaMetricsTimer(*this, &InspectorDOMAgent::mediaMetricsTimerFired)
    285288{
    286289}
     
    21792182        createEventListener(eventNames().volumechangeEvent);
    21802183        createEventListener(eventNames().waitingEvent);
     2184
     2185        if (!m_mediaMetricsTimer.isActive())
     2186            m_mediaMetricsTimer.start(0_s, 1_s / 15.);
    21812187    }
    21822188}
     
    24482454}
    24492455
     2456void InspectorDOMAgent::mediaMetricsTimerFired()
     2457{
     2458    // FIXME: remove metrics information for any media element when it's destroyed
     2459
     2460    if (HTMLMediaElement::allMediaElements().isEmpty()) {
     2461        if (m_mediaMetricsTimer.isActive())
     2462            m_mediaMetricsTimer.stop();
     2463        m_mediaMetrics.clear();
     2464        return;
     2465    }
     2466
     2467    for (auto* mediaElement : HTMLMediaElement::allMediaElements()) {
     2468        if (!is<HTMLVideoElement>(mediaElement) || !mediaElement->isPlaying())
     2469            continue;
     2470
     2471        auto videoPlaybackQuality = mediaElement->getVideoPlaybackQuality();
     2472        unsigned displayCompositedVideoFrames = videoPlaybackQuality->displayCompositedVideoFrames();
     2473
     2474        auto iterator = m_mediaMetrics.find(mediaElement);
     2475        if (iterator == m_mediaMetrics.end()) {
     2476            m_mediaMetrics.set(mediaElement, MediaMetrics(displayCompositedVideoFrames));
     2477            continue;
     2478        }
     2479
     2480        bool isLowPower = (displayCompositedVideoFrames - iterator->value.displayCompositedFrames) > 0;
     2481        if (iterator->value.isLowPower != isLowPower) {
     2482            iterator->value.isLowPower = isLowPower;
     2483
     2484            int nodeId = pushNodePathToFrontend(mediaElement);
     2485            if (nodeId) {
     2486                auto timestamp = m_environment.executionStopwatch()->elapsedTime().seconds();
     2487                m_frontendDispatcher->videoLowPowerChanged(nodeId, timestamp, iterator->value.isLowPower);
     2488            }
     2489        }
     2490
     2491        iterator->value.displayCompositedFrames = displayCompositedVideoFrames;
     2492    }
     2493
     2494    m_mediaMetrics.removeIf([&] (auto& entry) {
     2495        return !HTMLMediaElement::allMediaElements().contains(entry.key);
     2496    });
     2497}
     2498
    24502499Node* InspectorDOMAgent::nodeForPath(const String& path)
    24512500{
  • trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h

    r237431 r237669  
    3232#include "EventTarget.h"
    3333#include "InspectorWebAgentBase.h"
     34#include "Timer.h"
    3435#include <JavaScriptCore/InspectorBackendDispatchers.h>
    3536#include <JavaScriptCore/InspectorFrontendDispatchers.h>
     
    6465class InspectorOverlay;
    6566class InspectorPageAgent;
     67class HTMLMediaElement;
    6668class HitTestResult;
    6769class Node;
     
    224226
    225227private:
     228    void mediaMetricsTimerFired();
     229
    226230    void highlightMousedOverNode();
    227231    void setSearchingForNode(ErrorString&, bool enabled, const JSON::Object* highlightConfig);
     
    285289    bool m_documentRequested { false };
    286290
     291    Timer m_mediaMetricsTimer;
     292    struct MediaMetrics {
     293        unsigned displayCompositedFrames { 0 };
     294        bool isLowPower { false };
     295
     296        MediaMetrics() { }
     297
     298        MediaMetrics(unsigned displayCompositedFrames)
     299            : displayCompositedFrames(displayCompositedFrames)
     300        {
     301        }
     302    };
     303
     304    // The pointer key for this map should not be used for anything other than matching.
     305    HashMap<HTMLMediaElement*, MediaMetrics> m_mediaMetrics;
     306
    287307    struct InspectorEventListener {
    288308        int identifier { 1 };
  • trunk/Source/WebInspectorUI/ChangeLog

    r237665 r237669  
     12018-10-31  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: display low-power enter/exit events in Timelines and Network node waterfalls
     4        https://bugs.webkit.org/show_bug.cgi?id=190641
     5        <rdar://problem/45319049>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        * UserInterface/Protocol/DOMObserver.js:
     10        (WI.DOMObserver.prototype.videoLowPowerChanged): Added.
     11
     12        * UserInterface/Controllers/DOMManager.js:
     13        (WI.DOMManager.prototype.videoLowPowerChanged): Added.
     14
     15        * UserInterface/Models/DOMNode.js:
     16        (WI.DOMNode):
     17        (WI.DOMNode.prototype.get lowPowerRanges): Added.
     18        (WI.DOMNode.prototype.videoLowPowerChanged): Added.
     19        (WI.DOMNode.prototype.canEnterLowPowerMode): Added.
     20
     21        * UserInterface/Views/NetworkTableContentView.js:
     22        (WI.NetworkTableContentView.prototype._populateDomainCell):
     23        (WI.NetworkTableContentView.prototype._tryLinkResourceToDOMNode):
     24        (WI.NetworkTableContentView.prototype._handleNodeLowPowerChanged): Added.
     25        * UserInterface/Views/NetworkTableContentView.css:
     26        (.network-table :not(.header) .cell.waterfall .waterfall-container > .area):
     27        (.network-table :not(.header) .cell.waterfall .waterfall-container > .area.dom-fullscreen): Added.
     28        (.network-table :not(.header) .cell.waterfall .waterfall-container > .area.low-power): Added.
     29        (.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-fullscreen): Deleted.
     30
     31        * UserInterface/Views/DOMNodeEventsContentView.js:
     32        (WI.DOMNodeEventsContentView):
     33        (WI.DOMNodeEventsContentView.prototype.initialLayout):
     34        (WI.DOMNodeEventsContentView.prototype.closed): Deleted.
     35        (WI.DOMNodeEventsContentView.prototype._handleDOMNodeDidFireEvent): Deleted.
     36
     37        * UserInterface/Views/DOMEventsBreakdownView.js:
     38        (WI.DOMEventsBreakdownView):
     39        (WI.DOMEventsBreakdownView.prototype.initialLayout):
     40        (WI.DOMEventsBreakdownView.prototype.layout): Added.
     41        (WI.DOMEventsBreakdownView.prototype._handleDOMNodeDidFireEvent): Added.
     42        (WI.DOMEventsBreakdownView.prototype._handleDOMNodeLowPowerChanged): Added.
     43        (WI.DOMEventsBreakdownView.prototype.addEvent): Deleted.
     44        (WI.DOMEventsBreakdownView.prototype._populateTable.percentOfTotalTime): Deleted.
     45        (WI.DOMEventsBreakdownView.prototype._populateTable): Deleted.
     46        * UserInterface/Views/DOMEventsBreakdownView.css:
     47        (.dom-events-breakdown .graph > .area): Added.
     48        (.dom-events-breakdown .graph > .area.fullscreen):
     49        (.dom-events-breakdown .graph > .area.low-power): Added.
     50
     51        * Localizations/en.lproj/localizedStrings.js:
     52
    1532018-10-31  Devin Rousso  <drousso@apple.com>
    254
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r237660 r237669  
    423423localizedStrings["Full Garbage Collection"] = "Full Garbage Collection";
    424424localizedStrings["Full URL"] = "Full URL";
     425localizedStrings["Fullscreen"] = "Fullscreen";
    425426localizedStrings["Fullscreen from “%s“"] = "Fullscreen from “%s“";
    426427localizedStrings["Function"] = "Function";
     
    536537localizedStrings["Logs"] = "Logs";
    537538localizedStrings["Low"] = "Low";
     539localizedStrings["Low Power Mode"] = "Low Power Mode";
    538540localizedStrings["Lowest: %s"] = "Lowest: %s";
    539541localizedStrings["MIME Type"] = "MIME Type";
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js

    r237652 r237669  
    148148    }
    149149
     150    videoLowPowerChanged(nodeId, timestamp, isLowPower)
     151    {
     152        // Called from WI.DOMObserver.
     153
     154        let node = this._idToDOMNode[nodeId];
     155        if (!node)
     156            return;
     157
     158        node.videoLowPowerChanged(timestamp, isLowPower);
     159    }
     160
    150161    // Private
    151162
  • trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js

    r237661 r237669  
    140140
    141141        this._domEvents = [];
     142        this._lowPowerRanges = [];
    142143
    143144        if (this._shouldListenForEventListeners())
     
    159160
    160161    get domEvents() { return this._domEvents; }
     162    get lowPowerRanges() { return this._lowPowerRanges; }
    161163
    162164    get frameIdentifier()
     
    727729    }
    728730
     731    videoLowPowerChanged(timestamp, isLowPower)
     732    {
     733        // Called from WI.DOMManager.
     734
     735        console.assert(this.canEnterLowPowerMode());
     736
     737        let lastValue = this._lowPowerRanges.lastValue;
     738
     739        if (isLowPower) {
     740            console.assert(!lastValue || lastValue.endTimestamp);
     741            if (!lastValue || lastValue.endTimestamp)
     742                this._lowPowerRanges.push({startTimestamp: timestamp});
     743        } else {
     744            console.assert(!lastValue || lastValue.startTimestamp);
     745            if (!lastValue)
     746                this._lowPowerRanges.push({endTimestamp: timestamp});
     747            else if (lastValue.startTimestamp)
     748                lastValue.endTimestamp = timestamp;
     749        }
     750
     751        this.dispatchEventToListeners(WI.DOMNode.Event.LowPowerChanged, {isLowPower, timestamp});
     752    }
     753
     754    canEnterLowPowerMode()
     755    {
     756        return this.localName() === "video" || this.nodeName().toLowerCase() === "video";
     757    }
     758
    729759    _handleDOMNodeDidFireEvent(event)
    730760    {
     
    899929    EventListenersChanged: "dom-node-event-listeners-changed",
    900930    DidFireEvent: "dom-node-did-fire-event",
     931    LowPowerChanged: "dom-node-video-low-power-changed",
    901932};
    902933
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js

    r237431 r237669  
    117117        WI.domManager.didFireEvent(nodeId, eventName, timestamp, data);
    118118    }
     119
     120    videoLowPowerChanged(nodeId, timestamp, isLowPower)
     121    {
     122        WI.domManager.videoLowPowerChanged(nodeId, timestamp, isLowPower);
     123    }
    119124};
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css

    r237431 r237669  
    7070}
    7171
    72 .dom-events-breakdown .graph > .area.fullscreen {
     72.dom-events-breakdown .graph > .area {
    7373    top: 0;
    7474    height: 100%;
    75     background-color: var(--panel-background-color);
     75}
     76
     77.dom-events-breakdown .graph > .area.fullscreen {
     78    background-color: hsla(0, 0%, 75%, 0.25);
     79}
     80
     81.dom-events-breakdown .graph > .area.low-power {
     82    background-color: hsla(83, 100%, 48%, 0.4);
    7683}
    7784
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js

    r237431 r237669  
    2626WI.DOMEventsBreakdownView = class DOMEventsBreakdownView extends WI.View
    2727{
    28     constructor(domEvents, {includeGraph, startTimestamp} = {})
     28    constructor(domNodeOrEvents, {includeGraph, startTimestamp} = {})
    2929    {
     30        console.assert(domNodeOrEvents instanceof WI.DOMNode || Array.isArray(domNodeOrEvents));
     31
    3032        super();
    3133
    32         this._domEvents = domEvents;
     34        if (domNodeOrEvents instanceof WI.DOMNode) {
     35            this._domNode = domNodeOrEvents;
     36            this._domNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleDOMNodeDidFireEvent, this);
     37            if (this._domNode.canEnterLowPowerMode())
     38                this._domNode.addEventListener(WI.DOMNode.Event.LowPowerChanged, this._handleDOMNodeLowPowerChanged, this);
     39
     40            this._domEvents = null;
     41        } else {
     42            this._domNode = null;
     43            this._domEvents = domNodeOrEvents;
     44            this._lowPowerRanges = [];
     45        }
     46
    3347        this._includeGraph = includeGraph || false;
    3448        this._startTimestamp = startTimestamp || 0;
     
    3751
    3852        this.element.classList.add("dom-events-breakdown");
    39     }
    40 
    41     // Public
    42 
    43     addEvent(domEvent)
    44     {
    45         this._domEvents.push(domEvent);
    46 
    47         this.soon._populateTable();
    4853    }
    4954
     
    7580
    7681        this._tableBodyElement = tableElement.appendChild(document.createElement("tbody"));
    77 
    78         this._populateTable();
    7982    }
    8083
    81     // Private
     84    layout()
     85    {
     86        if (this.layoutReason !== WI.View.LayoutReason.Dirty)
     87            return;
    8288
    83     _populateTable()
    84     {
    8589        this._tableBodyElement.removeChildren();
    8690
    87         let startTimestamp = this._domEvents[0].timestamp;
    88         let endTimestamp = this._domEvents.lastValue.timestamp;
     91        console.assert(this._domEvents || (this._domNode && this._domNode.domEvents));
     92        let domEvents = this._domEvents || this._domNode.domEvents;
     93        let startTimestamp = domEvents[0].timestamp;
     94        let endTimestamp = domEvents.lastValue.timestamp;
    8995        let totalTime = endTimestamp - startTimestamp;
    9096        let styleAttribute = WI.resolvedLayoutDirection() === WI.LayoutDirection.LTR ? "left" : "right";
     
    95101
    96102        let fullscreenRanges = [];
    97         let fullscreenDOMEvents = WI.DOMNode.getFullscreenDOMEvents(this._domEvents);
     103        let fullscreenDOMEvents = WI.DOMNode.getFullscreenDOMEvents(domEvents);
    98104        for (let fullscreenDOMEvent of fullscreenDOMEvents) {
    99105            let {enabled} = fullscreenDOMEvent.data;
     
    104110            }
    105111            fullscreenRanges.lastValue.endTimestamp = (enabled && fullscreenDOMEvent === fullscreenDOMEvents.lastValue) ? endTimestamp : fullscreenDOMEvent.timestamp;
     112            if (fullscreenDOMEvent.originator)
     113                fullscreenRanges.lastValue.originator = fullscreenDOMEvent.originator;
    106114        }
    107115
    108         for (let domEvent of this._domEvents) {
     116        let lowPowerRanges = this._domNode ? this._domNode.lowPowerRanges : [];
     117
     118        for (let domEvent of domEvents) {
    109119            let rowElement = this._tableBodyElement.appendChild(document.createElement("tr"));
    110120
     
    123133                    fullscreenArea.style.setProperty(styleAttribute, percentOfTotalTime(fullscreenRange.startTimestamp - startTimestamp) + "%");
    124134                    fullscreenArea.style.setProperty("width", percentOfTotalTime(fullscreenRange.endTimestamp - fullscreenRange.startTimestamp) + "%");
     135
     136                    if (fullscreenRange.originator)
     137                        fullscreenArea.title = WI.UIString("Fullscreen from “%s“").format(fullscreenRange.originator.displayName);
     138                    else
     139                        fullscreenArea.title = WI.UIString("Fullscreen");
     140                }
     141
     142                let lowPowerRange = lowPowerRanges.find((range) => domEvent.timestamp >= range.startTimestamp && domEvent.timestamp <= range.endTimestamp);
     143                if (lowPowerRange) {
     144                    let lowPowerArea = graphCell.appendChild(document.createElement("div"));
     145                    lowPowerArea.classList.add("area", "low-power");
     146                    lowPowerArea.title = WI.UIString("Low Power Mode");
     147                    lowPowerArea.style.setProperty(styleAttribute, percentOfTotalTime(lowPowerRange.startTimestamp - startTimestamp) + "%");
     148                    lowPowerArea.style.setProperty("width", percentOfTotalTime(lowPowerRange.endTimestamp - lowPowerRange.startTimestamp) + "%");
    125149                }
    126150
     
    146170        }
    147171    }
     172
     173    // Private
     174
     175    _handleDOMNodeDidFireEvent(event)
     176    {
     177        this.needsLayout();
     178    }
     179
     180    _handleDOMNodeLowPowerChanged(event)
     181    {
     182        this.needsLayout();
     183    }
    148184};
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeEventsContentView.js

    r237028 r237669  
    4747        super.initialLayout();
    4848
    49         this._breakdownView = new WI.DOMEventsBreakdownView(this._domNode.domEvents.slice(), {
     49        this._breakdownView = new WI.DOMEventsBreakdownView(this._domNode, {
    5050            includeGraph: true,
    5151            startTimestamp: this._startTimestamp,
    5252        });
    5353        this.addSubview(this._breakdownView);
    54 
    55         this._domNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleDOMNodeDidFireEvent, this);
    56     }
    57 
    58     closed()
    59     {
    60         this._domNode.removeEventListener(null, null, this);
    61 
    62         super.closed();
    63     }
    64 
    65     // Private
    66 
    67     _handleDOMNodeDidFireEvent(event)
    68     {
    69         let {domEvent} = event.data;
    70 
    71         if (this._breakdownView)
    72             this._breakdownView.addEvent(domEvent);
    7354    }
    7455};
  • trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css

    r237432 r237669  
    176176}
    177177
     178.network-table :not(.header) .cell.waterfall .waterfall-container > .area {
     179    position: absolute;
     180    top: var(--area-padding);
     181    height: calc(100% - (var(--area-padding) * 2));
     182
     183    /* Half of the vertical space above any .dom-event node */
     184    --area-padding: calc((50% - (var(--node-waterfall-dom-event-size) / 2)) / 2);
     185}
     186
     187.network-table :not(.header) .cell.waterfall .waterfall-container > .area.dom-fullscreen {
     188    background-color: hsla(0, 0%, 75%, 0.75);
     189}
     190
     191.network-table :not(.header) .cell.waterfall .waterfall-container > .area.low-power {
     192    background-color: var(--network-request-color);
     193}
     194
    178195.network-table .timeline-ruler {
    179196    position: absolute;
     
    181198    bottom: 0;
    182199    overflow: hidden;
    183 }
    184 
    185 .network-table :not(.header) .cell.waterfall .waterfall-container > .dom-fullscreen {
    186     position: absolute;
    187     top: var(--dom-fullscreen-vertical-padding);
    188     height: calc(100% - (var(--dom-fullscreen-vertical-padding) * 2));
    189     background-color: lightgrey;
    190 
    191     /* Half of the vertical space above any .dom-event node */
    192     --dom-fullscreen-vertical-padding: calc((50% - (var(--node-waterfall-dom-event-size) / 2)) / 2);
    193200}
    194201
  • trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js

    r237661 r237669  
    543543            }
    544544
    545             cell.append(domain);
     545            cell.append(domain || emDash);
    546546        }
    547547
     
    556556
    557557            createIconAndText(uniqueSchemeValues.values().next().value, uniqueDomainValues.values().next().value);
    558             return;
    559         }
    560 
    561         if (!entry.domain) {
    562             cell.textContent = emDash;
    563558            return;
    564559        }
     
    687682                for (let i = 0; i < fullscreenDOMEvents.length; i += 2) {
    688683                    let fullscreenElement = container.appendChild(document.createElement("div"));
    689                     fullscreenElement.classList.add("dom-fullscreen");
     684                    fullscreenElement.classList.add("area", "dom-fullscreen");
    690685                    positionByStartOffset(fullscreenElement, fullscreenDOMEvents[i].timestamp);
    691686                    setWidthForDuration(fullscreenElement, fullscreenDOMEvents[i].timestamp, fullscreenDOMEvents[i + 1].timestamp);
     
    694689                    if (originator)
    695690                        fullscreenElement.title = WI.UIString("Fullscreen from “%s“").format(originator.displayName);
     691                    else
     692                        fullscreenElement.title = WI.UIString("Fullscreen");
    696693                }
     694            }
     695
     696            for (let lowPowerRange of domNode.lowPowerRanges) {
     697                let startTimestamp = lowPowerRange.startTimestamp || graphStartTime;
     698                let endTimestamp = lowPowerRange.endTimestamp || this._waterfallEndTime;
     699
     700                let lowPowerElement = container.appendChild(document.createElement("div"));
     701                lowPowerElement.classList.add("area", "low-power");
     702                lowPowerElement.title = WI.UIString("Low Power Mode");
     703                positionByStartOffset(lowPowerElement, startTimestamp);
     704                setWidthForDuration(lowPowerElement, startTimestamp, endTimestamp);
    697705            }
    698706
     
    15591567
    15601568            resource.initiatorNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleNodeDidFireEvent, this);
     1569            if (resource.initiatorNode.canEnterLowPowerMode())
     1570                resource.initiatorNode.addEventListener(WI.DOMNode.Event.LowPowerChanged, this._handleNodeLowPowerChanged, this);
    15611571        }
    15621572
     
    15901600        if (domEvent.timestamp > this._waterfallEndTime)
    15911601            this._waterfallEndTime = domEvent.timestamp + (this._waterfallTimelineRuler.secondsPerPixel * 10);
     1602
     1603        this.needsLayout();
     1604    }
     1605
     1606    _handleNodeLowPowerChanged(event)
     1607    {
     1608        let domNode = event.target;
     1609        let {timestamp} = event.data;
     1610
     1611        this._pendingUpdates.push(domNode);
     1612
     1613        if (timestamp > this._waterfallEndTime)
     1614            this._waterfallEndTime = timestamp + (this._waterfallTimelineRuler.secondsPerPixel * 10);
    15921615
    15931616        this.needsLayout();
Note: See TracChangeset for help on using the changeset viewer.