LayoutTests/ChangeLog

 12018-09-21 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: group media network entries by the node that triggered the request
 4 https://bugs.webkit.org/show_bug.cgi?id=189606
 5 <rdar://problem/44438527>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * http/tests/inspector/network/resource-initiatorNode-expected.txt: Added.
 10 * http/tests/inspector/network/resource-initiatorNode.html: Added.
 11
 12 * http/tests/inspector/network/har/har-basic.html:
 13 * inspector/unit-tests/resource-collection.html:
 14 Update for changes to `WI.Resource`.
 15
 16 * inspector/canvas/requestNode.html:
 17 Test case no longer needed since the document is always requested once it's available.
 18
1192018-09-21 Ryan Haddad <ryanhaddad@apple.com>
220
321 [macOS EWS] Layout test accessibility/smart-invert-reference.html is a flaky failure

LayoutTests/http/tests/inspector/network/har/har-basic.html

@@function test()
3434 const url = "https://example.com/fake.js";
3535 const mimeType = "text/javascript";
3636 const type = WI.Resource.Type.Script;
37  const loaderIdentifier = undefined;
38  const targetId = undefined;
39  const requestIdentifier = undefined;
4037 const requestMethod = "GET";
4138 const requestHeaders = {"Test-Request-Header": "Test Request Header Value"};
4239 const responseHeaders = {"Test-Response-Header": "Test Response Header Value"};
4340 const statusCode = 200;
4441 const statusText = "OK";
4542 const source = "network";
46  const requestData = null;
4743 const requestSentWalltime = 1508723752694 / 1000; // Sun Oct 22 2017 18:55:52 GMT-0700, when this test was written.
48  const initiatorSourceCodeLocation = null;
49  const timestamp = undefined;
5044 const size = 1234;
5145 const timingData = {
5246 startTime: 1,

@@function test()
7266 requestHeaders,
7367 };
7468
75  let bareResource = new WI.Resource(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, timestamp, requestSentWalltime, initiatorSourceCodeLocation, timestamp);
76  bareResource.markAsFinished(undefined);
 69 let bareResource = new WI.Resource(url, {mimeType, type, requestMethod, requestHeaders, requestSentWalltime});
 70 bareResource.markAsFinished();
7771
78  let fullResource = new WI.Resource(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, timestamp, requestSentWalltime, initiatorSourceCodeLocation, timestamp);
 72 let fullResource = new WI.Resource(url, {mimeType, type, requestMethod, requestHeaders, requestSentWalltime});
 73
 74 const timestamp = null;
7975 fullResource.updateForResponse(url, mimeType, type, responseHeaders, statusCode, statusText, timestamp, timingData, source);
8076 fullResource.increaseSize(size);
8177 fullResource.updateWithMetrics(metrics);
82  fullResource.markAsFinished(1.7);
 78
 79 const elapsedTime = 1.7;
 80 fullResource.markAsFinished(elapsedTime);
8381
8482 let har = await WI.HARBuilder.buildArchive([bareResource, fullResource]);
8583 InspectorTest.json(har, HARJSONFilter);

LayoutTests/http/tests/inspector/network/resource-initiatorNode-expected.txt

 1Tests that Request initiatorNode is set correctly.
 2
 3
 4
 5== Running test suite: WI.Resource.initiatorNode
 6-- Running test case: WI.Resource.initiatorNode.posterPNG
 7PASS: Resource should have an initiatorNode
 8PASS: Resource initiatorNode should match video node id
 9
 10-- Running test case: WI.Resource.initiatorNode.sourceMP4
 11PASS: Resource should have an initiatorNode
 12PASS: Resource initiatorNode should match video node id
 13
 14-- Running test case: WI.Resource.initiatorNode.trackVTT
 15PASS: Resource should have an initiatorNode
 16PASS: Resource initiatorNode should match video node id
 17

LayoutTests/http/tests/inspector/network/resource-initiatorNode.html

 1<!doctype html>
 2<html>
 3<head>
 4<script src="../resources/inspector-test.js"></script>
 5<script>
 6
 7function replay() {
 8 let videoElement = document.getElementById("video");
 9 videoElement.pause();
 10 videoElement.currentTime = 0;
 11 videoElement.load();
 12}
 13
 14function loadPoster(url) {
 15 document.getElementById("video").poster = url;
 16
 17 replay();
 18}
 19
 20function loadSource(url, type) {
 21 let sourceElement = document.createElement("source");
 22 sourceElement.type = type;
 23 sourceElement.src = url;
 24
 25 document.getElementById("video").appendChild(sourceElement);
 26
 27 replay();
 28}
 29
 30function loadTrack(url, kind) {
 31 let trackElement = document.createElement("track");
 32 trackElement.kind = kind;
 33 trackElement.default = true;
 34 trackElement.src = url;
 35
 36 trackElement.track.mode = "hidden";
 37
 38 document.getElementById("video").appendChild(trackElement);
 39
 40 replay();
 41}
 42
 43function handleVideoEnded(event) {
 44 TestPage.dispatchEventToFrontend("TestPage-video-ended");
 45}
 46
 47function test()
 48{
 49 let suite = InspectorTest.createAsyncSuite("WI.Resource.initiatorNode");
 50
 51 let videoNode = null;
 52
 53 suite.addTestCase({
 54 name: "WI.Resource.initiatorNode.posterPNG",
 55 test(resolve, reject) {
 56 let file = "white.png";
 57
 58 WI.Frame.awaitEvent(WI.Frame.Event.ResourceWasAdded)
 59 .then((event) => {
 60 let resource = event.data.resource;
 61
 62 InspectorTest.assert(resource.url.endsWith(file), `Resource should be "${file}"`);
 63
 64 InspectorTest.expectNotNull(resource.initiatorNode, "Resource should have an initiatorNode");
 65 if (resource.initiatorNode)
 66 InspectorTest.expectEqual(resource.initiatorNode.id, videoNode.id, "Resource initiatorNode should match video node id");
 67 })
 68 .then(resolve, reject);
 69
 70 InspectorTest.evaluateInPage(`loadPoster("resources/${file}")`);
 71 }
 72 });
 73
 74 suite.addTestCase({
 75 name: "WI.Resource.initiatorNode.sourceMP4",
 76 test(resolve, reject) {
 77 let file = "white.mp4";
 78
 79 WI.Frame.awaitEvent(WI.Frame.Event.ResourceWasAdded)
 80 .then((event) => {
 81 let resource = event.data.resource;
 82
 83 InspectorTest.assert(resource.url.endsWith(file), `Resource should be "${file}"`);
 84
 85 InspectorTest.expectNotNull(resource.initiatorNode, "Resource should have an initiatorNode");
 86 if (resource.initiatorNode)
 87 InspectorTest.expectEqual(resource.initiatorNode.id, videoNode.id, "Resource initiatorNode should match video node id");
 88 })
 89 .then(resolve, reject);
 90
 91 InspectorTest.evaluateInPage(`loadSource("resources/${file}", "video/mp4")`);
 92 }
 93 });
 94
 95 suite.addTestCase({
 96 name: "WI.Resource.initiatorNode.trackVTT",
 97 test(resolve, reject) {
 98 let file = "white.vtt";
 99
 100 // Loading a track causes a bunch of media controls to be loaded.
 101 let listener = WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, (event) => {
 102 let resource = event.data.resource;
 103 if (!resource.url.endsWith(file))
 104 return;
 105
 106 InspectorTest.expectNotNull(resource.initiatorNode, "Resource should have an initiatorNode");
 107 if (resource.initiatorNode)
 108 InspectorTest.expectEqual(resource.initiatorNode.id, videoNode.id, "Resource initiatorNode should match video node id");
 109
 110 WI.Frame.removeEventListener(WI.Frame.Event.ResourceWasAdded, listener);
 111
 112 resolve();
 113 });
 114
 115 InspectorTest.evaluateInPage(`loadTrack("resources/${file}", "captions")`);
 116 }
 117 });
 118
 119 WI.domTreeManager.requestDocument((documentNode) => {
 120 WI.domTreeManager.querySelector(documentNode.id, "video#video", (videoNodeId) => {
 121 videoNode = WI.domTreeManager.nodeForId(videoNodeId);
 122 if (videoNode)
 123 suite.runTestCasesAndFinish();
 124 else {
 125 InspectorTest.fail(`DOM node for "video#video" not found.`);
 126 InspectorTest.completeTest();
 127 }
 128 });
 129 });
 130}
 131</script>
 132</head>
 133<body onload="runTest()">
 134 <p>Tests that Request initiatorNode is set correctly.</p>
 135 <video id="video" muted autoplay></video>
 136</body>
 137</html>

LayoutTests/http/tests/inspector/network/resources/white.mp4

Binary file, nothing to see here

LayoutTests/http/tests/inspector/network/resources/white.png


Added


LayoutTests/http/tests/inspector/network/resources/white.vtt

 1WEBVTT
 2
 300:00:00.000 --> 00:00:00.999
 40.000 to 0.999
 5
 600:00:01.000 --> 00:00:01.999
 71.000 to 1.999

LayoutTests/inspector/canvas/requestNode-expected.txt

@@Test that CanvasAgent.requestNode can properly resolve the owner canvas node.
22
33
44== Running test suite: Canvas.requestNode
5 -- Running test case: Canvas.requestNode.missingDocument
6 PASS: The page should have three canvases.
7 PASS: Should produce an error.
8 Error: Document has not been requested
9 
105-- Running test case: Canvas.requestNode.validCanvasId
116PASS: Canvas "CSS canvas “css”" has node with valid id.
127PASS: Canvas "CSS canvas “css”" has node with type "CANVAS".

LayoutTests/inspector/canvas/requestNode.html

