OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 /** | |
32 * @implements {SDK.SDKModelObserver<!SDK.NetworkManager>} | |
33 */ | |
34 SDK.NetworkLog = class { | |
35 constructor() { | |
36 /** @type {!Array<!SDK.NetworkRequest>} */ | |
37 this._requests = []; | |
38 /** @type {!Map<!SDK.Target, !Map<string, !SDK.NetworkRequest>>} */ | |
39 this._requestsByTargetAndId = new Map(); | |
40 /** @type {!Map<!SDK.Target, !SDK.PageLoad>} */ | |
41 this._currentPageLoad = new Map(); | |
42 SDK.targetManager.observeModels(SDK.NetworkManager, this); | |
43 } | |
44 | |
45 /** | |
46 * @override | |
47 * @param {!SDK.NetworkManager} networkManager | |
48 */ | |
49 modelAdded(networkManager) { | |
50 var eventListeners = []; | |
51 eventListeners.push( | |
52 networkManager.addEventListener(SDK.NetworkManager.Events.RequestStarted
, this._onRequestStarted, this)); | |
53 eventListeners.push(networkManager.on(SDK.NetworkManager.RequestRedirectEven
t, this._onRequestRedirect, this)); | |
54 | |
55 var resourceTreeModel = networkManager.target().model(SDK.ResourceTreeModel)
; | |
56 if (resourceTreeModel) { | |
57 eventListeners.push(resourceTreeModel.addEventListener( | |
58 SDK.ResourceTreeModel.Events.MainFrameNavigated, this._onMainFrameNavi
gated, this)); | |
59 eventListeners.push(resourceTreeModel.addEventListener( | |
60 SDK.ResourceTreeModel.Events.Load, this._onLoad.bind(this, resourceTre
eModel))); | |
61 eventListeners.push(resourceTreeModel.addEventListener( | |
62 SDK.ResourceTreeModel.Events.DOMContentLoaded, this._onDOMContentLoade
d.bind(this, resourceTreeModel))); | |
63 } | |
64 | |
65 networkManager[SDK.NetworkLog._events] = eventListeners; | |
66 this._requestsByTargetAndId.set(networkManager.target(), new Map()); | |
67 } | |
68 | |
69 /** | |
70 * @override | |
71 * @param {!SDK.NetworkManager} networkManager | |
72 */ | |
73 modelRemoved(networkManager) { | |
74 this._requestsByTargetAndId.delete(networkManager.target()); | |
75 Common.EventTarget.removeEventListeners(networkManager[SDK.NetworkLog._event
s]); | |
76 } | |
77 | |
78 /** | |
79 * @param {string} url | |
80 * @return {?SDK.NetworkRequest} | |
81 */ | |
82 requestForURL(url) { | |
83 return this._requests.find(request => request.url() === url) || null; | |
84 } | |
85 | |
86 /** | |
87 * @return {!Array<!SDK.NetworkRequest>} | |
88 */ | |
89 requests() { | |
90 return this._requests; | |
91 } | |
92 | |
93 /** | |
94 * @param {!SDK.Target} target | |
95 * @return {!Array<!SDK.NetworkRequest>} | |
96 */ | |
97 requestsForTarget(target) { | |
98 var map = this._requestsByTargetAndId.get(target); | |
99 return map ? Array.from(map.values()) : []; | |
100 } | |
101 | |
102 /** | |
103 * @param {string} url | |
104 * @param {!SDK.Target} target | |
105 * @return {?SDK.NetworkRequest} | |
106 */ | |
107 _requestForURLInTarget(url, target) { | |
108 var map = this._requestsByTargetAndId.get(target); | |
109 if (!map) | |
110 return null; | |
111 for (var request of map.values()) { | |
112 if (request.url() === url) | |
113 return request; | |
114 } | |
115 return null; | |
116 } | |
117 | |
118 /** | |
119 * @param {!SDK.NetworkRequest} request | |
120 */ | |
121 _initializeInitiatorSymbolIfNeeded(request) { | |
122 if (!request[SDK.NetworkLog._initiatorDataSymbol]) { | |
123 /** @type {!{info: ?SDK.NetworkLog._InitiatorInfo, chain: !Set<!SDK.Networ
kRequest>, request: (?SDK.NetworkRequest|undefined)}} */ | |
124 request[SDK.NetworkLog._initiatorDataSymbol] = { | |
125 info: null, | |
126 chain: null, | |
127 request: undefined, | |
128 }; | |
129 } | |
130 } | |
131 | |
132 /** | |
133 * @param {!SDK.NetworkRequest} request | |
134 * @return {!SDK.NetworkLog._InitiatorInfo} | |
135 */ | |
136 initiatorInfoForRequest(request) { | |
137 this._initializeInitiatorSymbolIfNeeded(request); | |
138 if (request[SDK.NetworkLog._initiatorDataSymbol].info) | |
139 return request[SDK.NetworkLog._initiatorDataSymbol].info; | |
140 | |
141 var type = SDK.NetworkRequest.InitiatorType.Other; | |
142 var url = ''; | |
143 var lineNumber = -Infinity; | |
144 var columnNumber = -Infinity; | |
145 var scriptId = null; | |
146 var initiator = request.initiator(); | |
147 | |
148 if (request.redirectSource) { | |
149 type = SDK.NetworkRequest.InitiatorType.Redirect; | |
150 url = request.redirectSource.url(); | |
151 } else if (initiator) { | |
152 if (initiator.type === Protocol.Network.InitiatorType.Parser) { | |
153 type = SDK.NetworkRequest.InitiatorType.Parser; | |
154 url = initiator.url ? initiator.url : url; | |
155 lineNumber = initiator.lineNumber ? initiator.lineNumber : lineNumber; | |
156 } else if (initiator.type === Protocol.Network.InitiatorType.Script) { | |
157 for (var stack = initiator.stack; stack; stack = stack.parent) { | |
158 var topFrame = stack.callFrames.length ? stack.callFrames[0] : null; | |
159 if (!topFrame) | |
160 continue; | |
161 type = SDK.NetworkRequest.InitiatorType.Script; | |
162 url = topFrame.url || Common.UIString('<anonymous>'); | |
163 lineNumber = topFrame.lineNumber; | |
164 columnNumber = topFrame.columnNumber; | |
165 scriptId = topFrame.scriptId; | |
166 break; | |
167 } | |
168 } else if (initiator.type === Protocol.Network.InitiatorType.Preload) { | |
169 type = SDK.NetworkRequest.InitiatorType.Preload; | |
170 } | |
171 } | |
172 | |
173 request[SDK.NetworkLog._initiatorDataSymbol].info = | |
174 {type: type, url: url, lineNumber: lineNumber, columnNumber: columnNumbe
r, scriptId: scriptId}; | |
175 return request[SDK.NetworkLog._initiatorDataSymbol].info; | |
176 } | |
177 | |
178 /** | |
179 * @param {!SDK.NetworkRequest} request | |
180 * @return {!SDK.NetworkLog.InitiatorGraph} | |
181 */ | |
182 initiatorGraphForRequest(request) { | |
183 /** @type {!Set<!SDK.NetworkRequest>} */ | |
184 var initiated = new Set(); | |
185 var map = this._requestsByTargetAndId.get(request.target()); | |
186 if (map) { | |
187 for (var otherRequest of map.values()) { | |
188 if (this._initiatorChain(otherRequest).has(request)) | |
189 initiated.add(otherRequest); | |
190 } | |
191 } | |
192 return {initiators: this._initiatorChain(request), initiated: initiated}; | |
193 } | |
194 | |
195 /** | |
196 * @param {!SDK.NetworkRequest} request | |
197 * @return {!Set<!SDK.NetworkRequest>} | |
198 */ | |
199 _initiatorChain(request) { | |
200 this._initializeInitiatorSymbolIfNeeded(request); | |
201 var initiatorChainCache = | |
202 /** @type {?Set<!SDK.NetworkRequest>} */ (request[SDK.NetworkLog._initia
torDataSymbol].chain); | |
203 if (initiatorChainCache) | |
204 return initiatorChainCache; | |
205 | |
206 initiatorChainCache = new Set(); | |
207 | |
208 var checkRequest = request; | |
209 do { | |
210 initiatorChainCache.add(checkRequest); | |
211 checkRequest = this._initiatorRequest(checkRequest); | |
212 } while (checkRequest); | |
213 request[SDK.NetworkLog._initiatorDataSymbol].chain = initiatorChainCache; | |
214 return initiatorChainCache; | |
215 } | |
216 | |
217 /** | |
218 * @param {!SDK.NetworkRequest} request | |
219 * @return {?SDK.NetworkRequest} | |
220 */ | |
221 _initiatorRequest(request) { | |
222 this._initializeInitiatorSymbolIfNeeded(request); | |
223 if (request[SDK.NetworkLog._initiatorDataSymbol].request !== undefined) | |
224 return request[SDK.NetworkLog._initiatorDataSymbol].request; | |
225 var url = this.initiatorInfoForRequest(request).url; | |
226 request[SDK.NetworkLog._initiatorDataSymbol].request = this._requestForURLIn
Target(url, request.target()); | |
227 return request[SDK.NetworkLog._initiatorDataSymbol].request; | |
228 } | |
229 | |
230 /** | |
231 * @param {!SDK.NetworkRequest} request | |
232 * @return {?SDK.PageLoad} | |
233 */ | |
234 pageLoadForRequest(request) { | |
235 return request[SDK.NetworkLog._pageLoadForRequestSymbol]; | |
236 } | |
237 | |
238 /** | |
239 * @param {!Common.Event} event | |
240 */ | |
241 _onMainFrameNavigated(event) { | |
242 var mainFrame = /** @type {!SDK.ResourceTreeFrame} */ (event.data); | |
243 var target = mainFrame.target(); | |
244 this._currentPageLoad.delete(target); | |
245 var oldRequests = this.requestsForTarget(target); | |
246 this._requests = this._requests.filter(request => request.target() !== targe
t); | |
247 var idMap = new Map(); | |
248 this._requestsByTargetAndId.set(target, idMap); | |
249 | |
250 // Preserve requests from the new session. | |
251 var currentPageLoad = null; | |
252 for (var i = 0; i < oldRequests.length; ++i) { | |
253 var request = oldRequests[i]; | |
254 if (request.loaderId === mainFrame.loaderId) { | |
255 if (!currentPageLoad) | |
256 currentPageLoad = new SDK.PageLoad(request); | |
257 this._requests.push(request); | |
258 idMap.set(request.requestId(), request); | |
259 request[SDK.NetworkLog._pageLoadForRequestSymbol] = currentPageLoad; | |
260 } | |
261 } | |
262 if (currentPageLoad) | |
263 this._currentPageLoad.set(target, currentPageLoad); | |
264 } | |
265 | |
266 /** | |
267 * @param {!Common.Event} event | |
268 */ | |
269 _onRequestStarted(event) { | |
270 var request = /** @type {!SDK.NetworkRequest} */ (event.data); | |
271 this._requests.push(request); | |
272 this._requestsByTargetAndId.get(request.target()).set(request.requestId(), r
equest); | |
273 request[SDK.NetworkLog._pageLoadForRequestSymbol] = this._currentPageLoad.ge
t(request.target()); | |
274 } | |
275 | |
276 /** | |
277 * @param {!SDK.NetworkManager.RequestRedirectEvent} event | |
278 */ | |
279 _onRequestRedirect(event) { | |
280 var request = event.request; | |
281 delete request[SDK.NetworkLog._initiatorDataSymbol]; | |
282 } | |
283 | |
284 /** | |
285 * @param {!SDK.ResourceTreeModel} resourceTreeModel | |
286 * @param {!Common.Event} event | |
287 */ | |
288 _onDOMContentLoaded(resourceTreeModel, event) { | |
289 var pageLoad = this._currentPageLoad.get(resourceTreeModel.target()); | |
290 if (pageLoad) | |
291 pageLoad.contentLoadTime = /** @type {number} */ (event.data); | |
292 } | |
293 | |
294 /** | |
295 * @param {!SDK.ResourceTreeModel} resourceTreeModel | |
296 * @param {!Common.Event} event | |
297 */ | |
298 _onLoad(resourceTreeModel, event) { | |
299 var pageLoad = this._currentPageLoad.get(resourceTreeModel.target()); | |
300 if (pageLoad) | |
301 pageLoad.loadTime = /** @type {number} */ (event.data); | |
302 } | |
303 | |
304 /** | |
305 * @param {!SDK.Target} target | |
306 * @param {!Protocol.Network.RequestId} requestId | |
307 * @return {?SDK.NetworkRequest} | |
308 */ | |
309 requestForId(target, requestId) { | |
310 var map = this._requestsByTargetAndId.get(target); | |
311 return map ? (map.get(requestId) || null) : null; | |
312 } | |
313 }; | |
314 | |
315 SDK.PageLoad = class { | |
316 /** | |
317 * @param {!SDK.NetworkRequest} mainRequest | |
318 */ | |
319 constructor(mainRequest) { | |
320 this.id = ++SDK.PageLoad._lastIdentifier; | |
321 this.url = mainRequest.url(); | |
322 this.startTime = mainRequest.startTime; | |
323 /** @type {number} */ | |
324 this.loadTime; | |
325 /** @type {number} */ | |
326 this.contentLoadTime; | |
327 } | |
328 }; | |
329 | |
330 SDK.PageLoad._lastIdentifier = 0; | |
331 | |
332 /** @typedef {!{initiators: !Set<!SDK.NetworkRequest>, initiated: !Set<!SDK.Netw
orkRequest>}} */ | |
333 SDK.NetworkLog.InitiatorGraph; | |
334 | |
335 /** @typedef {!{type: !SDK.NetworkRequest.InitiatorType, url: string, lineNumber
: number, columnNumber: number, scriptId: ?string}} */ | |
336 SDK.NetworkLog._InitiatorInfo; | |
337 | |
338 SDK.NetworkLog._initiatorDataSymbol = Symbol('InitiatorData'); | |
339 SDK.NetworkLog._pageLoadForRequestSymbol = Symbol('PageLoadForRequest'); | |
340 SDK.NetworkLog._events = Symbol('SDK.NetworkLog.events'); | |
341 | |
342 /** @type {!SDK.NetworkLog} */ | |
343 SDK.networkLog; | |
OLD | NEW |