OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
13 * distribution. | 13 * distribution. |
14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
17 * | 17 * |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | |
31 /** | 30 /** |
32 * @constructor | 31 * @unrestricted |
33 * @extends {WebInspector.SDKModel} | |
34 * @param {!WebInspector.Target} target | |
35 * @param {?WebInspector.NetworkManager} networkManager | |
36 * @param {!WebInspector.SecurityOriginManager} securityOriginManager | |
37 */ | 32 */ |
38 WebInspector.ResourceTreeModel = function(target, networkManager, securityOrigin
Manager) | 33 WebInspector.ResourceTreeModel = class extends WebInspector.SDKModel { |
39 { | 34 /** |
40 WebInspector.SDKModel.call(this, WebInspector.ResourceTreeModel, target); | 35 * @param {!WebInspector.Target} target |
| 36 * @param {?WebInspector.NetworkManager} networkManager |
| 37 * @param {!WebInspector.SecurityOriginManager} securityOriginManager |
| 38 */ |
| 39 constructor(target, networkManager, securityOriginManager) { |
| 40 super(WebInspector.ResourceTreeModel, target); |
41 if (networkManager) { | 41 if (networkManager) { |
42 networkManager.addEventListener(WebInspector.NetworkManager.Events.Reque
stFinished, | 42 networkManager.addEventListener( |
43 this._onRequestFinished, this); | 43 WebInspector.NetworkManager.Events.RequestFinished, this._onRequestFin
ished, this); |
44 networkManager.addEventListener(WebInspector.NetworkManager.Events.Reque
stUpdateDropped, | 44 networkManager.addEventListener( |
45 this._onRequestUpdateDropped, this); | 45 WebInspector.NetworkManager.Events.RequestUpdateDropped, this._onReque
stUpdateDropped, this); |
46 } | 46 } |
47 | 47 |
48 this._agent = target.pageAgent(); | 48 this._agent = target.pageAgent(); |
49 this._agent.enable(); | 49 this._agent.enable(); |
50 this._securityOriginManager = securityOriginManager; | 50 this._securityOriginManager = securityOriginManager; |
51 | 51 |
52 this._fetchResourceTree(); | 52 this._fetchResourceTree(); |
53 | 53 |
54 target.registerPageDispatcher(new WebInspector.PageDispatcher(this)); | 54 target.registerPageDispatcher(new WebInspector.PageDispatcher(this)); |
55 | 55 |
56 this._pendingReloadOptions = null; | 56 this._pendingReloadOptions = null; |
57 this._reloadSuspensionCount = 0; | 57 this._reloadSuspensionCount = 0; |
| 58 } |
| 59 |
| 60 /** |
| 61 * @param {!WebInspector.Target} target |
| 62 * @return {?WebInspector.ResourceTreeModel} |
| 63 */ |
| 64 static fromTarget(target) { |
| 65 return /** @type {?WebInspector.ResourceTreeModel} */ (target.model(WebInspe
ctor.ResourceTreeModel)); |
| 66 } |
| 67 |
| 68 /** |
| 69 * @return {!Array.<!WebInspector.ResourceTreeFrame>} |
| 70 */ |
| 71 static frames() { |
| 72 var result = []; |
| 73 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca
pability.DOM)) |
| 74 result = result.concat(WebInspector.ResourceTreeModel.fromTarget(target)._
frames.valuesArray()); |
| 75 return result; |
| 76 } |
| 77 |
| 78 /** |
| 79 * @param {string} url |
| 80 * @return {?WebInspector.Resource} |
| 81 */ |
| 82 static resourceForURL(url) { |
| 83 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca
pability.DOM)) { |
| 84 var mainFrame = WebInspector.ResourceTreeModel.fromTarget(target).mainFram
e; |
| 85 var result = mainFrame ? mainFrame.resourceForURL(url) : null; |
| 86 if (result) |
| 87 return result; |
| 88 } |
| 89 return null; |
| 90 } |
| 91 |
| 92 _fetchResourceTree() { |
| 93 /** @type {!Map<string, !WebInspector.ResourceTreeFrame>} */ |
| 94 this._frames = new Map(); |
| 95 this._cachedResourcesProcessed = false; |
| 96 this._agent.getResourceTree(this._processCachedResources.bind(this)); |
| 97 } |
| 98 |
| 99 _processCachedResources(error, mainFramePayload) { |
| 100 if (!error) { |
| 101 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.WillLo
adCachedResources); |
| 102 this._addFramesRecursively(null, mainFramePayload); |
| 103 this.target().setInspectedURL(mainFramePayload.frame.url); |
| 104 } |
| 105 this._cachedResourcesProcessed = true; |
| 106 this.target().runtimeModel.setExecutionContextComparator(this._executionCont
extComparator.bind(this)); |
| 107 this.target().runtimeModel.fireExecutionContextOrderChanged(); |
| 108 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.CachedRe
sourcesLoaded); |
| 109 } |
| 110 |
| 111 /** |
| 112 * @return {boolean} |
| 113 */ |
| 114 cachedResourcesLoaded() { |
| 115 return this._cachedResourcesProcessed; |
| 116 } |
| 117 |
| 118 /** |
| 119 * @param {!WebInspector.ResourceTreeFrame} frame |
| 120 * @param {boolean=} aboutToNavigate |
| 121 */ |
| 122 _addFrame(frame, aboutToNavigate) { |
| 123 this._frames.set(frame.id, frame); |
| 124 if (frame.isMainFrame()) { |
| 125 this.mainFrame = frame; |
| 126 this._securityOriginManager.setMainSecurityOrigin(frame.url); |
| 127 } |
| 128 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.FrameAdd
ed, frame); |
| 129 if (!aboutToNavigate) |
| 130 this._securityOriginManager.addSecurityOrigin(frame.securityOrigin); |
| 131 } |
| 132 |
| 133 /** |
| 134 * @param {!WebInspector.ResourceTreeFrame} mainFrame |
| 135 */ |
| 136 _handleMainFrameDetached(mainFrame) { |
| 137 /** |
| 138 * @param {!WebInspector.ResourceTreeFrame} frame |
| 139 * @this {WebInspector.ResourceTreeModel} |
| 140 */ |
| 141 function removeOriginForFrame(frame) { |
| 142 for (var i = 0; i < frame.childFrames.length; ++i) |
| 143 removeOriginForFrame.call(this, frame.childFrames[i]); |
| 144 if (!frame.isMainFrame()) |
| 145 this._securityOriginManager.removeSecurityOrigin(frame.securityOrigin); |
| 146 } |
| 147 removeOriginForFrame.call(this, mainFrame); |
| 148 } |
| 149 |
| 150 /** |
| 151 * @param {!PageAgent.FrameId} frameId |
| 152 * @param {?PageAgent.FrameId} parentFrameId |
| 153 * @return {?WebInspector.ResourceTreeFrame} |
| 154 */ |
| 155 _frameAttached(frameId, parentFrameId) { |
| 156 // Do nothing unless cached resource tree is processed - it will overwrite e
verything. |
| 157 if (!this._cachedResourcesProcessed && parentFrameId) |
| 158 return null; |
| 159 if (this._frames.has(frameId)) |
| 160 return null; |
| 161 |
| 162 var parentFrame = parentFrameId ? (this._frames.get(parentFrameId) || null)
: null; |
| 163 var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, frameId); |
| 164 if (frame.isMainFrame() && this.mainFrame) { |
| 165 this._handleMainFrameDetached(this.mainFrame); |
| 166 // Navigation to the new backend process. |
| 167 this._frameDetached(this.mainFrame.id); |
| 168 } |
| 169 this._addFrame(frame, true); |
| 170 return frame; |
| 171 } |
| 172 |
| 173 /** |
| 174 * @param {!PageAgent.Frame} framePayload |
| 175 */ |
| 176 _frameNavigated(framePayload) { |
| 177 // Do nothing unless cached resource tree is processed - it will overwrite e
verything. |
| 178 if (!this._cachedResourcesProcessed && framePayload.parentId) |
| 179 return; |
| 180 var frame = this._frames.get(framePayload.id); |
| 181 if (!frame) { |
| 182 // Simulate missed "frameAttached" for a main frame navigation to the new
backend process. |
| 183 console.assert(!framePayload.parentId, 'Main frame shouldn\'t have parent
frame id.'); |
| 184 frame = this._frameAttached(framePayload.id, framePayload.parentId || ''); |
| 185 console.assert(frame); |
| 186 } |
| 187 |
| 188 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.FrameWil
lNavigate, frame); |
| 189 |
| 190 this._securityOriginManager.removeSecurityOrigin(frame.securityOrigin); |
| 191 frame._navigate(framePayload); |
| 192 var addedOrigin = frame.securityOrigin; |
| 193 |
| 194 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.FrameNav
igated, frame); |
| 195 if (frame.isMainFrame()) { |
| 196 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.MainFr
ameNavigated, frame); |
| 197 if (WebInspector.moduleSetting('preserveConsoleLog').get()) |
| 198 WebInspector.console.log(WebInspector.UIString('Navigated to %s', frame.
url)); |
| 199 else |
| 200 this.target().consoleModel.clear(); |
| 201 } |
| 202 if (addedOrigin) |
| 203 this._securityOriginManager.addSecurityOrigin(addedOrigin); |
| 204 |
| 205 // Fill frame with retained resources (the ones loaded using new loader). |
| 206 var resources = frame.resources(); |
| 207 for (var i = 0; i < resources.length; ++i) |
| 208 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.Resour
ceAdded, resources[i]); |
| 209 |
| 210 if (frame.isMainFrame()) |
| 211 this.target().setInspectedURL(frame.url); |
| 212 } |
| 213 |
| 214 /** |
| 215 * @param {!PageAgent.FrameId} frameId |
| 216 */ |
| 217 _frameDetached(frameId) { |
| 218 // Do nothing unless cached resource tree is processed - it will overwrite e
verything. |
| 219 if (!this._cachedResourcesProcessed) |
| 220 return; |
| 221 |
| 222 var frame = this._frames.get(frameId); |
| 223 if (!frame) |
| 224 return; |
| 225 |
| 226 this._securityOriginManager.removeSecurityOrigin(frame.securityOrigin); |
| 227 if (frame.parentFrame) |
| 228 frame.parentFrame._removeChildFrame(frame); |
| 229 else |
| 230 frame._remove(); |
| 231 } |
| 232 |
| 233 /** |
| 234 * @param {!WebInspector.Event} event |
| 235 */ |
| 236 _onRequestFinished(event) { |
| 237 if (!this._cachedResourcesProcessed) |
| 238 return; |
| 239 |
| 240 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); |
| 241 if (request.failed || request.resourceType() === WebInspector.resourceTypes.
XHR) |
| 242 return; |
| 243 |
| 244 var frame = this._frames.get(request.frameId); |
| 245 if (frame) |
| 246 frame._addRequest(request); |
| 247 } |
| 248 |
| 249 /** |
| 250 * @param {!WebInspector.Event} event |
| 251 */ |
| 252 _onRequestUpdateDropped(event) { |
| 253 if (!this._cachedResourcesProcessed) |
| 254 return; |
| 255 |
| 256 var frameId = event.data.frameId; |
| 257 var frame = this._frames.get(frameId); |
| 258 if (!frame) |
| 259 return; |
| 260 |
| 261 var url = event.data.url; |
| 262 if (frame._resourcesMap[url]) |
| 263 return; |
| 264 |
| 265 var resource = new WebInspector.Resource( |
| 266 this.target(), null, url, frame.url, frameId, event.data.loaderId, |
| 267 WebInspector.resourceTypes[event.data.resourceType], event.data.mimeType
, event.data.lastModified, null); |
| 268 frame.addResource(resource); |
| 269 } |
| 270 |
| 271 /** |
| 272 * @param {!PageAgent.FrameId} frameId |
| 273 * @return {!WebInspector.ResourceTreeFrame} |
| 274 */ |
| 275 frameForId(frameId) { |
| 276 return this._frames.get(frameId); |
| 277 } |
| 278 |
| 279 /** |
| 280 * @param {function(!WebInspector.Resource)} callback |
| 281 * @return {boolean} |
| 282 */ |
| 283 forAllResources(callback) { |
| 284 if (this.mainFrame) |
| 285 return this.mainFrame._callForFrameResources(callback); |
| 286 return false; |
| 287 } |
| 288 |
| 289 /** |
| 290 * @return {!Array<!WebInspector.ResourceTreeFrame>} |
| 291 */ |
| 292 frames() { |
| 293 return this._frames.valuesArray(); |
| 294 } |
| 295 |
| 296 /** |
| 297 * @param {string} url |
| 298 * @return {?WebInspector.Resource} |
| 299 */ |
| 300 resourceForURL(url) { |
| 301 // Workers call into this with no frames available. |
| 302 return this.mainFrame ? this.mainFrame.resourceForURL(url) : null; |
| 303 } |
| 304 |
| 305 /** |
| 306 * @param {?WebInspector.ResourceTreeFrame} parentFrame |
| 307 * @param {!PageAgent.FrameResourceTree} frameTreePayload |
| 308 */ |
| 309 _addFramesRecursively(parentFrame, frameTreePayload) { |
| 310 var framePayload = frameTreePayload.frame; |
| 311 var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePaylo
ad.id, framePayload); |
| 312 this._addFrame(frame); |
| 313 |
| 314 var frameResource = this._createResourceFromFramePayload( |
| 315 framePayload, framePayload.url, WebInspector.resourceTypes.Document, fra
mePayload.mimeType, null, null); |
| 316 frame.addResource(frameResource); |
| 317 |
| 318 for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFr
ames.length; ++i) |
| 319 this._addFramesRecursively(frame, frameTreePayload.childFrames[i]); |
| 320 |
| 321 for (var i = 0; i < frameTreePayload.resources.length; ++i) { |
| 322 var subresource = frameTreePayload.resources[i]; |
| 323 var resource = this._createResourceFromFramePayload( |
| 324 framePayload, subresource.url, WebInspector.resourceTypes[subresource.
type], subresource.mimeType, |
| 325 subresource.lastModified || null, subresource.contentSize || null); |
| 326 frame.addResource(resource); |
| 327 } |
| 328 } |
| 329 |
| 330 /** |
| 331 * @param {!PageAgent.Frame} frame |
| 332 * @param {string} url |
| 333 * @param {!WebInspector.ResourceType} type |
| 334 * @param {string} mimeType |
| 335 * @param {?number} lastModifiedTime |
| 336 * @param {?number} contentSize |
| 337 * @return {!WebInspector.Resource} |
| 338 */ |
| 339 _createResourceFromFramePayload(frame, url, type, mimeType, lastModifiedTime,
contentSize) { |
| 340 var lastModified = typeof lastModifiedTime === 'number' ? new Date(lastModif
iedTime * 1000) : null; |
| 341 return new WebInspector.Resource( |
| 342 this.target(), null, url, frame.url, frame.id, frame.loaderId, type, mim
eType, lastModified, contentSize); |
| 343 } |
| 344 |
| 345 suspendReload() { |
| 346 this._reloadSuspensionCount++; |
| 347 } |
| 348 |
| 349 resumeReload() { |
| 350 this._reloadSuspensionCount--; |
| 351 console.assert(this._reloadSuspensionCount >= 0, 'Unbalanced call to Resourc
eTreeModel.resumeReload()'); |
| 352 if (!this._reloadSuspensionCount && this._pendingReloadOptions) |
| 353 this.reloadPage.apply(this, this._pendingReloadOptions); |
| 354 } |
| 355 |
| 356 /** |
| 357 * @param {boolean=} bypassCache |
| 358 * @param {string=} scriptToEvaluateOnLoad |
| 359 */ |
| 360 reloadPage(bypassCache, scriptToEvaluateOnLoad) { |
| 361 // Only dispatch PageReloadRequested upon first reload request to simplify c
lient logic. |
| 362 if (!this._pendingReloadOptions) |
| 363 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.PageRe
loadRequested); |
| 364 if (this._reloadSuspensionCount) { |
| 365 this._pendingReloadOptions = [bypassCache, scriptToEvaluateOnLoad]; |
| 366 return; |
| 367 } |
| 368 this._pendingReloadOptions = null; |
| 369 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.WillRelo
adPage); |
| 370 this._agent.reload(bypassCache, scriptToEvaluateOnLoad); |
| 371 } |
| 372 |
| 373 /** |
| 374 * @param {function(string, ?string,!Array<!PageAgent.AppManifestError>)} call
back |
| 375 */ |
| 376 fetchAppManifest(callback) { |
| 377 this._agent.getAppManifest(myCallback); |
| 378 /** |
| 379 * @param {?Protocol.Error} protocolError |
| 380 * @param {string} url |
| 381 * @param {!Array<!PageAgent.AppManifestError>} errors |
| 382 * @param {string=} data |
| 383 */ |
| 384 function myCallback(protocolError, url, errors, data) { |
| 385 if (protocolError) { |
| 386 callback(url, null, []); |
| 387 return; |
| 388 } |
| 389 callback(url, data || null, errors); |
| 390 } |
| 391 } |
| 392 /** |
| 393 * @param {!WebInspector.ExecutionContext} a |
| 394 * @param {!WebInspector.ExecutionContext} b |
| 395 * @return {number} |
| 396 */ |
| 397 _executionContextComparator(a, b) { |
| 398 /** |
| 399 * @param {!WebInspector.ResourceTreeFrame} frame |
| 400 */ |
| 401 function framePath(frame) { |
| 402 var currentFrame = frame; |
| 403 var parents = []; |
| 404 while (currentFrame) { |
| 405 parents.push(currentFrame); |
| 406 currentFrame = currentFrame.parentFrame; |
| 407 } |
| 408 return parents.reverse(); |
| 409 } |
| 410 |
| 411 var framesA = a.frameId ? framePath(this.frameForId(a.frameId)) : []; |
| 412 var framesB = b.frameId ? framePath(this.frameForId(b.frameId)) : []; |
| 413 var frameA; |
| 414 var frameB; |
| 415 for (var i = 0;; i++) { |
| 416 if (!framesA[i] || !framesB[i] || (framesA[i] !== framesB[i])) { |
| 417 frameA = framesA[i]; |
| 418 frameB = framesB[i]; |
| 419 break; |
| 420 } |
| 421 } |
| 422 if (!frameA && frameB) |
| 423 return -1; |
| 424 |
| 425 if (!frameB && frameA) |
| 426 return 1; |
| 427 |
| 428 if (frameA && frameB) { |
| 429 return frameA.id.localeCompare(frameB.id); |
| 430 } |
| 431 return WebInspector.ExecutionContext.comparator(a, b); |
| 432 } |
58 }; | 433 }; |
59 | 434 |
60 /** @enum {symbol} */ | 435 /** @enum {symbol} */ |
61 WebInspector.ResourceTreeModel.Events = { | 436 WebInspector.ResourceTreeModel.Events = { |
62 FrameAdded: Symbol("FrameAdded"), | 437 FrameAdded: Symbol('FrameAdded'), |
63 FrameNavigated: Symbol("FrameNavigated"), | 438 FrameNavigated: Symbol('FrameNavigated'), |
64 FrameDetached: Symbol("FrameDetached"), | 439 FrameDetached: Symbol('FrameDetached'), |
65 FrameResized: Symbol("FrameResized"), | 440 FrameResized: Symbol('FrameResized'), |
66 FrameWillNavigate: Symbol("FrameWillNavigate"), | 441 FrameWillNavigate: Symbol('FrameWillNavigate'), |
67 MainFrameNavigated: Symbol("MainFrameNavigated"), | 442 MainFrameNavigated: Symbol('MainFrameNavigated'), |
68 ResourceAdded: Symbol("ResourceAdded"), | 443 ResourceAdded: Symbol('ResourceAdded'), |
69 WillLoadCachedResources: Symbol("WillLoadCachedResources"), | 444 WillLoadCachedResources: Symbol('WillLoadCachedResources'), |
70 CachedResourcesLoaded: Symbol("CachedResourcesLoaded"), | 445 CachedResourcesLoaded: Symbol('CachedResourcesLoaded'), |
71 DOMContentLoaded: Symbol("DOMContentLoaded"), | 446 DOMContentLoaded: Symbol('DOMContentLoaded'), |
72 Load: Symbol("Load"), | 447 Load: Symbol('Load'), |
73 PageReloadRequested: Symbol("PageReloadRequested"), | 448 PageReloadRequested: Symbol('PageReloadRequested'), |
74 WillReloadPage: Symbol("WillReloadPage"), | 449 WillReloadPage: Symbol('WillReloadPage'), |
75 ScreencastFrame: Symbol("ScreencastFrame"), | 450 ScreencastFrame: Symbol('ScreencastFrame'), |
76 ScreencastVisibilityChanged: Symbol("ScreencastVisibilityChanged"), | 451 ScreencastVisibilityChanged: Symbol('ScreencastVisibilityChanged'), |
77 ColorPicked: Symbol("ColorPicked"), | 452 ColorPicked: Symbol('ColorPicked'), |
78 InterstitialShown: Symbol("InterstitialShown"), | 453 InterstitialShown: Symbol('InterstitialShown'), |
79 InterstitialHidden: Symbol("InterstitialHidden") | 454 InterstitialHidden: Symbol('InterstitialHidden') |
80 }; | 455 }; |
81 | 456 |
| 457 |
82 /** | 458 /** |
83 * @param {!WebInspector.Target} target | 459 * @unrestricted |
84 * @return {?WebInspector.ResourceTreeModel} | |
85 */ | 460 */ |
86 WebInspector.ResourceTreeModel.fromTarget = function(target) | 461 WebInspector.ResourceTreeFrame = class { |
87 { | 462 /** |
88 return /** @type {?WebInspector.ResourceTreeModel} */ (target.model(WebInspe
ctor.ResourceTreeModel)); | 463 * @param {!WebInspector.ResourceTreeModel} model |
89 }; | 464 * @param {?WebInspector.ResourceTreeFrame} parentFrame |
90 | 465 * @param {!PageAgent.FrameId} frameId |
91 /** | 466 * @param {!PageAgent.Frame=} payload |
92 * @return {!Array.<!WebInspector.ResourceTreeFrame>} | 467 */ |
93 */ | 468 constructor(model, parentFrame, frameId, payload) { |
94 WebInspector.ResourceTreeModel.frames = function() | |
95 { | |
96 var result = []; | |
97 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca
pability.DOM)) | |
98 result = result.concat(WebInspector.ResourceTreeModel.fromTarget(target)
._frames.valuesArray()); | |
99 return result; | |
100 }; | |
101 | |
102 /** | |
103 * @param {string} url | |
104 * @return {?WebInspector.Resource} | |
105 */ | |
106 WebInspector.ResourceTreeModel.resourceForURL = function(url) | |
107 { | |
108 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca
pability.DOM)) { | |
109 var mainFrame = WebInspector.ResourceTreeModel.fromTarget(target).mainFr
ame; | |
110 var result = mainFrame ? mainFrame.resourceForURL(url) : null; | |
111 if (result) | |
112 return result; | |
113 } | |
114 return null; | |
115 }; | |
116 | |
117 WebInspector.ResourceTreeModel.prototype = { | |
118 _fetchResourceTree: function() | |
119 { | |
120 /** @type {!Map<string, !WebInspector.ResourceTreeFrame>} */ | |
121 this._frames = new Map(); | |
122 this._cachedResourcesProcessed = false; | |
123 this._agent.getResourceTree(this._processCachedResources.bind(this)); | |
124 }, | |
125 | |
126 _processCachedResources: function(error, mainFramePayload) | |
127 { | |
128 if (!error) { | |
129 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.
WillLoadCachedResources); | |
130 this._addFramesRecursively(null, mainFramePayload); | |
131 this.target().setInspectedURL(mainFramePayload.frame.url); | |
132 } | |
133 this._cachedResourcesProcessed = true; | |
134 this.target().runtimeModel.setExecutionContextComparator(this._execution
ContextComparator.bind(this)); | |
135 this.target().runtimeModel.fireExecutionContextOrderChanged(); | |
136 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.Cach
edResourcesLoaded); | |
137 }, | |
138 | |
139 /** | |
140 * @return {boolean} | |
141 */ | |
142 cachedResourcesLoaded: function() | |
143 { | |
144 return this._cachedResourcesProcessed; | |
145 }, | |
146 | |
147 /** | |
148 * @param {!WebInspector.ResourceTreeFrame} frame | |
149 * @param {boolean=} aboutToNavigate | |
150 */ | |
151 _addFrame: function(frame, aboutToNavigate) | |
152 { | |
153 this._frames.set(frame.id, frame); | |
154 if (frame.isMainFrame()) { | |
155 this.mainFrame = frame; | |
156 this._securityOriginManager.setMainSecurityOrigin(frame.url); | |
157 } | |
158 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.Fram
eAdded, frame); | |
159 if (!aboutToNavigate) | |
160 this._securityOriginManager.addSecurityOrigin(frame.securityOrigin); | |
161 }, | |
162 | |
163 /** | |
164 * @param {!WebInspector.ResourceTreeFrame} mainFrame | |
165 */ | |
166 _handleMainFrameDetached: function(mainFrame) | |
167 { | |
168 /** | |
169 * @param {!WebInspector.ResourceTreeFrame} frame | |
170 * @this {WebInspector.ResourceTreeModel} | |
171 */ | |
172 function removeOriginForFrame(frame) | |
173 { | |
174 for (var i = 0; i < frame.childFrames.length; ++i) | |
175 removeOriginForFrame.call(this, frame.childFrames[i]); | |
176 if (!frame.isMainFrame()) | |
177 this._securityOriginManager.removeSecurityOrigin(frame.securityO
rigin); | |
178 } | |
179 removeOriginForFrame.call(this, mainFrame); | |
180 }, | |
181 | |
182 /** | |
183 * @param {!PageAgent.FrameId} frameId | |
184 * @param {?PageAgent.FrameId} parentFrameId | |
185 * @return {?WebInspector.ResourceTreeFrame} | |
186 */ | |
187 _frameAttached: function(frameId, parentFrameId) | |
188 { | |
189 // Do nothing unless cached resource tree is processed - it will overwri
te everything. | |
190 if (!this._cachedResourcesProcessed && parentFrameId) | |
191 return null; | |
192 if (this._frames.has(frameId)) | |
193 return null; | |
194 | |
195 var parentFrame = parentFrameId ? (this._frames.get(parentFrameId) || nu
ll) : null; | |
196 var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, frameI
d); | |
197 if (frame.isMainFrame() && this.mainFrame) { | |
198 this._handleMainFrameDetached(this.mainFrame); | |
199 // Navigation to the new backend process. | |
200 this._frameDetached(this.mainFrame.id); | |
201 } | |
202 this._addFrame(frame, true); | |
203 return frame; | |
204 }, | |
205 | |
206 /** | |
207 * @param {!PageAgent.Frame} framePayload | |
208 */ | |
209 _frameNavigated: function(framePayload) | |
210 { | |
211 // Do nothing unless cached resource tree is processed - it will overwri
te everything. | |
212 if (!this._cachedResourcesProcessed && framePayload.parentId) | |
213 return; | |
214 var frame = this._frames.get(framePayload.id); | |
215 if (!frame) { | |
216 // Simulate missed "frameAttached" for a main frame navigation to th
e new backend process. | |
217 console.assert(!framePayload.parentId, "Main frame shouldn't have pa
rent frame id."); | |
218 frame = this._frameAttached(framePayload.id, framePayload.parentId |
| ""); | |
219 console.assert(frame); | |
220 } | |
221 | |
222 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.Fram
eWillNavigate, frame); | |
223 | |
224 this._securityOriginManager.removeSecurityOrigin(frame.securityOrigin); | |
225 frame._navigate(framePayload); | |
226 var addedOrigin = frame.securityOrigin; | |
227 | |
228 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.Fram
eNavigated, frame); | |
229 if (frame.isMainFrame()) { | |
230 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.
MainFrameNavigated, frame); | |
231 if (WebInspector.moduleSetting("preserveConsoleLog").get()) | |
232 WebInspector.console.log(WebInspector.UIString("Navigated to %s"
, frame.url)); | |
233 else | |
234 this.target().consoleModel.clear(); | |
235 } | |
236 if (addedOrigin) | |
237 this._securityOriginManager.addSecurityOrigin(addedOrigin); | |
238 | |
239 // Fill frame with retained resources (the ones loaded using new loader)
. | |
240 var resources = frame.resources(); | |
241 for (var i = 0; i < resources.length; ++i) | |
242 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.
ResourceAdded, resources[i]); | |
243 | |
244 if (frame.isMainFrame()) | |
245 this.target().setInspectedURL(frame.url); | |
246 }, | |
247 | |
248 /** | |
249 * @param {!PageAgent.FrameId} frameId | |
250 */ | |
251 _frameDetached: function(frameId) | |
252 { | |
253 // Do nothing unless cached resource tree is processed - it will overwri
te everything. | |
254 if (!this._cachedResourcesProcessed) | |
255 return; | |
256 | |
257 var frame = this._frames.get(frameId); | |
258 if (!frame) | |
259 return; | |
260 | |
261 this._securityOriginManager.removeSecurityOrigin(frame.securityOrigin); | |
262 if (frame.parentFrame) | |
263 frame.parentFrame._removeChildFrame(frame); | |
264 else | |
265 frame._remove(); | |
266 }, | |
267 | |
268 /** | |
269 * @param {!WebInspector.Event} event | |
270 */ | |
271 _onRequestFinished: function(event) | |
272 { | |
273 if (!this._cachedResourcesProcessed) | |
274 return; | |
275 | |
276 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); | |
277 if (request.failed || request.resourceType() === WebInspector.resourceTy
pes.XHR) | |
278 return; | |
279 | |
280 var frame = this._frames.get(request.frameId); | |
281 if (frame) | |
282 frame._addRequest(request); | |
283 }, | |
284 | |
285 /** | |
286 * @param {!WebInspector.Event} event | |
287 */ | |
288 _onRequestUpdateDropped: function(event) | |
289 { | |
290 if (!this._cachedResourcesProcessed) | |
291 return; | |
292 | |
293 var frameId = event.data.frameId; | |
294 var frame = this._frames.get(frameId); | |
295 if (!frame) | |
296 return; | |
297 | |
298 var url = event.data.url; | |
299 if (frame._resourcesMap[url]) | |
300 return; | |
301 | |
302 var resource = new WebInspector.Resource(this.target(), null, url, frame
.url, frameId, event.data.loaderId, WebInspector.resourceTypes[event.data.resour
ceType], event.data.mimeType, event.data.lastModified, null); | |
303 frame.addResource(resource); | |
304 }, | |
305 | |
306 /** | |
307 * @param {!PageAgent.FrameId} frameId | |
308 * @return {!WebInspector.ResourceTreeFrame} | |
309 */ | |
310 frameForId: function(frameId) | |
311 { | |
312 return this._frames.get(frameId); | |
313 }, | |
314 | |
315 /** | |
316 * @param {function(!WebInspector.Resource)} callback | |
317 * @return {boolean} | |
318 */ | |
319 forAllResources: function(callback) | |
320 { | |
321 if (this.mainFrame) | |
322 return this.mainFrame._callForFrameResources(callback); | |
323 return false; | |
324 }, | |
325 | |
326 /** | |
327 * @return {!Array<!WebInspector.ResourceTreeFrame>} | |
328 */ | |
329 frames: function() | |
330 { | |
331 return this._frames.valuesArray(); | |
332 }, | |
333 | |
334 /** | |
335 * @param {string} url | |
336 * @return {?WebInspector.Resource} | |
337 */ | |
338 resourceForURL: function(url) | |
339 { | |
340 // Workers call into this with no frames available. | |
341 return this.mainFrame ? this.mainFrame.resourceForURL(url) : null; | |
342 }, | |
343 | |
344 /** | |
345 * @param {?WebInspector.ResourceTreeFrame} parentFrame | |
346 * @param {!PageAgent.FrameResourceTree} frameTreePayload | |
347 */ | |
348 _addFramesRecursively: function(parentFrame, frameTreePayload) | |
349 { | |
350 var framePayload = frameTreePayload.frame; | |
351 var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, frameP
ayload.id, framePayload); | |
352 this._addFrame(frame); | |
353 | |
354 var frameResource = this._createResourceFromFramePayload(framePayload, f
ramePayload.url, WebInspector.resourceTypes.Document, framePayload.mimeType, nul
l, null); | |
355 frame.addResource(frameResource); | |
356 | |
357 for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.chi
ldFrames.length; ++i) | |
358 this._addFramesRecursively(frame, frameTreePayload.childFrames[i]); | |
359 | |
360 for (var i = 0; i < frameTreePayload.resources.length; ++i) { | |
361 var subresource = frameTreePayload.resources[i]; | |
362 var resource = this._createResourceFromFramePayload(framePayload, su
bresource.url, WebInspector.resourceTypes[subresource.type], subresource.mimeTyp
e, subresource.lastModified || null, subresource.contentSize || null); | |
363 frame.addResource(resource); | |
364 } | |
365 }, | |
366 | |
367 /** | |
368 * @param {!PageAgent.Frame} frame | |
369 * @param {string} url | |
370 * @param {!WebInspector.ResourceType} type | |
371 * @param {string} mimeType | |
372 * @param {?number} lastModifiedTime | |
373 * @param {?number} contentSize | |
374 * @return {!WebInspector.Resource} | |
375 */ | |
376 _createResourceFromFramePayload: function(frame, url, type, mimeType, lastMo
difiedTime, contentSize) | |
377 { | |
378 var lastModified = typeof lastModifiedTime === "number" ? new Date(lastM
odifiedTime * 1000) : null; | |
379 return new WebInspector.Resource(this.target(), null, url, frame.url, fr
ame.id, frame.loaderId, type, mimeType, lastModified, contentSize); | |
380 }, | |
381 | |
382 suspendReload: function() | |
383 { | |
384 this._reloadSuspensionCount++; | |
385 }, | |
386 | |
387 resumeReload: function() | |
388 { | |
389 this._reloadSuspensionCount--; | |
390 console.assert(this._reloadSuspensionCount >= 0, "Unbalanced call to Res
ourceTreeModel.resumeReload()"); | |
391 if (!this._reloadSuspensionCount && this._pendingReloadOptions) | |
392 this.reloadPage.apply(this, this._pendingReloadOptions); | |
393 }, | |
394 | |
395 /** | |
396 * @param {boolean=} bypassCache | |
397 * @param {string=} scriptToEvaluateOnLoad | |
398 */ | |
399 reloadPage: function(bypassCache, scriptToEvaluateOnLoad) | |
400 { | |
401 // Only dispatch PageReloadRequested upon first reload request to simpli
fy client logic. | |
402 if (!this._pendingReloadOptions) | |
403 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.
PageReloadRequested); | |
404 if (this._reloadSuspensionCount) { | |
405 this._pendingReloadOptions = [bypassCache, scriptToEvaluateOnLoad]; | |
406 return; | |
407 } | |
408 this._pendingReloadOptions = null; | |
409 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.Will
ReloadPage); | |
410 this._agent.reload(bypassCache, scriptToEvaluateOnLoad); | |
411 }, | |
412 | |
413 /** | |
414 * @param {function(string, ?string,!Array<!PageAgent.AppManifestError>)} ca
llback | |
415 */ | |
416 fetchAppManifest: function(callback) | |
417 { | |
418 this._agent.getAppManifest(myCallback); | |
419 /** | |
420 * @param {?Protocol.Error} protocolError | |
421 * @param {string} url | |
422 * @param {!Array<!PageAgent.AppManifestError>} errors | |
423 * @param {string=} data | |
424 */ | |
425 function myCallback(protocolError, url, errors, data) | |
426 { | |
427 if (protocolError) { | |
428 callback(url, null, []); | |
429 return; | |
430 } | |
431 callback(url, data || null, errors); | |
432 } | |
433 }, | |
434 /** | |
435 * @param {!WebInspector.ExecutionContext} a | |
436 * @param {!WebInspector.ExecutionContext} b | |
437 * @return {number} | |
438 */ | |
439 _executionContextComparator: function(a,b) | |
440 { | |
441 /** | |
442 * @param {!WebInspector.ResourceTreeFrame} frame | |
443 */ | |
444 function framePath(frame) | |
445 { | |
446 var currentFrame = frame; | |
447 var parents = []; | |
448 while (currentFrame) { | |
449 parents.push(currentFrame); | |
450 currentFrame = currentFrame.parentFrame; | |
451 } | |
452 return parents.reverse(); | |
453 } | |
454 | |
455 var framesA = a.frameId ? framePath(this.frameForId(a.frameId)) : []; | |
456 var framesB = b.frameId ? framePath(this.frameForId(b.frameId)) : []; | |
457 var frameA; | |
458 var frameB; | |
459 for (var i = 0; ; i++) { | |
460 if (!framesA[i] || !framesB[i] || (framesA[i] !== framesB[i])) { | |
461 frameA = framesA[i]; | |
462 frameB = framesB[i]; | |
463 break; | |
464 } | |
465 } | |
466 if (!frameA && frameB) | |
467 return -1; | |
468 | |
469 if (!frameB && frameA) | |
470 return 1; | |
471 | |
472 if (frameA && frameB) { | |
473 return frameA.id.localeCompare(frameB.id); | |
474 } | |
475 return WebInspector.ExecutionContext.comparator(a,b); | |
476 }, | |
477 | |
478 __proto__: WebInspector.SDKModel.prototype | |
479 }; | |
480 | |
481 /** | |
482 * @constructor | |
483 * @param {!WebInspector.ResourceTreeModel} model | |
484 * @param {?WebInspector.ResourceTreeFrame} parentFrame | |
485 * @param {!PageAgent.FrameId} frameId | |
486 * @param {!PageAgent.Frame=} payload | |
487 */ | |
488 WebInspector.ResourceTreeFrame = function(model, parentFrame, frameId, payload) | |
489 { | |
490 this._model = model; | 469 this._model = model; |
491 this._parentFrame = parentFrame; | 470 this._parentFrame = parentFrame; |
492 this._id = frameId; | 471 this._id = frameId; |
493 this._url = ""; | 472 this._url = ''; |
494 | 473 |
495 if (payload) { | 474 if (payload) { |
496 this._loaderId = payload.loaderId; | 475 this._loaderId = payload.loaderId; |
497 this._name = payload.name; | 476 this._name = payload.name; |
498 this._url = payload.url; | 477 this._url = payload.url; |
499 this._securityOrigin = payload.securityOrigin; | 478 this._securityOrigin = payload.securityOrigin; |
500 this._mimeType = payload.mimeType; | 479 this._mimeType = payload.mimeType; |
501 } | 480 } |
502 | 481 |
503 /** | 482 /** |
504 * @type {!Array.<!WebInspector.ResourceTreeFrame>} | 483 * @type {!Array.<!WebInspector.ResourceTreeFrame>} |
505 */ | 484 */ |
506 this._childFrames = []; | 485 this._childFrames = []; |
507 | 486 |
508 /** | 487 /** |
509 * @type {!Object.<string, !WebInspector.Resource>} | 488 * @type {!Object.<string, !WebInspector.Resource>} |
510 */ | 489 */ |
511 this._resourcesMap = {}; | 490 this._resourcesMap = {}; |
512 | 491 |
513 if (this._parentFrame) | 492 if (this._parentFrame) |
514 this._parentFrame._childFrames.push(this); | 493 this._parentFrame._childFrames.push(this); |
515 }; | 494 } |
516 | 495 |
517 /** | 496 /** |
518 * @param {!WebInspector.ExecutionContext|!WebInspector.CSSStyleSheetHeader|!Web
Inspector.Resource} object | 497 * @param {!WebInspector.ExecutionContext|!WebInspector.CSSStyleSheetHeader|!W
ebInspector.Resource} object |
519 * @return {?WebInspector.ResourceTreeFrame} | 498 * @return {?WebInspector.ResourceTreeFrame} |
520 */ | 499 */ |
521 WebInspector.ResourceTreeFrame._fromObject = function(object) | 500 static _fromObject(object) { |
522 { | |
523 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(object.tar
get()); | 501 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(object.tar
get()); |
524 var frameId = object.frameId; | 502 var frameId = object.frameId; |
525 if (!resourceTreeModel || !frameId) | 503 if (!resourceTreeModel || !frameId) |
526 return null; | 504 return null; |
527 return resourceTreeModel.frameForId(frameId); | 505 return resourceTreeModel.frameForId(frameId); |
528 }; | 506 } |
529 | 507 |
530 /** | 508 /** |
531 * @param {!WebInspector.Script} script | 509 * @param {!WebInspector.Script} script |
532 * @return {?WebInspector.ResourceTreeFrame} | 510 * @return {?WebInspector.ResourceTreeFrame} |
533 */ | 511 */ |
534 WebInspector.ResourceTreeFrame.fromScript = function(script) | 512 static fromScript(script) { |
535 { | |
536 var executionContext = script.executionContext(); | 513 var executionContext = script.executionContext(); |
537 if (!executionContext) | 514 if (!executionContext) |
538 return null; | 515 return null; |
539 return WebInspector.ResourceTreeFrame._fromObject(executionContext); | 516 return WebInspector.ResourceTreeFrame._fromObject(executionContext); |
| 517 } |
| 518 |
| 519 /** |
| 520 * @param {!WebInspector.CSSStyleSheetHeader} header |
| 521 * @return {?WebInspector.ResourceTreeFrame} |
| 522 */ |
| 523 static fromStyleSheet(header) { |
| 524 return WebInspector.ResourceTreeFrame._fromObject(header); |
| 525 } |
| 526 |
| 527 /** |
| 528 * @param {!WebInspector.Resource} resource |
| 529 * @return {?WebInspector.ResourceTreeFrame} |
| 530 */ |
| 531 static fromResource(resource) { |
| 532 return WebInspector.ResourceTreeFrame._fromObject(resource); |
| 533 } |
| 534 |
| 535 /** |
| 536 * @return {!WebInspector.Target} |
| 537 */ |
| 538 target() { |
| 539 return this._model.target(); |
| 540 } |
| 541 |
| 542 /** |
| 543 * @return {string} |
| 544 */ |
| 545 get id() { |
| 546 return this._id; |
| 547 } |
| 548 |
| 549 /** |
| 550 * @return {string} |
| 551 */ |
| 552 get name() { |
| 553 return this._name || ''; |
| 554 } |
| 555 |
| 556 /** |
| 557 * @return {string} |
| 558 */ |
| 559 get url() { |
| 560 return this._url; |
| 561 } |
| 562 |
| 563 /** |
| 564 * @return {string} |
| 565 */ |
| 566 get securityOrigin() { |
| 567 return this._securityOrigin; |
| 568 } |
| 569 |
| 570 /** |
| 571 * @return {string} |
| 572 */ |
| 573 get loaderId() { |
| 574 return this._loaderId; |
| 575 } |
| 576 |
| 577 /** |
| 578 * @return {?WebInspector.ResourceTreeFrame} |
| 579 */ |
| 580 get parentFrame() { |
| 581 return this._parentFrame; |
| 582 } |
| 583 |
| 584 /** |
| 585 * @return {!Array.<!WebInspector.ResourceTreeFrame>} |
| 586 */ |
| 587 get childFrames() { |
| 588 return this._childFrames; |
| 589 } |
| 590 |
| 591 /** |
| 592 * @return {boolean} |
| 593 */ |
| 594 isMainFrame() { |
| 595 return !this._parentFrame; |
| 596 } |
| 597 |
| 598 /** |
| 599 * @param {!PageAgent.Frame} framePayload |
| 600 */ |
| 601 _navigate(framePayload) { |
| 602 this._loaderId = framePayload.loaderId; |
| 603 this._name = framePayload.name; |
| 604 this._url = framePayload.url; |
| 605 this._securityOrigin = framePayload.securityOrigin; |
| 606 this._mimeType = framePayload.mimeType; |
| 607 |
| 608 var mainResource = this._resourcesMap[this._url]; |
| 609 this._resourcesMap = {}; |
| 610 this._removeChildFrames(); |
| 611 if (mainResource && mainResource.loaderId === this._loaderId) |
| 612 this.addResource(mainResource); |
| 613 } |
| 614 |
| 615 /** |
| 616 * @return {!WebInspector.Resource} |
| 617 */ |
| 618 get mainResource() { |
| 619 return this._resourcesMap[this._url]; |
| 620 } |
| 621 |
| 622 /** |
| 623 * @param {!WebInspector.ResourceTreeFrame} frame |
| 624 */ |
| 625 _removeChildFrame(frame) { |
| 626 this._childFrames.remove(frame); |
| 627 frame._remove(); |
| 628 } |
| 629 |
| 630 _removeChildFrames() { |
| 631 var frames = this._childFrames; |
| 632 this._childFrames = []; |
| 633 for (var i = 0; i < frames.length; ++i) |
| 634 frames[i]._remove(); |
| 635 } |
| 636 |
| 637 _remove() { |
| 638 this._removeChildFrames(); |
| 639 this._model._frames.delete(this.id); |
| 640 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.F
rameDetached, this); |
| 641 } |
| 642 |
| 643 /** |
| 644 * @param {!WebInspector.Resource} resource |
| 645 */ |
| 646 addResource(resource) { |
| 647 if (this._resourcesMap[resource.url] === resource) { |
| 648 // Already in the tree, we just got an extra update. |
| 649 return; |
| 650 } |
| 651 this._resourcesMap[resource.url] = resource; |
| 652 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.R
esourceAdded, resource); |
| 653 } |
| 654 |
| 655 /** |
| 656 * @param {!WebInspector.NetworkRequest} request |
| 657 */ |
| 658 _addRequest(request) { |
| 659 var resource = this._resourcesMap[request.url]; |
| 660 if (resource && resource.request === request) { |
| 661 // Already in the tree, we just got an extra update. |
| 662 return; |
| 663 } |
| 664 resource = new WebInspector.Resource( |
| 665 this.target(), request, request.url, request.documentURL, request.frameI
d, request.loaderId, |
| 666 request.resourceType(), request.mimeType, null, null); |
| 667 this._resourcesMap[resource.url] = resource; |
| 668 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.Events.R
esourceAdded, resource); |
| 669 } |
| 670 |
| 671 /** |
| 672 * @return {!Array.<!WebInspector.Resource>} |
| 673 */ |
| 674 resources() { |
| 675 var result = []; |
| 676 for (var url in this._resourcesMap) |
| 677 result.push(this._resourcesMap[url]); |
| 678 return result; |
| 679 } |
| 680 |
| 681 /** |
| 682 * @param {string} url |
| 683 * @return {?WebInspector.Resource} |
| 684 */ |
| 685 resourceForURL(url) { |
| 686 var resource = this._resourcesMap[url] || null; |
| 687 if (resource) |
| 688 return resource; |
| 689 for (var i = 0; !resource && i < this._childFrames.length; ++i) |
| 690 resource = this._childFrames[i].resourceForURL(url); |
| 691 return resource; |
| 692 } |
| 693 |
| 694 /** |
| 695 * @param {function(!WebInspector.Resource)} callback |
| 696 * @return {boolean} |
| 697 */ |
| 698 _callForFrameResources(callback) { |
| 699 for (var url in this._resourcesMap) { |
| 700 if (callback(this._resourcesMap[url])) |
| 701 return true; |
| 702 } |
| 703 |
| 704 for (var i = 0; i < this._childFrames.length; ++i) { |
| 705 if (this._childFrames[i]._callForFrameResources(callback)) |
| 706 return true; |
| 707 } |
| 708 return false; |
| 709 } |
| 710 |
| 711 /** |
| 712 * @return {string} |
| 713 */ |
| 714 displayName() { |
| 715 if (!this._parentFrame) |
| 716 return WebInspector.UIString('top'); |
| 717 var subtitle = new WebInspector.ParsedURL(this._url).displayName; |
| 718 if (subtitle) { |
| 719 if (!this._name) |
| 720 return subtitle; |
| 721 return this._name + ' (' + subtitle + ')'; |
| 722 } |
| 723 return WebInspector.UIString('<iframe>'); |
| 724 } |
540 }; | 725 }; |
541 | 726 |
| 727 |
542 /** | 728 /** |
543 * @param {!WebInspector.CSSStyleSheetHeader} header | 729 * @implements {PageAgent.Dispatcher} |
544 * @return {?WebInspector.ResourceTreeFrame} | 730 * @unrestricted |
545 */ | 731 */ |
546 WebInspector.ResourceTreeFrame.fromStyleSheet = function(header) | 732 WebInspector.PageDispatcher = class { |
547 { | 733 constructor(resourceTreeModel) { |
548 return WebInspector.ResourceTreeFrame._fromObject(header); | 734 this._resourceTreeModel = resourceTreeModel; |
| 735 } |
| 736 |
| 737 /** |
| 738 * @override |
| 739 * @param {number} time |
| 740 */ |
| 741 domContentEventFired(time) { |
| 742 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeMo
del.Events.DOMContentLoaded, time); |
| 743 } |
| 744 |
| 745 /** |
| 746 * @override |
| 747 * @param {number} time |
| 748 */ |
| 749 loadEventFired(time) { |
| 750 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeMo
del.Events.Load, time); |
| 751 } |
| 752 |
| 753 /** |
| 754 * @override |
| 755 * @param {!PageAgent.FrameId} frameId |
| 756 * @param {!PageAgent.FrameId} parentFrameId |
| 757 */ |
| 758 frameAttached(frameId, parentFrameId) { |
| 759 this._resourceTreeModel._frameAttached(frameId, parentFrameId); |
| 760 } |
| 761 |
| 762 /** |
| 763 * @override |
| 764 * @param {!PageAgent.Frame} frame |
| 765 */ |
| 766 frameNavigated(frame) { |
| 767 this._resourceTreeModel._frameNavigated(frame); |
| 768 } |
| 769 |
| 770 /** |
| 771 * @override |
| 772 * @param {!PageAgent.FrameId} frameId |
| 773 */ |
| 774 frameDetached(frameId) { |
| 775 this._resourceTreeModel._frameDetached(frameId); |
| 776 } |
| 777 |
| 778 /** |
| 779 * @override |
| 780 * @param {!PageAgent.FrameId} frameId |
| 781 */ |
| 782 frameStartedLoading(frameId) { |
| 783 } |
| 784 |
| 785 /** |
| 786 * @override |
| 787 * @param {!PageAgent.FrameId} frameId |
| 788 */ |
| 789 frameStoppedLoading(frameId) { |
| 790 } |
| 791 |
| 792 /** |
| 793 * @override |
| 794 * @param {!PageAgent.FrameId} frameId |
| 795 * @param {number} delay |
| 796 */ |
| 797 frameScheduledNavigation(frameId, delay) { |
| 798 } |
| 799 |
| 800 /** |
| 801 * @override |
| 802 * @param {!PageAgent.FrameId} frameId |
| 803 */ |
| 804 frameClearedScheduledNavigation(frameId) { |
| 805 } |
| 806 |
| 807 /** |
| 808 * @override |
| 809 */ |
| 810 frameResized() { |
| 811 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeMo
del.Events.FrameResized, null); |
| 812 } |
| 813 |
| 814 /** |
| 815 * @override |
| 816 * @param {string} message |
| 817 * @param {string} dialogType |
| 818 */ |
| 819 javascriptDialogOpening(message, dialogType) { |
| 820 } |
| 821 |
| 822 /** |
| 823 * @override |
| 824 * @param {boolean} result |
| 825 */ |
| 826 javascriptDialogClosed(result) { |
| 827 } |
| 828 |
| 829 /** |
| 830 * @override |
| 831 * @param {string} data |
| 832 * @param {!PageAgent.ScreencastFrameMetadata=} metadata |
| 833 * @param {number=} sessionId |
| 834 */ |
| 835 screencastFrame(data, metadata, sessionId) { |
| 836 this._resourceTreeModel._agent.screencastFrameAck(sessionId); |
| 837 this._resourceTreeModel.dispatchEventToListeners( |
| 838 WebInspector.ResourceTreeModel.Events.ScreencastFrame, {data: data, meta
data: metadata}); |
| 839 } |
| 840 |
| 841 /** |
| 842 * @override |
| 843 * @param {boolean} visible |
| 844 */ |
| 845 screencastVisibilityChanged(visible) { |
| 846 this._resourceTreeModel.dispatchEventToListeners( |
| 847 WebInspector.ResourceTreeModel.Events.ScreencastVisibilityChanged, {visi
ble: visible}); |
| 848 } |
| 849 |
| 850 /** |
| 851 * @override |
| 852 * @param {!DOMAgent.RGBA} color |
| 853 */ |
| 854 colorPicked(color) { |
| 855 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeMo
del.Events.ColorPicked, color); |
| 856 } |
| 857 |
| 858 /** |
| 859 * @override |
| 860 */ |
| 861 interstitialShown() { |
| 862 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeMo
del.Events.InterstitialShown); |
| 863 } |
| 864 |
| 865 /** |
| 866 * @override |
| 867 */ |
| 868 interstitialHidden() { |
| 869 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeMo
del.Events.InterstitialHidden); |
| 870 } |
| 871 |
| 872 /** |
| 873 * @override |
| 874 */ |
| 875 navigationRequested() { |
| 876 // Frontend is not interested in when navigations are requested. |
| 877 } |
549 }; | 878 }; |
550 | |
551 /** | |
552 * @param {!WebInspector.Resource} resource | |
553 * @return {?WebInspector.ResourceTreeFrame} | |
554 */ | |
555 WebInspector.ResourceTreeFrame.fromResource = function(resource) | |
556 { | |
557 return WebInspector.ResourceTreeFrame._fromObject(resource); | |
558 }; | |
559 | |
560 WebInspector.ResourceTreeFrame.prototype = { | |
561 /** | |
562 * @return {!WebInspector.Target} | |
563 */ | |
564 target: function() | |
565 { | |
566 return this._model.target(); | |
567 }, | |
568 | |
569 /** | |
570 * @return {string} | |
571 */ | |
572 get id() | |
573 { | |
574 return this._id; | |
575 }, | |
576 | |
577 /** | |
578 * @return {string} | |
579 */ | |
580 get name() | |
581 { | |
582 return this._name || ""; | |
583 }, | |
584 | |
585 /** | |
586 * @return {string} | |
587 */ | |
588 get url() | |
589 { | |
590 return this._url; | |
591 }, | |
592 | |
593 /** | |
594 * @return {string} | |
595 */ | |
596 get securityOrigin() | |
597 { | |
598 return this._securityOrigin; | |
599 }, | |
600 | |
601 /** | |
602 * @return {string} | |
603 */ | |
604 get loaderId() | |
605 { | |
606 return this._loaderId; | |
607 }, | |
608 | |
609 /** | |
610 * @return {?WebInspector.ResourceTreeFrame} | |
611 */ | |
612 get parentFrame() | |
613 { | |
614 return this._parentFrame; | |
615 }, | |
616 | |
617 /** | |
618 * @return {!Array.<!WebInspector.ResourceTreeFrame>} | |
619 */ | |
620 get childFrames() | |
621 { | |
622 return this._childFrames; | |
623 }, | |
624 | |
625 /** | |
626 * @return {boolean} | |
627 */ | |
628 isMainFrame: function() | |
629 { | |
630 return !this._parentFrame; | |
631 }, | |
632 | |
633 /** | |
634 * @param {!PageAgent.Frame} framePayload | |
635 */ | |
636 _navigate: function(framePayload) | |
637 { | |
638 this._loaderId = framePayload.loaderId; | |
639 this._name = framePayload.name; | |
640 this._url = framePayload.url; | |
641 this._securityOrigin = framePayload.securityOrigin; | |
642 this._mimeType = framePayload.mimeType; | |
643 | |
644 var mainResource = this._resourcesMap[this._url]; | |
645 this._resourcesMap = {}; | |
646 this._removeChildFrames(); | |
647 if (mainResource && mainResource.loaderId === this._loaderId) | |
648 this.addResource(mainResource); | |
649 }, | |
650 | |
651 /** | |
652 * @return {!WebInspector.Resource} | |
653 */ | |
654 get mainResource() | |
655 { | |
656 return this._resourcesMap[this._url]; | |
657 }, | |
658 | |
659 /** | |
660 * @param {!WebInspector.ResourceTreeFrame} frame | |
661 */ | |
662 _removeChildFrame: function(frame) | |
663 { | |
664 this._childFrames.remove(frame); | |
665 frame._remove(); | |
666 }, | |
667 | |
668 _removeChildFrames: function() | |
669 { | |
670 var frames = this._childFrames; | |
671 this._childFrames = []; | |
672 for (var i = 0; i < frames.length; ++i) | |
673 frames[i]._remove(); | |
674 }, | |
675 | |
676 _remove: function() | |
677 { | |
678 this._removeChildFrames(); | |
679 this._model._frames.delete(this.id); | |
680 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.Even
ts.FrameDetached, this); | |
681 }, | |
682 | |
683 /** | |
684 * @param {!WebInspector.Resource} resource | |
685 */ | |
686 addResource: function(resource) | |
687 { | |
688 if (this._resourcesMap[resource.url] === resource) { | |
689 // Already in the tree, we just got an extra update. | |
690 return; | |
691 } | |
692 this._resourcesMap[resource.url] = resource; | |
693 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.Even
ts.ResourceAdded, resource); | |
694 }, | |
695 | |
696 /** | |
697 * @param {!WebInspector.NetworkRequest} request | |
698 */ | |
699 _addRequest: function(request) | |
700 { | |
701 var resource = this._resourcesMap[request.url]; | |
702 if (resource && resource.request === request) { | |
703 // Already in the tree, we just got an extra update. | |
704 return; | |
705 } | |
706 resource = new WebInspector.Resource(this.target(), request, request.url
, request.documentURL, request.frameId, request.loaderId, request.resourceType()
, request.mimeType, null, null); | |
707 this._resourcesMap[resource.url] = resource; | |
708 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.Even
ts.ResourceAdded, resource); | |
709 }, | |
710 | |
711 /** | |
712 * @return {!Array.<!WebInspector.Resource>} | |
713 */ | |
714 resources: function() | |
715 { | |
716 var result = []; | |
717 for (var url in this._resourcesMap) | |
718 result.push(this._resourcesMap[url]); | |
719 return result; | |
720 }, | |
721 | |
722 /** | |
723 * @param {string} url | |
724 * @return {?WebInspector.Resource} | |
725 */ | |
726 resourceForURL: function(url) | |
727 { | |
728 var resource = this._resourcesMap[url] || null; | |
729 if (resource) | |
730 return resource; | |
731 for (var i = 0; !resource && i < this._childFrames.length; ++i) | |
732 resource = this._childFrames[i].resourceForURL(url); | |
733 return resource; | |
734 }, | |
735 | |
736 /** | |
737 * @param {function(!WebInspector.Resource)} callback | |
738 * @return {boolean} | |
739 */ | |
740 _callForFrameResources: function(callback) | |
741 { | |
742 for (var url in this._resourcesMap) { | |
743 if (callback(this._resourcesMap[url])) | |
744 return true; | |
745 } | |
746 | |
747 for (var i = 0; i < this._childFrames.length; ++i) { | |
748 if (this._childFrames[i]._callForFrameResources(callback)) | |
749 return true; | |
750 } | |
751 return false; | |
752 }, | |
753 | |
754 /** | |
755 * @return {string} | |
756 */ | |
757 displayName: function() | |
758 { | |
759 if (!this._parentFrame) | |
760 return WebInspector.UIString("top"); | |
761 var subtitle = new WebInspector.ParsedURL(this._url).displayName; | |
762 if (subtitle) { | |
763 if (!this._name) | |
764 return subtitle; | |
765 return this._name + " (" + subtitle + ")"; | |
766 } | |
767 return WebInspector.UIString("<iframe>"); | |
768 } | |
769 }; | |
770 | |
771 /** | |
772 * @constructor | |
773 * @implements {PageAgent.Dispatcher} | |
774 */ | |
775 WebInspector.PageDispatcher = function(resourceTreeModel) | |
776 { | |
777 this._resourceTreeModel = resourceTreeModel; | |
778 }; | |
779 | |
780 WebInspector.PageDispatcher.prototype = { | |
781 /** | |
782 * @override | |
783 * @param {number} time | |
784 */ | |
785 domContentEventFired: function(time) | |
786 { | |
787 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.DOMContentLoaded, time); | |
788 }, | |
789 | |
790 /** | |
791 * @override | |
792 * @param {number} time | |
793 */ | |
794 loadEventFired: function(time) | |
795 { | |
796 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.Load, time); | |
797 }, | |
798 | |
799 /** | |
800 * @override | |
801 * @param {!PageAgent.FrameId} frameId | |
802 * @param {!PageAgent.FrameId} parentFrameId | |
803 */ | |
804 frameAttached: function(frameId, parentFrameId) | |
805 { | |
806 this._resourceTreeModel._frameAttached(frameId, parentFrameId); | |
807 }, | |
808 | |
809 /** | |
810 * @override | |
811 * @param {!PageAgent.Frame} frame | |
812 */ | |
813 frameNavigated: function(frame) | |
814 { | |
815 this._resourceTreeModel._frameNavigated(frame); | |
816 }, | |
817 | |
818 /** | |
819 * @override | |
820 * @param {!PageAgent.FrameId} frameId | |
821 */ | |
822 frameDetached: function(frameId) | |
823 { | |
824 this._resourceTreeModel._frameDetached(frameId); | |
825 }, | |
826 | |
827 /** | |
828 * @override | |
829 * @param {!PageAgent.FrameId} frameId | |
830 */ | |
831 frameStartedLoading: function(frameId) | |
832 { | |
833 }, | |
834 | |
835 /** | |
836 * @override | |
837 * @param {!PageAgent.FrameId} frameId | |
838 */ | |
839 frameStoppedLoading: function(frameId) | |
840 { | |
841 }, | |
842 | |
843 /** | |
844 * @override | |
845 * @param {!PageAgent.FrameId} frameId | |
846 * @param {number} delay | |
847 */ | |
848 frameScheduledNavigation: function(frameId, delay) | |
849 { | |
850 }, | |
851 | |
852 /** | |
853 * @override | |
854 * @param {!PageAgent.FrameId} frameId | |
855 */ | |
856 frameClearedScheduledNavigation: function(frameId) | |
857 { | |
858 }, | |
859 | |
860 /** | |
861 * @override | |
862 */ | |
863 frameResized: function() | |
864 { | |
865 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.FrameResized, null); | |
866 }, | |
867 | |
868 /** | |
869 * @override | |
870 * @param {string} message | |
871 * @param {string} dialogType | |
872 */ | |
873 javascriptDialogOpening: function(message, dialogType) | |
874 { | |
875 }, | |
876 | |
877 /** | |
878 * @override | |
879 * @param {boolean} result | |
880 */ | |
881 javascriptDialogClosed: function(result) | |
882 { | |
883 }, | |
884 | |
885 /** | |
886 * @override | |
887 * @param {string} data | |
888 * @param {!PageAgent.ScreencastFrameMetadata=} metadata | |
889 * @param {number=} sessionId | |
890 */ | |
891 screencastFrame: function(data, metadata, sessionId) | |
892 { | |
893 this._resourceTreeModel._agent.screencastFrameAck(sessionId); | |
894 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.ScreencastFrame, { data: data, metadata: metadata }); | |
895 }, | |
896 | |
897 /** | |
898 * @override | |
899 * @param {boolean} visible | |
900 */ | |
901 screencastVisibilityChanged: function(visible) | |
902 { | |
903 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.ScreencastVisibilityChanged, { visible: visible }); | |
904 }, | |
905 | |
906 /** | |
907 * @override | |
908 * @param {!DOMAgent.RGBA} color | |
909 */ | |
910 colorPicked: function(color) | |
911 { | |
912 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.ColorPicked, color); | |
913 }, | |
914 | |
915 /** | |
916 * @override | |
917 */ | |
918 interstitialShown: function() | |
919 { | |
920 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.InterstitialShown); | |
921 }, | |
922 | |
923 /** | |
924 * @override | |
925 */ | |
926 interstitialHidden: function() | |
927 { | |
928 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTr
eeModel.Events.InterstitialHidden); | |
929 }, | |
930 | |
931 /** | |
932 * @override | |
933 */ | |
934 navigationRequested: function() | |
935 { | |
936 // Frontend is not interested in when navigations are requested. | |
937 } | |
938 | |
939 }; | |
OLD | NEW |