@@function load() {
1414function test() {
1515 let suite = InspectorTest.createAsyncSuite("Canvas.requestNode");
1616
17  suite.addTestCase({
18  name: "Canvas.requestNode.missingDocument",
19  description: "Getting the canvas node requires that WebInspector knows about the document.",
20  test(resolve, reject) {
21  let canvases = WI.canvasManager.canvases;
22  InspectorTest.expectEqual(canvases.length, 3, "The page should have three canvases.");
23  if (!canvases.length) {
24  reject("Missing canvas.");
25  return;
26  }
27 
28  CanvasAgent.requestNode(canvases[0].identifier, (error) => {
29  InspectorTest.expectThat(error, "Should produce an error.");
30  InspectorTest.log("Error: " + error);
31  resolve();
32  });
33  }
34  });
35 
3617 suite.addTestCase({
3718 name: "Canvas.requestNode.validCanvasId",
3819 description: "Get the node id for each canvas on the page.",

LayoutTests/inspector/unit-tests/resource-collection.html

@@function test()
88 let suite = InspectorTest.createAsyncSuite("ResourceCollection");
99
1010 function createResource(url, type) {
11  return new WI.Resource(url, null, type);
 11 return new WI.Resource(url, {type});
1212 }
1313
1414 function logResourceNames(collection) {

Source/JavaScriptCore/ChangeLog

 12018-09-21 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: group media network entries by the node that triggered the request
 4 https://bugs.webkit.org/show_bug.cgi?id=189606
 5 <rdar://problem/44438527>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * inspector/protocol/Network.json:
 10 Add an optional `nodeId` field to the `Initiator` object that is set it is possible to
 11 determine which ancestor node triggered the load. It may not correspond directly to the node
 12 with the href/src, as that url may only be used by an ancestor for loading.
 13
1142018-09-21 Keith Miller <keith_miller@apple.com>
215
316 Add Promise SPI

Source/JavaScriptCore/inspector/protocol/Network.json

142142 { "name": "type", "type": "string", "enum": ["parser", "script", "other"], "description": "Type of this initiator." },
143143 { "name": "stackTrace", "type": "array", "items": { "$ref": "Console.CallFrame" }, "optional": true, "description": "Initiator JavaScript stack trace, set for Script only." },
144144 { "name": "url", "type": "string", "optional": true, "description": "Initiator URL, set for Parser type only." },
145  { "name": "lineNumber", "type": "number", "optional": true, "description": "Initiator line number, set for Parser type only." }
 145 { "name": "lineNumber", "type": "number", "optional": true, "description": "Initiator line number, set for Parser type only." },
 146 { "name": "nodeId", "$ref": "DOM.NodeId", "optional": true, "description": "Set if the load was triggered by a DOM node, in addition to the other initiator information." }
146147 ]
147148 }
148149 ],

Source/WebCore/ChangeLog

 12018-09-21 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: group media network entries by the node that triggered the request
 4 https://bugs.webkit.org/show_bug.cgi?id=189606
 5 <rdar://problem/44438527>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Test: http/tests/inspector/network/resource-initiatorNode.html
 10
 11 Add extra arguments to functions that create `ResourceRequest` objets for media resources so
 12 that `initiatorNodeIdentifier` can be set for WebInspector frontend to use for grouping.
 13
 14 * html/HTMLMediaElement.cpp:
 15 (WebCore::HTMLMediaElement::loadResource):
 16 * html/HTMLVideoElement.cpp:
 17 (WebCore::HTMLVideoElement::setDisplayMode):
 18 * loader/FrameLoader.h:
 19 * loader/FrameLoader.cpp:
 20 (WebCore::FrameLoader::willLoadMediaElementURL):
 21 Handles initial (e.g. DNT) resource requests.
 22
 23 * loader/ImageLoader.cpp:
 24 (ImageLoader::updateFromElement):
 25 Handles "poster" requests.
 26
 27 * loader/MediaResourceLoader.cpp:
 28 (MediaResourceLoader::requestResource):
 29 Handles byte-range requests.
 30
 31 * html/track/LoadableTextTrack.cpp:
 32 (WebCore::LoadableTextTrack::loadTimerFired):
 33 * loader/TextTrackLoader.h:
 34 * loader/TextTrackLoader.cpp:
 35 (WebCore::TextTrackLoader::load):
 36 * html/HTMLTrackElement.h:
 37 Handles <track> (e.g. subtitle) requests.
 38
 39 * inspector/agents/InspectorDOMAgent.cpp:
 40 (WebCore::InspectorDOMAgent::identifierForNode):
 41 * inspector/InspectorInstrumentation.h:
 42 (WebCore::InspectorInstrumentation::identifierForNode):
 43 * inspector/InspectorInstrumentation.cpp:
 44 (WebCore::InspectorInstrumentation::identifierForNodeImpl):
 45 Allows callers to get a `DOM.nodeId` for the given `Node`, which is (in this patch) attached
 46 to the `ResourceRequest` and later used by `InspectorNetworkAgent`.
 47
 48 * inspector/agents/InspectorNetworkAgent.h:
 49 * inspector/agents/InspectorNetworkAgent.cpp:
 50 (WebCore::InspectorNetworkAgent::willSendRequest):
 51 (WebCore::InspectorNetworkAgent::didLoadResourceFromMemoryCache):
 52 (WebCore::InspectorNetworkAgent::buildInitiatorObject):
 53
 54 * platform/network/ResourceRequestBase.h:
 55 (WebCore::ResourceRequestBase::initiatorNodeIdentifier const):
 56 (WebCore::ResourceRequestBase::setInitiatorNodeIdentifier):
 57 * platform/network/ResourceRequestBase.cpp:
 58 (WebCore::ResourceRequestBase::setAsIsolatedCopy):
 59 * platform/network/cf/ResourceRequestCFNet.cpp:
 60 (WebCore::ResourceRequest::updateFromDelegatePreservingOldProperties):
 61 * loader/cache/CachedResourceLoader.cpp:
 62 (WebCore::CachedResourceLoader::shouldContinueAfterNotifyingLoadedFromMemoryCache):
 63
 64 * inspector/InspectorCanvas.h:
 65 * inspector/InspectorCanvas.cpp:
 66 (WebCore::InspectorCanvas::buildObjectForCanvas):
 67 * inspector/agents/InspectorCanvasAgent.cpp:
 68 (WebCore::InspectorCanvasAgent::enable):
 69 (WebCore::InspectorCanvasAgent::didCreateCanvasRenderingContext):
 70 Don't try to push the canvas' node to the frontend, as this will create a dangling node in
 71 `InspectorDOMAgent` if the canvas' node is detached from the DOM.
 72
1732018-09-21 Ryosuke Niwa <rniwa@webkit.org>
274
375 Custom elements in a reaction queue can lose its JS wrapper and become HTMLUnknownElement

Source/WebCore/html/HTMLMediaElement.cpp

@@void HTMLMediaElement::loadResource(const URL& initialURL, ContentType& contentT
15911591 }
15921592
15931593 URL url = initialURL;
1594  if (!url.isEmpty() && !frame->loader().willLoadMediaElementURL(url)) {
 1594 if (!url.isEmpty() && !frame->loader().willLoadMediaElementURL(url, *this)) {
15951595 mediaLoadingFailed(MediaPlayer::FormatError);
15961596 return;
15971597 }

Source/WebCore/html/HTMLTrackElement.h

@@public:
5858 enum LoadStatus { Failure, Success };
5959 void didCompleteLoad(LoadStatus);
6060
 61 RefPtr<HTMLMediaElement> mediaElement() const;
6162 const AtomicString& mediaElementCrossOriginAttribute() const;
6263
6364private:

@@private:
7374
7475 void loadTimerFired();
7576
76  RefPtr<HTMLMediaElement> mediaElement() const;
77 
7877 // TextTrackClient
7978 void textTrackModeChanged(TextTrack&) final;
8079 void textTrackKindChanged(TextTrack&) final;

Source/WebCore/html/HTMLVideoElement.cpp

@@void HTMLVideoElement::setDisplayMode(DisplayMode mode)
263263 bool canLoad = true;
264264 if (!poster.isEmpty()) {
265265 if (RefPtr<Frame> frame = document().frame())
266  canLoad = frame->loader().willLoadMediaElementURL(poster);
 266 canLoad = frame->loader().willLoadMediaElementURL(poster, *this);
267267 }
268268 if (canLoad)
269269 player()->setPoster(poster);

Source/WebCore/html/track/LoadableTextTrack.cpp

@@void LoadableTextTrack::loadTimerFired()
8282 // mode being the state of the media element's crossorigin content attribute, the origin being the
8383 // origin of the media element's Document, and the default origin behaviour set to fail.
8484 m_loader = std::make_unique<TextTrackLoader>(static_cast<TextTrackLoaderClient&>(*this), static_cast<ScriptExecutionContext*>(&m_trackElement->document()));
85  if (!m_loader->load(m_url, m_trackElement->mediaElementCrossOriginAttribute(), m_trackElement->isInUserAgentShadowTree()))
 85 if (!m_loader->load(m_url, *m_trackElement))
8686 m_trackElement->didCompleteLoad(HTMLTrackElement::Failure);
8787}
8888

Source/WebCore/inspector/InspectorCanvas.cpp

4444#include "ImageBuffer.h"
4545#include "ImageData.h"
4646#include "InspectorDOMAgent.h"
47 #include "InstrumentingAgents.h"
4847#include "JSCanvasDirection.h"
4948#include "JSCanvasFillRule.h"
5049#include "JSCanvasLineCap.h"

@@bool InspectorCanvas::hasBufferSpace() const
217216 return m_bufferUsed < m_bufferLimit;
218217}
219218
220 Ref<Inspector::Protocol::Canvas::Canvas> InspectorCanvas::buildObjectForCanvas(InstrumentingAgents& instrumentingAgents, bool captureBacktrace)
 219Ref<Inspector::Protocol::Canvas::Canvas> InspectorCanvas::buildObjectForCanvas(bool captureBacktrace)
221220{
222221 Inspector::Protocol::Canvas::ContextType contextType;
223222 if (is<CanvasRenderingContext2D>(m_context))

@@Ref<Inspector::Protocol::Canvas::Canvas> InspectorCanvas::buildObjectForCanvas(I
250249 String cssCanvasName = node->document().nameForCSSCanvasElement(*node);
251250 if (!cssCanvasName.isEmpty())
252251 canvas->setCssCanvasName(cssCanvasName);
253  else {
254  InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent();
255  int nodeId = domAgent->boundNodeId(node);
256  if (!nodeId) {
257  if (int documentNodeId = domAgent->boundNodeId(&node->document())) {
258  ErrorString ignored;
259  nodeId = domAgent->pushNodeToFrontend(ignored, documentNodeId, node);
260  }
261  }
262 
263  if (nodeId)
264  canvas->setNodeId(nodeId);
265  }
266252 }
267253
268254 if (is<ImageBitmapRenderingContext>(m_context)) {

Source/WebCore/inspector/InspectorCanvas.h

@@class HTMLImageElement;
4242class HTMLVideoElement;
4343class ImageBitmap;
4444class ImageData;
45 class InstrumentingAgents;
4645
4746class InspectorCanvas final : public RefCounted<InspectorCanvas> {
4847public:

@@public:
7574 bool singleFrame() const { return m_singleFrame; }
7675 void setSingleFrame(bool singleFrame) { m_singleFrame = singleFrame; }
7776
78  Ref<Inspector::Protocol::Canvas::Canvas> buildObjectForCanvas(InstrumentingAgents&, bool captureBacktrace);
 77 Ref<Inspector::Protocol::Canvas::Canvas> buildObjectForCanvas(bool captureBacktrace);
7978
8079private:
8180 InspectorCanvas(CanvasRenderingContext&);

Source/WebCore/inspector/InspectorInstrumentation.cpp

@@bool InspectorInstrumentation::isDebuggerPausedImpl(InstrumentingAgents& instrum
128128 return false;
129129}
130130
 131int InspectorInstrumentation::identifierForNodeImpl(InstrumentingAgents& instrumentingAgents, Node& node)
 132{
 133 if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent())
 134 return domAgent->identifierForNode(node);
 135 return 0;
 136}
 137
131138void InspectorInstrumentation::willInsertDOMNodeImpl(InstrumentingAgents& instrumentingAgents, Node& parent)
132139{
133140 if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())

Source/WebCore/inspector/InspectorInstrumentation.h

@@public:
106106 static void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&);
107107 static bool isDebuggerPaused(Frame*);
108108
 109 static int identifierForNode(Node&);
109110 static void willInsertDOMNode(Document&, Node& parent);
110111 static void didInsertDOMNode(Document&, Node&);
111112 static void willRemoveDOMNode(Document&, Node&);

@@private:
290291 static void didClearWindowObjectInWorldImpl(InstrumentingAgents&, Frame&, DOMWrapperWorld&);
291292 static bool isDebuggerPausedImpl(InstrumentingAgents&);
292293
 294 static int identifierForNodeImpl(InstrumentingAgents&, Node&);
293295 static void willInsertDOMNodeImpl(InstrumentingAgents&, Node& parent);
294296 static void didInsertDOMNodeImpl(InstrumentingAgents&, Node&);
295297 static void willRemoveDOMNodeImpl(InstrumentingAgents&, Node&);

@@inline bool InspectorInstrumentation::isDebuggerPaused(Frame* frame)
470472 return false;
471473}
472474
 475inline int InspectorInstrumentation::identifierForNode(Node& node)
 476{
 477 FAST_RETURN_IF_NO_FRONTENDS(0);
 478 if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(node.document()))
 479 return identifierForNodeImpl(*instrumentingAgents, node);
 480 return 0;
 481}
 482
