ResourceTreeModel.js [plain text]
WebInspector.ResourceTreeModel = function(networkManager)
{
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceTrackingEnabled, this._onResourceTrackingEnabled, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdated, this._onRequestUpdated, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestUpdated, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, this._onRequestUpdateDropped, this);
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
PageAgent.enable();
NetworkAgent.enable();
this._fetchResourceTree();
InspectorBackend.registerPageDispatcher(new WebInspector.PageDispatcher(this));
this._pendingConsoleMessages = {};
}
WebInspector.ResourceTreeModel.EventTypes = {
FrameAdded: "FrameAdded",
FrameNavigated: "FrameNavigated",
FrameDetached: "FrameDetached",
MainFrameNavigated: "MainFrameNavigated",
ResourceAdded: "ResourceAdded",
ResourceContentCommitted: "resource-content-committed",
WillLoadCachedResources: "WillLoadCachedResources",
CachedResourcesLoaded: "CachedResourcesLoaded",
DOMContentLoaded: "DOMContentLoaded",
OnLoad: "OnLoad",
InspectedURLChanged: "InspectedURLChanged"
}
WebInspector.ResourceTreeModel.prototype = {
_onResourceTrackingEnabled: function()
{
this._fetchResourceTree();
},
_fetchResourceTree: function()
{
this._frames = {};
delete this._cachedResourcesProcessed;
PageAgent.getResourceTree(this._processCachedResources.bind(this));
},
_processCachedResources: function(error, mainFramePayload)
{
if (error) {
console.error(JSON.stringify(error));
return;
}
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources);
WebInspector.inspectedPageURL = mainFramePayload.frame.url;
this._addFramesRecursively(null, mainFramePayload);
this._dispatchInspectedURLChanged();
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded);
WebInspector.Resource.restoreRevisions();
this._cachedResourcesProcessed = true;
},
_dispatchInspectedURLChanged: function()
{
InspectorFrontendHost.inspectedURLChanged(WebInspector.inspectedPageURL);
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, WebInspector.inspectedPageURL);
},
_addFrame: function(frame)
{
this._frames[frame.id] = frame;
if (frame.isMainFrame())
this.mainFrame = frame;
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame);
},
_frameNavigated: function(framePayload)
{
if (this._frontendReused(framePayload))
return;
if (!this._cachedResourcesProcessed)
return;
var frame = this._frames[framePayload.id];
if (frame) {
frame._navigate(framePayload);
} else {
var parentFrame = this._frames[framePayload.parentId];
frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload);
if (frame.isMainFrame() && this.mainFrame) {
this._frameDetached(this.mainFrame.id);
}
this._addFrame(frame);
}
if (frame.isMainFrame())
WebInspector.inspectedPageURL = frame.url;
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, frame);
if (frame.isMainFrame())
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, frame);
var resources = frame.resources();
for (var i = 0; i < resources.length; ++i)
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resources[i]);
if (frame.isMainFrame())
this._dispatchInspectedURLChanged();
},
_frontendReused: function(framePayload)
{
if (!framePayload.parentId && !WebInspector.networkLog.requests.length) {
this._fetchResourceTree();
return true;
}
return false;
},
_frameDetached: function(frameId)
{
if (!this._cachedResourcesProcessed)
return;
var frame = this._frames[frameId];
if (!frame)
return;
if (frame.parentFrame)
frame.parentFrame._removeChildFrame(frame);
else
frame._remove();
},
_onRequestUpdated: function(event)
{
if (!this._cachedResourcesProcessed)
return;
var request = event.data;
if (request.failed || request.type === WebInspector.resourceTypes.XHR)
return;
var frame = this._frames[request.frameId];
if (frame) {
var resource = frame._addRequest(request);
this._addPendingConsoleMessagesToResource(resource);
}
},
_onRequestUpdateDropped: function(event)
{
if (!this._cachedResourcesProcessed)
return;
var frameId = event.data.frameId;
var frame = this._frames[frameId];
if (!frame)
return;
var url = event.data.url;
if (frame._resourcesMap[url])
return;
var resource = new WebInspector.Resource(null, url, frame.url, frameId, event.data.loaderId, WebInspector.resourceTypes[event.data.resourceType], event.data.mimeType);
frame._addResource(resource);
},
frameForId: function(frameId)
{
return this._frames[frameId];
},
forAllResources: function(callback)
{
if (this.mainFrame)
return this.mainFrame._callForFrameResources(callback);
return false;
},
_consoleMessageAdded: function(event)
{
var msg = event.data;
var resource = msg.url ? this.resourceForURL(msg.url) : null;
if (resource)
this._addConsoleMessageToResource(msg, resource);
else
this._addPendingConsoleMessage(msg);
},
_addPendingConsoleMessage: function(msg)
{
if (!msg.url)
return;
if (!this._pendingConsoleMessages[msg.url])
this._pendingConsoleMessages[msg.url] = [];
this._pendingConsoleMessages[msg.url].push(msg);
},
_addPendingConsoleMessagesToResource: function(resource)
{
var messages = this._pendingConsoleMessages[resource.url];
if (messages) {
for (var i = 0; i < messages.length; i++)
this._addConsoleMessageToResource(messages[i], resource);
delete this._pendingConsoleMessages[resource.url];
}
},
_addConsoleMessageToResource: function(msg, resource)
{
switch (msg.level) {
case WebInspector.ConsoleMessage.MessageLevel.Warning:
resource.warnings += msg.repeatDelta;
break;
case WebInspector.ConsoleMessage.MessageLevel.Error:
resource.errors += msg.repeatDelta;
break;
}
resource.addMessage(msg);
},
_consoleCleared: function()
{
function callback(resource)
{
resource.clearErrorsAndWarnings();
}
this._pendingConsoleMessages = {};
this.forAllResources(callback);
},
resourceForURL: function(url)
{
return this.mainFrame ? this.mainFrame.resourceForURL(url) : null;
},
_addFramesRecursively: function(parentFrame, frameTreePayload)
{
var framePayload = frameTreePayload.frame;
var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload);
var frameResource = this._createResourceFromFramePayload(framePayload, framePayload.url, WebInspector.resourceTypes.Document, framePayload.mimeType);
if (frame.isMainFrame())
WebInspector.inspectedPageURL = frameResource.url;
this._addFrame(frame);
frame._addResource(frameResource);
for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i)
this._addFramesRecursively(frame, frameTreePayload.childFrames[i]);
if (!frameTreePayload.resources)
return;
for (var i = 0; i < frameTreePayload.resources.length; ++i) {
var subresource = frameTreePayload.resources[i];
var resource = this._createResourceFromFramePayload(framePayload, subresource.url, WebInspector.resourceTypes[subresource.type], subresource.mimeType);
frame._addResource(resource);
}
},
_createResourceFromFramePayload: function(frame, url, type, mimeType)
{
return new WebInspector.Resource(null, url, frame.url, frame.id, frame.loaderId, type, mimeType);
}
}
WebInspector.ResourceTreeModel.prototype.__proto__ = WebInspector.Object.prototype;
WebInspector.ResourceTreeFrame = function(model, parentFrame, payload)
{
this._model = model;
this._parentFrame = parentFrame;
this._id = payload.id;
this._loaderId = payload.loaderId;
this._name = payload.name;
this._url = payload.url;
this._securityOrigin = payload.securityOrigin || "";
this._mimeType = payload.mimeType;
this._childFrames = [];
this._resourcesMap = {};
if (this._parentFrame)
this._parentFrame._childFrames.push(this);
}
WebInspector.ResourceTreeFrame.prototype = {
get id()
{
return this._id;
},
get name()
{
return this._name || "";
},
get url()
{
return this._url;
},
get securityOrigin()
{
return this._securityOrigin;
},
get loaderId()
{
return this._loaderId;
},
get parentFrame()
{
return this._parentFrame;
},
get childFrames()
{
return this._childFrames;
},
isMainFrame: function()
{
return !this._parentFrame;
},
_navigate: function(framePayload)
{
this._loaderId = framePayload.loaderId;
this._name = framePayload.name;
this._url = framePayload.url;
this._securityOrigin = framePayload.securityOrigin || "";
this._mimeType = framePayload.mimeType;
var mainResource = this._resourcesMap[this._url];
this._resourcesMap = {};
this._removeChildFrames();
if (mainResource && mainResource.loaderId === this._loaderId)
this._addResource(mainResource);
},
get mainResource()
{
return this._resourcesMap[this._url];
},
_removeChildFrame: function(frame)
{
this._childFrames.remove(frame);
frame._remove();
},
_removeChildFrames: function()
{
var copy = this._childFrames.slice();
for (var i = 0; i < copy.length; ++i)
this._removeChildFrame(copy[i]);
},
_remove: function()
{
this._removeChildFrames();
delete this._model._frames[this.id];
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this);
},
_addResource: function(resource)
{
if (this._resourcesMap[resource.url] === resource) {
return;
}
this._resourcesMap[resource.url] = resource;
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
},
_addRequest: function(request)
{
var resource = this._resourcesMap[request.url];
if (resource && resource.request === request) {
return resource;
}
resource = new WebInspector.Resource(request, request.url, request.documentURL, request.frameId, request.loaderId, request.type, request.mimeType);
this._resourcesMap[resource.url] = resource;
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
return resource;
},
resources: function()
{
var result = [];
for (var url in this._resourcesMap)
result.push(this._resourcesMap[url]);
return result;
},
resourceForURL: function(url)
{
var result;
function filter(resource)
{
if (resource.url === url) {
result = resource;
return true;
}
}
this._callForFrameResources(filter);
return result;
},
_callForFrameResources: function(callback)
{
for (var url in this._resourcesMap) {
if (callback(this._resourcesMap[url]))
return true;
}
for (var i = 0; i < this._childFrames.length; ++i) {
if (this._childFrames[i]._callForFrameResources(callback))
return true;
}
return false;
}
}
WebInspector.PageDispatcher = function(resourceTreeModel)
{
this._resourceTreeModel = resourceTreeModel;
}
WebInspector.PageDispatcher.prototype = {
domContentEventFired: function(time)
{
this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, time);
},
loadEventFired: function(time)
{
this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.OnLoad, time);
},
frameNavigated: function(frame)
{
this._resourceTreeModel._frameNavigated(frame);
},
frameDetached: function(frameId)
{
this._resourceTreeModel._frameDetached(frameId);
}
}
WebInspector.resourceTreeModel = null;