Title: [121767] trunk
Revision
121767
Author
[email protected]
Date
2012-07-03 08:27:06 -0700 (Tue, 03 Jul 2012)

Log Message

Web Inspector: Forward message loop instrumentation data to frontend.
https://bugs.webkit.org/show_bug.cgi?id=89584

Patch by Eugene Klyuchnikov <[email protected]> on 2012-07-03
Reviewed by Yury Semikhatsky.

Transmit collected message loop tasks to inspector frontend.
Now "Program" should be a top-level event on browsers that
support message loop instrumentation.
Frontend was changed so that user will not see any changes.

Source/WebCore:

* inspector/InspectorTimelineAgent.cpp:
(TimelineRecordType):
Added new event type - "Program"
(WebCore::InspectorTimelineAgent::willProcessTask):
Begin "Program" event.
(WebCore::InspectorTimelineAgent::didProcessTask):
Finish "Program" event.
(WebCore::InspectorTimelineAgent::setHeapSizeStatistic):
Do not add counters to "Program" events.
(WebCore):
(WebCore::InspectorTimelineAgent::innerSetHeapSizeStatistic):
Renamed from "setHeapSizeStatistic"
* inspector/InspectorTimelineAgent.h:
(InspectorTimelineAgent):
* inspector/front-end/MemoryStatistics.js:
(WebInspector.MemoryStatistics.prototype._onRecordAdded):
Unwraps "Program" events.
(WebInspector.MemoryStatistics.prototype._innerRecordAdded):
Renamed from "_onRecordAdded"
* inspector/front-end/TimelineFrameController.js:
(WebInspector.TimelineFrameController.prototype._addRecord):
Unwraps "Program" events.
(WebInspector.TimelineFrameController.prototype._innerAddRecord):
Renamed from "_addRecord"
* inspector/front-end/TimelineModel.js:
* inspector/front-end/TimelineOverviewPane.js:
(WebInspector.TimelineCategoryStrips.prototype.update.appendRecord):
Filter out "Program" category.
(WebInspector.TimelineCategoryStrips.prototype.update):
* inspector/front-end/TimelinePanel.js:
(WebInspector.TimelinePanel.prototype._createStatusbarButtons):
Filter out "Program" category.
(WebInspector.TimelinePanel.prototype._innerAddRecordToTimeline):
Unwraps "Program" events.
* inspector/front-end/TimelinePresentationModel.js:
(WebInspector.TimelinePresentationModel.categories):
Added "Program" category.
(WebInspector.TimelinePresentationModel.recordStyle):
Ditto.
(WebInspector.TimelinePresentationModel.prototype.addRecord):
Unwraps "Program" events.
(WebInspector.TimelinePresentationModel.prototype._addRecord):
Renamed from "addRecord"

LayoutTests:

* inspector/timeline/timeline-enum-stability-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (121766 => 121767)


--- trunk/LayoutTests/ChangeLog	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/LayoutTests/ChangeLog	2012-07-03 15:27:06 UTC (rev 121767)
@@ -1,3 +1,17 @@
+2012-07-03  Eugene Klyuchnikov  <[email protected]>
+
+        Web Inspector: Forward message loop instrumentation data to frontend.
+        https://bugs.webkit.org/show_bug.cgi?id=89584
+
+        Reviewed by Yury Semikhatsky.
+
+        Transmit collected message loop tasks to inspector frontend.
+        Now "Program" should be a top-level event on browsers that
+        support message loop instrumentation.
+        Frontend was changed so that user will not see any changes.
+
+        * inspector/timeline/timeline-enum-stability-expected.txt:
+
 2012-07-03  Vsevolod Vlasov  <[email protected]>
 
         inspector/debugger/script-snippet-model.html fails

Modified: trunk/LayoutTests/inspector/timeline/timeline-enum-stability-expected.txt (121766 => 121767)