473483inline void InspectorInstrumentation::willInsertDOMNode(Document& document, Node& parent)
474484{
475485 FAST_RETURN_IF_NO_FRONTENDS(void());

Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp

@@void InspectorCanvasAgent::enable(ErrorString&)
9999
100100 const bool captureBacktrace = false;
101101 for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
102  m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(m_instrumentingAgents, captureBacktrace));
 102 m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(captureBacktrace));
103103
104104#if ENABLE(WEBGL)
105105 if (is<WebGLRenderingContextBase>(inspectorCanvas->context())) {

@@void InspectorCanvasAgent::didCreateCanvasRenderingContext(CanvasRenderingContex
431431
432432 if (m_enabled) {
433433 const bool captureBacktrace = true;
434  m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(m_instrumentingAgents, captureBacktrace));
 434 m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(captureBacktrace));
435435 }
436436
437437 m_identifierToInspectorCanvas.set(inspectorCanvas->identifier(), WTFMove(inspectorCanvas));

Source/WebCore/inspector/agents/InspectorDOMAgent.cpp

@@void InspectorDOMAgent::didCommitLoad(Document* document)
20852085 m_frontendDispatcher->childNodeInserted(parentId, prevId, WTFMove(value));
20862086}
20872087
 2088int InspectorDOMAgent::identifierForNode(Node& node)
 2089{
 2090 return pushNodePathToFrontend(&node);
 2091}
 2092
20882093void InspectorDOMAgent::didInsertDOMNode(Node& node)
20892094{
20902095 if (containsOnlyHTMLWhitespace(&node))

Source/WebCore/inspector/agents/InspectorDOMAgent.h

@@public:
157157
158158
159159 // InspectorInstrumentation
 160 int identifierForNode(Node&);
160161 void didInsertDOMNode(Node&);
161162 void didRemoveDOMNode(Node&);
162163 void willModifyDOMAttr(Element&, const AtomicString& oldValue, const AtomicString& newValue);

Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp

4545#include "FrameLoader.h"
4646#include "HTTPHeaderMap.h"
4747#include "HTTPHeaderNames.h"
 48#include "InspectorDOMAgent.h"
4849#include "InspectorTimelineAgent.h"
4950#include "InstrumentingAgents.h"
5051#include "JSExecState.h"

@@void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLo
386387 auto protocolResourceType = InspectorPageAgent::resourceTypeJSON(type);
387388
388389 Document* document = loader && loader->frame() ? loader->frame()->document() : nullptr;
389  auto initiatorObject = buildInitiatorObject(document);
 390 auto initiatorObject = buildInitiatorObject(document, request);
390391
391392 String url = loader ? loader->url().string() : request.url();
392393 m_frontendDispatcher->requestWillBeSent(requestId, frameId, loaderId, url, buildObjectForResourceRequest(request), sendTimestamp, walltime.secondsSinceEpoch().seconds(), initiatorObject, buildObjectForResourceResponse(redirectResponse, nullptr), type != InspectorPageAgent::OtherResource ? &protocolResourceType : nullptr, targetId.isEmpty() ? nullptr : &targetId);

@@void InspectorNetworkAgent::didLoadResourceFromMemoryCache(DocumentLoader* loade
566567
567568 m_resourcesData->resourceCreated(requestId, loaderId, resource);
568569
569  RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : nullptr);
 570 auto initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : nullptr, resource.resourceRequest());
570571
571572 // FIXME: It would be ideal to generate the Network.Response with the MemoryCache source
572573 // instead of whatever ResourceResponse::Source the CachedResources's response has.

@@void InspectorNetworkAgent::didScheduleStyleRecalculation(Document& document)
636637 m_styleRecalculationInitiator = buildInitiatorObject(&document);
637638}
638639
639 RefPtr<Inspector::Protocol::Network::Initiator> InspectorNetworkAgent::buildInitiatorObject(Document* document)
 640RefPtr<Inspector::Protocol::Network::Initiator> InspectorNetworkAgent::buildInitiatorObject(Document* document, std::optional<const ResourceRequest&> resourceRequest)
640641{
641642 // FIXME: Worker support.
642643 if (!isMainThread()) {

@@RefPtr<Inspector::Protocol::Network::Initiator> InspectorNetworkAgent::buildInit
645646 .release();
646647 }
647648
 649 RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject;
 650
648651 Ref<ScriptCallStack> stackTrace = createScriptCallStack(JSExecState::currentState());
649652 if (stackTrace->size() > 0) {
650  auto initiatorObject = Inspector::Protocol::Network::Initiator::create()
 653 initiatorObject = Inspector::Protocol::Network::Initiator::create()
651654 .setType(Inspector::Protocol::Network::Initiator::Type::Script)
652655 .release();
653656 initiatorObject->setStackTrace(stackTrace->buildInspectorArray());
654  return WTFMove(initiatorObject);
655  }
656 
657  if (document && document->scriptableDocumentParser()) {
658  auto initiatorObject = Inspector::Protocol::Network::Initiator::create()
 657 } else if (document && document->scriptableDocumentParser()) {
 658 initiatorObject = Inspector::Protocol::Network::Initiator::create()
659659 .setType(Inspector::Protocol::Network::Initiator::Type::Parser)
660660 .release();
661661 initiatorObject->setUrl(document->url().string());
662662 initiatorObject->setLineNumber(document->scriptableDocumentParser()->textPosition().m_line.oneBasedInt());
663  return WTFMove(initiatorObject);
664663 }
665664
 665 auto domAgent = m_instrumentingAgents.inspectorDOMAgent();
 666 if (domAgent && resourceRequest) {
 667 if (int initiatorNodeIdentifier = resourceRequest->initiatorNodeIdentifier()) {
 668 if (!initiatorObject) {
 669 initiatorObject = Inspector::Protocol::Network::Initiator::create()
 670 .setType(Inspector::Protocol::Network::Initiator::Type::Other)
 671 .release();
 672 }
 673
 674 initiatorObject->setNodeId(initiatorNodeIdentifier);
 675 }
 676 }
 677
 678 if (initiatorObject)
 679 return initiatorObject;
 680
666681 if (m_isRecalculatingStyle && m_styleRecalculationInitiator)
667682 return m_styleRecalculationInitiator;
668683

Source/WebCore/inspector/agents/InspectorNetworkAgent.h

@@private:
132132
133133 WebSocket* webSocketForRequestId(const String& requestId);
134134
135  RefPtr<Inspector::Protocol::Network::Initiator> buildInitiatorObject(Document*);
 135 RefPtr<Inspector::Protocol::Network::Initiator> buildInitiatorObject(Document*, std::optional<const ResourceRequest&> = std::nullopt);
136136 Ref<Inspector::Protocol::Network::ResourceTiming> buildObjectForTiming(const NetworkLoadMetrics&, ResourceLoader&);
137137 Ref<Inspector::Protocol::Network::Metrics> buildObjectForMetrics(const NetworkLoadMetrics&);
138138 RefPtr<Inspector::Protocol::Network::Response> buildObjectForResourceResponse(const ResourceResponse&, ResourceLoader*);

Source/WebCore/loader/FrameLoader.cpp

8888#include "MemoryRelease.h"
8989#include "NavigationDisabler.h"
9090#include "NavigationScheduler.h"
 91#include "Node.h"
9192#include "Page.h"
9293#include "PageCache.h"
9394#include "PageTransitionEvent.h"

@@const ResourceRequest& FrameLoader::initialRequest() const
16521653 return activeDocumentLoader()->originalRequest();
16531654}
16541655
1655 bool FrameLoader::willLoadMediaElementURL(URL& url)
 1656bool FrameLoader::willLoadMediaElementURL(URL& url, Node& initiatorNode)
16561657{
16571658#if PLATFORM(IOS)
16581659 // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource

@@bool FrameLoader::willLoadMediaElementURL(URL& url)
16621663#endif
16631664
16641665 ResourceRequest request(url);
 1666 request.setInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(initiatorNode));
16651667
16661668 unsigned long identifier;
16671669 ResourceError error;

Source/WebCore/loader/FrameLoader.h

@@class HistoryController;
7272class HistoryItem;
7373class NavigationAction;
7474class NetworkingContext;
 75class Node;
7576class Page;
7677class PolicyChecker;
7778class ResourceError;

@@public:
177178 const ResourceRequest& initialRequest() const;
178179 void receivedMainResourceError(const ResourceError&);
179180
180  bool willLoadMediaElementURL(URL&);
 181 bool willLoadMediaElementURL(URL&, Node&);
181182
182183 void handleFallbackContent();
183184

Source/WebCore/loader/ImageLoader.cpp

3737#include "HTMLNames.h"
3838#include "HTMLObjectElement.h"
3939#include "HTMLParserIdioms.h"
 40#include "InspectorInstrumentation.h"
4041#include "Page.h"
4142#include "RenderImage.h"
4243#include "RenderSVGImage.h"

@@void ImageLoader::updateFromElement()
179180 options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set;
180181
181182 auto crossOriginAttribute = element().attributeWithoutSynchronization(HTMLNames::crossoriginAttr);
182  auto request = createPotentialAccessControlRequest(document.completeURL(sourceURI(attr)), document, crossOriginAttribute, WTFMove(options));
 183
 184 ResourceRequest resourceRequest(document.completeURL(sourceURI(attr)));
 185 resourceRequest.setInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(m_element));
 186
 187 auto request = createPotentialAccessControlRequest(WTFMove(resourceRequest), document, crossOriginAttribute, WTFMove(options));
