[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.16-1409-g5afdf4d
pfeldman at chromium.org
pfeldman at chromium.org
Thu Dec 3 13:43:30 UTC 2009
The following commit has been merged in the webkit-1.1 branch:
commit b5042aaadd7056acc7644ee712bbea1fda66726f
Author: pfeldman at chromium.org <pfeldman at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Tue Nov 24 17:15:01 2009 +0000
2009-11-23 Pavel Feldman <pfeldman at chromium.org>
Reviewed by Timothy Hatcher.
Web Inspector: Implement expandable compartments on timeline panel.
https://bugs.webkit.org/show_bug.cgi?id=31796
* inspector/front-end/TimelineOverviewPane.js:
(WebInspector.TimelineOverviewPane.prototype._setWindowPosition):
* inspector/front-end/TimelinePanel.js:
(WebInspector.TimelinePanel):
(WebInspector.TimelinePanel.prototype.addRecordToTimeline):
(WebInspector.TimelinePanel.prototype._innerAddRecordToTimeline):
(WebInspector.TimelinePanel.prototype._formatRecord):
(WebInspector.TimelinePanel.prototype._refreshRecords):
(WebInspector.TimelinePanel.prototype._addToRecordsWindow):
(WebInspector.TimelineRecordListRow):
(WebInspector.TimelineRecordListRow.prototype.update):
(WebInspector.TimelineRecordListRow.prototype.dispose):
(WebInspector.TimelineRecordGraphRow):
(WebInspector.TimelineRecordGraphRow.prototype.update):
(WebInspector.TimelineRecordGraphRow.prototype._onClick):
(WebInspector.TimelineRecordGraphRow.prototype.dispose):
* inspector/front-end/inspector.css:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51339 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/inspector/timeline-test.js b/LayoutTests/inspector/timeline-test.js
index d019d5f..45bcadc 100644
--- a/LayoutTests/inspector/timeline-test.js
+++ b/LayoutTests/inspector/timeline-test.js
@@ -118,9 +118,15 @@ function timelineAgentTypeToString(numericType)
// Injected into Inspector window
function frontend_getTimelineResults() {
var result = [];
- var records = WebInspector.panels.timeline._records;
- for (var i = 0; i < records.length; ++i) {
- result.push(records[i].record);
+ function addRecords(records)
+ {
+ if (!records)
+ return;
+ for (var i = 0; i < records.length; ++i) {
+ result.push(records[i].record);
+ addRecords(records[i].children);
+ }
}
+ addRecords(WebInspector.panels.timeline._records);
return result;
}
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 88d47cb..00eb9b6 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,29 @@
+2009-11-23 Pavel Feldman <pfeldman at chromium.org>
+
+ Reviewed by Timothy Hatcher.
+
+ Web Inspector: Implement expandable compartments on timeline panel.
+
+ https://bugs.webkit.org/show_bug.cgi?id=31796
+
+ * inspector/front-end/TimelineOverviewPane.js:
+ (WebInspector.TimelineOverviewPane.prototype._setWindowPosition):
+ * inspector/front-end/TimelinePanel.js:
+ (WebInspector.TimelinePanel):
+ (WebInspector.TimelinePanel.prototype.addRecordToTimeline):
+ (WebInspector.TimelinePanel.prototype._innerAddRecordToTimeline):
+ (WebInspector.TimelinePanel.prototype._formatRecord):
+ (WebInspector.TimelinePanel.prototype._refreshRecords):
+ (WebInspector.TimelinePanel.prototype._addToRecordsWindow):
+ (WebInspector.TimelineRecordListRow):
+ (WebInspector.TimelineRecordListRow.prototype.update):
+ (WebInspector.TimelineRecordListRow.prototype.dispose):
+ (WebInspector.TimelineRecordGraphRow):
+ (WebInspector.TimelineRecordGraphRow.prototype.update):
+ (WebInspector.TimelineRecordGraphRow.prototype._onClick):
+ (WebInspector.TimelineRecordGraphRow.prototype.dispose):
+ * inspector/front-end/inspector.css:
+
2009-11-24 Mark Rowe <mrowe at apple.com>
Fix production builds where the source tree may be read-only.
diff --git a/WebCore/inspector/front-end/TimelineGrid.js b/WebCore/inspector/front-end/TimelineGrid.js
index 7ed94b6..2866ecd 100644
--- a/WebCore/inspector/front-end/TimelineGrid.js
+++ b/WebCore/inspector/front-end/TimelineGrid.js
@@ -55,35 +55,65 @@ WebInspector.TimelineGrid.prototype = {
return this._itemsGraphsElement;
},
- updateDividers: function(force, calculator)
+ updateDividers: function(force, calculator, paddingLeft)
{
var dividerCount = Math.round(this._dividersElement.offsetWidth / 64);
var slice = calculator.boundarySpan / dividerCount;
if (!force && this._currentDividerSlice === slice)
return false;
+ if (!(typeof paddingLeft === "number"))
+ paddingLeft = 0;
this._currentDividerSlice = slice;
- this._dividersElement.removeChildren();
this._eventDividersElement.removeChildren();
- this._dividersLabelBarElement.removeChildren();
+ // Reuse divider elements and labels.
+ var divider = this._dividersElement.firstChild;
+ var dividerLabelBar = this._dividersLabelBarElement.firstChild;
+
+ var clientWidth = this._dividersLabelBarElement.clientWidth - paddingLeft;
+ for (var i = paddingLeft ? 0 : 1; i <= dividerCount; ++i) {
+ if (!divider) {
+ divider = document.createElement("div");
+ divider.className = "resources-divider";
+ this._dividersElement.appendChild(divider);
+
+ dividerLabelBar = document.createElement("div");
+ dividerLabelBar.className = "resources-divider";
+ var label = document.createElement("div");
+ label.className = "resources-divider-label";
+ dividerLabelBar._labelElement = label;
+ dividerLabelBar.appendChild(label);
+ this._dividersLabelBarElement.appendChild(dividerLabelBar);
+ }
- for (var i = 1; i <= dividerCount; ++i) {
- var divider = document.createElement("div");
- divider.className = "resources-divider";
if (i === dividerCount)
divider.addStyleClass("last");
- divider.style.left = ((i / dividerCount) * 100) + "%";
+ else
+ divider.removeStyleClass("last");
- this._dividersElement.appendChild(divider.cloneNode());
+ var left = paddingLeft + clientWidth * (i / dividerCount);
+ var percentLeft = 100 * left / this._dividersLabelBarElement.clientWidth + "%";
+ divider.style.left = percentLeft;
+ dividerLabelBar.style.left = percentLeft;
- var label = document.createElement("div");
- label.className = "resources-divider-label";
if (!isNaN(slice))
- label.textContent = calculator.formatValue(slice * i);
- divider.appendChild(label);
+ dividerLabelBar._labelElement.textContent = calculator.formatValue(slice * i);
- this._dividersLabelBarElement.appendChild(divider);
+ divider = divider.nextSibling;
+ dividerLabelBar = dividerLabelBar.nextSibling;
+ }
+
+ // Remove extras.
+ while (divider) {
+ var nextDivider = divider.nextSibling;
+ this._dividersElement.removeChild(divider);
+ divider = nextDivider;
+ }
+ while (dividerLabelBar) {
+ var nextDivider = dividerLabelBar.nextSibling;
+ this._dividersLabelBarElement.removeChild(dividerLabelBar);
+ dividerLabelBar = nextDivider;
}
return true;
},
diff --git a/WebCore/inspector/front-end/TimelineOverviewPane.js b/WebCore/inspector/front-end/TimelineOverviewPane.js
index 3479d4c..b673abe 100644
--- a/WebCore/inspector/front-end/TimelineOverviewPane.js
+++ b/WebCore/inspector/front-end/TimelineOverviewPane.js
@@ -112,21 +112,30 @@ WebInspector.TimelineOverviewPane.prototype = {
this._categoryGraphs[category].clearChunks();
}
+ function forAllRecords(recordsArray, callback)
+ {
+ if (!recordsArray)
+ return;
+ for (var i = 0; i < recordsArray.length; ++i) {
+ callback(recordsArray[i]);
+ forAllRecords(recordsArray[i].children, callback);
+ }
+ }
+
// Create sparse arrays with 101 cells each to fill with chunks for a given category.
this._overviewCalculator.reset();
+ forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator));
- for (var i = 1; i < records.length; ++i)
- this._overviewCalculator.updateBoundaries(records[i]);
-
- for (var i = 0; i < records.length; ++i) {
- var record = records[i];
+ function markTimeline(record)
+ {
var percentages = this._overviewCalculator.computeBarGraphPercentages(record);
-
+
var end = Math.round(percentages.end);
var categoryName = record.category.name;
for (var j = Math.round(percentages.start); j <= end; ++j)
timelines[categoryName][j] = true;
}
+ forAllRecords(records, markTimeline.bind(this));
// Convert sparse arrays to continuous segments, render graphs for each.
for (var category in this._categories) {
@@ -230,16 +239,16 @@ WebInspector.TimelineOverviewPane.prototype = {
_setWindowPosition: function(start, end)
{
if (typeof start === "number") {
- if (start > this._rightResizeElement.offsetLeft - 25)
- start = this._rightResizeElement.offsetLeft - 25;
+ if (start > this._rightResizeElement.offsetLeft - 4)
+ start = this._rightResizeElement.offsetLeft - 4;
this.windowLeft = start / this._overviewGrid.element.clientWidth;
this._leftResizeElement.style.left = this.windowLeft * 100 + "%";
this._overviewWindowElement.style.left = this.windowLeft * 100 + "%";
}
if (typeof end === "number") {
- if (end < this._leftResizeElement.offsetLeft + 30)
- end = this._leftResizeElement.offsetLeft + 30;
+ if (end < this._leftResizeElement.offsetLeft + 12)
+ end = this._leftResizeElement.offsetLeft + 12;
this.windowRight = end / this._overviewGrid.element.clientWidth;
this._rightResizeElement.style.left = this.windowRight * 100 + "%";
diff --git a/WebCore/inspector/front-end/TimelinePanel.js b/WebCore/inspector/front-end/TimelinePanel.js
index 81455a1..1cafd77 100644
--- a/WebCore/inspector/front-end/TimelinePanel.js
+++ b/WebCore/inspector/front-end/TimelinePanel.js
@@ -60,20 +60,20 @@ WebInspector.TimelinePanel = function()
this._containerElement.appendChild(this._containerContentElement);
this._timelineGrid = new WebInspector.TimelineGrid();
- var itemsGraphsElement = this._timelineGrid.itemsGraphsElement;
- itemsGraphsElement.id = "timeline-graphs";
+ this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement;
+ this._itemsGraphsElement.id = "timeline-graphs";
this._containerContentElement.appendChild(this._timelineGrid.element);
this._topGapElement = document.createElement("div");
this._topGapElement.className = "timeline-gap";
- itemsGraphsElement.appendChild(this._topGapElement);
+ this._itemsGraphsElement.appendChild(this._topGapElement);
this._graphRowsElement = document.createElement("div");
- itemsGraphsElement.appendChild(this._graphRowsElement);
+ this._itemsGraphsElement.appendChild(this._graphRowsElement);
this._bottomGapElement = document.createElement("div");
this._bottomGapElement.className = "timeline-gap";
- itemsGraphsElement.appendChild(this._bottomGapElement);
+ this._itemsGraphsElement.appendChild(this._bottomGapElement);
this._createStatusbarButtons();
@@ -136,7 +136,14 @@ WebInspector.TimelinePanel.prototype = {
addRecordToTimeline: function(record)
{
+ this._innerAddRecordToTimeline(record, this._records);
+ this._scheduleRefresh();
+ },
+
+ _innerAddRecordToTimeline: function(record, collection)
+ {
var formattedRecord = this._formatRecord(record);
+
// Glue subsequent records with same category and title together if they are closer than 100ms to each other.
if (this._lastRecord && (!record.children || !record.children.length) &&
this._lastRecord.category == formattedRecord.category &&
@@ -146,13 +153,16 @@ WebInspector.TimelinePanel.prototype = {
this._lastRecord.endTime = formattedRecord.endTime;
this._lastRecord.count++;
} else {
- this._records.push(formattedRecord);
-
- for (var i = 0; record.children && i < record.children.length; ++i)
- this.addRecordToTimeline(record.children[i]);
+ collection.push(formattedRecord);
+ for (var i = 0; record.children && i < record.children.length; ++i) {
+ if (!formattedRecord.children)
+ formattedRecord.children = [];
+ var formattedChild = this._innerAddRecordToTimeline(record.children[i], formattedRecord.children);
+ formattedChild.parent = formattedRecord;
+ }
this._lastRecord = record.children && record.children.length ? null : formattedRecord;
}
- this._scheduleRefresh();
+ return formattedRecord;
},
_formatRecord: function(record)
@@ -196,9 +206,11 @@ WebInspector.TimelinePanel.prototype = {
this._sendRequestRecords[record.data.identifier] = formattedRecord;
} else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse) {
var sendRequestRecord = this._sendRequestRecords[record.data.identifier];
- sendRequestRecord._responseReceivedFormattedTime = formattedRecord.startTime;
- formattedRecord.startTime = sendRequestRecord.startTime;
- sendRequestRecord.details = this._getRecordDetails(record);
+ if (sendRequestRecord) { // False if we started instrumentation in the middle of request.
+ sendRequestRecord._responseReceivedFormattedTime = formattedRecord.startTime;
+ formattedRecord.startTime = sendRequestRecord.startTime;
+ sendRequestRecord.details = this._getRecordDetails(record);
+ }
} else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceFinish) {
var sendRequestRecord = this._sendRequestRecords[record.data.identifier];
if (sendRequestRecord) // False for main resource.
@@ -314,20 +326,37 @@ WebInspector.TimelinePanel.prototype = {
var record = this._records[i];
var percentages = this._calculator.computeBarGraphPercentages(record);
if (percentages.start < 100 && percentages.end >= 0 && !record.category.hidden)
- recordsInWindow.push(record);
+ this._addToRecordsWindow(record, recordsInWindow);
}
// Calculate the visible area.
var visibleTop = this._containerElement.scrollTop;
var visibleBottom = visibleTop + this._containerElement.clientHeight;
+
+ // Define row height, should be in sync with styles for timeline graphs.
const rowHeight = 18;
+ const expandOffset = 15;
- // Convert visible area to visible indexes.
+ // Convert visible area to visible indexes. Always include top-level record for a visible nested record.
var startIndex = Math.max(0, Math.floor(visibleTop / rowHeight) - 1);
+ while (startIndex > 0 && recordsInWindow[startIndex].parent)
+ startIndex--;
var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight));
+ while (endIndex < recordsInWindow.length - 1 && recordsInWindow[startIndex].parent)
+ endIndex++;
+ // Resize gaps first.
+ const top = (startIndex * rowHeight) + "px";
+ this._topGapElement.style.height = top;
+ this.sidebarElement.style.top = top;
+ this.sidebarResizeElement.style.top = top;
+ this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px";
+
+ // Update visible rows.
var listRowElement = this._sidebarListElement.firstChild;
var graphRowElement = this._graphRowsElement.firstChild;
+ var width = this._graphRowsElement.offsetWidth;
+ var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true);
for (var i = startIndex; i < endIndex; ++i) {
var record = recordsInWindow[i];
var isEven = !(i % 2);
@@ -337,39 +366,46 @@ WebInspector.TimelinePanel.prototype = {
this._sidebarListElement.appendChild(listRowElement);
}
if (!graphRowElement) {
- graphRowElement = new WebInspector.TimelineRecordGraphRow().element;
+ graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, scheduleRefreshCallback, rowHeight).element;
this._graphRowsElement.appendChild(graphRowElement);
}
listRowElement.listRow.update(record, isEven);
- graphRowElement.graphRow.update(record, isEven, this._calculator);
+ graphRowElement.graphRow.update(record, isEven, this._calculator, width, expandOffset);
listRowElement = listRowElement.nextSibling;
graphRowElement = graphRowElement.nextSibling;
}
+ // Remove extra rows.
while (listRowElement) {
var nextElement = listRowElement.nextSibling;
- listRowElement.parentElement.removeChild(listRowElement);
+ listRowElement.listRow.dispose();
listRowElement = nextElement;
}
-
while (graphRowElement) {
var nextElement = graphRowElement.nextSibling;
- graphRowElement.parentElement.removeChild(graphRowElement);
+ graphRowElement.graphRow.dispose();
graphRowElement = nextElement;
}
- this._timelineGrid.updateDividers(true, this._calculator);
-
- const top = (startIndex * rowHeight) + "px";
- this._topGapElement.style.height = top;
- this.sidebarElement.style.top = top;
- this.sidebarResizeElement.style.top = top;
- this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px";
+ // Reserve some room for expand / collapse controls to the left for records that start at 0ms.
+ var timelinePaddingLeft = this._calculator.windowLeft === 0 ? expandOffset : 0;
+ this._timelineGrid.updateDividers(true, this._calculator, timelinePaddingLeft);
this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight);
},
+ _addToRecordsWindow: function(record, recordsWindow)
+ {
+ recordsWindow.push(record);
+ if (!record.collapsed) {
+ var index = recordsWindow.length;
+ for (var i = 0; record.children && i < record.children.length; ++i)
+ this._addToRecordsWindow(record.children[i], recordsWindow);
+ record.visibleChildrenCount = recordsWindow.length - index;
+ }
+ },
+
_adjustScrollPosition: function(totalHeight)
{
// Prevent the container from being scrolled off the end.
@@ -474,7 +510,6 @@ WebInspector.TimelineRecordListRow = function()
{
this.element = document.createElement("div");
this.element.listRow = this;
-
var iconElement = document.createElement("span");
iconElement.className = "timeline-tree-icon";
this.element.appendChild(iconElement);
@@ -516,11 +551,16 @@ WebInspector.TimelineRecordListRow.prototype = {
this._repeatCountElement.textContent = "\u2009\u00d7\u2009" + record.count;
else
this._repeatCountElement.textContent = "";
+ },
+
+ dispose: function()
+ {
+ this.element.parentElement.removeChild(this.element);
}
}
-WebInspector.TimelineRecordGraphRow = function()
+WebInspector.TimelineRecordGraphRow = function(graphContainer, refreshCallback, rowHeight)
{
this.element = document.createElement("div");
this.element.graphRow = this;
@@ -532,14 +572,59 @@ WebInspector.TimelineRecordGraphRow = function()
this._barElement = document.createElement("div");
this._barElement.className = "timeline-graph-bar";
this._barAreaElement.appendChild(this._barElement);
+
+ this._expandElement = document.createElement("div");
+ this._expandElement.className = "timeline-expandable";
+ graphContainer.appendChild(this._expandElement);
+
+ var leftBorder = document.createElement("div");
+ leftBorder.className = "timeline-expandable-left";
+ this._expandElement.appendChild(leftBorder);
+
+ this._expandElement.addEventListener("click", this._onClick.bind(this));
+ this._refreshCallback = refreshCallback;
+ this._rowHeight = rowHeight;
}
WebInspector.TimelineRecordGraphRow.prototype = {
- update: function(record, isEven, calculator)
+ update: function(record, isEven, calculator, clientWidth, expandOffset)
{
+ this._record = record;
this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : "");
var percentages = calculator.computeBarGraphPercentages(record);
- this._barElement.style.setProperty("left", percentages.start + "%");
- this._barElement.style.setProperty("right", (100 - percentages.end) + "%");
+ var left = percentages.start / 100 * clientWidth;
+ var width = (percentages.end - percentages.start) / 100 * clientWidth;
+ this._barElement.style.left = (left + expandOffset) + "px";
+ this._barElement.style.width = width + "px";
+
+ if (record.visibleChildrenCount) {
+ this._expandElement.style.top = this.element.offsetTop + "px";
+ this._expandElement.style.left = left + "px";
+ this._expandElement.style.width = Math.max(12, width + 25) + "px";
+ if (!record.collapsed) {
+ this._expandElement.style.height = (record.visibleChildrenCount + 1) * this._rowHeight + "px";
+ this._expandElement.addStyleClass("timeline-expandable-expanded");
+ this._expandElement.removeStyleClass("timeline-expandable-collapsed");
+ } else {
+ this._expandElement.style.height = this._rowHeight + "px";
+ this._expandElement.addStyleClass("timeline-expandable-collapsed");
+ this._expandElement.removeStyleClass("timeline-expandable-expanded");
+ }
+ this._expandElement.removeStyleClass("hidden");
+ } else {
+ this._expandElement.addStyleClass("hidden");
+ }
+ },
+
+ _onClick: function(event)
+ {
+ this._record.collapsed = !this._record.collapsed;
+ this._refreshCallback();
+ },
+
+ dispose: function()
+ {
+ this.element.parentElement.removeChild(this.element);
+ this._expandElement.parentElement.removeChild(this._expandElement);
}
}
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 486930e..3ac365c 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -3288,6 +3288,11 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
bottom: 0;
}
+.timeline .sidebar {
+ overflow-y: hidden;
+ z-index: 100;
+}
+
#timeline-overview-separator {
position: absolute;
top: 80px;
@@ -3411,6 +3416,7 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
.timeline-tree-item {
height: 18px;
line-height: 15px;
+ padding-right: 5px;
padding-left: 10px;
padding-top: 2px;
white-space: nowrap;
@@ -3418,6 +3424,35 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
overflow: hidden;
}
+.timeline-expandable {
+ position: absolute;
+ border-left: 1px solid rgb(163, 163, 163);
+}
+
+.timeline-expandable-left {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 3px;
+ border-top: 1px solid rgb(163, 163, 163);
+ border-bottom: 1px solid rgb(163, 163, 163);
+}
+
+.timeline-expandable-collapsed {
+ background-image: url(Images/disclosureTriangleSmallRightBlack.png);
+ background-position-x: 1px;
+ background-position-y: 2px;
+ background-repeat: no-repeat;
+}
+
+.timeline-expandable-expanded {
+ background-image: url(Images/disclosureTriangleSmallDownBlack.png);
+ background-position-x: 1px;
+ background-position-y: 3px;
+ background-repeat: no-repeat;
+}
+
.timeline-tree-item .type {
padding-left: 14px;
}
@@ -3484,8 +3519,8 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
position: absolute;
top: 0;
bottom: 0;
- right: 8px;
- left: 9px;
+ right: 0;
+ left: 3px;
pointer-events: none;
}
diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js
index 54720ee..d52c9a3 100644
--- a/WebCore/inspector/front-end/utilities.js
+++ b/WebCore/inspector/front-end/utilities.js
@@ -550,6 +550,9 @@ Number.secondsToString = function(seconds, formatterFunction, higherResolution)
if (!formatterFunction)
formatterFunction = String.sprintf;
+ if (seconds === 0)
+ return "0";
+
var ms = seconds * 1000;
if (higherResolution && ms < 1000)
return formatterFunction("%.3fms", ms);
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list