--- trunk/LayoutTests/inspector/timeline/timeline-enum-stability-expected.txt	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/LayoutTests/inspector/timeline/timeline-enum-stability-expected.txt	2012-07-03 15:27:06 UTC (rev 121767)
@@ -4,6 +4,7 @@
 
 {
     Root : "Root"
+    Program : "Program"
     EventDispatch : "EventDispatch"
     BeginFrame : "BeginFrame"
     Layout : "Layout"

Added: trunk/LayoutTests/inspector/timeline-dfs-expected.txt (0 => 121767)


--- trunk/LayoutTests/inspector/timeline-dfs-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/timeline-dfs-expected.txt	2012-07-03 15:27:06 UTC (rev 121767)
@@ -0,0 +1,34 @@
+Tests TimelinePresentationModel.forAllRecords function.
+
+DFS preorder:
+a
+aa
+aaa
+aab
+ab
+aba
+abb
+b
+ba
+baa
+bab
+bb
+bba
+bbb
+
+DFS postorder:
+aaa
+aab
+aa
+aba
+abb
+ab
+a
+baa
+bab
+ba
+bba
+bbb
+bb
+b
+
Property changes on: trunk/LayoutTests/inspector/timeline-dfs-expected.txt
___________________________________________________________________

Added: svn:eol-style

Added: trunk/LayoutTests/inspector/timeline-dfs.html (0 => 121767)


--- trunk/LayoutTests/inspector/timeline-dfs.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/timeline-dfs.html	2012-07-03 15:27:06 UTC (rev 121767)
@@ -0,0 +1,50 @@
+<html>
+<head>
+<script src=""
+<script type="text/_javascript_">
+
+var test = function()
+{
+    function dumper(record)
+    {
+        InspectorTest.addResult(record.name);
+    }
+
+    var records = [
+        {"name" : "a", "children" : [
+            {"name" : "aa", "children": [
+                {"name" : "aaa"},
+                {"name" : "aab"},
+            ]},
+            {"name" : "ab", "children":[
+                {"name" : "aba"},
+                {"name" : "abb"},
+            ]}
+        ]},
+        {"name" : "b", "children" : [
+            {"name" : "ba", "children" : [
+                {"name" : "baa"},
+                {"name" : "bab"},
+            ]},
+            {"name" : "bb", "children":[
+                {"name" : "bba"},
+                {"name" : "bbb"},
+            ]}
+        ]},
+    ];
+
+    InspectorTest.addResult("DFS preorder:");
+    WebInspector.TimelinePresentationModel.forAllRecords(records, dumper);
+    InspectorTest.addResult("");
+
+    InspectorTest.addResult("DFS postorder:");
+    WebInspector.TimelinePresentationModel.forAllRecords(records, null, dumper);
+    InspectorTest.completeTest();
+}
+
+</script>
+</head>
+<body _onload_="runTest()">
+<p>Tests TimelinePresentationModel.forAllRecords function.</p>
+</body>
+</html>
Property changes on: trunk/LayoutTests/inspector/timeline-dfs.html
___________________________________________________________________

Added: svn:eol-style

Modified: trunk/Source/WebCore/ChangeLog (121766 => 121767)


--- trunk/Source/WebCore/ChangeLog	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/ChangeLog	2012-07-03 15:27:06 UTC (rev 121767)
@@ -1,3 +1,59 @@
+2012-07-03  Eugene Klyuchnikov  <[email protected]>
+
+        Web Inspector: Forward message loop instrumentation data to frontend.
+        https://bugs.webkit.org/show_bug.cgi?id=89584
+
+        Reviewed by Yury Semikhatsky.
+
+        Transmit collected message loop tasks to inspector frontend.
+        Now "Program" should be a top-level event on browsers that
+        support message loop instrumentation.
+        Frontend was changed so that user will not see any changes.
+
+        * inspector/InspectorTimelineAgent.cpp:
+        (TimelineRecordType):
+        Added new event type - "Program"
+        (WebCore::InspectorTimelineAgent::willProcessTask):
+        Begin "Program" event.
+        (WebCore::InspectorTimelineAgent::didProcessTask):
+        Finish "Program" event.
+        (WebCore::InspectorTimelineAgent::setHeapSizeStatistic):
+        Do not add counters to "Program" events.
+        (WebCore):
+        (WebCore::InspectorTimelineAgent::innerSetHeapSizeStatistic):
+        Renamed from "setHeapSizeStatistic"
+        * inspector/InspectorTimelineAgent.h:
+        (InspectorTimelineAgent):
+        * inspector/front-end/MemoryStatistics.js:
+        (WebInspector.MemoryStatistics.prototype._onRecordAdded):
+        Unwraps "Program" events.
+        (WebInspector.MemoryStatistics.prototype._innerRecordAdded):
+        Renamed from "_onRecordAdded"
+        * inspector/front-end/TimelineFrameController.js:
+        (WebInspector.TimelineFrameController.prototype._addRecord):
+        Unwraps "Program" events.
+        (WebInspector.TimelineFrameController.prototype._innerAddRecord):
+        Renamed from "_addRecord"
+        * inspector/front-end/TimelineModel.js:
+        * inspector/front-end/TimelineOverviewPane.js:
+        (WebInspector.TimelineCategoryStrips.prototype.update.appendRecord):
+        Filter out "Program" category.
+        (WebInspector.TimelineCategoryStrips.prototype.update):
+        * inspector/front-end/TimelinePanel.js:
+        (WebInspector.TimelinePanel.prototype._createStatusbarButtons):
+        Filter out "Program" category.
+        (WebInspector.TimelinePanel.prototype._innerAddRecordToTimeline):
+        Unwraps "Program" events.
+        * inspector/front-end/TimelinePresentationModel.js:
+        (WebInspector.TimelinePresentationModel.categories):
+        Added "Program" category.
+        (WebInspector.TimelinePresentationModel.recordStyle):
+        Ditto.
+        (WebInspector.TimelinePresentationModel.prototype.addRecord):
+        Unwraps "Program" events.
+        (WebInspector.TimelinePresentationModel.prototype._addRecord):
+        Renamed from "addRecord"
+
 2012-07-03  Tor Arne Vestbø  <[email protected]>
 
         [Qt] Make use of .qmake.cache for caching features

Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp (121766 => 121767)


--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp	2012-07-03 15:27:06 UTC (rev 121767)
@@ -60,6 +60,8 @@
 
 // Must be kept in sync with WebInspector.TimelineModel.RecordType in TimelineModel.js
 namespace TimelineRecordType {
+static const char Program[] = "Program";
+
 static const char EventDispatch[] = "EventDispatch";
 static const char BeginFrame[] = "BeginFrame";
 static const char Layout[] = "Layout";
@@ -342,7 +344,7 @@
         String frameId(m_pageAgent->frameId(frame));
         recordRaw->setString("frameId", frameId);
     }
-    setHeapSizeStatistic(recordRaw.get());
+    setHeapSizeStatistics(recordRaw.get());
     // FIXME: runtimeCast is a hack. We do it because we can't build TimelineEvent directly now.
     RefPtr<TypeBuilder::Timeline::TimelineEvent> record = TypeBuilder::Timeline::TimelineEvent::runtimeCast(recordRaw.release());
     m_frontend->eventRecorded(record.release());
@@ -427,12 +429,12 @@
 
 void InspectorTimelineAgent::willProcessTask()
 {
-    // TODO: Record task processing start time.
+    pushCurrentRecord(InspectorObject::create(), TimelineRecordType::Program, false, 0);
 }
 
 void InspectorTimelineAgent::didProcessTask()
 {
-    // TODO: Record task processing end time.
+    didCompleteCurrentRecord(TimelineRecordType::Program);
 }
 
 void InspectorTimelineAgent::addRecordToTimeline(PassRefPtr<InspectorObject> record, const String& type, const String& frameId)
@@ -443,11 +445,15 @@
 
 void InspectorTimelineAgent::innerAddRecordToTimeline(PassRefPtr<InspectorObject> prpRecord, const String& type, const String& frameId)
 {
+    DEFINE_STATIC_LOCAL(String, program, (TimelineRecordType::Program));
+
     RefPtr<InspectorObject> record(prpRecord);
     record->setString("type", type);
     if (!frameId.isEmpty())
         record->setString("frameId", frameId);
-    setHeapSizeStatistic(record.get());
+    if (type != program)
+        setHeapSizeStatistics(record.get());
+
     if (m_recordStack.isEmpty()) {
         // FIXME: runtimeCast is a hack. We do it because we can't build TimelineEvent directly now.
         RefPtr<TypeBuilder::Timeline::TimelineEvent> recordChecked = TypeBuilder::Timeline::TimelineEvent::runtimeCast(record.release());
@@ -458,7 +464,7 @@
     }
 }
 
-void InspectorTimelineAgent::setHeapSizeStatistic(InspectorObject* record)
+void InspectorTimelineAgent::setHeapSizeStatistics(InspectorObject* record)
 {
     size_t usedHeapSize = 0;
     size_t totalHeapSize = 0;

Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.h (121766 => 121767)


--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2012-07-03 15:27:06 UTC (rev 121767)
@@ -163,8 +163,8 @@
     InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorState*, InspectorType, InspectorClient*);
 
     void pushCurrentRecord(PassRefPtr<InspectorObject>, const String& type, bool captureCallStack, Frame*);
-    void setHeapSizeStatistic(InspectorObject* record);
-        
+    void setHeapSizeStatistics(InspectorObject* record);
+
     void didCompleteCurrentRecord(const String& type);
     void appendRecord(PassRefPtr<InspectorObject> data, const String& type, bool captureCallStack, Frame*);
     void pushCancelableRecord(PassRefPtr<InspectorObject>, const String& type, Frame*);

Modified: trunk/Source/WebCore/inspector/front-end/MemoryStatistics.js (121766 => 121767)


--- trunk/Source/WebCore/inspector/front-end/MemoryStatistics.js	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/front-end/MemoryStatistics.js	2012-07-03 15:27:06 UTC (rev 121767)
@@ -257,15 +257,20 @@
 
     _onRecordAdded: function(event)
     {
-        var counters = event.data["counters"];
-        if (!counters)
-            return;
-        this._counters.push({
-            time: event.data.endTime || event.data.startTime,
-            documentCount: counters["documents"],
-            nodeCount: counters["nodes"],
-            listenerCount: counters["jsEventListeners"]
-        });
+        var statistics = this._counters;
+        function addStatistics(record)
+        {
+            var counters = record["counters"];
+            if (!counters)
+                return;
+            statistics.push({
+                time: record.endTime || record.startTime,
+                documentCount: counters["documents"],
+                nodeCount: counters["nodes"],
+                listenerCount: counters["jsEventListeners"]
+            });
+        }
+        WebInspector.TimelinePresentationModel.forAllRecords([event.data], null, addStatistics);
     },
 
     _draw: function()

Modified: trunk/Source/WebCore/inspector/front-end/TimelineFrameController.js (121766 => 121767)


--- trunk/Source/WebCore/inspector/front-end/TimelineFrameController.js	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/front-end/TimelineFrameController.js	2012-07-03 15:27:06 UTC (rev 121767)
@@ -61,6 +61,16 @@
 
     _addRecord: function(record)
     {
+        var records;
+        if (record.type === WebInspector.TimelineModel.RecordType.Program)
+            records = record["children"] || [];
+        else
+            records = [record];
+        records.forEach(this._innerAddRecord, this);
+    },
+
+    _innerAddRecord: function(record)
+    {
         if (record.type === WebInspector.TimelineModel.RecordType.BeginFrame && this._lastFrame)
             this._flushFrame(record);
         else {

Modified: trunk/Source/WebCore/inspector/front-end/TimelineModel.js (121766 => 121767)


--- trunk/Source/WebCore/inspector/front-end/TimelineModel.js	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/front-end/TimelineModel.js	2012-07-03 15:27:06 UTC (rev 121767)
@@ -44,6 +44,7 @@
 
 WebInspector.TimelineModel.RecordType = {
     Root: "Root",
+    Program: "Program",
     EventDispatch: "EventDispatch",
 
     BeginFrame: "BeginFrame",

Modified: trunk/Source/WebCore/inspector/front-end/TimelineOverviewPane.js (121766 => 121767)


--- trunk/Source/WebCore/inspector/front-end/TimelineOverviewPane.js	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/front-end/TimelineOverviewPane.js	2012-07-03 15:27:06 UTC (rev 121767)
@@ -885,6 +885,8 @@
             var recordStart = Math.floor((WebInspector.TimelineModel.startTimeInSeconds(record) - timeOffset) * scale);
             var recordEnd = Math.ceil((WebInspector.TimelineModel.endTimeInSeconds(record) - timeOffset) * scale);
             var category = WebInspector.TimelinePresentationModel.categoryForRecord(record);
+            if (category.overviewStripGroupIndex < 0)
+                return;
             var bar = lastBarByGroup[category.overviewStripGroupIndex];
             // This bar may be merged with previous -- so just adjust the previous bar.
             const barsMergeThreshold = 2;

Modified: trunk/Source/WebCore/inspector/front-end/TimelinePanel.js (121766 => 121767)


--- trunk/Source/WebCore/inspector/front-end/TimelinePanel.js	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/front-end/TimelinePanel.js	2012-07-03 15:27:06 UTC (rev 121767)
@@ -232,6 +232,8 @@
         var categories = WebInspector.TimelinePresentationModel.categories();
         for (var categoryName in categories) {
             var category = categories[categoryName];
+            if (category.overviewStripGroupIndex < 0)
+                continue;
             this.statusBarFilters.appendChild(this._createTimelineCategoryStatusBarCheckbox(category, this._onCategoryCheckboxClicked.bind(this, category)));
         }
     },
@@ -495,8 +497,8 @@
 
     _innerAddRecordToTimeline: function(record, parentRecord)
     {
-        var formattedRecord = this._presentationModel.addRecord(record, parentRecord);
-        ++this._allRecordsCount;
+        var records = this._presentationModel.addRecord(record, parentRecord);
+        this._allRecordsCount += records.length;
         var recordTypes = WebInspector.TimelineModel.RecordType;
         var timeStampRecords = this._timeStampRecords;
         var hasVisibleRecords = false;
@@ -507,10 +509,14 @@
                 timeStampRecords.push(record);
             hasVisibleRecords |= presentationModel.isVisible(record);
         }
-        var records = [ formattedRecord ];
         WebInspector.TimelinePresentationModel.forAllRecords(records, processRecord);
+
+        function isAdoptedRecord(record)
+        {
+            return record.parent !== presentationModel.rootRecord;
+        }
         // Tell caller update is necessary either if we added a visible record or if we re-parented a record.
-        return hasVisibleRecords || formattedRecord.parent !== this._presentationModel.rootRecord;
+        return hasVisibleRecords || records.some(isAdoptedRecord);
     },
 
     sidebarResized: function(event)

Modified: trunk/Source/WebCore/inspector/front-end/TimelinePresentationModel.js (121766 => 121767)


--- trunk/Source/WebCore/inspector/front-end/TimelinePresentationModel.js	2012-07-03 15:23:20 UTC (rev 121766)
+++ trunk/Source/WebCore/inspector/front-end/TimelinePresentationModel.js	2012-07-03 15:27:06 UTC (rev 121767)
@@ -47,6 +47,7 @@
     if (WebInspector.TimelinePresentationModel._categories)
         return WebInspector.TimelinePresentationModel._categories;
     WebInspector.TimelinePresentationModel._categories = {
+        program: new WebInspector.TimelineCategory("program", WebInspector.UIString("Program"), -1, "#BBBBBB", "#DDDDDD", "#FFFFFF"),
         loading: new WebInspector.TimelineCategory("loading", WebInspector.UIString("Loading"), 0, "#5A8BCC", "#8EB6E9", "#70A2E3"),
         scripting: new WebInspector.TimelineCategory("scripting", WebInspector.UIString("Scripting"), 1, "#D8AA34", "#F3D07A", "#F1C453"),
         rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), 2, "#8266CC", "#AF9AEB", "#9A7EE6"),
@@ -68,6 +69,7 @@
 
     var recordStyles = {};
     recordStyles[recordTypes.Root] = { title: "#root", category: categories["loading"] };
+    recordStyles[recordTypes.Program] = { title: WebInspector.UIString("Program"), category: categories["program"] };
     recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: categories["scripting"] };
     recordStyles[recordTypes.BeginFrame] = { title: WebInspector.UIString("Frame Start"), category: categories["rendering"] };
     recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: categories["rendering"] };