183188 request.setInitiator(element());
184189
185190 if (m_loadManually) {

Source/WebCore/loader/MediaResourceLoader.cpp

3535#include "CrossOriginAccessControl.h"
3636#include "Document.h"
3737#include "HTMLMediaElement.h"
 38#include "InspectorInstrumentation.h"
3839#include "SecurityOrigin.h"
3940#include <wtf/NeverDestroyed.h>
4041

@@RefPtr<PlatformMediaResource> MediaResourceLoader::requestResource(ResourceReque
6970 auto cachingPolicy = options & LoadOption::DisallowCaching ? CachingPolicy::DisallowCaching : CachingPolicy::AllowCaching;
7071
7172 request.setRequester(ResourceRequest::Requester::Media);
 73
 74 if (m_mediaElement)
 75 request.setInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(*m_mediaElement));
 76
7277#if HAVE(AVFOUNDATION_LOADER_DELEGATE) && PLATFORM(MAC)
7378 // FIXME: Workaround for <rdar://problem/26071607>. We are not able to do CORS checking on 304 responses because they are usually missing the headers we need.
7479 if (!m_crossOriginMode.isNull())

Source/WebCore/loader/TextTrackLoader.cpp

3535#include "CachedTextTrack.h"
3636#include "CrossOriginAccessControl.h"
3737#include "Document.h"
 38#include "HTMLTrackElement.h"
 39#include "InspectorInstrumentation.h"
3840#include "Logging.h"
3941#include "SharedBuffer.h"
4042#include "VTTCue.h"

@@void TextTrackLoader::notifyFinished(CachedResource& resource)
142144 cancelLoad();
143145}
144146
145 bool TextTrackLoader::load(const URL& url, const String& crossOriginMode, bool isInitiatingElementInUserAgentShadowTree)
 147bool TextTrackLoader::load(const URL& url, HTMLTrackElement& element)
146148{
147149 cancelLoad();
148150

@@bool TextTrackLoader::load(const URL& url, const String& crossOriginMode, bool i
150152 Document& document = downcast<Document>(*m_scriptExecutionContext);
151153
152154 ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
153  options.contentSecurityPolicyImposition = isInitiatingElementInUserAgentShadowTree ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
 155 options.contentSecurityPolicyImposition = element.isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
154156
155  auto cueRequest = createPotentialAccessControlRequest(document.completeURL(url), document, crossOriginMode, WTFMove(options));
 157 ResourceRequest resourceRequest(document.completeURL(url));
 158
 159 if (auto mediaElement = element.mediaElement())
 160 resourceRequest.setInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(*mediaElement));
 161
 162 auto cueRequest = createPotentialAccessControlRequest(WTFMove(resourceRequest), document, element.mediaElementCrossOriginAttribute(), WTFMove(options));
156163 m_resource = document.cachedResourceLoader().requestTextTrack(WTFMove(cueRequest)).value_or(nullptr);
157164 if (!m_resource)
158165 return false;

Source/WebCore/loader/TextTrackLoader.h

@@namespace WebCore {
3737
3838class CachedTextTrack;
3939class Document;
 40class HTMLTrackElement;
4041class TextTrackLoader;
4142class ScriptExecutionContext;
4243

@@public:
5657 TextTrackLoader(TextTrackLoaderClient&, ScriptExecutionContext*);
5758 virtual ~TextTrackLoader();
5859
59  bool load(const URL&, const String& crossOriginMode, bool isInitiatingElementInUserAgentShadowTree);
 60 bool load(const URL&, HTMLTrackElement&);
6061 void cancelLoad();
6162 void getNewCues(Vector<RefPtr<TextTrackCue>>& outputCues);
6263 void getNewRegions(Vector<RefPtr<VTTRegion>>& outputRegions);

Source/WebCore/loader/cache/CachedResourceLoader.cpp

@@bool CachedResourceLoader::shouldContinueAfterNotifyingLoadedFromMemoryCache(con
600600
601601 ResourceRequest newRequest = ResourceRequest(resource.url());
602602 newRequest.setInitiatorIdentifier(request.resourceRequest().initiatorIdentifier());
 603 newRequest.setInitiatorNodeIdentifier(request.resourceRequest().initiatorNodeIdentifier());
603604 if (request.resourceRequest().hiddenFromInspector())
604605 newRequest.setHiddenFromInspector(true);
605606 frame()->loader().loadedResourceFromMemoryCache(resource, newRequest, error);

Source/WebCore/platform/network/ResourceRequestBase.cpp

@@void ResourceRequestBase::setAsIsolatedCopy(const ResourceRequest& other)
6565 setPriority(other.priority());
6666 setRequester(other.requester());
6767 setInitiatorIdentifier(other.initiatorIdentifier().isolatedCopy());
 68 setInitiatorNodeIdentifier(other.initiatorNodeIdentifier());
6869 setCachePartition(other.cachePartition().isolatedCopy());
6970
7071 if (!other.isSameSiteUnspecified()) {

Source/WebCore/platform/network/ResourceRequestBase.h

@@public:
172172 String initiatorIdentifier() const { return m_initiatorIdentifier; }
173173 void setInitiatorIdentifier(const String& identifier) { m_initiatorIdentifier = identifier; }
174174
 175 // Additional information for the Inspector to be able to identify the node that initiated this request.
 176 int initiatorNodeIdentifier() const { return m_initiatorNodeIdentifier; }
 177 void setInitiatorNodeIdentifier(int initiatorNodeIdentifier) { m_initiatorNodeIdentifier = initiatorNodeIdentifier; }
 178
175179#if USE(SYSTEM_PREVIEW)
176180 WEBCORE_EXPORT bool isSystemPreview() const;
177181 WEBCORE_EXPORT void setSystemPreview(bool);

@@protected:
232236 SameSiteDisposition m_sameSiteDisposition { SameSiteDisposition::Unspecified };
233237 ResourceLoadPriority m_priority { ResourceLoadPriority::Low };
234238 Requester m_requester { Requester::Unspecified };
 239 int m_initiatorNodeIdentifier;
235240 bool m_allowCookies { false };
236241 mutable bool m_resourceRequestUpdated { false };
237242 mutable bool m_platformRequestUpdated { false };

Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp

@@void ResourceRequest::updateFromDelegatePreservingOldProperties(const ResourceRe
371371 bool isHiddenFromInspector = hiddenFromInspector();
372372 auto oldRequester = requester();
373373 auto oldInitiatorIdentifier = initiatorIdentifier();
 374 auto oldInitiatorNodeIdentifier = initiatorNodeIdentifier();
374375
375376 *this = delegateProvidedRequest;
376377

@@void ResourceRequest::updateFromDelegatePreservingOldProperties(const ResourceRe
379380 setHiddenFromInspector(isHiddenFromInspector);
380381 setRequester(oldRequester);
381382 setInitiatorIdentifier(oldInitiatorIdentifier);
 383 setInitiatorNodeIdentifier(oldInitiatorNodeIdentifier);
382384}
383385
384386bool ResourceRequest::httpPipeliningEnabled()

Source/WebInspectorUI/ChangeLog

 12018-09-21 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: group media network entries by the node that triggered the request
 4 https://bugs.webkit.org/show_bug.cgi?id=189606
 5 <rdar://problem/44438527>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Introduces a `WI.NavigationItem` for changing whether network entries are grouped by the
 10 node that initiated the load (if appliable). When grouped by node, a tree-like layout of the
 11 table cells (including expand/collapse) is used for resources that share the same initiator
 12 node. The values for the node's cell are based on it's initated resources.
 13
 14 * Localizations/en.lproj/localizedStrings.js:
 15 * UserInterface/Base/Setting.js:
 16
 17 * UserInterface/Controllers/DOMTreeManager.js:
 18 (WI.DOMTreeManager):
 19 (WI.DOMTreeManager.prototype._mainResourceDidChange):
 20 Whenever the frame navigates, re-reqeust the document so that `NetworkAgent` is able to send
 21 valid `nodeId` for each request's `initiatorNode`. This means that the document should
 22 always be available.
 23
 24 * UserInterface/Views/NetworkTableContentView.js:
 25 (WI.NetworkTableContentView):
 26 (WI.NetworkTableContentView.prototype.get filterNavigationItems):
 27 (WI.NetworkTableContentView.prototype.closed):
 28 (WI.NetworkTableContentView.prototype.reset):
 29 (WI.NetworkTableContentView.prototype.tableSortChanged):
 30 (WI.NetworkTableContentView.prototype.tableSelectedRowChanged):
 31 (WI.NetworkTableContentView.prototype.tablePopulateCell):
 32 (WI.NetworkTableContentView.prototype._populateNameCell.createIconElement): Added.
 33 (WI.NetworkTableContentView.prototype._populateNameCell):
 34 (WI.NetworkTableContentView.prototype._populateDomainCell.createIconAndText): Added.
 35 (WI.NetworkTableContentView.prototype._populateDomainCell):
 36 (WI.NetworkTableContentView.prototype._populateInitiatorCell):
 37 (WI.NetworkTableContentView.prototype._populateTransferSizeCell):
 38 (WI.NetworkTableContentView.prototype._generateSortComparator):
 39 (WI.NetworkTableContentView.prototype._processPendingEntries):
 40 (WI.NetworkTableContentView.prototype._updateEntryForResource.updateEntry): Added.
 41 (WI.NetworkTableContentView.prototype._updateEntryForResource):
 42 (WI.NetworkTableContentView.prototype._insertResourceAndReloadTable):
 43 (WI.NetworkTableContentView.prototype._entryForDOMNode): Added.
 44 (WI.NetworkTableContentView.prototype._tryLinkResourceToDOMNode): Added.
 45 (WI.NetworkTableContentView.prototype._uniqueValuesForDOMNodeEntry): Added.
 46 (WI.NetworkTableContentView.prototype._updateFilteredEntries):
 47 (WI.NetworkTableContentView.prototype._handleGroupByDOMNodeCheckedDidChange): Added.
 48 * UserInterface/Views/NetworkTableContentView.css:
 49 (.network-table .cell.dom-node.name .icon): Added.
 50 (.network-table .cell.dom-node.name .disclosure): Added.
 51 (body[dir=rtl] .network-table .cell.dom-node.name .disclosure): Added.
 52 (.network-table:focus li.selected .cell.dom-node.name .disclosure): Added.
 53 (.network-table .cell.dom-node.name .disclosure.expanded): Added.
 54 (.network-table:focus li.selected .cell.node.name .disclosure.expanded): Added.
 55 (.network-table .cell.grouped-by-node.name): Added.
 56 (body[dir=ltr] .network-table .cell.grouped-by-node.name): Added.
 57 (body[dir=rtl] .network-table .cell.grouped-by-node.name): Added.
 58 (.network-table li:not(.selected) .cell:matches(.cache-type, .multiple)): Added.
 59 (.network-table li.selected .cell.domain > .lock): Added.
 60 (.network-table .cache-type): Deleted.
 61 When two resources are added that share the same `initiatorNode`, insert a node entry into
 62 the `WI.Table` before the first resource entry for that node (based on the current sort).
 63 This node entry is added after the resource entries are filtered, so they won't appear in
 64 the default entries list.
 65
 66 * UserInterface/Models/Resource.js:
 67 (WI.Resource):
 68 * UserInterface/Models/SourceMapResource.js:
 69 (WI.SourceMapResource):
 70 * UserInterface/Models/WebSocketResource.js:
 71 (WI.WebSocketResource):
 72 * UserInterface/Controllers/FrameResourceManager.js:
 73 (WI.FrameResourceManager.prototype.frameDidNavigate):
 74 (WI.FrameResourceManager.prototype.resourceRequestWillBeSent):
 75 (WI.FrameResourceManager.prototype.webSocketWillSendHandshakeRequest):
 76 (WI.FrameResourceManager.prototype.resourceRequestWasServedFromMemoryCache):
 77 (WI.FrameResourceManager.prototype.resourceRequestDidReceiveResponse):
 78 (WI.FrameResourceManager.prototype._addNewResourceToFrameOrTarget.createResourceFromArguments): Added.
 79 (WI.FrameResourceManager.prototype._addNewResourceToFrameOrTarget):
 80 (WI.FrameResourceManager.prototype._initiatorNodeFromPayload):
 81 (WI.FrameResourceManager.prototype._createFrame):
 82 (WI.FrameResourceManager.prototype._createResource):
 83 Use an object to pass all optional parameters when creating `WI.Resource`.
 84
 85 * UserInterface/Images/Range.svg: Added.
 86 * UserInterface/Views/ResourceIcons.css:
 87 (.resource-icon.resource-type-range .icon): Added.
 88
1892018-09-21 Nikita Vasilyev <nvasilyev@apple.com>
290
391 REGRESSION(r236237): Web Inspector: DarkMode: white background in Elements and Timelines

Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

@@localizedStrings["(async)"] = "(async)";
5757localizedStrings["(disk)"] = "(disk)";
5858localizedStrings["(many)"] = "(many)";
5959localizedStrings["(memory)"] = "(memory)";
 60localizedStrings["(multiple)"] = "(multiple)";
6061localizedStrings["(program)"] = "(program)";
6162localizedStrings["(service worker)"] = "(service worker)";
6263localizedStrings["(uninitialized)"] = "(uninitialized)";

@@localizedStrings["Breakpoints"] = "Breakpoints";
139140localizedStrings["Breakpoints disabled"] = "Breakpoints disabled";
140141localizedStrings["Bubbling"] = "Bubbling";
141142localizedStrings["Busy"] = "Busy";
 143localizedStrings["Byte Range %s"] = "Byte Range %s";
142144localizedStrings["Bytes Received"] = "Bytes Received";
143145localizedStrings["Bytes Sent"] = "Bytes Sent";
144146localizedStrings["CSP Hash"] = "CSP Hash";

Source/WebInspectorUI/UserInterface/Base/Setting.js

@@WI.settings = {
117117 showCanvasPath: new WI.Setting("show-canvas-path", false),
118118 selectedNetworkDetailContentViewIdentifier: new WI.Setting("network-detail-content-view-identifier", "preview"),
119119 showRulers: new WI.Setting("show-rulers", false),
 120 groupByDOMNode: new WI.Setting("group-by-dom-node", false),
120121
121122 // Experimental
122123 experimentalEnableLayersTab: new WI.Setting("experimental-enable-layers-tab", false),

Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js

@@WI.DOMTreeManager = class DOMTreeManager extends WI.Object
4646 this._breakpointsForEventListeners = new Map;
4747
4848 WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
 49
 50 this.ensureDocument();
4951 }
5052
5153 // Public

@@WI.DOMTreeManager = class DOMTreeManager extends WI.Object
628630
629631 _mainResourceDidChange(event)
630632 {
631  if (event.target.isMainFrame())
632  this._restoreSelectedNodeIsAllowed = true;
 633 if (!event.target.isMainFrame())
 634 return;
 635
 636 this._restoreSelectedNodeIsAllowed = true;
 637
 638 this.ensureDocument();
633639 }
634640};
635641

Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
8888 // If the frame wasn't known before now, then the main resource was loaded instantly (about:blank, etc.)
8989 // Make a new resource (which will make the frame). Mark will mark it as loaded at the end too since we
9090 // don't expect any more events about the load finishing for these frames.
91  var frameResource = this._addNewResourceToFrameOrTarget(null, framePayload.id, framePayload.loaderId, framePayload.url, null, null, null, null, null, null, framePayload.name, framePayload.securityOrigin);
 91 const requestIdentifier = null;
 92 const type = null;
 93 const requestMethod = null;
 94 const requestHeaders = null;
 95 const requestData = null;
 96 const elapsedTime = null;
 97 const walltime = null;
 98 var frameResource = this._addNewResourceToFrameOrTarget(requestIdentifier, framePayload.id, framePayload.loaderId, framePayload.url, type, requestMethod, requestHeaders, requestData, elapsedTime, walltime, framePayload.name, framePayload.securityOrigin);
9299 frame = frameResource.parentFrame;
93100 frameWasLoadedInstantly = true;
94101

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
101108 // There was a provisional load in progress, commit it.
102109 frame.commitProvisionalLoad(framePayload.securityOrigin);
103110 } else {
 111 let mainResource = null;
104112 if (frame.mainResource.url !== framePayload.url || frame.loaderIdentifier !== framePayload.loaderId) {
105113 // Navigations like back/forward do not have provisional loads, so create a new main resource here.
106  var mainResource = new WI.Resource(framePayload.url, framePayload.mimeType, null, framePayload.loaderId);
 114 mainResource = new WI.Resource(framePayload.url, {
 115 mimeType: framePayload.mimeType,
 116 loaderIdentifier: framePayload.loaderId,
 117 });
107118 } else {
108119 // The main resource is already correct, so reuse it.
109  var mainResource = frame.mainResource;
 120 mainResource = frame.mainResource;
110121 }
111122
112123 frame.initialize(framePayload.name, framePayload.securityOrigin, framePayload.loaderId, mainResource);

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
192203 }
193204
194205 var initiatorSourceCodeLocation = this._initiatorSourceCodeLocationFromPayload(initiator);
 206 let initiatorNode = this._initiatorNodeFromPayload(initiator);
195207
196208 // This is a new request, make a new resource and add it to the right frame.
197  resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, request.url, type, request.method, request.headers, request.postData, elapsedTime, walltime, null, null, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId);
 209 const frameName = null;
 210 const frameSecurityOrigin = null;
 211 resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, request.url, type, request.method, request.headers, request.postData, elapsedTime, walltime, frameName, frameSecurityOrigin, initiatorSourceCodeLocation, initiatorNode, originalRequestWillBeSentTimestamp, targetId);
198212
199213 // Associate the resource with the requestIdentifier so it can be found in future loading events.
200214 this._resourceRequestIdentifierMap.set(requestIdentifier, resource);

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
205219 this._webSocketIdentifierToURL.set(requestId, url);
206220 }
207221
208  webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request)
 222 webSocketWillSendHandshakeRequest(requestIdentifier, timestamp, walltime, request)
