Diff
Modified: trunk/LayoutTests/ChangeLog (129335 => 129336)
--- trunk/LayoutTests/ChangeLog 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/LayoutTests/ChangeLog 2012-09-24 09:23:20 UTC (rev 129336)
@@ -1,3 +1,21 @@
+2012-09-21 Andrey Kosyakov <[email protected]>
+
+ Web Inspector: support saving HAR with resources content
+ https://bugs.webkit.org/show_bug.cgi?id=97341
+
+ Reviewed by Vsevolod Vlasov.
+
+ - moved StringOutputStream to inspector-test.js for reuse;
+ - added test for HARWriter and response content in HAR.
+
+ * http/tests/inspector/inspector-test.js:
+ (initialize_InspectorTest):
+ (initialize_InspectorTest.):
+ * http/tests/inspector/network/har-content-expected.txt: Added.
+ * http/tests/inspector/network/har-content.html: Added.
+ * inspector/timeline/timeline-test.js:
+ (initialize_Timeline):
+
2012-09-24 Yury Semikhatsky <[email protected]>
Unreviewed. Updated test expectations for webaudio/biquad-getFrequencyResponse.html
Modified: trunk/LayoutTests/http/tests/inspector/inspector-test.js (129335 => 129336)
--- trunk/LayoutTests/http/tests/inspector/inspector-test.js 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/LayoutTests/http/tests/inspector/inspector-test.js 2012-09-24 09:23:20 UTC (rev 129336)
@@ -372,8 +372,28 @@
return buffer;
}
+InspectorTest.StringOutputStream = function(callback)
+{
+ this._callback = callback;
+ this._buffer = "";
};
+InspectorTest.StringOutputStream.prototype = {
+ write: function(chunk, callback)
+ {
+ this._buffer += chunk;
+ if (callback)
+ callback(this);
+ },
+
+ close: function()
+ {
+ this._callback(this._buffer);
+ }
+};
+
+};
+
var initializeCallId = 0;
var runTestCallId = 1;
var completeTestCallId = 2;
Added: trunk/LayoutTests/http/tests/inspector/network/har-content-expected.txt (0 => 129336)
--- trunk/LayoutTests/http/tests/inspector/network/har-content-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/inspector/network/har-content-expected.txt 2012-09-24 09:23:20 UTC (rev 129336)
@@ -0,0 +1,13 @@
+CONSOLE MESSAGE: line 6: XHR loaded: 1
+Tests conversion of Inspector's resource representation into HAR format.
+
+initiator.css: .image-background {
+ background-image: url("resource.php?type=image&random=1&size=200");
+}
+
+.image-background-2 {
+ background-image: url("resource.php?type=image&random=1&size=300");
+}
+
+
+
Property changes on: trunk/LayoutTests/http/tests/inspector/network/har-content-expected.txt
___________________________________________________________________
Added: svn:eol-style
Added: trunk/LayoutTests/http/tests/inspector/network/har-content.html (0 => 129336)
--- trunk/LayoutTests/http/tests/inspector/network/har-content.html (rev 0)
+++ trunk/LayoutTests/http/tests/inspector/network/har-content.html 2012-09-24 09:23:20 UTC (rev 129336)
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script src=""
+
+<script>
+var test = function()
+{
+ const requestRegExp = /\/initiator.css$/;
+
+ function onRequestFinished()
+ {
+ var writer = new WebInspector.HARWriter();
+ var stream = new InspectorTest.StringOutputStream(onSaved);
+ writer.write(stream, WebInspector.networkLog.requests, new WebInspector.Progress());
+ }
+
+ function onSaved(data)
+ {
+ var har = JSON.parse(data);
+ InspectorTest.addResult("initiator.css: " + findEntry(har, requestRegExp).response.content.text);
+ InspectorTest.completeTest();
+ }
+
+ function findEntry(har, regexp)
+ {
+ var entries = har.log.entries;
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (regexp.test(entry.request.url))
+ return entry;
+ }
+ InspectorTest.addResult("FAIL: can't find resource for " + regexp);
+ return null;
+ }
+
+ InspectorTest.makeSimpleXHR("GET", "resources/initiator.css", false, onRequestFinished);
+}
+</script>
+
+
+</head>
+
+<body _onload_="runTest()">
+<p>
+Tests conversion of Inspector's resource representation into HAR format.
+</p>
+
+</body>
+</html>
Property changes on: trunk/LayoutTests/http/tests/inspector/network/har-content.html
___________________________________________________________________
Added: svn:eol-style
Modified: trunk/LayoutTests/inspector/timeline/timeline-test.js (129335 => 129336)
--- trunk/LayoutTests/inspector/timeline/timeline-test.js 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/LayoutTests/inspector/timeline/timeline-test.js 2012-09-24 09:23:20 UTC (rev 129336)
@@ -207,24 +207,4 @@
}
};
-InspectorTest.StringOutputStream = function(callback)
-{
- this._callback = callback;
- this._buffer = "";
};
-
-InspectorTest.StringOutputStream.prototype = {
- write: function(chunk, callback)
- {
- this._buffer += chunk;
- if (callback)
- callback(this);
- },
-
- close: function()
- {
- this._callback(this._buffer);
- }
-};
-
-};
Modified: trunk/Source/WebCore/ChangeLog (129335 => 129336)
--- trunk/Source/WebCore/ChangeLog 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/Source/WebCore/ChangeLog 2012-09-24 09:23:20 UTC (rev 129336)
@@ -1,3 +1,35 @@
+2012-09-21 Andrey Kosyakov <[email protected]>
+
+ Web Inspector: support saving HAR with resources content
+ https://bugs.webkit.org/show_bug.cgi?id=97341
+
+ Reviewed by Vsevolod Vlasov.
+
+ - add WebInspector.HARWriter that writes HAR with content to a stream;
+ - replace Save all as HAR with Save all with Content as HAR in network's panel context menu;
+ - remove entries for copying/saving of individual request items to reduce clutter in context menu;
+ - a drive-by fix of an exception when invoking context menu not on a network item;
+
+ Test: http/tests/inspector/network/har-content.html
+
+ * English.lproj/localizedStrings.js:
+ * inspector/front-end/FileUtils.js:
+ * inspector/front-end/HAREntry.js:
+ (WebInspector.HAREntry.prototype._buildPostData):
+ (WebInspector.HARLog.prototype.build):
+ (WebInspector.HARLog.prototype._creator):
+ (WebInspector.HARWriter):
+ (WebInspector.HARWriter.prototype.write):
+ (WebInspector.HARWriter.prototype._onContentAvailable):
+ (WebInspector.HARWriter.prototype._beginWrite):
+ (WebInspector.HARWriter.prototype._writeNextChunk):
+ * inspector/front-end/NetworkPanel.js:
+ (WebInspector.NetworkLogView.prototype.get statusBarItems):
+ (WebInspector.NetworkLogView.prototype._createStatusBarItems):
+ (WebInspector.NetworkLogView.prototype._contextMenu):
+ (WebInspector.NetworkLogView.prototype._exportAll.openCallback):
+ (WebInspector.NetworkLogView.prototype._exportAll):
+
2012-09-24 Nico Weber <[email protected]>
[chromium] Remove BitLockerSkia. It's apparently not used.
Modified: trunk/Source/WebCore/English.lproj/localizedStrings.js (129335 => 129336)
--- trunk/Source/WebCore/English.lproj/localizedStrings.js 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/Source/WebCore/English.lproj/localizedStrings.js 2012-09-24 09:23:20 UTC (rev 129336)
@@ -129,14 +129,10 @@
localizedStrings["Continue to here"] = "Continue to here";
localizedStrings["Continue"] = "Continue";
localizedStrings["Copy as HTML"] = "Copy as HTML";
-localizedStrings["Copy entry as HAR"] = "Copy entry as HAR";
-localizedStrings["Copy Entry as HAR"] = "Copy Entry as HAR";
-localizedStrings["Save entry as HAR"] = "Save entry as HAR";
-localizedStrings["Save Entry as HAR"] = "Save Entry as HAR";
localizedStrings["Copy all as HAR"] = "Copy all as HAR";
localizedStrings["Copy All as HAR"] = "Copy All as HAR";
-localizedStrings["Save all as HAR"] = "Save all as HAR";
-localizedStrings["Save All as HAR"] = "Save All as HAR";
+localizedStrings["Save as HAR with content"] = "Save as HAR with content";
+localizedStrings["Save as HAR with Content"] = "Save as HAR with Content";
localizedStrings["Copy link address"] = "Copy link address";
localizedStrings["Copy Link Address"] = "Copy Link Address";
localizedStrings["Copy request headers"] = "Copy request headers";
@@ -749,3 +745,5 @@
localizedStrings["Paused on assertion."] = "Paused on assertion.";
localizedStrings["%s (%s%s)"] = "%s (%s%s)";
localizedStrings["Running audit"] = "Running audit";
+localizedStrings["Collecting content…"] = "Collecting content…";
+localizedStrings["Writing file…"] = "Writing file…";
Modified: trunk/Source/WebCore/inspector/front-end/FileUtils.js (129335 => 129336)
--- trunk/Source/WebCore/inspector/front-end/FileUtils.js 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/Source/WebCore/inspector/front-end/FileUtils.js 2012-09-24 09:23:20 UTC (rev 129336)
@@ -40,8 +40,6 @@
onChunkTransferred: function(source) { },
- onTransferFinished: function(source) { },
-
onError: function(source, event) { }
}
Modified: trunk/Source/WebCore/inspector/front-end/HAREntry.js (129335 => 129336)
--- trunk/Source/WebCore/inspector/front-end/HAREntry.js 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/Source/WebCore/inspector/front-end/HAREntry.js 2012-09-24 09:23:20 UTC (rev 129336)
@@ -164,7 +164,7 @@
text: this._request.requestFormData
};
if (this._request.formParameters)
- res.params = this._buildParameters(this._request.formParameters);
+ res.params = this._buildParameters(this._request.formParameters);
return res;
},
@@ -279,19 +279,24 @@
*/
build: function()
{
- var webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent);
-
return {
version: "1.2",
- creator: {
- name: "WebInspector",
- version: webKitVersion ? webKitVersion[1] : "n/a"
- },
+ creator: this._creator(),
pages: this._buildPages(),
entries: this._requests.map(this._convertResource.bind(this))
}
},
+ _creator: function()
+ {
+ var webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent);
+
+ return {
+ name: "WebInspector",
+ version: webKitVersion ? webKitVersion[1] : "n/a"
+ };
+ },
+
/**
* @return {Array}
*/
@@ -348,3 +353,87 @@
return WebInspector.HAREntry._toMilliseconds(time - startTime);
}
}
+
+/**
+ * @constructor
+ */
+WebInspector.HARWriter = function()
+{
+}
+
+WebInspector.HARWriter.prototype = {
+ /**
+ * @param {WebInspector.OutputStream} stream
+ * @param {Array.<WebInspector.NetworkRequest>} requests
+ * @param {WebInspector.Progress} progress
+ */
+ write: function(stream, requests, progress)
+ {
+ this._stream = stream;
+ this._harLog = (new WebInspector.HARLog(requests)).build();
+ this._pendingRequests = 1; // Guard against completing resource transfer before all requests are made.
+ var entries = this._harLog.entries;
+ for (var i = 0; i < entries.length; ++i) {
+ var content = requests[i].content;
+ if (typeof content === "undefined" && requests[i].finished) {
+ ++this._pendingRequests;
+ requests[i].requestContent(this._onContentAvailable.bind(this, entries[i]));
+ } else if (content !== null)
+ entries[i].response.content.text = content;
+ }
+ var compositeProgress = new WebInspector.CompositeProgress(progress);
+ this._writeProgress = compositeProgress.createSubProgress();
+ if (--this._pendingRequests) {
+ this._requestsProgress = compositeProgress.createSubProgress();
+ this._requestsProgress.setTitle(WebInspector.UIString("Collecting content…"));
+ this._requestsProgress.setTotalWork(this._pendingRequests);
+ } else
+ this._beginWrite();
+ },
+
+ /**
+ * @param {Object} entry
+ * @param {string|null} content
+ * @param {boolean} contentEncoded
+ * @param {string=} mimeType
+ */
+ _onContentAvailable: function(entry, content, contentEncoded, mimeType)
+ {
+ if (content !== null)
+ entry.response.content.text = content;
+ if (this._requestsProgress)
+ this._requestsProgress.worked();
+ if (!--this._pendingRequests) {
+ this._requestsProgress.done();
+ this._beginWrite();
+ }
+ },
+
+ _beginWrite: function()
+ {
+ const jsonIndent = 2;
+ this._text = JSON.stringify({log: this._harLog}, null, jsonIndent);
+ this._writeProgress.setTitle(WebInspector.UIString("Writing file…"));
+ this._writeProgress.setTotalWork(this._text.length);
+ this._bytesWritten = 0;
+ this._writeNextChunk(this._stream);
+ },
+
+ /**
+ * @param {WebInspector.OutputStream} stream
+ * @param {string} error
+ */
+ _writeNextChunk: function(stream, error)
+ {
+ if (this._bytesWritten >= this._text.length || error) {
+ stream.close();
+ this._writeProgress.done();
+ return;
+ }
+ const chunkSize = 100000;
+ var text = this._text.substring(this._bytesWritten, this._bytesWritten + chunkSize);
+ this._bytesWritten += text.length;
+ stream.write(text, this._writeNextChunk.bind(this));
+ this._writeProgress.setWorked(this._bytesWritten);
+ }
+}
Modified: trunk/Source/WebCore/inspector/front-end/NetworkPanel.js (129335 => 129336)
--- trunk/Source/WebCore/inspector/front-end/NetworkPanel.js 2012-09-24 09:15:49 UTC (rev 129335)
+++ trunk/Source/WebCore/inspector/front-end/NetworkPanel.js 2012-09-24 09:23:20 UTC (rev 129336)
@@ -65,7 +65,7 @@
this._currentMatchedRequestIndex = -1;
this._createStatusbarButtons();
- this._createFilterStatusBarItems();
+ this._createStatusBarItems();
this._linkifier = new WebInspector.Linkifier();
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this);
@@ -118,7 +118,7 @@
get statusBarItems()
{
- return [this._largerRequestsButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement];
+ return [this._largerRequestsButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement, this._progressBarContainer];
},
get useLargeRows()
@@ -325,7 +325,7 @@
this._updateOffscreenRows();
},
- _createFilterStatusBarItems: function()
+ _createStatusBarItems: function()
{
var filterBarElement = document.createElement("div");
filterBarElement.className = "scope-bar status-bar-item";
@@ -358,6 +358,8 @@
createFilterElement.call(this, type.name(), type.categoryTitle());
}
this._filterBarElement = filterBarElement;
+ this._progressBarContainer = document.createElement("div");
+ this._progressBarContainer.className = "status-bar-item";
},
_createSummaryBar: function()
@@ -944,15 +946,12 @@
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy request headers" : "Copy Request Headers"), this._copyRequestHeaders.bind(this, request));
if (request.responseHeadersText)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy response headers" : "Copy Response Headers"), this._copyResponseHeaders.bind(this, request));
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy entry as HAR" : "Copy Entry as HAR"), this._copyRequest.bind(this, request));
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy all as HAR" : "Copy All as HAR"), this._copyAll.bind(this));
if (InspectorFrontendHost.canSave()) {
contextMenu.appendSeparator();
- if (request)
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save entry as HAR" : "Save Entry as HAR"), this._exportRequest.bind(this, request));
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save all as HAR" : "Save All as HAR"), this._exportAll.bind(this));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as HAR with content" : "Save as HAR with Content"), this._exportAll.bind(this));
}
if (this._canClearBrowserCache || this._canClearBrowserCookies)
@@ -963,7 +962,7 @@
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear browser cookies" : "Clear Browser Cookies"), this._clearBrowserCookies.bind(this));
- if (request.type === WebInspector.resourceTypes.XHR) {
+ if (request && request.type === WebInspector.resourceTypes.XHR) {
contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString("Replay XHR"), this._replayXHR.bind(this, request.requestId));
contextMenu.appendSeparator();
@@ -986,12 +985,6 @@
InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2));
},
- _copyRequest: function(request)
- {
- var har = (new WebInspector.HAREntry(request)).build();
- InspectorFrontendHost.copyText(JSON.stringify(har, null, 2));
- },
-
_copyLocation: function(request)
{
InspectorFrontendHost.copyText(request.url);
@@ -1009,19 +1002,18 @@
_exportAll: function()
{
- var harArchive = {
- log: (new WebInspector.HARLog(this._requests)).build()
- };
-
- WebInspector.fileManager.save(WebInspector.inspectedPageDomain + ".har", JSON.stringify(harArchive, null, 2), true);
+ var filename = WebInspector.inspectedPageDomain + ".har";
+ var stream = new WebInspector.FileOutputStream();
+ stream.open(filename, openCallback.bind(this));
+ function openCallback()
+ {
+ var progressIndicator = new WebInspector.ProgressIndicator();
+ this._progressBarContainer.appendChild(progressIndicator.element);
+ var harWriter = new WebInspector.HARWriter();
+ harWriter.write(stream, this._requests, progressIndicator);
+ }
},
- _exportRequest: function(request)
- {
- var har = (new WebInspector.HAREntry(request)).build();
- WebInspector.fileManager.save(request.displayName + ".har", JSON.stringify(har, null, 2), true);
- },
-
_clearBrowserCache: function(event)
{
if (confirm(WebInspector.UIString("Are you sure you want to clear browser cache?")))