blob: 4d690b3659d829777cc2625c7e53823db4450f27 [file] [log] [blame]
/*
* 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.
*/
// See http://groups.google.com/group/http-archive-specification/web/har-1-2-spec
// for HAR specification.
WebInspector.HAREntry = function(resource)
{
this._resource = resource;
}
WebInspector.HAREntry.prototype = {
build: function()
{
return {
pageref: this._resource.documentURL,
startedDateTime: new Date(this._resource.startTime * 1000),
time: WebInspector.HAREntry._toMilliseconds(this._resource.duration),
request: this._buildRequest(),
response: this._buildResponse(),
// cache: {...}, -- Not supproted yet.
timings: this._buildTimings()
};
},
_buildRequest: function()
{
var res = {
method: this._resource.requestMethod,
url: this._resource.url,
// httpVersion: "HTTP/1.1" -- Not available.
headers: this._buildHeaders(this._resource.requestHeaders),
headersSize: -1, // Not available.
bodySize: -1 // Not available.
};
if (this._resource.queryParameters)
res.queryString = this._buildParameters(this._resource.queryParameters);
if (this._resource.requestFormData)
res.postData = this._buildPostData();
if (this._resource.requestCookies)
res.cookies = this._buildCookies(this._resource.requestCookies);
return res;
},
_buildResponse: function()
{
var res = {
status: this._resource.statusCode,
statusText: this._resource.statusText,
// "httpVersion": "HTTP/1.1" -- Not available.
headers: this._buildHeaders(this._resource.responseHeaders),
content: this._buildContent(),
redirectURL: this._resource.responseHeaderValue("Location") || "",
headersSize: -1, // Not available.
bodySize: this._resource.resourceSize
};
if (this._resource.responseCookies)
res.cookies = this._buildCookies(this._resource.responseCookies);
return res;
},
_buildContent: function()
{
return {
size: this._resource.resourceSize,
// compression: 0, -- Not available.
mimeType: this._resource.mimeType,
// text: -- Not available.
};
},
_buildTimings: function()
{
var waitForConnection = this._interval("connectStart", "connectEnd");
var blocked;
var connect;
var dns = this._interval("dnsStart", "dnsEnd");
var send = this._interval("sendStart", "sendEnd");
var ssl = this._interval("sslStart", "sslEnd");
if (ssl !== -1 && send !== -1)
send -= ssl;
if (this._resource.connectionReused) {
connect = -1;
blocked = waitForConnection;
} else {
blocked = 0;
connect = waitForConnection;
if (dns !== -1)
connect -= dns;
}
return {
blocked: blocked,
dns: dns,
connect: connect,
send: send,
wait: this._interval("sendEnd", "receiveHeadersEnd"),
receive: WebInspector.HAREntry._toMilliseconds(this._resource.receiveDuration),
ssl: ssl
};
},
_buildHeaders: function(headers)
{
var result = [];
for (var name in headers)
result.push({ name: name, value: headers[name] });
return result;
},
_buildPostData: function()
{
var res = {
mimeType: this._resource.requestHeaderValue("Content-Type"),
text: this._resource.requestFormData
};
if (this._resource.formParameters)
res.params = this._buildParameters(this._resource.formParameters);
return res;
},
_buildParameters: function(parameters)
{
return parameters.slice();
},
_buildCookies: function(cookies)
{
return cookies.map(this._buildCookie.bind(this));
},
_buildCookie: function(cookie)
{
return {
name: cookie.name,
value: cookie.value,
path: cookie.path,
domain: cookie.domain,
expires: cookie.expires(new Date(this._resource.startTime * 1000)),
httpOnly: cookie.httpOnly,
secure: cookie.secure
};
},
_interval: function(start, end)
{
var timing = this._resource.timing;
if (!timing)
return -1;
var startTime = timing[start];
return typeof startTime !== "number" || startTime === -1 ? -1 : Math.round(timing[end] - startTime);
}
}
WebInspector.HAREntry._toMilliseconds = function(time)
{
return time === -1 ? -1 : Math.round(time * 1000);
}
WebInspector.HARLog = function()
{
this.includeResourceIds = false;
}
WebInspector.HARLog.prototype = {
build: function()
{
var webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent);
return {
version: "1.2",
creator: {
name: "WebInspector",
version: webKitVersion ? webKitVersion[1] : "n/a"
},
pages: this._buildPages(),
entries: WebInspector.networkResources.map(this._convertResource.bind(this))
}
},
_buildPages: function()
{
return [
{
startedDateTime: new Date(WebInspector.mainResource.startTime * 1000),
id: WebInspector.mainResource.documentURL,
title: "",
pageTimings: this.buildMainResourceTimings()
}
];
},
buildMainResourceTimings: function()
{
return {
onContentLoad: this._pageEventTime(WebInspector.mainResourceDOMContentTime),
onLoad: this._pageEventTime(WebInspector.mainResourceLoadTime),
}
},
_convertResource: function(resource)
{
var entry = (new WebInspector.HAREntry(resource)).build();
if (this.includeResourceIds)
entry._resourceId = resource.identifier;
return entry;
},
_pageEventTime: function(time)
{
var startTime = WebInspector.mainResource.startTime;
if (time === -1 || startTime === -1)
return -1;
return WebInspector.HAREntry._toMilliseconds(time - startTime);
}
}