209223 {
210  let url = this._webSocketIdentifierToURL.get(requestId);
 224 let url = this._webSocketIdentifierToURL.get(requestIdentifier);
211225 console.assert(url);
212226 if (!url)
213227 return;

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
221235 // FIXME: <webkit.org/b/168475> Web Inspector: Correctly display iframe's and worker's WebSockets
222236 let frameIdentifier = WI.frameResourceManager.mainFrame.id;
223237 let loaderIdentifier = WI.frameResourceManager.mainFrame.id;
224  let targetId;
225238
226239 let frame = this.frameForIdentifier(frameIdentifier);
227  let requestData = null;
228  let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
229  let initiatorSourceCodeLocation = null;
230240
231  let resource = new WI.WebSocketResource(url, loaderIdentifier, targetId, requestId, request.headers, requestData, timestamp, walltime, elapsedTime, initiatorSourceCodeLocation);
 241 let resource = new WI.WebSocketResource(url, {
 242 loaderIdentifier,
 243 requestIdentifier,
 244 requestHeaders: request.headers,
 245 timestamp,
 246 walltime,
 247 elapsedTime: WI.timelineManager.computeElapsedTime(timestamp),
 248 });
232249
233250 frame.addResource(resource);
234251
235  this._resourceRequestIdentifierMap.set(requestId, resource);
 252 this._resourceRequestIdentifierMap.set(requestIdentifier, resource);
236253 }
237254
238255 webSocketHandshakeResponseReceived(requestId, timestamp, response)

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
325342
326343 console.assert(!this._resourceRequestIdentifierMap.has(requestIdentifier));
327344
 345 const requestMethod = "GET";
 346 const requestHeaders = null;
 347 const requestData = null;
328348 let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
 349 const walltime = null;
 350 const frameName = null;
 351 const frameSecurityOrigin = null;
329352 let initiatorSourceCodeLocation = this._initiatorSourceCodeLocationFromPayload(initiator);
 353 let initiatorNode = this._initiatorNodeFromPayload(initiator);
 354 let resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, cachedResourcePayload.url, cachedResourcePayload.type, requestMethod, requestHeaders, requestData, elapsedTime, walltime, frameName, frameSecurityOrigin, initiatorSourceCodeLocation, initiatorNode);
 355
330356 let response = cachedResourcePayload.response;
331357 const responseSource = NetworkAgent.ResponseSource.MemoryCache;
332 
333  let resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, cachedResourcePayload.url, cachedResourcePayload.type, "GET", null, null, elapsedTime, null, null, null, initiatorSourceCodeLocation);
334358 resource.updateForResponse(cachedResourcePayload.url, response.mimeType, cachedResourcePayload.type, response.headers, response.status, response.statusText, elapsedTime, response.timing, responseSource);
335359 resource.increaseSize(cachedResourcePayload.bodySize, elapsedTime);
336360 resource.increaseTransferSize(cachedResourcePayload.bodySize);

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
377401 // If we haven't found an existing Resource by now, then it is a resource that was loading when the inspector
378402 // opened and we just missed the resourceRequestWillBeSent for it. So make a new resource and add it.
379403 if (!resource) {
380  resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, response.url, type, null, response.requestHeaders, null, elapsedTime, null, null, null, null);
 404 const requestMethod = null;
 405 const requestData = null;
 406 resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, response.url, type, requestMethod, response.requestHeaders, requestData, elapsedTime);
381407
382408 // Associate the resource with the requestIdentifier so it can be found in future loading events.
383409 this._resourceRequestIdentifierMap.set(requestIdentifier, resource);

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
501527
502528 // Private
503529
504  _addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, url, type, requestMethod, requestHeaders, requestData, elapsedTime, walltime, frameName, frameSecurityOrigin, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId)
 530 _addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, url, type, requestMethod, requestHeaders, requestData, elapsedTime, walltime, frameName, frameSecurityOrigin, initiatorSourceCodeLocation, initiatorNode, originalRequestWillBeSentTimestamp, targetIdentifier)