@@ -103,7 +105,7 @@
 
 WebInspector.TimelinePresentationModel.categoryForRecord = function(record)
 {
-    return WebInspector.TimelinePresentationModel.recordStyle(record).category;
+        return WebInspector.TimelinePresentationModel.recordStyle(record).category;
 }
 
 WebInspector.TimelinePresentationModel.isEventDivider = function(record)
@@ -117,7 +119,12 @@
     return false;
 }
 
-WebInspector.TimelinePresentationModel.forAllRecords = function(recordsArray, callback)
+/**
+ * @param {Array} recordsArray
+ * @param {?function(*)} preOrderCallback
+ * @param {function(*)=} postOrderCallback
+ */
+WebInspector.TimelinePresentationModel.forAllRecords = function(recordsArray, preOrderCallback, postOrderCallback)
 {
     if (!recordsArray)
         return;
@@ -127,13 +134,18 @@
         var records = entry.array;
         if (entry.index < records.length) {
              var record = records[entry.index];
-             if (callback(record))
+             if (preOrderCallback && preOrderCallback(record))
                  return;
              if (record.children)
-                 stack.push({array: record.children, index: 0});
+                 stack.push({array: record.children, index: 0, record: record});
+             else if (postOrderCallback && postOrderCallback(record))
+                return;
              ++entry.index;
-        } else
+        } else {
+            if (entry.record && postOrderCallback && postOrderCallback(entry.record))
+                return;
             stack.pop();
+        }
     }
 }
 
