<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[237669] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/237669">237669</a></dd>
<dt>Author</dt> <dd>drousso@apple.com</dd>
<dt>Date</dt> <dd>2018-10-31 21:12:59 -0700 (Wed, 31 Oct 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>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:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolDOMjson">trunk/Source/JavaScriptCore/inspector/protocol/DOM.json</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectoragentsInspectorDOMAgentcpp">trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectoragentsInspectorDOMAgenth">trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersDOMManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsDOMNodejs">trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceProtocolDOMObserverjs">trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDOMEventsBreakdownViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDOMEventsBreakdownViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDOMNodeEventsContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeEventsContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkTableContentViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkTableContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/JavaScriptCore/ChangeLog       2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2018-10-31  Devin Rousso  <drousso@apple.com>
+
+        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.
+
+        * 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.
+
</ins><span class="cx"> 2018-10-31  Tadeu Zagallo  <tzagallo@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Adjust inlining threshold for new bytecode format
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolDOMjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/DOM.json (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/DOM.json  2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/JavaScriptCore/inspector/protocol/DOM.json     2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -669,6 +669,15 @@
</span><span class="cx">                 { "name": "timestamp", "$ref": "Network.Timestamp", "description": "Time when the event was fired" },
</span><span class="cx">                 { "name": "data", "type": "object", "optional": true, "description": "Holds ancillary information about the event or its target." }
</span><span class="cx">             ]
</span><ins>+        },
+        {
+            "name": "videoLowPowerChanged",
+            "description": "Called when a video element enters/exits low power mode.",
+            "parameters": [
+                { "name": "nodeId", "$ref": "NodeId" },
+                { "name": "timestamp", "$ref": "Network.Timestamp", "description": "Time when the video element entered/exited low power mode" },
+                { "name": "isLowPower", "type": "boolean" }
+            ]
</ins><span class="cx">         }
</span><span class="cx">     ]
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebCore/ChangeLog      2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2018-10-31  Devin Rousso  <drousso@apple.com>
+
+        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.
+
+        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.
+
</ins><span class="cx"> 2018-10-31  Alicia Boya García  <aboya@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [MSE] Use tolerance when growing the coded frame group
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectoragentsInspectorDOMAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp      2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp 2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -67,6 +67,7 @@
</span><span class="cx"> #include "HTMLScriptElement.h"
</span><span class="cx"> #include "HTMLStyleElement.h"
</span><span class="cx"> #include "HTMLTemplateElement.h"
</span><ins>+#include "HTMLVideoElement.h"
</ins><span class="cx"> #include "HitTestResult.h"
</span><span class="cx"> #include "InspectorClient.h"
</span><span class="cx"> #include "InspectorController.h"
</span><span class="lines">@@ -96,6 +97,7 @@
</span><span class="cx"> #include "Text.h"
</span><span class="cx"> #include "TextNodeTraversal.h"
</span><span class="cx"> #include "Timer.h"
</span><ins>+#include "VideoPlaybackQuality.h"
</ins><span class="cx"> #include "WebInjectedScriptManager.h"
</span><span class="cx"> #include "XPathResult.h"
</span><span class="cx"> #include "markup.h"
</span><span class="lines">@@ -282,6 +284,7 @@
</span><span class="cx">     , m_backendDispatcher(Inspector::DOMBackendDispatcher::create(context.backendDispatcher, this))
</span><span class="cx">     , m_pageAgent(pageAgent)
</span><span class="cx">     , m_overlay(overlay)
</span><ins>+    , m_mediaMetricsTimer(*this, &InspectorDOMAgent::mediaMetricsTimerFired)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2178,6 +2181,9 @@
</span><span class="cx">         createEventListener(eventNames().timeupdateEvent);
</span><span class="cx">         createEventListener(eventNames().volumechangeEvent);
</span><span class="cx">         createEventListener(eventNames().waitingEvent);
</span><ins>+
+        if (!m_mediaMetricsTimer.isActive())
+            m_mediaMetricsTimer.start(0_s, 1_s / 15.);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2447,6 +2453,49 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InspectorDOMAgent::mediaMetricsTimerFired()
+{
+    // FIXME: remove metrics information for any media element when it's destroyed
+
+    if (HTMLMediaElement::allMediaElements().isEmpty()) {
+        if (m_mediaMetricsTimer.isActive())
+            m_mediaMetricsTimer.stop();
+        m_mediaMetrics.clear();
+        return;
+    }
+
+    for (auto* mediaElement : HTMLMediaElement::allMediaElements()) {
+        if (!is<HTMLVideoElement>(mediaElement) || !mediaElement->isPlaying())
+            continue;
+
+        auto videoPlaybackQuality = mediaElement->getVideoPlaybackQuality();
+        unsigned displayCompositedVideoFrames = videoPlaybackQuality->displayCompositedVideoFrames();
+
+        auto iterator = m_mediaMetrics.find(mediaElement);
+        if (iterator == m_mediaMetrics.end()) {
+            m_mediaMetrics.set(mediaElement, MediaMetrics(displayCompositedVideoFrames));
+            continue;
+        }
+
+        bool isLowPower = (displayCompositedVideoFrames - iterator->value.displayCompositedFrames) > 0;
+        if (iterator->value.isLowPower != isLowPower) {
+            iterator->value.isLowPower = isLowPower;
+
+            int nodeId = pushNodePathToFrontend(mediaElement);
+            if (nodeId) {
+                auto timestamp = m_environment.executionStopwatch()->elapsedTime().seconds();
+                m_frontendDispatcher->videoLowPowerChanged(nodeId, timestamp, iterator->value.isLowPower);
+            }
+        }
+
+        iterator->value.displayCompositedFrames = displayCompositedVideoFrames;
+    }
+
+    m_mediaMetrics.removeIf([&] (auto& entry) {
+        return !HTMLMediaElement::allMediaElements().contains(entry.key);
+    });
+}
+
</ins><span class="cx"> Node* InspectorDOMAgent::nodeForPath(const String& path)
</span><span class="cx"> {
</span><span class="cx">     // The path is of form "1,HTML,2,BODY,1,DIV"
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectoragentsInspectorDOMAgenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h        2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h   2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "EventTarget.h"
</span><span class="cx"> #include "InspectorWebAgentBase.h"
</span><ins>+#include "Timer.h"
</ins><span class="cx"> #include <JavaScriptCore/InspectorBackendDispatchers.h>
</span><span class="cx"> #include <JavaScriptCore/InspectorFrontendDispatchers.h>
</span><span class="cx"> #include <wtf/HashMap.h>
</span><span class="lines">@@ -63,6 +64,7 @@
</span><span class="cx"> class InspectorHistory;
</span><span class="cx"> class InspectorOverlay;
</span><span class="cx"> class InspectorPageAgent;
</span><ins>+class HTMLMediaElement;
</ins><span class="cx"> class HitTestResult;
</span><span class="cx"> class Node;
</span><span class="cx"> class PseudoElement;
</span><span class="lines">@@ -223,6 +225,8 @@
</span><span class="cx">     int idForEventListener(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    void mediaMetricsTimerFired();
+
</ins><span class="cx">     void highlightMousedOverNode();
</span><span class="cx">     void setSearchingForNode(ErrorString&, bool enabled, const JSON::Object* highlightConfig);
</span><span class="cx">     std::unique_ptr<HighlightConfig> highlightConfigFromInspectorObject(ErrorString&, const JSON::Object* highlightInspectorObject);
</span><span class="lines">@@ -284,6 +288,22 @@
</span><span class="cx">     bool m_suppressAttributeModifiedEvent { false };
</span><span class="cx">     bool m_documentRequested { false };
</span><span class="cx"> 
</span><ins>+    Timer m_mediaMetricsTimer;
+    struct MediaMetrics {
+        unsigned displayCompositedFrames { 0 };
+        bool isLowPower { false };
+
+        MediaMetrics() { }
+
+        MediaMetrics(unsigned displayCompositedFrames)
+            : displayCompositedFrames(displayCompositedFrames)
+        {
+        }
+    };
+
+    // The pointer key for this map should not be used for anything other than matching.
+    HashMap<HTMLMediaElement*, MediaMetrics> m_mediaMetrics;
+
</ins><span class="cx">     struct InspectorEventListener {
</span><span class="cx">         int identifier { 1 };
</span><span class="cx">         RefPtr<EventTarget> eventTarget;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog    2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/ChangeLog       2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -1,5 +1,57 @@
</span><span class="cx"> 2018-10-31  Devin Rousso  <drousso@apple.com>
</span><span class="cx"> 
</span><ins>+        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.
+
+        * 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:
+
+2018-10-31  Devin Rousso  <drousso@apple.com>
+
</ins><span class="cx">         Web Inspector: Audit: save imported audits across WebInspector sessions
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=190858
</span><span class="cx">         <rdar://problem/45527625>
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js   2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js      2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -422,6 +422,7 @@
</span><span class="cx"> localizedStrings["Frames %d \u2013 %d"] = "Frames %d \u2013 %d";
</span><span class="cx"> localizedStrings["Full Garbage Collection"] = "Full Garbage Collection";
</span><span class="cx"> localizedStrings["Full URL"] = "Full URL";
</span><ins>+localizedStrings["Fullscreen"] = "Fullscreen";
</ins><span class="cx"> localizedStrings["Fullscreen from “%s“"] = "Fullscreen from “%s“";
</span><span class="cx"> localizedStrings["Function"] = "Function";
</span><span class="cx"> localizedStrings["Function Name Variable"] = "Function Name Variable";
</span><span class="lines">@@ -535,6 +536,7 @@
</span><span class="cx"> localizedStrings["Log: "] = "Log: ";
</span><span class="cx"> localizedStrings["Logs"] = "Logs";
</span><span class="cx"> localizedStrings["Low"] = "Low";
</span><ins>+localizedStrings["Low Power Mode"] = "Low Power Mode";
</ins><span class="cx"> localizedStrings["Lowest: %s"] = "Lowest: %s";
</span><span class="cx"> localizedStrings["MIME Type"] = "MIME Type";
</span><span class="cx"> localizedStrings["MIME Type:"] = "MIME Type:";
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersDOMManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js      2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js 2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -147,6 +147,17 @@
</span><span class="cx">         node.didFireEvent(eventName, timestamp, data);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    videoLowPowerChanged(nodeId, timestamp, isLowPower)
+    {
+        // Called from WI.DOMObserver.
+
+        let node = this._idToDOMNode[nodeId];
+        if (!node)
+            return;
+
+        node.videoLowPowerChanged(timestamp, isLowPower);
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _wrapClientCallback(callback)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsDOMNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js      2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js 2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -139,6 +139,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         this._domEvents = [];
</span><ins>+        this._lowPowerRanges = [];
</ins><span class="cx"> 
</span><span class="cx">         if (this._shouldListenForEventListeners())
</span><span class="cx">             WI.DOMNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleDOMNodeDidFireEvent, this);
</span><span class="lines">@@ -158,6 +159,7 @@
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get domEvents() { return this._domEvents; }
</span><ins>+    get lowPowerRanges() { return this._lowPowerRanges; }
</ins><span class="cx"> 
</span><span class="cx">     get frameIdentifier()
</span><span class="cx">     {
</span><span class="lines">@@ -726,6 +728,34 @@
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    videoLowPowerChanged(timestamp, isLowPower)
+    {
+        // Called from WI.DOMManager.
+
+        console.assert(this.canEnterLowPowerMode());
+
+        let lastValue = this._lowPowerRanges.lastValue;
+
+        if (isLowPower) {
+            console.assert(!lastValue || lastValue.endTimestamp);
+            if (!lastValue || lastValue.endTimestamp)
+                this._lowPowerRanges.push({startTimestamp: timestamp});
+        } else {
+            console.assert(!lastValue || lastValue.startTimestamp);
+            if (!lastValue)
+                this._lowPowerRanges.push({endTimestamp: timestamp});
+            else if (lastValue.startTimestamp)
+                lastValue.endTimestamp = timestamp;
+        }
+
+        this.dispatchEventToListeners(WI.DOMNode.Event.LowPowerChanged, {isLowPower, timestamp});
+    }
+
+    canEnterLowPowerMode()
+    {
+        return this.localName() === "video" || this.nodeName().toLowerCase() === "video";
+    }
+
</ins><span class="cx">     _handleDOMNodeDidFireEvent(event)
</span><span class="cx">     {
</span><span class="cx">         if (event.target === this || !event.target.isAncestor(this))
</span><span class="lines">@@ -898,6 +928,7 @@
</span><span class="cx">     AttributeRemoved: "dom-node-attribute-removed",
</span><span class="cx">     EventListenersChanged: "dom-node-event-listeners-changed",
</span><span class="cx">     DidFireEvent: "dom-node-did-fire-event",
</span><ins>+    LowPowerChanged: "dom-node-video-low-power-changed",
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WI.DOMNode.PseudoElementType = {
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceProtocolDOMObserverjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js        2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js   2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -116,4 +116,9 @@
</span><span class="cx">     {
</span><span class="cx">         WI.domManager.didFireEvent(nodeId, eventName, timestamp, data);
</span><span class="cx">     }
</span><ins>+
+    videoLowPowerChanged(nodeId, timestamp, isLowPower)
+    {
+        WI.domManager.videoLowPowerChanged(nodeId, timestamp, isLowPower);
+    }
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDOMEventsBreakdownViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css       2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css  2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -69,12 +69,19 @@
</span><span class="cx">     border-radius: 50%;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.dom-events-breakdown .graph > .area.fullscreen {
</del><ins>+.dom-events-breakdown .graph > .area {
</ins><span class="cx">     top: 0;
</span><span class="cx">     height: 100%;
</span><del>-    background-color: var(--panel-background-color);
</del><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.dom-events-breakdown .graph > .area.fullscreen {
+    background-color: hsla(0, 0%, 75%, 0.25);
+}
+
+.dom-events-breakdown .graph > .area.low-power {
+    background-color: hsla(83, 100%, 48%, 0.4);
+}
+
</ins><span class="cx"> .dom-events-breakdown .time {
</span><span class="cx">     text-align: end;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDOMEventsBreakdownViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js        2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js   2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -25,11 +25,25 @@
</span><span class="cx"> 
</span><span class="cx"> WI.DOMEventsBreakdownView = class DOMEventsBreakdownView extends WI.View
</span><span class="cx"> {
</span><del>-    constructor(domEvents, {includeGraph, startTimestamp} = {})
</del><ins>+    constructor(domNodeOrEvents, {includeGraph, startTimestamp} = {})
</ins><span class="cx">     {
</span><ins>+        console.assert(domNodeOrEvents instanceof WI.DOMNode || Array.isArray(domNodeOrEvents));
+
</ins><span class="cx">         super();
</span><span class="cx"> 
</span><del>-        this._domEvents = domEvents;
</del><ins>+        if (domNodeOrEvents instanceof WI.DOMNode) {
+            this._domNode = domNodeOrEvents;
+            this._domNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleDOMNodeDidFireEvent, this);
+            if (this._domNode.canEnterLowPowerMode())
+                this._domNode.addEventListener(WI.DOMNode.Event.LowPowerChanged, this._handleDOMNodeLowPowerChanged, this);
+
+            this._domEvents = null;
+        } else {
+            this._domNode = null;
+            this._domEvents = domNodeOrEvents;
+            this._lowPowerRanges = [];
+        }
+
</ins><span class="cx">         this._includeGraph = includeGraph || false;
</span><span class="cx">         this._startTimestamp = startTimestamp || 0;
</span><span class="cx"> 
</span><span class="lines">@@ -38,15 +52,6 @@
</span><span class="cx">         this.element.classList.add("dom-events-breakdown");
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Public
-
-    addEvent(domEvent)
-    {
-        this._domEvents.push(domEvent);
-
-        this.soon._populateTable();
-    }
-
</del><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     initialLayout()
</span><span class="lines">@@ -74,18 +79,19 @@
</span><span class="cx">         originatorHeadCell.textContent = WI.UIString("Originator");
</span><span class="cx"> 
</span><span class="cx">         this._tableBodyElement = tableElement.appendChild(document.createElement("tbody"));
</span><del>-
-        this._populateTable();
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Private
</del><ins>+    layout()
+    {
+        if (this.layoutReason !== WI.View.LayoutReason.Dirty)
+            return;
</ins><span class="cx"> 
</span><del>-    _populateTable()
-    {
</del><span class="cx">         this._tableBodyElement.removeChildren();
</span><span class="cx"> 
</span><del>-        let startTimestamp = this._domEvents[0].timestamp;
-        let endTimestamp = this._domEvents.lastValue.timestamp;
</del><ins>+        console.assert(this._domEvents || (this._domNode && this._domNode.domEvents));
+        let domEvents = this._domEvents || this._domNode.domEvents;
+        let startTimestamp = domEvents[0].timestamp;
+        let endTimestamp = domEvents.lastValue.timestamp;
</ins><span class="cx">         let totalTime = endTimestamp - startTimestamp;
</span><span class="cx">         let styleAttribute = WI.resolvedLayoutDirection() === WI.LayoutDirection.LTR ? "left" : "right";
</span><span class="cx"> 
</span><span class="lines">@@ -94,7 +100,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         let fullscreenRanges = [];
</span><del>-        let fullscreenDOMEvents = WI.DOMNode.getFullscreenDOMEvents(this._domEvents);
</del><ins>+        let fullscreenDOMEvents = WI.DOMNode.getFullscreenDOMEvents(domEvents);
</ins><span class="cx">         for (let fullscreenDOMEvent of fullscreenDOMEvents) {
</span><span class="cx">             let {enabled} = fullscreenDOMEvent.data;
</span><span class="cx">             if (enabled || !fullscreenRanges.length) {
</span><span class="lines">@@ -103,9 +109,13 @@
</span><span class="cx">                 });
</span><span class="cx">             }
</span><span class="cx">             fullscreenRanges.lastValue.endTimestamp = (enabled && fullscreenDOMEvent === fullscreenDOMEvents.lastValue) ? endTimestamp : fullscreenDOMEvent.timestamp;
</span><ins>+            if (fullscreenDOMEvent.originator)
+                fullscreenRanges.lastValue.originator = fullscreenDOMEvent.originator;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        for (let domEvent of this._domEvents) {
</del><ins>+        let lowPowerRanges = this._domNode ? this._domNode.lowPowerRanges : [];
+
+        for (let domEvent of domEvents) {
</ins><span class="cx">             let rowElement = this._tableBodyElement.appendChild(document.createElement("tr"));
</span><span class="cx"> 
</span><span class="cx">             let nameCell = rowElement.appendChild(document.createElement("td"));
</span><span class="lines">@@ -122,8 +132,22 @@
</span><span class="cx">                     fullscreenArea.classList.add("area", "fullscreen");
</span><span class="cx">                     fullscreenArea.style.setProperty(styleAttribute, percentOfTotalTime(fullscreenRange.startTimestamp - startTimestamp) + "%");
</span><span class="cx">                     fullscreenArea.style.setProperty("width", percentOfTotalTime(fullscreenRange.endTimestamp - fullscreenRange.startTimestamp) + "%");
</span><ins>+
+                    if (fullscreenRange.originator)
+                        fullscreenArea.title = WI.UIString("Fullscreen from “%s“").format(fullscreenRange.originator.displayName);
+                    else
+                        fullscreenArea.title = WI.UIString("Fullscreen");
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><ins>+                let lowPowerRange = lowPowerRanges.find((range) => domEvent.timestamp >= range.startTimestamp && domEvent.timestamp <= range.endTimestamp);
+                if (lowPowerRange) {
+                    let lowPowerArea = graphCell.appendChild(document.createElement("div"));
+                    lowPowerArea.classList.add("area", "low-power");
+                    lowPowerArea.title = WI.UIString("Low Power Mode");
+                    lowPowerArea.style.setProperty(styleAttribute, percentOfTotalTime(lowPowerRange.startTimestamp - startTimestamp) + "%");
+                    lowPowerArea.style.setProperty("width", percentOfTotalTime(lowPowerRange.endTimestamp - lowPowerRange.startTimestamp) + "%");
+                }
+
</ins><span class="cx">                 let graphPoint = graphCell.appendChild(document.createElement("div"));
</span><span class="cx">                 graphPoint.classList.add("point");
</span><span class="cx">                 graphPoint.style.setProperty(styleAttribute, `calc(${percentOfTotalTime(domEvent.timestamp - startTimestamp)}% - (var(--point-size) / 2))`);
</span><span class="lines">@@ -145,4 +169,16 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
+    // Private
+
+    _handleDOMNodeDidFireEvent(event)
+    {
+        this.needsLayout();
+    }
+
+    _handleDOMNodeLowPowerChanged(event)
+    {
+        this.needsLayout();
+    }
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDOMNodeEventsContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeEventsContentView.js (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeEventsContentView.js      2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeEventsContentView.js 2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -46,29 +46,10 @@
</span><span class="cx">     {
</span><span class="cx">         super.initialLayout();
</span><span class="cx"> 
</span><del>-        this._breakdownView = new WI.DOMEventsBreakdownView(this._domNode.domEvents.slice(), {
</del><ins>+        this._breakdownView = new WI.DOMEventsBreakdownView(this._domNode, {
</ins><span class="cx">             includeGraph: true,
</span><span class="cx">             startTimestamp: this._startTimestamp,
</span><span class="cx">         });
</span><span class="cx">         this.addSubview(this._breakdownView);
</span><del>-
-        this._domNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleDOMNodeDidFireEvent, this);
</del><span class="cx">     }
</span><del>-
-    closed()
-    {
-        this._domNode.removeEventListener(null, null, this);
-
-        super.closed();
-    }
-
-    // Private
-
-    _handleDOMNodeDidFireEvent(event)
-    {
-        let {domEvent} = event.data;
-
-        if (this._breakdownView)
-            this._breakdownView.addEvent(domEvent);
-    }
</del><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkTableContentViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css      2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css 2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -175,6 +175,23 @@
</span><span class="cx">     border-top-style: solid;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.network-table :not(.header) .cell.waterfall .waterfall-container > .area {
+    position: absolute;
+    top: var(--area-padding);
+    height: calc(100% - (var(--area-padding) * 2));
+
+    /* Half of the vertical space above any .dom-event node */
+    --area-padding: calc((50% - (var(--node-waterfall-dom-event-size) / 2)) / 2);
+}
+
+.network-table :not(.header) .cell.waterfall .waterfall-container > .area.dom-fullscreen {
+    background-color: hsla(0, 0%, 75%, 0.75);
+}
+
+.network-table :not(.header) .cell.waterfall .waterfall-container > .area.low-power {
+    background-color: var(--network-request-color);
+}
+
</ins><span class="cx"> .network-table .timeline-ruler {
</span><span class="cx">     position: absolute;
</span><span class="cx">     top: 0;
</span><span class="lines">@@ -182,16 +199,6 @@
</span><span class="cx">     overflow: hidden;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-fullscreen {
-    position: absolute;
-    top: var(--dom-fullscreen-vertical-padding);
-    height: calc(100% - (var(--dom-fullscreen-vertical-padding) * 2));
-    background-color: lightgrey;
-
-    /* Half of the vertical space above any .dom-event node */
-    --dom-fullscreen-vertical-padding: calc((50% - (var(--node-waterfall-dom-event-size) / 2)) / 2);
-}
-
</del><span class="cx"> .network-table .timeline-ruler > .header {
</span><span class="cx">     top: calc(var(--navigation-bar-height) - var(--timeline-ruler-height));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkTableContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js (237668 => 237669)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js       2018-11-01 04:08:19 UTC (rev 237668)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js  2018-11-01 04:12:59 UTC (rev 237669)
</span><span class="lines">@@ -542,7 +542,7 @@
</span><span class="cx">                 lockIconElement.className = "lock";
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            cell.append(domain);
</del><ins>+            cell.append(domain || emDash);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         let uniqueSchemeValues = this._uniqueValuesForDOMNodeEntry(entry, (resourceEntry) => resourceEntry.scheme);
</span><span class="lines">@@ -558,11 +558,6 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!entry.domain) {
-            cell.textContent = emDash;
-            return;
-        }
-
</del><span class="cx">         createIconAndText(entry.scheme, entry.domain);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -686,7 +681,7 @@
</span><span class="cx"> 
</span><span class="cx">                 for (let i = 0; i < fullscreenDOMEvents.length; i += 2) {
</span><span class="cx">                     let fullscreenElement = container.appendChild(document.createElement("div"));
</span><del>-                    fullscreenElement.classList.add("dom-fullscreen");
</del><ins>+                    fullscreenElement.classList.add("area", "dom-fullscreen");
</ins><span class="cx">                     positionByStartOffset(fullscreenElement, fullscreenDOMEvents[i].timestamp);
</span><span class="cx">                     setWidthForDuration(fullscreenElement, fullscreenDOMEvents[i].timestamp, fullscreenDOMEvents[i + 1].timestamp);
</span><span class="cx"> 
</span><span class="lines">@@ -693,9 +688,22 @@
</span><span class="cx">                     let originator = fullscreenDOMEvents[i].originator || fullscreenDOMEvents[i + 1].originator;
</span><span class="cx">                     if (originator)
</span><span class="cx">                         fullscreenElement.title = WI.UIString("Fullscreen from “%s“").format(originator.displayName);
</span><ins>+                    else
+                        fullscreenElement.title = WI.UIString("Fullscreen");
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            for (let lowPowerRange of domNode.lowPowerRanges) {
+                let startTimestamp = lowPowerRange.startTimestamp || graphStartTime;
+                let endTimestamp = lowPowerRange.endTimestamp || this._waterfallEndTime;
+
+                let lowPowerElement = container.appendChild(document.createElement("div"));
+                lowPowerElement.classList.add("area", "low-power");
+                lowPowerElement.title = WI.UIString("Low Power Mode");
+                positionByStartOffset(lowPowerElement, startTimestamp);
+                setWidthForDuration(lowPowerElement, startTimestamp, endTimestamp);
+            }
+
</ins><span class="cx">             let playing = false;
</span><span class="cx"> 
</span><span class="cx">             function createDOMEventLine(domEvents, startTimestamp, endTimestamp) {
</span><span class="lines">@@ -1558,6 +1566,8 @@
</span><span class="cx">             this._domNodeEntries.set(resource.initiatorNode, nodeEntry);
</span><span class="cx"> 
</span><span class="cx">             resource.initiatorNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleNodeDidFireEvent, this);
</span><ins>+            if (resource.initiatorNode.canEnterLowPowerMode())
+                resource.initiatorNode.addEventListener(WI.DOMNode.Event.LowPowerChanged, this._handleNodeLowPowerChanged, this);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!this._entriesSortComparator)
</span><span class="lines">@@ -1593,6 +1603,19 @@
</span><span class="cx">         this.needsLayout();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _handleNodeLowPowerChanged(event)
+    {
+        let domNode = event.target;
+        let {timestamp} = event.data;
+
+        this._pendingUpdates.push(domNode);
+
+        if (timestamp > this._waterfallEndTime)
+            this._waterfallEndTime = timestamp + (this._waterfallTimelineRuler.secondsPerPixel * 10);
+
+        this.needsLayout();
+    }
+
</ins><span class="cx">     _hasTypeFilter()
</span><span class="cx">     {
</span><span class="cx">         return !!this._activeTypeFilters;
</span></span></pre>
</div>
</div>

</body>
</html>