| /* |
| * Copyright (C) 2011 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| WebInspector.ResourceTreeModel = function(networkManager) |
| { |
| WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this); |
| WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this); |
| WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this); |
| WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.FrameDetached, this._onFrameDetachedFromParent, this); |
| WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.FrameCommittedLoad, this._onCommitLoad, this); |
| |
| this.frontendReused(); |
| } |
| |
| WebInspector.ResourceTreeModel.EventTypes = { |
| FrameAdded: "FrameAdded", |
| FrameNavigated: "FrameNavigated", |
| FrameDetached: "FrameDetached", |
| ResourceAdded: "ResourceAdded", |
| CachedResourcesLoaded: "CachedResourcesLoaded" |
| } |
| |
| WebInspector.ResourceTreeModel.prototype = { |
| frontendReused: function() |
| { |
| this._resourcesByURL = {}; |
| this._resourcesByFrameId = {}; |
| this._subframes = {}; |
| NetworkAgent.getCachedResources(this._processCachedResources.bind(this)); |
| }, |
| |
| _processCachedResources: function(error, mainFramePayload) |
| { |
| if (error) |
| return; |
| |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, 0); |
| |
| WebInspector.mainResource = this._addFramesRecursively(mainFramePayload); |
| this._cachedResourcesProcessed = true; |
| |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded); |
| }, |
| |
| _addOrUpdateFrame: function(frame) |
| { |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame); |
| |
| var subframes = this._subframes[frame.parentId]; |
| if (!subframes) { |
| subframes = []; |
| this._subframes[frame.parentId || 0] = subframes; |
| } |
| subframes.push(frame); |
| }, |
| |
| frames: function(parentFrameId) |
| { |
| return this._subframes[parentFrameId] || []; |
| }, |
| |
| subframes: function(parentFrameId) |
| { |
| return this._subframes[parentFrameId] || []; |
| }, |
| |
| resources: function(frameId) |
| { |
| var result = []; |
| var resources = this._resourcesByFrameId[frameId] || {}; |
| for (var url in resources) |
| result.push(resources[url]); |
| return result; |
| }, |
| |
| _onCommitLoad: function(event) |
| { |
| if (!this._cachedResourcesProcessed) |
| return; |
| |
| var frame = event.data.frame; |
| var loaderId = event.data.loaderId; |
| var isMainFrame = !frame.parentId; |
| |
| // frame.parentId === 0 is when main frame navigation happens. |
| this._clearChildFramesAndResources(isMainFrame ? 0 : frame.id, loaderId); |
| |
| this._addOrUpdateFrame(frame); |
| |
| var resourcesForFrame = this._resourcesByFrameId[frame.id]; |
| if (resourcesForFrame) { |
| for (var url in resourcesForFrame) |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resourcesForFrame[url]); |
| } |
| |
| if (isMainFrame && this.resourceForURL(frame.url)) |
| WebInspector.mainResource = this.resourceForURL(frame.url); |
| }, |
| |
| _onFrameDetachedFromParent: function(event) |
| { |
| if (!this._cachedResourcesProcessed) |
| return; |
| |
| var frameId = event.data; |
| this._clearChildFramesAndResources(frameId, 0); |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, frameId); |
| }, |
| |
| _onResourceStarted: function(event) |
| { |
| if (!this._cachedResourcesProcessed) |
| return; |
| this._bindResourceURL(event.data); |
| }, |
| |
| _onResourceUpdated: function(event) |
| { |
| if (!this._cachedResourcesProcessed) |
| return; |
| this._addResourceToFrame(event.data); |
| }, |
| |
| _addResourceToFrame: function(resource) |
| { |
| var frameId = resource.frameId; |
| var resourcesForFrame = this._resourcesByFrameId[frameId]; |
| if (!resourcesForFrame) { |
| resourcesForFrame = {}; |
| this._resourcesByFrameId[frameId] = resourcesForFrame; |
| } |
| if (resourcesForFrame[resource.url] === resource) { |
| // Already in the tree, we just got an extra update. |
| return; |
| } |
| |
| resourcesForFrame[resource.url] = resource; |
| this._bindResourceURL(resource); |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource); |
| }, |
| |
| forAllResources: function(callback) |
| { |
| this._callForFrameResources(0, callback); |
| }, |
| |
| addConsoleMessage: function(msg) |
| { |
| var resource = this.resourceForURL(msg.url); |
| if (!resource) |
| return; |
| |
| switch (msg.level) { |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: |
| resource.warnings += msg.repeatDelta; |
| break; |
| case WebInspector.ConsoleMessage.MessageLevel.Error: |
| resource.errors += msg.repeatDelta; |
| break; |
| } |
| |
| var view = WebInspector.ResourceView.resourceViewForResource(resource); |
| if (view.addMessage && msg.isErrorOrWarning() && msg.message) |
| view.addMessage(msg); |
| }, |
| |
| clearConsoleMessages: function() |
| { |
| function callback(resource) |
| { |
| resource.clearErrorsAndWarnings(); |
| } |
| this.forAllResources(callback); |
| }, |
| |
| resourceForURL: function(url) |
| { |
| return this._resourcesByURL[url]; |
| }, |
| |
| _bindResourceURL: function(resource) |
| { |
| this._resourcesByURL[resource.url] = resource; |
| }, |
| |
| _clearChildFramesAndResources: function(frameId, loaderToPreserveId) |
| { |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, frameId); |
| |
| this._clearResources(frameId, loaderToPreserveId); |
| var subframes = this._subframes[frameId]; |
| for (var i = 0; subframes && i < subframes.length; ++ i) { |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameRemoved, subframes[i].id); |
| this._clearChildFramesAndResources(subframes[i].id, loaderToPreserveId); |
| } |
| delete this._subframes[frameId]; |
| }, |
| |
| _clearResources: function(frameId, loaderToPreserveId) |
| { |
| var resourcesForFrame = this._resourcesByFrameId[frameId]; |
| if (!resourcesForFrame) |
| return; |
| |
| var preservedResourcesForFrame = []; |
| for (var url in resourcesForFrame) { |
| var resource = resourcesForFrame[url]; |
| if (resource.loaderId === loaderToPreserveId) { |
| preservedResourcesForFrame[url] = resource; |
| continue; |
| } |
| this._unbindResourceURL(resource); |
| } |
| |
| delete this._resourcesByFrameId[frameId]; |
| if (preservedResourcesForFrame.length) { |
| this._resourcesByFrameId[frameId] = preservedResourcesForFrame; |
| } |
| }, |
| |
| _callForFrameResources: function(frameId, callback) |
| { |
| var resources = this._resourcesByFrameId[frameId]; |
| |
| for (var url in resources) { |
| if (callback(resources[url])) |
| return true; |
| } |
| |
| var frames = this._subframes[frameId]; |
| for (var i = 0; frames && i < frames.length; ++i) { |
| if (this._callForFrameResources(frames[i].id, callback)) |
| return true; |
| } |
| return false; |
| }, |
| |
| _unbindResourceURL: function(resource) |
| { |
| delete this._resourcesByURL[resource.url]; |
| }, |
| |
| _addFramesRecursively: function(frameTreePayload) |
| { |
| var framePayload = frameTreePayload.frame; |
| |
| // Create frame resource. |
| var frameResource = this._createResource(framePayload, framePayload.url); |
| frameResource.type = WebInspector.Resource.Type.Document; |
| frameResource.finished = true; |
| |
| this._addOrUpdateFrame(framePayload); |
| this._addResourceToFrame(frameResource); |
| |
| for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i) |
| this._addFramesRecursively(frameTreePayload.childFrames[i]); |
| |
| if (!frameTreePayload.resources) |
| return; |
| |
| // Create frame subresources. |
| for (var i = 0; i < frameTreePayload.resources.length; ++i) { |
| var subresource = frameTreePayload.resources[i]; |
| var resource = this._createResource(framePayload, subresource.url); |
| resource.type = WebInspector.Resource.Type[subresource.type]; |
| resource.finished = true; |
| this._addResourceToFrame(resource); |
| } |
| return frameResource; |
| }, |
| |
| _createResource: function(frame, url) |
| { |
| var resource = new WebInspector.Resource(null, url); |
| resource.frameId = frame.id; |
| resource.loaderId = frame.loaderId; |
| resource.documentURL = frame.url; |
| return resource; |
| } |
| } |
| |
| WebInspector.ResourceTreeModel.prototype.__proto__ = WebInspector.Object.prototype; |