dataview.js revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * This view displays options for importing/exporting the captured data. Its
7 * primarily usefulness is to allow users to copy-paste their data in an easy
8 * to read format for bug reports.
9 *
10 *   - Has a button to generate a text report.
11 *   - Has a button to generate a raw JSON dump (most useful for testing).
12 *
13 *  @constructor
14 */
15function DataView(mainBoxId, outputTextBoxId, exportTextButtonId) {
16  DivView.call(this, mainBoxId);
17
18  this.textPre_ = document.getElementById(outputTextBoxId);
19  var exportTextButton = document.getElementById(exportTextButtonId);
20
21  exportTextButton.onclick = this.onExportToText_.bind(this);
22}
23
24inherits(DataView, DivView);
25
26/**
27 * Presents the captured data as formatted text.
28 */
29DataView.prototype.onExportToText_ = function() {
30  this.setText_("Generating...");
31
32  var text = [];
33
34  // Print some basic information about our environment.
35  text.push('Data exported on: ' + (new Date()).toLocaleString());
36  text.push('');
37  text.push('Number of passively captured events: ' +
38            g_browser.getAllPassivelyCapturedEvents().length);
39  text.push('Number of actively captured events: ' +
40            g_browser.getAllActivelyCapturedEvents().length);
41  text.push('');
42
43  text.push('Chrome version: ' + ClientInfo.version +
44            ' (' + ClientInfo.official +
45            ' ' + ClientInfo.cl +
46            ') ' + ClientInfo.version_mod);
47  text.push('Command line: ' + ClientInfo.command_line);
48
49  text.push('');
50  text.push('----------------------------------------------');
51  text.push(' Proxy settings');
52  text.push('----------------------------------------------');
53  text.push('');
54
55  text.push(g_browser.proxySettings_.currentData_);
56
57  text.push('');
58  text.push('----------------------------------------------');
59  text.push(' Bad proxies cache');
60  text.push('----------------------------------------------');
61
62  var badProxiesList = g_browser.badProxies_.currentData_;
63  if (badProxiesList.length == 0) {
64    text.push('');
65    text.push('None');
66  } else {
67    for (var i = 0; i < badProxiesList.length; ++i) {
68      var e = badProxiesList[i];
69      text.push('');
70      text.push('(' + (i+1) + ')');
71      text.push('Proxy: ' + e.proxy_uri);
72      text.push('Bad until: ' + this.formatExpirationTime_(e.bad_until));
73    }
74  }
75
76  text.push('');
77  text.push('----------------------------------------------');
78  text.push(' Host resolver cache');
79  text.push('----------------------------------------------');
80  text.push('');
81
82  var hostResolverCache = g_browser.hostResolverCache_.currentData_;
83
84  text.push('Capcity: ' + hostResolverCache.capacity);
85  text.push('Time to live for successful resolves (ms): ' +
86            hostResolverCache.ttl_success_ms);
87  text.push('Time to live for failed resolves (ms): ' +
88            hostResolverCache.ttl_failure_ms);
89
90  if (hostResolverCache.entries.length > 0) {
91    for (var i = 0; i < hostResolverCache.entries.length; ++i) {
92      var e = hostResolverCache.entries[i];
93
94      text.push('');
95      text.push('(' + (i+1) + ')');
96      text.push('Hostname: ' + e.hostname);
97      text.push('Address family: ' + e.address_family);
98
99      if (e.error != undefined) {
100         text.push('Error: ' + e.error);
101      } else {
102        for (var j = 0; j < e.addresses.length; ++j) {
103          text.push('Address ' + (j + 1) + ': ' + e.addresses[j]);
104        }
105      }
106
107      text.push('Valid until: ' + this.formatExpirationTime_(e.expiration));
108    }
109  } else {
110    text.push('');
111    text.push('None');
112  }
113
114  text.push('');
115  text.push('----------------------------------------------');
116  text.push(' Requests');
117  text.push('----------------------------------------------');
118  text.push('');
119
120  this.appendRequestsPrintedAsText_(text);
121
122  text.push('');
123  text.push('----------------------------------------------');
124  text.push(' Http cache stats');
125  text.push('----------------------------------------------');
126  text.push('');
127
128  var httpCacheStats = g_browser.httpCacheInfo_.currentData_.stats;
129  for (var statName in httpCacheStats)
130    text.push(statName + ': ' + httpCacheStats[statName]);
131
132  // Open a new window to display this text.
133  this.setText_(text.join('\n'));
134};
135
136DataView.prototype.appendRequestsPrintedAsText_ = function(out) {
137  // Concatenate the passively captured events with the actively captured events
138  // into a single array.
139  var allEvents = g_browser.getAllPassivelyCapturedEvents().concat(
140      g_browser.getAllActivelyCapturedEvents());
141
142  // Group the events into buckets by source ID, and buckets by source type.
143  var sourceIds = [];
144  var sourceIdToEventList = {};
145  var sourceTypeToSourceIdList = {}
146
147  for (var i = 0; i < allEvents.length; ++i) {
148    var e = allEvents[i];
149    var eventList = sourceIdToEventList[e.source.id];
150    if (!eventList) {
151      eventList = [];
152      sourceIdToEventList[e.source.id] = eventList;
153
154      // Update sourceIds
155      sourceIds.push(e.source.id);
156
157      // Update the sourceTypeToSourceIdList list.
158      var idList = sourceTypeToSourceIdList[e.source.type];
159      if (!idList) {
160        idList = [];
161        sourceTypeToSourceIdList[e.source.type] = idList;
162      }
163      idList.push(e.source.id);
164    }
165    eventList.push(e);
166  }
167
168
169  // For each source (ordered by when that source was first started).
170  for (var i = 0; i < sourceIds.length; ++i) {
171    var sourceId = sourceIds[i];
172    var eventList = sourceIdToEventList[sourceId];
173    var sourceType = eventList[0].source.type;
174
175    out.push('------------------------------');
176    out.push(getKeyWithValue(LogSourceType, sourceType) +
177             ' (id=' + sourceId + ')');
178    out.push('------------------------------');
179
180    out.push(PrintSourceEntriesAsText(eventList));
181  }
182};
183
184/**
185 * Helper function to set this view's content to |text|.
186 */
187DataView.prototype.setText_ = function(text) {
188  this.textPre_.innerHTML = '';
189  addTextNode(this.textPre_, text);
190};
191
192/**
193 * Format a time ticks count as a timestamp.
194 */
195DataView.prototype.formatExpirationTime_ = function(timeTicks) {
196  var d = g_browser.convertTimeTicksToDate(timeTicks);
197  var isExpired = d.getTime() < (new Date()).getTime();
198  return 't=' + d.getTime() + (isExpired ? ' [EXPIRED]' : '');
199};
200
201
202