| /* |
| * Copyright (C) 2007, 2008 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. |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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.Resource = function(identifier, url) |
| { |
| this.identifier = identifier; |
| this._url = url; |
| this._startTime = -1; |
| this._endTime = -1; |
| this._requestMethod = ""; |
| this._requestFormData = ""; |
| this._category = WebInspector.resourceCategories.other; |
| } |
| |
| WebInspector.Resource.StatusText = { |
| 100: "Continue", |
| 101: "Switching Protocols", |
| 102: "Processing (WebDav)", |
| 200: "OK", |
| 201: "Created", |
| 202: "Accepted", |
| 203: "Non-Authoritative Information", |
| 204: "No Content", |
| 205: "Reset Content", |
| 206: "Partial Content", |
| 207: "Multi-Status (WebDav)", |
| 300: "Multiple Choices", |
| 301: "Moved Permanently", |
| 302: "Found", |
| 303: "See Other", |
| 304: "Not Modified", |
| 305: "Use Proxy", |
| 306: "Switch Proxy", |
| 307: "Temporary", |
| 400: "Bad Request", |
| 401: "Unauthorized", |
| 402: "Payment Required", |
| 403: "Forbidden", |
| 404: "Not Found", |
| 405: "Method Not Allowed", |
| 406: "Not Acceptable", |
| 407: "Proxy Authentication Required", |
| 408: "Request Timeout", |
| 409: "Conflict", |
| 410: "Gone", |
| 411: "Length Required", |
| 412: "Precondition Failed", |
| 413: "Request Entity Too Large", |
| 414: "Request-URI Too Long", |
| 415: "Unsupported Media Type", |
| 416: "Requested Range Not Satisfiable", |
| 417: "Expectation Failed", |
| 418: "I'm a teapot", |
| 422: "Unprocessable Entity (WebDav)", |
| 423: "Locked (WebDav)", |
| 424: "Failed Dependency (WebDav)", |
| 425: "Unordered Collection", |
| 426: "Upgrade Required", |
| 449: "Retry With", |
| 500: "Internal Server Error", |
| 501: "Not Implemented", |
| 502: "Bad Gateway", |
| 503: "Service Unavailable", |
| 504: "Gateway Timeout", |
| 505: "HTTP Version Not Supported", |
| 506: "Variant Also Negotiates", |
| 507: "Insufficient Storage (WebDav)", |
| 509: "Bandwidth Limit Exceeded", |
| 510: "Not Extended" |
| }; |
| |
| // Keep these in sync with WebCore::InspectorResource::Type |
| WebInspector.Resource.Type = { |
| Document: 0, |
| Stylesheet: 1, |
| Image: 2, |
| Font: 3, |
| Script: 4, |
| XHR: 5, |
| Media: 6, |
| Other: 7, |
| |
| isTextType: function(type) |
| { |
| return (type === this.Document) || (type === this.Stylesheet) || (type === this.Script) || (type === this.XHR); |
| }, |
| |
| toString: function(type) |
| { |
| switch (type) { |
| case this.Document: |
| return WebInspector.UIString("document"); |
| case this.Stylesheet: |
| return WebInspector.UIString("stylesheet"); |
| case this.Image: |
| return WebInspector.UIString("image"); |
| case this.Font: |
| return WebInspector.UIString("font"); |
| case this.Script: |
| return WebInspector.UIString("script"); |
| case this.XHR: |
| return WebInspector.UIString("XHR"); |
| case this.Other: |
| default: |
| return WebInspector.UIString("other"); |
| } |
| } |
| } |
| |
| WebInspector.Resource.prototype = { |
| get url() |
| { |
| return this._url; |
| }, |
| |
| set url(x) |
| { |
| if (this._url === x) |
| return; |
| |
| var oldURL = this._url; |
| this._url = x; |
| |
| // FIXME: We should make the WebInspector object listen for the "url changed" event. |
| // Then resourceURLChanged can be removed. |
| WebInspector.resourceURLChanged(this, oldURL); |
| |
| this.dispatchEventToListeners("url changed"); |
| }, |
| |
| get documentURL() |
| { |
| return this._documentURL; |
| }, |
| |
| set documentURL(x) |
| { |
| if (this._documentURL === x) |
| return; |
| this._documentURL = x; |
| }, |
| |
| get domain() |
| { |
| return this._domain; |
| }, |
| |
| set domain(x) |
| { |
| if (this._domain === x) |
| return; |
| this._domain = x; |
| }, |
| |
| get lastPathComponent() |
| { |
| return this._lastPathComponent; |
| }, |
| |
| set lastPathComponent(x) |
| { |
| if (this._lastPathComponent === x) |
| return; |
| this._lastPathComponent = x; |
| this._lastPathComponentLowerCase = x ? x.toLowerCase() : null; |
| }, |
| |
| get displayName() |
| { |
| var title = this.lastPathComponent; |
| if (!title) |
| title = this.displayDomain; |
| if (!title && this.url) |
| title = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : ""); |
| if (title === "/") |
| title = this.url; |
| return title; |
| }, |
| |
| get displayDomain() |
| { |
| // WebInspector.Database calls this, so don't access more than this.domain. |
| if (this.domain && (!WebInspector.mainResource || (WebInspector.mainResource && this.domain !== WebInspector.mainResource.domain))) |
| return this.domain; |
| return ""; |
| }, |
| |
| get startTime() |
| { |
| return this._startTime || -1; |
| }, |
| |
| set startTime(x) |
| { |
| if (this._startTime === x) |
| return; |
| |
| this._startTime = x; |
| |
| if (WebInspector.panels.resources) |
| WebInspector.panels.resources.refreshResource(this); |
| }, |
| |
| get responseReceivedTime() |
| { |
| return this._responseReceivedTime || -1; |
| }, |
| |
| set responseReceivedTime(x) |
| { |
| if (this._responseReceivedTime === x) |
| return; |
| |
| this._responseReceivedTime = x; |
| |
| if (WebInspector.panels.resources) |
| WebInspector.panels.resources.refreshResource(this); |
| }, |
| |
| get endTime() |
| { |
| return this._endTime || -1; |
| }, |
| |
| set endTime(x) |
| { |
| if (this._endTime === x) |
| return; |
| |
| this._endTime = x; |
| |
| if (WebInspector.panels.resources) |
| WebInspector.panels.resources.refreshResource(this); |
| }, |
| |
| get duration() |
| { |
| if (this._endTime === -1 || this._startTime === -1) |
| return -1; |
| return this._endTime - this._startTime; |
| }, |
| |
| get latency() |
| { |
| if (this._responseReceivedTime === -1 || this._startTime === -1) |
| return -1; |
| return this._responseReceivedTime - this._startTime; |
| }, |
| |
| get resourceSize() |
| { |
| return this._resourceSize || 0; |
| }, |
| |
| set resourceSize(x) |
| { |
| if (this._resourceSize === x) |
| return; |
| |
| this._resourceSize = x; |
| |
| if (WebInspector.panels.resources) |
| WebInspector.panels.resources.refreshResource(this); |
| }, |
| |
| get transferSize() |
| { |
| // FIXME: this is wrong for chunked-encoding resources. |
| return this.cached ? 0 : Number(this.responseHeaders["Content-Length"] || this.resourceSize || 0); |
| }, |
| |
| get expectedContentLength() |
| { |
| return this._expectedContentLength || 0; |
| }, |
| |
| set expectedContentLength(x) |
| { |
| if (this._expectedContentLength === x) |
| return; |
| this._expectedContentLength = x; |
| }, |
| |
| get finished() |
| { |
| return this._finished; |
| }, |
| |
| set finished(x) |
| { |
| if (this._finished === x) |
| return; |
| |
| this._finished = x; |
| |
| if (x) { |
| this._checkWarnings(); |
| this.dispatchEventToListeners("finished"); |
| } |
| }, |
| |
| get failed() |
| { |
| return this._failed; |
| }, |
| |
| set failed(x) |
| { |
| this._failed = x; |
| }, |
| |
| get category() |
| { |
| return this._category; |
| }, |
| |
| set category(x) |
| { |
| if (this._category === x) |
| return; |
| |
| var oldCategory = this._category; |
| if (oldCategory) |
| oldCategory.removeResource(this); |
| |
| this._category = x; |
| |
| if (this._category) |
| this._category.addResource(this); |
| |
| if (WebInspector.panels.resources) { |
| WebInspector.panels.resources.refreshResource(this); |
| WebInspector.panels.resources.recreateViewForResourceIfNeeded(this); |
| } |
| }, |
| |
| get mimeType() |
| { |
| return this._mimeType; |
| }, |
| |
| set mimeType(x) |
| { |
| if (this._mimeType === x) |
| return; |
| |
| this._mimeType = x; |
| }, |
| |
| get type() |
| { |
| return this._type; |
| }, |
| |
| set type(x) |
| { |
| if (this._type === x) |
| return; |
| |
| this._type = x; |
| |
| switch (x) { |
| case WebInspector.Resource.Type.Document: |
| this.category = WebInspector.resourceCategories.documents; |
| break; |
| case WebInspector.Resource.Type.Stylesheet: |
| this.category = WebInspector.resourceCategories.stylesheets; |
| break; |
| case WebInspector.Resource.Type.Script: |
| this.category = WebInspector.resourceCategories.scripts; |
| break; |
| case WebInspector.Resource.Type.Image: |
| this.category = WebInspector.resourceCategories.images; |
| break; |
| case WebInspector.Resource.Type.Font: |
| this.category = WebInspector.resourceCategories.fonts; |
| break; |
| case WebInspector.Resource.Type.XHR: |
| this.category = WebInspector.resourceCategories.xhr; |
| break; |
| case WebInspector.Resource.Type.Other: |
| default: |
| this.category = WebInspector.resourceCategories.other; |
| break; |
| } |
| }, |
| |
| get requestHeaders() |
| { |
| if (this._requestHeaders === undefined) |
| this._requestHeaders = {}; |
| return this._requestHeaders; |
| }, |
| |
| set requestHeaders(x) |
| { |
| if (this._requestHeaders === x) |
| return; |
| |
| this._requestHeaders = x; |
| delete this._sortedRequestHeaders; |
| |
| this.dispatchEventToListeners("requestHeaders changed"); |
| }, |
| |
| get sortedRequestHeaders() |
| { |
| if (this._sortedRequestHeaders !== undefined) |
| return this._sortedRequestHeaders; |
| |
| this._sortedRequestHeaders = []; |
| for (var key in this.requestHeaders) |
| this._sortedRequestHeaders.push({header: key, value: this.requestHeaders[key]}); |
| this._sortedRequestHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) }); |
| |
| return this._sortedRequestHeaders; |
| }, |
| |
| get responseHeaders() |
| { |
| if (this._responseHeaders === undefined) |
| this._responseHeaders = {}; |
| return this._responseHeaders; |
| }, |
| |
| set responseHeaders(x) |
| { |
| if (this._responseHeaders === x) |
| return; |
| |
| this._responseHeaders = x; |
| delete this._sortedResponseHeaders; |
| |
| this.dispatchEventToListeners("responseHeaders changed"); |
| }, |
| |
| get sortedResponseHeaders() |
| { |
| if (this._sortedResponseHeaders !== undefined) |
| return this._sortedResponseHeaders; |
| |
| this._sortedResponseHeaders = []; |
| for (var key in this.responseHeaders) |
| this._sortedResponseHeaders.push({header: key, value: this.responseHeaders[key]}); |
| this._sortedResponseHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) }); |
| |
| return this._sortedResponseHeaders; |
| }, |
| |
| get scripts() |
| { |
| if (!("_scripts" in this)) |
| this._scripts = []; |
| return this._scripts; |
| }, |
| |
| addScript: function(script) |
| { |
| if (!script) |
| return; |
| this.scripts.unshift(script); |
| script.resource = this; |
| }, |
| |
| removeAllScripts: function() |
| { |
| if (!this._scripts) |
| return; |
| |
| for (var i = 0; i < this._scripts.length; ++i) { |
| if (this._scripts[i].resource === this) |
| delete this._scripts[i].resource; |
| } |
| |
| delete this._scripts; |
| }, |
| |
| removeScript: function(script) |
| { |
| if (!script) |
| return; |
| |
| if (script.resource === this) |
| delete script.resource; |
| |
| if (!this._scripts) |
| return; |
| |
| this._scripts.remove(script); |
| }, |
| |
| get errors() |
| { |
| return this._errors || 0; |
| }, |
| |
| set errors(x) |
| { |
| this._errors = x; |
| }, |
| |
| get warnings() |
| { |
| return this._warnings || 0; |
| }, |
| |
| set warnings(x) |
| { |
| this._warnings = x; |
| }, |
| |
| _mimeTypeIsConsistentWithType: function() |
| { |
| if (typeof this.type === "undefined" |
| || this.type === WebInspector.Resource.Type.Other |
| || this.type === WebInspector.Resource.Type.XHR) |
| return true; |
| |
| if (this.mimeType in WebInspector.MIMETypes) |
| return this.type in WebInspector.MIMETypes[this.mimeType]; |
| |
| return false; |
| }, |
| |
| _checkWarnings: function() |
| { |
| for (var warning in WebInspector.Warnings) |
| this._checkWarning(WebInspector.Warnings[warning]); |
| }, |
| |
| _checkWarning: function(warning) |
| { |
| var msg; |
| switch (warning.id) { |
| case WebInspector.Warnings.IncorrectMIMEType.id: |
| if (!this._mimeTypeIsConsistentWithType()) |
| msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other, |
| WebInspector.ConsoleMessage.MessageType.Log, |
| WebInspector.ConsoleMessage.MessageLevel.Warning, -1, this.url, null, 1, |
| String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message, |
| WebInspector.Resource.Type.toString(this.type), this.mimeType)); |
| break; |
| } |
| |
| if (msg) |
| WebInspector.console.addMessage(msg); |
| } |
| } |
| |
| WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype; |
| |
| WebInspector.Resource.CompareByStartTime = function(a, b) |
| { |
| return a.startTime - b.startTime; |
| } |
| |
| WebInspector.Resource.CompareByResponseReceivedTime = function(a, b) |
| { |
| var aVal = a.responseReceivedTime; |
| var bVal = b.responseReceivedTime; |
| if (aVal === -1 ^ bVal === -1) |
| return bVal - aVal; |
| return aVal - bVal; |
| } |
| |
| WebInspector.Resource.CompareByEndTime = function(a, b) |
| { |
| var aVal = a.endTime; |
| var bVal = b.endTime; |
| if (aVal === -1 ^ bVal === -1) |
| return bVal - aVal; |
| return aVal - bVal; |
| } |
| |
| WebInspector.Resource.CompareByDuration = function(a, b) |
| { |
| return a.duration - b.duration; |
| } |
| |
| WebInspector.Resource.CompareByLatency = function(a, b) |
| { |
| return a.latency - b.latency; |
| } |
| |
| WebInspector.Resource.CompareBySize = function(a, b) |
| { |
| return a.resourceSize - b.resourceSize; |
| } |
| |
| WebInspector.Resource.CompareByTransferSize = function(a, b) |
| { |
| return a.transferSize - b.transferSize; |
| } |
| |
| |
| WebInspector.Resource.StatusTextForCode = function(code) |
| { |
| return code ? code + " " + WebInspector.Resource.StatusText[code] : ""; |
| } |