summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js640
1 files changed, 640 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js b/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js
new file mode 100644
index 000000000..2fa0c936f
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2013 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.FrameResourceManager = class FrameResourceManager extends WebInspector.Object
+{
+ constructor()
+ {
+ super();
+
+ if (window.PageAgent)
+ PageAgent.enable();
+ if (window.NetworkAgent)
+ NetworkAgent.enable();
+
+ WebInspector.notifications.addEventListener(WebInspector.Notification.ExtraDomainsActivated, this._extraDomainsActivated, this);
+
+ this.initialize();
+ }
+
+ // Public
+
+ initialize()
+ {
+ var oldMainFrame = this._mainFrame;
+
+ this._frameIdentifierMap = new Map;
+ this._mainFrame = null;
+ this._resourceRequestIdentifierMap = new Map;
+ this._orphanedResources = new Map;
+
+ if (this._mainFrame !== oldMainFrame)
+ this._mainFrameDidChange(oldMainFrame);
+
+ this._waitingForMainFrameResourceTreePayload = true;
+ if (window.PageAgent)
+ PageAgent.getResourceTree(this._processMainFrameResourceTreePayload.bind(this));
+ }
+
+ get mainFrame()
+ {
+ return this._mainFrame;
+ }
+
+ get frames()
+ {
+ return [...this._frameIdentifierMap.values()];
+ }
+
+ frameForIdentifier(frameId)
+ {
+ return this._frameIdentifierMap.get(frameId) || null;
+ }
+
+ frameDidNavigate(framePayload)
+ {
+ // Called from WebInspector.PageObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ var frameWasLoadedInstantly = false;
+
+ var frame = this.frameForIdentifier(framePayload.id);
+ if (!frame) {
+ // If the frame wasn't known before now, then the main resource was loaded instantly (about:blank, etc.)
+ // Make a new resource (which will make the frame). Mark will mark it as loaded at the end too since we
+ // don't expect any more events about the load finishing for these frames.
+ var frameResource = this._addNewResourceToFrameOrTarget(null, framePayload.id, framePayload.loaderId, framePayload.url, null, null, null, null, null, framePayload.name, framePayload.securityOrigin);
+ frame = frameResource.parentFrame;
+ frameWasLoadedInstantly = true;
+
+ console.assert(frame);
+ if (!frame)
+ return;
+ }
+
+ if (framePayload.loaderId === frame.provisionalLoaderIdentifier) {
+ // There was a provisional load in progress, commit it.
+ frame.commitProvisionalLoad(framePayload.securityOrigin);
+ } else {
+ if (frame.mainResource.url !== framePayload.url || frame.loaderIdentifier !== framePayload.loaderId) {
+ // Navigations like back/forward do not have provisional loads, so create a new main resource here.
+ var mainResource = new WebInspector.Resource(framePayload.url, framePayload.mimeType, null, framePayload.loaderId);
+ } else {
+ // The main resource is already correct, so reuse it.
+ var mainResource = frame.mainResource;
+ }
+
+ frame.initialize(framePayload.name, framePayload.securityOrigin, framePayload.loaderId, mainResource);
+ }
+
+ var oldMainFrame = this._mainFrame;
+
+ if (framePayload.parentId) {
+ var parentFrame = this.frameForIdentifier(framePayload.parentId);
+ console.assert(parentFrame);
+
+ if (frame === this._mainFrame)
+ this._mainFrame = null;
+
+ if (frame.parentFrame !== parentFrame)
+ parentFrame.addChildFrame(frame);
+ } else {
+ if (frame.parentFrame)
+ frame.parentFrame.removeChildFrame(frame);
+ this._mainFrame = frame;
+ }
+
+ if (this._mainFrame !== oldMainFrame)
+ this._mainFrameDidChange(oldMainFrame);
+
+ if (frameWasLoadedInstantly)
+ frame.mainResource.markAsFinished();
+ }
+
+ frameDidDetach(frameId)
+ {
+ // Called from WebInspector.PageObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ var frame = this.frameForIdentifier(frameId);
+ if (!frame)
+ return;
+
+ if (frame.parentFrame)
+ frame.parentFrame.removeChildFrame(frame);
+
+ this._frameIdentifierMap.delete(frame.id);
+
+ var oldMainFrame = this._mainFrame;
+
+ if (frame === this._mainFrame)
+ this._mainFrame = null;
+
+ frame.clearExecutionContexts();
+
+ this.dispatchEventToListeners(WebInspector.FrameResourceManager.Event.FrameWasRemoved, {frame});
+
+ if (this._mainFrame !== oldMainFrame)
+ this._mainFrameDidChange(oldMainFrame);
+ }
+
+ resourceRequestWillBeSent(requestIdentifier, frameIdentifier, loaderIdentifier, request, type, redirectResponse, timestamp, initiator, targetId)
+ {
+ // Called from WebInspector.NetworkObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ // COMPATIBILITY (iOS 8): Timeline timestamps for legacy backends are computed
+ // dynamically from the first backend timestamp received. For navigations we
+ // need to reset that base timestamp, and an appropriate timestamp to use is
+ // the new main resource's will be sent timestamp. So save this value on the
+ // resource in case it becomes a main resource.
+ var originalRequestWillBeSentTimestamp = timestamp;
+
+ var elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
+ let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
+ if (resource) {
+ // This is an existing request which is being redirected, update the resource.
+ console.assert(redirectResponse);
+ console.assert(!targetId);
+ resource.updateForRedirectResponse(request.url, request.headers, elapsedTime);
+ return;
+ }
+
+ var initiatorSourceCodeLocation = this._initiatorSourceCodeLocationFromPayload(initiator);
+
+ // This is a new request, make a new resource and add it to the right frame.
+ resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, request.url, type, request.method, request.headers, request.postData, elapsedTime, null, null, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId);
+
+ // Associate the resource with the requestIdentifier so it can be found in future loading events.
+ this._resourceRequestIdentifierMap.set(requestIdentifier, resource);
+ }
+
+ markResourceRequestAsServedFromMemoryCache(requestIdentifier)
+ {
+ // Called from WebInspector.NetworkObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
+
+ // We might not have a resource if the inspector was opened during the page load (after resourceRequestWillBeSent is called).
+ // We don't want to assert in this case since we do likely have the resource, via PageAgent.getResourceTree. The Resource
+ // just doesn't have a requestIdentifier for us to look it up.
+ if (!resource)
+ return;
+
+ resource.markAsCached();
+ }
+
+ resourceRequestWasServedFromMemoryCache(requestIdentifier, frameIdentifier, loaderIdentifier, cachedResourcePayload, timestamp, initiator)
+ {
+ // Called from WebInspector.NetworkObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ console.assert(!this._resourceRequestIdentifierMap.has(requestIdentifier));
+
+ var elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
+ var initiatorSourceCodeLocation = this._initiatorSourceCodeLocationFromPayload(initiator);
+ var response = cachedResourcePayload.response;
+ var resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, cachedResourcePayload.url, cachedResourcePayload.type, "GET", null, null, elapsedTime, null, null, initiatorSourceCodeLocation);
+ resource.markAsCached();
+ resource.updateForResponse(cachedResourcePayload.url, response.mimeType, cachedResourcePayload.type, response.headers, response.status, response.statusText, elapsedTime, response.timing);
+ resource.increaseSize(cachedResourcePayload.bodySize, elapsedTime);
+ resource.increaseTransferSize(cachedResourcePayload.bodySize);
+ resource.markAsFinished(elapsedTime);
+
+ if (cachedResourcePayload.sourceMapURL)
+ WebInspector.sourceMapManager.downloadSourceMap(cachedResourcePayload.sourceMapURL, resource.url, resource);
+
+ // No need to associate the resource with the requestIdentifier, since this is the only event
+ // sent for memory cache resource loads.
+ }
+
+ resourceRequestDidReceiveResponse(requestIdentifier, frameIdentifier, loaderIdentifier, type, response, timestamp)
+ {
+ // Called from WebInspector.NetworkObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ var elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
+ let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
+
+ // We might not have a resource if the inspector was opened during the page load (after resourceRequestWillBeSent is called).
+ // We don't want to assert in this case since we do likely have the resource, via PageAgent.getResourceTree. The Resource
+ // just doesn't have a requestIdentifier for us to look it up, but we can try to look it up by its URL.
+ if (!resource) {
+ var frame = this.frameForIdentifier(frameIdentifier);
+ if (frame)
+ resource = frame.resourceForURL(response.url);
+
+ // If we find the resource this way we had marked it earlier as finished via PageAgent.getResourceTree.
+ // Associate the resource with the requestIdentifier so it can be found in future loading events.
+ // and roll it back to an unfinished state, we know now it is still loading.
+ if (resource) {
+ this._resourceRequestIdentifierMap.set(requestIdentifier, resource);
+ resource.revertMarkAsFinished();
+ }
+ }
+
+ // If we haven't found an existing Resource by now, then it is a resource that was loading when the inspector
+ // opened and we just missed the resourceRequestWillBeSent for it. So make a new resource and add it.
+ if (!resource) {
+ resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, response.url, type, null, response.requestHeaders, null, elapsedTime, null, null, null);
+
+ // Associate the resource with the requestIdentifier so it can be found in future loading events.
+ this._resourceRequestIdentifierMap.set(requestIdentifier, resource);
+ }
+
+ if (response.fromDiskCache)
+ resource.markAsCached();
+
+ resource.updateForResponse(response.url, response.mimeType, type, response.headers, response.status, response.statusText, elapsedTime, response.timing);
+ }
+
+ resourceRequestDidReceiveData(requestIdentifier, dataLength, encodedDataLength, timestamp)
+ {
+ // Called from WebInspector.NetworkObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
+ var elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
+
+ // We might not have a resource if the inspector was opened during the page load (after resourceRequestWillBeSent is called).
+ // We don't want to assert in this case since we do likely have the resource, via PageAgent.getResourceTree. The Resource
+ // just doesn't have a requestIdentifier for us to look it up.
+ if (!resource)
+ return;
+
+ resource.increaseSize(dataLength, elapsedTime);
+
+ if (encodedDataLength !== -1)
+ resource.increaseTransferSize(encodedDataLength);
+ }
+
+ resourceRequestDidFinishLoading(requestIdentifier, timestamp, sourceMapURL)
+ {
+ // Called from WebInspector.NetworkObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ // By now we should always have the Resource. Either it was fetched when the inspector first opened with
+ // PageAgent.getResourceTree, or it was a currently loading resource that we learned about in resourceRequestDidReceiveResponse.
+ let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
+ console.assert(resource);
+ if (!resource)
+ return;
+
+ var elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
+ resource.markAsFinished(elapsedTime);
+
+ if (sourceMapURL)
+ WebInspector.sourceMapManager.downloadSourceMap(sourceMapURL, resource.url, resource);
+
+ this._resourceRequestIdentifierMap.delete(requestIdentifier);
+ }
+
+ resourceRequestDidFailLoading(requestIdentifier, canceled, timestamp)
+ {
+ // Called from WebInspector.NetworkObserver.
+
+ // Ignore this while waiting for the whole frame/resource tree.
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ // By now we should always have the Resource. Either it was fetched when the inspector first opened with
+ // PageAgent.getResourceTree, or it was a currently loading resource that we learned about in resourceRequestDidReceiveResponse.
+ let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
+ console.assert(resource);
+ if (!resource)
+ return;
+
+ var elapsedTime = WebInspector.timelineManager.computeElapsedTime(timestamp);
+ resource.markAsFailed(canceled, elapsedTime);
+
+ if (resource === resource.parentFrame.provisionalMainResource)
+ resource.parentFrame.clearProvisionalLoad();
+
+ this._resourceRequestIdentifierMap.delete(requestIdentifier);
+ }
+
+ executionContextCreated(contextPayload)
+ {
+ // Called from WebInspector.RuntimeObserver.
+
+ var frame = this.frameForIdentifier(contextPayload.frameId);
+ console.assert(frame);
+ if (!frame)
+ return;
+
+ var displayName = contextPayload.name || frame.mainResource.displayName;
+ var executionContext = new WebInspector.ExecutionContext(WebInspector.mainTarget, contextPayload.id, displayName, contextPayload.isPageContext, frame);
+ frame.addExecutionContext(executionContext);
+ }
+
+ resourceForURL(url)
+ {
+ if (!this._mainFrame)
+ return null;
+
+ if (this._mainFrame.mainResource.url === url)
+ return this._mainFrame.mainResource;
+
+ return this._mainFrame.resourceForURL(url, true);
+ }
+
+ adoptOrphanedResourcesForTarget(target)
+ {
+ let resources = this._orphanedResources.take(target.identifier);
+ if (!resources)
+ return;
+
+ for (let resource of resources)
+ target.adoptResource(resource);
+ }
+
+ // Private
+
+ _addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, url, type, requestMethod, requestHeaders, requestData, elapsedTime, frameName, frameSecurityOrigin, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId)
+ {
+ console.assert(!this._waitingForMainFrameResourceTreePayload);
+
+ let resource = null;
+
+ let frame = this.frameForIdentifier(frameIdentifier);
+ if (frame) {
+ // This is a new request for an existing frame, which might be the main resource or a new resource.
+ if (frame.mainResource.url === url && frame.loaderIdentifier === loaderIdentifier)
+ resource = frame.mainResource;
+ else if (frame.provisionalMainResource && frame.provisionalMainResource.url === url && frame.provisionalLoaderIdentifier === loaderIdentifier)
+ resource = frame.provisionalMainResource;
+ else {
+ resource = new WebInspector.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
+ if (resource.target === WebInspector.mainTarget)
+ this._addResourceToFrame(frame, resource);
+ else if (resource.target)
+ resource.target.addResource(resource);
+ else
+ this._addOrphanedResource(resource, targetId);
+ }
+ } else {
+ // This is a new request for a new frame, which is always the main resource.
+ console.assert(!targetId);
+ resource = new WebInspector.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
+ frame = new WebInspector.Frame(frameIdentifier, frameName, frameSecurityOrigin, loaderIdentifier, resource);
+ this._frameIdentifierMap.set(frame.id, frame);
+
+ // If we don't have a main frame, assume this is it. This can change later in
+ // frameDidNavigate when the parent frame is known.
+ if (!this._mainFrame) {
+ this._mainFrame = frame;
+ this._mainFrameDidChange(null);
+ }
+
+ this._dispatchFrameWasAddedEvent(frame);
+ }
+
+ console.assert(resource);
+
+ return resource;
+ }
+
+ _addResourceToFrame(frame, resource)
+ {
+ console.assert(!this._waitingForMainFrameResourceTreePayload);
+ if (this._waitingForMainFrameResourceTreePayload)
+ return;
+
+ console.assert(frame);
+ console.assert(resource);
+
+ if (resource.loaderIdentifier !== frame.loaderIdentifier && !frame.provisionalLoaderIdentifier) {
+ // This is the start of a provisional load which happens before frameDidNavigate is called.
+ // This resource will be the new mainResource if frameDidNavigate is called.
+ frame.startProvisionalLoad(resource);
+ return;
+ }
+
+ // This is just another resource, either for the main loader or the provisional loader.
+ console.assert(resource.loaderIdentifier === frame.loaderIdentifier || resource.loaderIdentifier === frame.provisionalLoaderIdentifier);
+ frame.addResource(resource);
+ }
+
+ _addResourceToTarget(target, resource)
+ {
+ console.assert(target !== WebInspector.mainTarget);
+ console.assert(resource);
+
+ target.addResource(resource);
+ }
+
+ _initiatorSourceCodeLocationFromPayload(initiatorPayload)
+ {
+ if (!initiatorPayload)
+ return null;
+
+ var url = null;
+ var lineNumber = NaN;
+ var columnNumber = 0;
+
+ if (initiatorPayload.stackTrace && initiatorPayload.stackTrace.length) {
+ var stackTracePayload = initiatorPayload.stackTrace;
+ for (var i = 0; i < stackTracePayload.length; ++i) {
+ var callFramePayload = stackTracePayload[i];
+ if (!callFramePayload.url || callFramePayload.url === "[native code]")
+ continue;
+
+ url = callFramePayload.url;
+
+ // The lineNumber is 1-based, but we expect 0-based.
+ lineNumber = callFramePayload.lineNumber - 1;
+
+ columnNumber = callFramePayload.columnNumber;
+
+ break;
+ }
+ } else if (initiatorPayload.url) {
+ url = initiatorPayload.url;
+
+ // The lineNumber is 1-based, but we expect 0-based.
+ lineNumber = initiatorPayload.lineNumber - 1;
+ }
+
+ if (!url || isNaN(lineNumber) || lineNumber < 0)
+ return null;
+
+ var sourceCode = WebInspector.frameResourceManager.resourceForURL(url);
+ if (!sourceCode)
+ sourceCode = WebInspector.debuggerManager.scriptsForURL(url, WebInspector.mainTarget)[0];
+
+ if (!sourceCode)
+ return null;
+
+ return sourceCode.createSourceCodeLocation(lineNumber, columnNumber);
+ }
+
+ _processMainFrameResourceTreePayload(error, mainFramePayload)
+ {
+ console.assert(this._waitingForMainFrameResourceTreePayload);
+ delete this._waitingForMainFrameResourceTreePayload;
+
+ if (error) {
+ console.error(JSON.stringify(error));
+ return;
+ }
+
+ console.assert(mainFramePayload);
+ console.assert(mainFramePayload.frame);
+
+ this._resourceRequestIdentifierMap = new Map;
+ this._frameIdentifierMap = new Map;
+
+ var oldMainFrame = this._mainFrame;
+
+ this._mainFrame = this._addFrameTreeFromFrameResourceTreePayload(mainFramePayload, true);
+
+ if (this._mainFrame !== oldMainFrame)
+ this._mainFrameDidChange(oldMainFrame);
+ }
+
+ _createFrame(payload)
+ {
+ // If payload.url is missing or empty then this page is likely the special empty page. In that case
+ // we will just say it is "about:blank" so we have a URL, which is required for resources.
+ var mainResource = new WebInspector.Resource(payload.url || "about:blank", payload.mimeType, null, payload.loaderId);
+ var frame = new WebInspector.Frame(payload.id, payload.name, payload.securityOrigin, payload.loaderId, mainResource);
+
+ this._frameIdentifierMap.set(frame.id, frame);
+
+ mainResource.markAsFinished();
+
+ return frame;
+ }
+
+ _createResource(payload, framePayload)
+ {
+ var resource = new WebInspector.Resource(payload.url, payload.mimeType, payload.type, framePayload.loaderId, payload.targetId);
+
+ if (payload.sourceMapURL)
+ WebInspector.sourceMapManager.downloadSourceMap(payload.sourceMapURL, resource.url, resource);
+
+ return resource;
+ }
+
+ _addFrameTreeFromFrameResourceTreePayload(payload, isMainFrame)
+ {
+ var frame = this._createFrame(payload.frame);
+ if (isMainFrame)
+ frame.markAsMainFrame();
+
+ for (var i = 0; payload.childFrames && i < payload.childFrames.length; ++i)
+ frame.addChildFrame(this._addFrameTreeFromFrameResourceTreePayload(payload.childFrames[i], false));
+
+ for (var i = 0; payload.resources && i < payload.resources.length; ++i) {
+ var resourcePayload = payload.resources[i];
+
+ // The main resource is included as a resource. We can skip it since we already created
+ // a main resource when we created the Frame. The resource payload does not include anything
+ // didn't already get from the frame payload.
+ if (resourcePayload.type === "Document" && resourcePayload.url === payload.frame.url)
+ continue;
+
+ var resource = this._createResource(resourcePayload, payload);
+ if (resource.target === WebInspector.mainTarget)
+ frame.addResource(resource);
+ else if (resource.target)
+ resource.target.addResource(resource);
+ else
+ this._addOrphanedResource(resource, resourcePayload.targetId);
+
+ if (resourcePayload.failed || resourcePayload.canceled)
+ resource.markAsFailed(resourcePayload.canceled);
+ else
+ resource.markAsFinished();
+ }
+
+ this._dispatchFrameWasAddedEvent(frame);
+
+ return frame;
+ }
+
+ _addOrphanedResource(resource, targetId)
+ {
+ let resources = this._orphanedResources.get(targetId);
+ if (!resources) {
+ resources = [];
+ this._orphanedResources.set(targetId, resources);
+ }
+
+ resources.push(resource);
+ }
+
+ _dispatchFrameWasAddedEvent(frame)
+ {
+ this.dispatchEventToListeners(WebInspector.FrameResourceManager.Event.FrameWasAdded, {frame});
+ }
+
+ _mainFrameDidChange(oldMainFrame)
+ {
+ if (oldMainFrame)
+ oldMainFrame.unmarkAsMainFrame();
+ if (this._mainFrame)
+ this._mainFrame.markAsMainFrame();
+
+ this.dispatchEventToListeners(WebInspector.FrameResourceManager.Event.MainFrameDidChange, {oldMainFrame});
+ }
+
+ _extraDomainsActivated(event)
+ {
+ if (event.data.domains.includes("Page") && window.PageAgent)
+ PageAgent.getResourceTree(this._processMainFrameResourceTreePayload.bind(this));
+ }
+};
+
+WebInspector.FrameResourceManager.Event = {
+ FrameWasAdded: "frame-resource-manager-frame-was-added",
+ FrameWasRemoved: "frame-resource-manager-frame-was-removed",
+ MainFrameDidChange: "frame-resource-manager-main-frame-did-change",
+};