@@ -205,12 +217,27 @@
 
     addRecord: function(record, parentRecord)
     {
+        if (this._minimumRecordTime === -1 || record.startTime < this._minimumRecordTime)
+            this._minimumRecordTime = WebInspector.TimelineModel.startTimeInSeconds(record);
+
+        var records;
+        if (record.type === WebInspector.TimelineModel.RecordType.Program)
+            records = record.children;
+        else
+            records = [record];
+
+        var formattedRecords = [];
+        var recordsCount = records.length;
+        for (var i = 0; i < recordsCount; ++i)
+            formattedRecords.push(this._innerAddRecord(records[i], parentRecord));
+        return formattedRecords;
+    },
+
+    _innerAddRecord: function(record, parentRecord)
+    {
         var connectedToOldRecord = false;
         var recordTypes = WebInspector.TimelineModel.RecordType;
 
-        if (this._minimumRecordTime === -1 || record.startTime < this._minimumRecordTime)
-            this._minimumRecordTime = WebInspector.TimelineModel.startTimeInSeconds(record);
-
         switch (record.type) {
         // No bar entry for load events.
         case recordTypes.MarkDOMContent:
@@ -257,7 +284,7 @@
 
         var childrenCount = children ? children.length : 0;
         for (var i = 0; i < childrenCount; ++i)
-            this.addRecord(children[i], formattedRecord);
+            this._innerAddRecord(children[i], formattedRecord);
 
         formattedRecord.calculateAggregatedStats(WebInspector.TimelinePresentationModel.categories());
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to