505531 {
506532 console.assert(!this._waitingForMainFrameResourceTreePayload);
507533
 534 function createResourceFromArguments() {
 535 return new WI.Resource(url, {
 536 type,
 537 loaderIdentifier,
 538 targetIdentifier,
 539 requestIdentifier,
 540 requestMethod,
 541 requestHeaders,
 542 requestData,
 543 requestSentTimestamp: elapsedTime,
 544 requestSentWalltime: walltime,
 545 initiatorSourceCodeLocation,
 546 initiatorNode,
 547 originalRequestWillBeSentTimestamp,
 548 });
 549 }
 550
508551 let resource = null;
509552
510  if (!frameIdentifier && targetId) {
 553 if (!frameIdentifier && targetIdentifier) {
511554 // This is a new resource for a ServiceWorker target.
512555 console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.ServiceWorker);
513  console.assert(targetId === WI.mainTarget.identifier);
514  resource = new WI.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, walltime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
 556 console.assert(targetIdentifier === WI.mainTarget.identifier);
 557 resource = createResourceFromArguments();
515558 resource.target.addResource(resource);
516559 return resource;
517560 }

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
524567 else if (type === "Document" && frame.provisionalMainResource && frame.provisionalMainResource.url === url && frame.provisionalLoaderIdentifier === loaderIdentifier)
525568 resource = frame.provisionalMainResource;
526569 else {
527  resource = new WI.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, walltime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
 570 resource = createResourceFromArguments();
528571 if (resource.target === WI.pageTarget)
529572 this._addResourceToFrame(frame, resource);
530573 else if (resource.target)
531574 resource.target.addResource(resource);
532575 else
533  this._addOrphanedResource(resource, targetId);
 576 this._addOrphanedResource(resource, targetIdentifier);
534577 }
535578 } else {
536579 // This is a new request for a new frame, which is always the main resource.
537580 console.assert(WI.sharedApp.debuggableType !== WI.DebuggableType.ServiceWorker);
538  console.assert(!targetId);
539  resource = new WI.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, walltime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
 581 console.assert(!targetIdentifier);
 582 resource = createResourceFromArguments();
540583 frame = new WI.Frame(frameIdentifier, frameName, frameSecurityOrigin, loaderIdentifier, resource);
541584 this._frameIdentifierMap.set(frame.id, frame);
542585

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
629672 return sourceCode.createSourceCodeLocation(lineNumber, columnNumber);
630673 }
631674
 675 _initiatorNodeFromPayload(initiatorPayload)
 676 {
 677 return WI.domTreeManager.nodeForId(initiatorPayload.nodeId);
 678 }
 679
