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