632680 _processServiceWorkerConfiguration(error, initializationPayload)
633681 {
634682 console.assert(this._waitingForMainFrameResourceTreePayload);

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
686734 {
687735 // If payload.url is missing or empty then this page is likely the special empty page. In that case
688736 // we will just say it is "about:blank" so we have a URL, which is required for resources.
689  var mainResource = new WI.Resource(payload.url || "about:blank", payload.mimeType, null, payload.loaderId);
 737 let mainResource = new WI.Resource(payload.url || "about:blank", {
 738 mimeType: payload.mimeType,
 739 loaderIdentifier: payload.loaderId,
 740 });
690741 var frame = new WI.Frame(payload.id, payload.name, payload.securityOrigin, payload.loaderId, mainResource);
691742
692743 this._frameIdentifierMap.set(frame.id, frame);

@@WI.FrameResourceManager = class FrameResourceManager extends WI.Object
698749
699750 _createResource(payload, framePayload)
700751 {
701  var resource = new WI.Resource(payload.url, payload.mimeType, payload.type, framePayload.loaderId, payload.targetId);
 752 let resource = new WI.Resource(payload.url, {
 753 mimeType: payload.mimeType,
 754 type: payload.type,
 755 loaderIdentifier: framePayload.loaderId,
 756 targetIdentifier: payload.targetId,
 757 });
702758
703759 if (payload.sourceMapURL)
704760 WI.sourceMapManager.downloadSourceMap(payload.sourceMapURL, resource.url, resource);

Source/WebInspectorUI/UserInterface/Images/Range.svg

 1<?xml version="1.0" encoding="utf-8"?>
 2<!-- Copyright © 2013 Apple Inc. All rights reserved. -->
 3<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
 4 <path fill="rgb(148, 183, 219)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 Z"/>
 5 <path fill="rgb(106, 136, 170)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2"/>
 6 <path fill="white" d="M 7 7.632812 L 7.027344 7.632812 C 8.28125 7.632812 9.0625 7.144531 9.0625 6.167969 C 9.0625 5.453125 8.347656 5.097656 7.230469 5.097656 L 7 5.097656 Z M 5 12 L 5 4 L 8.109375 4 C 9.800781 4 11 4.675781 11 6 C 11 6.496094 10.855469 6.941406 10.570312 7.347656 C 10.285156 7.753906 9.53125 8.050781 9.03125 8.265625 L 11.75 12 L 9.402344 12 L 7.34375 8.730469 L 7 8.730469 L 7 12 Z"/>
 7 <path fill="rgb(113, 146, 184)" d="M 8.109375 3 L 4 3 L 4 13 L 8 13 L 8 11.644531 L 8.558594 12.53125 L 8.851562 13 L 13.714844 13 L 12.558594 11.410156 L 10.550781 8.652344 C 10.875 8.460938 11.175781 8.226562 11.386719 7.925781 C 11.792969 7.351562 12 6.703125 12 6 C 12 4.179688 10.472656 3 8.109375 3 M 7 7.632812 L 7.027344 7.632812 C 8.28125 7.632812 9.0625 7.144531 9.0625 6.167969 C 9.0625 5.453125 8.347656 5.097656 7.230469 5.097656 L 7 5.097656 L 7 7.632812 M 8.109375 4 C 9.796875 4 11 4.679688 11 6 C 11 6.492188 10.855469 6.941406 10.570312 7.347656 C 10.285156 7.753906 9.535156 8.050781 9.03125 8.265625 L 11.75 12 L 9.40625 12 L 7.34375 8.730469 L 7 8.730469 L 7 12 L 5 12 L 5 4 L 8.109375 4"/>
 8</svg>

Source/WebInspectorUI/UserInterface/Models/Resource.js

2626
2727WI.Resource = class Resource extends WI.SourceCode
2828{
29  constructor(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, requestSentTimestamp, requestSentWalltime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp)
 29 constructor(url, {mimeType, type, loaderIdentifier, targetIdentifier, requestIdentifier, requestMethod, requestHeaders, requestData, requestSentTimestamp, requestSentWalltime, initiatorSourceCodeLocation, initiatorNode, originalRequestWillBeSentTimestamp} = {})
3030 {
3131 super();
3232

@@WI.Resource = class Resource extends WI.SourceCode
5353 this._parentFrame = null;
5454 this._initiatorSourceCodeLocation = initiatorSourceCodeLocation || null;
5555 this._initiatedResources = [];
 56 this._initiatorNode = initiatorNode || null;
5657 this._originalRequestWillBeSentTimestamp = originalRequestWillBeSentTimestamp || null;
5758 this._requestSentTimestamp = requestSentTimestamp || NaN;
5859 this._requestSentWalltime = requestSentWalltime || NaN;

@@WI.Resource = class Resource extends WI.SourceCode
7475 this._priority = WI.Resource.NetworkPriority.Unknown;
7576 this._remoteAddress = null;
7677 this._connectionIdentifier = null;
77  this._target = targetId ? WI.targetManager.targetForIdentifier(targetId) : WI.mainTarget;
 78 this._target = targetIdentifier ? WI.targetManager.targetForIdentifier(targetIdentifier) : WI.mainTarget;
7879
7980 // Exact sizes if loaded over the network or cache.
8081 this._requestHeadersTransferSize = NaN;

@@WI.Resource = class Resource extends WI.SourceCode
286287 get requestIdentifier() { return this._requestIdentifier; }
287288 get requestMethod() { return this._requestMethod; }
288289 get requestData() { return this._requestData; }
 290 get initiatorSourceCodeLocation() { return this._initiatorSourceCodeLocation; }
 291 get initiatedResources() { return this._initiatedResources; }
 292 get initiatorNode() { return this._initiatorNode; }
 293 get originalRequestWillBeSentTimestamp() { return this._originalRequestWillBeSentTimestamp; }
289294 get statusCode() { return this._statusCode; }
290295 get statusText() { return this._statusText; }
291296 get responseSource() { return this._responseSource; }

@@WI.Resource = class Resource extends WI.SourceCode
319324 return WI.truncateURL(this._url, isMultiLine, dataURIMaxSize);
320325 }
321326
322  get initiatorSourceCodeLocation()
323  {
324  return this._initiatorSourceCodeLocation;
325  }
326 
327  get initiatedResources()
328  {
329  return this._initiatedResources;
330  }
331 
332  get originalRequestWillBeSentTimestamp()
333  {
334  return this._originalRequestWillBeSentTimestamp;
335  }
336 
337327 get mimeType()
338328 {
339329 return this._mimeType;

Source/WebInspectorUI/UserInterface/Models/SourceMapResource.js

@@WI.SourceMapResource = class SourceMapResource extends WI.Resource
2727{
2828 constructor(url, sourceMap)
2929 {
30  super(url, null);
 30 super(url);
3131
3232 console.assert(url);
3333 console.assert(sourceMap);

Source/WebInspectorUI/UserInterface/Models/WebSocketResource.js

2525
2626WI.WebSocketResource = class WebSocketResource extends WI.Resource
2727{
28  constructor(url, loaderIdentifier, targetId, requestIdentifier, requestHeaders, requestData, timestamp, walltime, requestSentTimestamp, initiatorSourceCodeLocation)
 28 constructor(url, {loaderIdentifier, targetIdentifier, requestIdentifier, requestHeaders, requestData, timestamp, walltime, requestSentTimestamp, initiatorSourceCodeLocation} = {})
2929 {
30  const type = WI.Resource.Type.WebSocket;
31  const mimeType = null;
32  const requestMethod = "GET";
33  super(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, requestSentTimestamp, initiatorSourceCodeLocation);
 30 super(url, {
 31 type: WI.Resource.Type.WebSocket,
 32 loaderIdentifier,
 33 targetIdentifier,
 34 requestIdentifier,
 35 requestMethod: "GET",
 36 requestHeaders,
 37 requestData,
 38 requestSentTimestamp,
 39 initiatorSourceCodeLocation,
 40 });
3441
3542 this._timestamp = timestamp;
3643 this._walltime = walltime;

Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css

4040 cursor: pointer;
4141}
4242
43 .network-table .cache-type {
 43.network-table .cell.dom-node.name .icon {
 44 content: url(../Images/DOMElement.svg);
 45}
 46
 47.network-table .cell.dom-node.name .disclosure {
 48 width: 13px;
 49 height: 13px;
 50 vertical-align: -2px;
 51 content: url(../Images/DisclosureTriangles.svg#closed-normal);
 52 background-size: 13px 13px;
 53 background-repeat: no-repeat;
 54}
 55
 56body[dir=rtl] .network-table .cell.dom-node.name .disclosure {
 57 transform: scaleX(-1);
 58}
 59
 60.network-table:focus li.selected .cell.dom-node.name .disclosure {
 61 content: url(../Images/DisclosureTriangles.svg#closed-selected);
 62}
 63
 64.network-table .cell.dom-node.name .disclosure.expanded {
 65 content: url(../Images/DisclosureTriangles.svg#open-normal);
 66}
 67
 68.network-table:focus li.selected .cell.dom-node.name .disclosure.expanded {
 69 content: url(../Images/DisclosureTriangles.svg#open-selected);
 70}
 71
 72.network-table .cell.grouped-by-node.name {
 73 --item-padding-start: 19px;
 74}
 75
 76body[dir=ltr] .network-table .cell.grouped-by-node.name {
 77 padding-left: var(--item-padding-start);
 78}
 79
 80body[dir=rtl] .network-table .cell.grouped-by-node.name {
 81 padding-right: var(--item-padding-start);
 82}
 83
 84.network-table li:not(.selected) .cell:matches(.cache-type, .multiple) {
4485 color: var(--text-color-gray-medium);
4586}
4687

5596 -webkit-margin-end: 5px;
5697}
5798
 99.network-table li.selected .cell.domain > .lock {
 100 filter: invert();
 101}
 102
58103body[dir=ltr] .network-table .cell.name > .status {
59104 float: right;
60105 margin-left: 4px;

Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
4444 this._resourceDetailView = null;
4545 this._resourceDetailViewMap = new Map;
4646
 47 this._domNodeEntries = new Map;
 48
4749 this._waterfallStartTime = NaN;
4850 this._waterfallEndTime = NaN;
4951 this._waterfallTimelineRuler = null;

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
8385 this._typeFilterScopeBar = new WI.ScopeBar("network-type-filter-scope-bar", typeFilterScopeBarItems, typeFilterScopeBarItems[0]);
8486 this._typeFilterScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._typeFilterScopeBarSelectionChanged, this);
8587
 88 this._groupByDOMNodeNavigationItem = new WI.CheckboxNavigationItem("group-by-node", WI.UIString("Group by Node"), WI.settings.groupByDOMNode.value);
 89 this._groupByDOMNodeNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleGroupByDOMNodeCheckedDidChange, this);
 90
8691 this._urlFilterSearchText = null;
8792 this._urlFilterSearchRegex = null;
8893 this._urlFilterIsActive = false;

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
201206
202207 get filterNavigationItems()
203208 {
204  return [this._urlFilterNavigationItem, this._typeFilterScopeBar];
 209 return [this._urlFilterNavigationItem, this._typeFilterScopeBar, this._groupByDOMNodeNavigationItem];
205210 }
206211
207212 get supportsSave()

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
241246 detailView.dispose();
242247 this._resourceDetailViewMap.clear();
243248
 249 this._domNodeEntries.clear();
 250
244251 this._hidePopover();
245252 this._hideResourceDetailView();
246253

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
264271 detailView.dispose();
265272 this._resourceDetailViewMap.clear();
266273
 274 this._domNodeEntries.clear();
 275
267276 this._waterfallStartTime = NaN;
268277 this._waterfallEndTime = NaN;
269278 this._updateWaterfallTimelineRuler();

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
320329
321330 this._hideResourceDetailView();
322331
323  this._entries = this._entries.sort(this._entriesSortComparator);
 332 for (let nodeEntry of this._domNodeEntries.values())
 333 nodeEntry.initiatedResourceEntries.sort(this._entriesSortComparator);
 334
 335 this._entries.sort(this._entriesSortComparator);
 336
324337 this._updateFilteredEntries();
325338 this._table.reloadData();
326339 }

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
360373 return;
361374
362375 this._selectedResource = entry.resource;
363  this._showResourceDetailView(this._selectedResource);
 376 if (this._selectedResource)
 377 this._showResourceDetailView(this._selectedResource);
 378 else
 379 this._hideResourceDetailView();
364380 }
365381
366382 tablePopulateCell(table, cell, column, rowIndex)
367383 {
368384 let entry = this._filteredEntries[rowIndex];
369385
370  cell.classList.toggle("error", entry.resource.hadLoadingError());
 386 if (entry.resource)
 387 cell.classList.toggle("error", entry.resource.hadLoadingError());
 388
 389 let setTextContent = (accessor) => {
 390 let uniqueValues = this._uniqueValuesForDOMNodeEntry(entry, accessor);
 391 if (uniqueValues) {
 392 if (uniqueValues.size > 1) {
 393 cell.classList.add("multiple");
 394 cell.textContent = WI.UIString("(multiple)");
 395 return;
 396 }
 397
 398 cell.textContent = uniqueValues.values().next().value || emDash;
 399 return;
 400 }
 401
 402 cell.textContent = accessor(entry) || emDash;
 403 };
371404
372405 switch (column.identifier) {
373406 case "name":

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
377410 this._populateDomainCell(cell, entry);
378411 break;
379412 case "type":
380  cell.textContent = entry.displayType || emDash;
 413 setTextContent((resourceEntry) => resourceEntry.displayType);
381414 break;
382415 case "mimeType":
383  cell.textContent = entry.mimeType || emDash;
 416 setTextContent((resourceEntry) => resourceEntry.mimeType);
384417 break;
385418 case "method":
386  cell.textContent = entry.method || emDash;
 419 setTextContent((resourceEntry) => resourceEntry.method);
387420 break;
388421 case "scheme":
389  cell.textContent = entry.scheme || emDash;
 422 setTextContent((resourceEntry) => resourceEntry.scheme);
390423 break;
391424 case "status":
392  cell.textContent = entry.status || emDash;
 425 setTextContent((resourceEntry) => resourceEntry.status);
393426 break;
394427 case "protocol":
395  cell.textContent = entry.protocol || emDash;
 428 setTextContent((resourceEntry) => resourceEntry.protocol);
396429 break;
397430 case "initiator":
398431 this._populateInitiatorCell(cell, entry);
399432 break;
400433 case "priority":
401  cell.textContent = WI.Resource.displayNameForPriority(entry.priority) || emDash;
 434 setTextContent((resourceEntry) => WI.Resource.displayNameForPriority(resourceEntry.priority));
402435 break;
403436 case "remoteAddress":
404  cell.textContent = entry.remoteAddress || emDash;
 437 setTextContent((resourceEntry) => resourceEntry.remoteAddress);
405438 break;
406439 case "connectionIdentifier":
407  cell.textContent = entry.connectionIdentifier || emDash;
 440 setTextContent((resourceEntry) => resourceEntry.connectionIdentifier);
408441 break;
409442 case "resourceSize":
410  cell.textContent = isNaN(entry.resourceSize) ? emDash : Number.bytesToString(entry.resourceSize);
 443 var resourceSize = entry.resourceSize;
 444 var resourceEntries = entry.initiatedResourceEntries;
 445 if (resourceEntries)
 446 resourceSize = resourceEntries.reduce((accumulator, current) => accumulator + (current.transferSize || 0), 0);
 447 cell.textContent = isNaN(resourceSize) ? emDash : Number.bytesToString(resourceSize);
411448 break;
412449 case "transferSize":
413450 this._populateTransferSizeCell(cell, entry);
414451 break;
415452 case "time":
416453 // FIXME: <https://webkit.org/b/176748> Web Inspector: Frontend sometimes receives resources with negative duration (responseEnd - requestStart)
417  cell.textContent = isNaN(entry.time) ? emDash : Number.secondsToString(Math.max(entry.time, 0));
 454 var time = entry.time;
 455 var resourceEntries = entry.initiatedResourceEntries;
 456 if (resourceEntries)
 457 time = resourceEntries.reduce((accumulator, current) => accumulator + (current.time || 0), 0);
 458 cell.textContent = isNaN(time) ? emDash : Number.secondsToString(Math.max(time, 0));
418459 break;
419460 case "waterfall":
420461 this._populateWaterfallGraph(cell, entry);

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
430471 {
431472 console.assert(!cell.firstChild, "We expect the cell to be empty.", cell, cell.firstChild);
432473
 474 function createIconElement() {
 475 let iconElement = cell.appendChild(document.createElement("img"));
 476 iconElement.className = "icon";
 477 }
 478
 479 let domNode = entry.domNode;
 480 if (domNode) {
 481 let disclosureElement = cell.appendChild(document.createElement("img"));
 482 disclosureElement.classList.add("disclosure");
 483 disclosureElement.classList.toggle("expanded", !!entry.expanded);
 484 disclosureElement.addEventListener("click", (event) => {
 485 entry.expanded = !entry.expanded;
 486
 487 this._updateFilteredEntries();
 488 this._table.reloadData();
 489 });
 490
 491 createIconElement();
 492
 493 cell.classList.add("dom-node");
 494 cell.appendChild(WI.linkifyNodeReference(domNode));
 495 return;
 496 }
 497
433498 let resource = entry.resource;
434499 if (resource.isLoading()) {
435500 let statusElement = cell.appendChild(document.createElement("div"));

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
438503 statusElement.appendChild(spinner.element);
439504 }
440505
441  let iconElement = cell.appendChild(document.createElement("img"));
442  iconElement.className = "icon";
443  cell.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName, entry.resource.type);
 506 createIconElement();
 507
 508 cell.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName);
444509
445510 let nameElement = cell.appendChild(document.createElement("span"));
446  nameElement.textContent = entry.name;
447511
448  cell.title = entry.resource.url;
 512 if (WI.settings.groupByDOMNode.value && resource.initiatorNode) {
 513 let nodeEntry = this._domNodeEntries.get(resource.initiatorNode);
 514 if (nodeEntry.initiatedResourceEntries.length > 1) {
 515 cell.classList.add("grouped-by-node");
 516
 517 if ("Range" in resource.requestHeaders) {
 518 cell.classList.add("resource-type-range");
 519 nameElement.textContent = WI.UIString("Byte Range %s").format(resource.requestHeaders["Range"].replace("bytes=", ""));
 520 }
 521 }
 522 }
 523
 524 if (!nameElement.textContent) {
 525 cell.classList.add(resource.type);
 526 nameElement.textContent = entry.name;
 527 }
 528
 529 cell.title = resource.url;
449530 }
450531
451532 _populateDomainCell(cell, entry)
452533 {
453534 console.assert(!cell.firstChild, "We expect the cell to be empty.", cell, cell.firstChild);
454535
 536 function createIconAndText(scheme, domain) {
 537 let secure = scheme === "https" || scheme === "wss";
 538 if (secure) {
 539 let lockIconElement = cell.appendChild(document.createElement("img"));
 540 lockIconElement.className = "lock";
 541 }
 542
 543 cell.append(domain);
 544 }
 545
 546 let uniqueSchemeValues = this._uniqueValuesForDOMNodeEntry(entry, (resourceEntry) => resourceEntry.scheme);
 547 let uniqueDomainValues = this._uniqueValuesForDOMNodeEntry(entry, (resourceEntry) => resourceEntry.domain);
 548 if (uniqueSchemeValues && uniqueDomainValues) {
 549 if (uniqueSchemeValues.size > 1 || uniqueDomainValues.size > 1) {
 550 cell.classList.add("multiple");
 551 cell.textContent = WI.UIString("(multiple)");
 552 return;
 553 }
 554
 555 createIconAndText(uniqueSchemeValues.values().next().value, uniqueDomainValues.values().next().value);
 556 return;
 557 }
 558
455559 if (!entry.domain) {
456560 cell.textContent = emDash;
457561 return;
458562 }
459563
460  let secure = entry.scheme === "https" || entry.scheme === "wss";
461  if (secure) {
462  let lockIconElement = cell.appendChild(document.createElement("img"));
463  lockIconElement.className = "lock";
464  }
465 
466  cell.append(entry.domain);
 564 createIconAndText(entry.scheme, entry.domain);
467565 }
468566
469567 _populateInitiatorCell(cell, entry)
470568 {
 569 let domNode = entry.domNode;
 570 if (domNode) {
 571 cell.textContent = emDash;
 572 return;
 573 }
 574
471575 let initiatorLocation = entry.resource.initiatorSourceCodeLocation;
472576 if (!initiatorLocation) {
473577 cell.textContent = emDash;

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
483587
484588 _populateTransferSizeCell(cell, entry)
485589 {
 590 let resourceEntries = entry.initiatedResourceEntries;
 591 if (resourceEntries) {
 592 if (resourceEntries.every((resourceEntry) => resourceEntry.resource.responseSource === WI.Resource.ResponseSource.MemoryCache)) {
 593 cell.classList.add("cache-type");
 594 cell.textContent = WI.UIString("(memory)");
 595 return;
 596 }
 597 if (resourceEntries.every((resourceEntry) => resourceEntry.resource.responseSource === WI.Resource.ResponseSource.DiskCache)) {
 598 cell.classList.add("cache-type");
 599 cell.textContent = WI.UIString("(disk)");
 600 return;
 601 }
 602 if (resourceEntries.every((resourceEntry) => resourceEntry.resource.responseSource === WI.Resource.ResponseSource.ServiceWorker)) {
 603 cell.classList.add("cache-type");
 604 cell.textContent = WI.UIString("(service worker)");
 605 return;
 606 }
 607 let transferSize = resourceEntries.reduce((accumulator, current) => accumulator + (current.transferSize || 0), 0);
 608 if (isNaN(transferSize))
 609 cell.textContent = emDash;
 610 else
 611 cell.textContent = Number.bytesToString(transferSize);
 612 return;
 613 }
 614
486615 let responseSource = entry.resource.responseSource;
487616 if (responseSource === WI.Resource.ResponseSource.MemoryCache) {
488617 cell.classList.add("cache-type");

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
509638 {
510639 cell.removeChildren();
511640
 641 let domNode = entry.domNode;
 642 if (domNode) {
 643 // FIXME: <https://webkit.org/b/189773>
 644 return;
 645 }
 646
512647 let resource = entry.resource;
513648 if (!resource.hasResponse()) {
514649 cell.textContent = zeroWidthSpace;

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
666801
667802 case "waterfall":
668803 // Sort by startTime number.
669  comparator = comparator = (a, b) => a.startTime - b.startTime;
 804 comparator = (a, b) => a.startTime - b.startTime;
670805 break;
671806
672807 default:

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
675810 }
676811
677812 let reverseFactor = this._table.sortOrder === WI.Table.SortOrder.Ascending ? 1 : -1;
678  this._entriesSortComparator = (a, b) => reverseFactor * comparator(a, b);
 813
 814 let substitute = (entry, other) => {
 815 if (WI.settings.groupByDOMNode.value && entry.resource.initiatorNode) {
 816 let nodeEntry = this._domNodeEntries.get(entry.resource.initiatorNode);
 817 if (!nodeEntry.initiatedResourceEntries.includes(other))
 818 return nodeEntry.initiatedResourceEntries[0];
 819 }
 820 return entry;
 821 };
 822
 823 this._entriesSortComparator = (a, b) => reverseFactor * comparator(substitute(a, b), substitute(b, a));
679824 }
680825
681826 // Protected

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
8831028 return;
8841029 }
8851030
886  for (let resource of this._pendingInsertions)
887  this._entries.push(this._entryForResource(resource));
 1031 for (let resource of this._pendingInsertions) {
 1032 let resourceEntry = this._entryForResource(resource);
 1033
 1034 this._tryLinkResourceToDOMNode(resourceEntry);
 1035
 1036 this._entries.push(resourceEntry);
 1037 }
8881038 this._pendingInsertions = [];
8891039
8901040 for (let resource of this._pendingUpdates)

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
9521102 return;
9531103
9541104 let entry = this._entryForResource(resource);
955  this._entries[index] = entry;
 1105
 1106 // Don't wipe out the previous entry, as it may be used by a node entry.
 1107 function updateEntry(existing) {
 1108 for (let key in entry)
 1109 existing[key] = entry[key];
 1110 }
 1111
 1112 updateEntry(this._entries[index]);
9561113
9571114 let rowIndex = this._rowIndexForResource(resource);
9581115 if (rowIndex === -1)
9591116 return;
9601117
961  this._filteredEntries[rowIndex] = entry;
 1118 updateEntry(this._filteredEntries[rowIndex]);
9621119 }
9631120
9641121 _hidePopover()

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
11851342 return;
11861343 }
11871344
1188  let entry = this._entryForResource(resource);
 1345 let resourceEntry = this._entryForResource(resource);
11891346
1190  // Default sort has fast path.
1191  if (this._isDefaultSort() || !this._entriesSortComparator) {
1192  this._entries.push(entry);
1193  if (this._passFilter(entry)) {
1194  this._filteredEntries.push(entry);
 1347 this._tryLinkResourceToDOMNode(resourceEntry);
 1348
 1349 if (WI.settings.groupByDOMNode.value && resource.initiatorNode) {
 1350 if (!this._entriesSortComparator)
 1351 this._generateSortComparator();
 1352 } else if (this._isDefaultSort() || !this._entriesSortComparator) {
 1353 // Default sort has fast path.
 1354 this._entries.push(resourceEntry);
 1355 if (this._passFilter(resourceEntry)) {
 1356 this._filteredEntries.push(resourceEntry);
11951357 this._table.reloadDataAddedToEndOnly();
11961358 }
11971359 return;
11981360 }
11991361
1200  insertObjectIntoSortedArray(entry, this._entries, this._entriesSortComparator);
 1362 insertObjectIntoSortedArray(resourceEntry, this._entries, this._entriesSortComparator);
12011363
1202  if (this._passFilter(entry)) {
1203  insertObjectIntoSortedArray(entry, this._filteredEntries, this._entriesSortComparator);
 1364 if (this._passFilter(resourceEntry)) {
 1365 if (WI.settings.groupByDOMNode.value)
 1366 this._updateFilteredEntries();
 1367 else
 1368 insertObjectIntoSortedArray(resourceEntry, this._filteredEntries, this._entriesSortComparator);
12041369
12051370 // Probably a useless optimization here, but if we only added this row to the end
12061371 // we may avoid recreating all visible rows by saying as such.
1207  if (this._filteredEntries.lastValue === entry)
 1372 if (this._filteredEntries.lastValue === resourceEntry)
12081373 this._table.reloadDataAddedToEndOnly();
12091374 else
12101375 this._table.reloadData();

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
12391404 };
12401405 }
12411406
 1407 _entryForDOMNode(domNode, requiredFields)
 1408 {
 1409 return {
 1410 domNode,
 1411 initiatedResourceEntries: [],
 1412 expanded: true,
 1413 };
 1414 }
 1415
 1416 _tryLinkResourceToDOMNode(resourceEntry)
 1417 {
 1418 let resource = resourceEntry.resource;
 1419 if (!resource || !resource.initiatorNode)
 1420 return;
 1421
 1422 let nodeEntry = this._domNodeEntries.get(resource.initiatorNode);
 1423 if (!nodeEntry) {
 1424 nodeEntry = this._entryForDOMNode(resource.initiatorNode, Object.keys(resourceEntry));
 1425 this._domNodeEntries.set(resource.initiatorNode, nodeEntry);
 1426 }
 1427
 1428 if (!this._entriesSortComparator)
 1429 this._generateSortComparator();
 1430
 1431 insertObjectIntoSortedArray(resourceEntry, nodeEntry.initiatedResourceEntries, this._entriesSortComparator);
 1432 }
 1433
 1434 _uniqueValuesForDOMNodeEntry(nodeEntry, accessor)
 1435 {
 1436 let resourceEntries = nodeEntry.initiatedResourceEntries;
 1437 if (!resourceEntries)
 1438 return null;
 1439
 1440 return resourceEntries.reduce((accumulator, current) => {
 1441 let value = accessor(current);
 1442 if (value || typeof value === "number")
 1443 accumulator.add(value);
 1444 return accumulator;
 1445 }, new Set);
 1446 }
 1447
12421448 _hasTypeFilter()
12431449 {
12441450 return !!this._activeTypeFilters;

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
12901496 else
12911497 this._filteredEntries = this._entries.slice();
12921498
 1499 if (WI.settings.groupByDOMNode.value) {
 1500 for (let nodeEntry of this._domNodeEntries.values()) {
 1501 if (nodeEntry.initiatedResourceEntries.length < 2)
 1502 continue;
 1503
 1504 let firstIndex = Infinity;
 1505 for (let resourceEntry of nodeEntry.initiatedResourceEntries) {
 1506 if (this._hasActiveFilter() && !this._passFilter(resourceEntry))
 1507 continue;
 1508
 1509 let index = this._filteredEntries.indexOf(resourceEntry);
 1510 if (index >= 0 && index < firstIndex)
 1511 firstIndex = index;
 1512 }
 1513
 1514 if (!isFinite(firstIndex))
 1515 continue;
 1516
 1517 this._filteredEntries.insertAtIndex(nodeEntry, firstIndex);
 1518 }
 1519
 1520 this._filteredEntries = this._filteredEntries.filter((entry) => {
 1521 if (entry.resource && entry.resource.initiatorNode) {
 1522 let nodeEntry = this._domNodeEntries.get(entry.resource.initiatorNode);
 1523 if (!nodeEntry.expanded)
 1524 return false;
 1525 }
 1526 return true;
 1527 });
 1528 }
 1529
12931530 this._restoreSelectedRow();
12941531
12951532 this._updateURLFilterActiveIndicator();

@@WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
13611598 this._table.reloadData();
13621599 }
13631600
 1601 _handleGroupByDOMNodeCheckedDidChange(event)
 1602 {
 1603 WI.settings.groupByDOMNode.value = this._groupByDOMNodeNavigationItem.checked;
 1604
 1605 this._updateSortAndFilteredEntries();
 1606 this._table.reloadData();
 1607 }
 1608
13641609 _urlFilterDidChange(event)
13651610 {
13661611 let searchQuery = this._urlFilterNavigationItem.filterBar.filters.text;

Source/WebInspectorUI/UserInterface/Views/ResourceIcons.css

7676 content: url(../Images/Beacon.svg);
7777}
7878
 79.resource-icon.resource-type-range .icon {
 80 content: url(../Images/Range.svg);
 81}
 82
7983.large .resource-icon .icon {
8084 content: image-set(url(../Images/DocumentGenericLarge.png) 1x, url(../Images/DocumentGenericLarge@2x.png) 2x);
8185}