1 // Copyright (c) 2012 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 network related log data and is specific fo ChromeOS. 7 * We get log data from chrome by filtering system logs for network related 8 * keywords. Logs are not fetched until we actually need them. 9 */ 10 var LogsView = (function() { 11 'use strict'; 12 13 // Special classes (defined in logs_view.css). 14 var LOG_ROW_COLLAPSED_CLASSNAME = 'logs-view-log-row-collapsed'; 15 var LOG_ROW_EXPANDED_CLASSNAME = 'logs-view-log-row-expanded'; 16 var LOG_CELL_TEXT_CLASSNAME = 'logs-view-log-cell-text'; 17 var LOG_CELL_LOG_CLASSNAME = 'logs-view-log-cell-log'; 18 var LOG_TABLE_BUTTON_COLUMN_CLASSNAME = 'logs-view-log-table-button-column'; 19 var LOG_BUTTON_CLASSNAME = 'logs-view-log-button'; 20 21 // We inherit from DivView. 22 var superClass = DivView; 23 24 /** 25 * @constructor 26 */ 27 function LogsView() { 28 assertFirstConstructorCall(LogsView); 29 30 // Call superclass's constructor. 31 superClass.call(this, LogsView.MAIN_BOX_ID); 32 33 var tableDiv = $(LogsView.TABLE_ID); 34 this.rows = []; 35 this.populateTable(tableDiv, LOG_FILTER_LIST); 36 $(LogsView.GLOBAL_SHOW_BUTTON_ID).addEventListener('click', 37 this.onGlobalChangeVisibleClick_.bind(this, true)); 38 $(LogsView.GLOBAL_HIDE_BUTTON_ID).addEventListener('click', 39 this.onGlobalChangeVisibleClick_.bind(this, false)); 40 $(LogsView.REFRESH_LOGS_BUTTON_ID).addEventListener('click', 41 this.onLogsRefresh_.bind(this)); 42 } 43 44 LogsView.TAB_ID = 'tab-handle-logs'; 45 LogsView.TAB_NAME = 'Logs'; 46 LogsView.TAB_HASH = '#logs'; 47 48 // IDs for special HTML elements in logs_view.html 49 LogsView.MAIN_BOX_ID = 'logs-view-tab-content'; 50 LogsView.TABLE_ID = 'logs-view-log-table'; 51 LogsView.GLOBAL_SHOW_BUTTON_ID = 'logs-view-global-show-btn'; 52 LogsView.GLOBAL_HIDE_BUTTON_ID = 'logs-view-global-hide-btn'; 53 LogsView.REFRESH_LOGS_BUTTON_ID = 'logs-view-refresh-btn'; 54 55 cr.addSingletonGetter(LogsView); 56 57 /** 58 * Contains log keys we are interested in. 59 */ 60 var LOG_FILTER_LIST = [ 61 { 62 key: 'syslog', 63 }, 64 { 65 key: 'ui_log', 66 }, 67 { 68 key: 'chrome_system_log', 69 }, 70 { 71 key: 'chrome_log', 72 } 73 ]; 74 75 LogsView.prototype = { 76 // Inherit the superclass's methods. 77 __proto__: superClass.prototype, 78 79 /** 80 * Called during View's initialization. Creates the row of a table logs will 81 * be shown in. Each row has 4 cells. 82 * 83 * First cell's content will be set to |logKey|, second will contain a 84 * button that will be used to show or hide third cell, which will contain 85 * the filtered log. 86 * |logKey| also tells us which log we are getting data from. 87 */ 88 createTableRow: function(logKey) { 89 var row = document.createElement('tr'); 90 91 var cells = []; 92 for (var i = 0; i < 3; i++) { 93 var rowCell = document.createElement('td'); 94 cells.push(rowCell); 95 row.appendChild(rowCell); 96 } 97 // Log key cell. 98 cells[0].className = LOG_CELL_TEXT_CLASSNAME; 99 cells[0].textContent = logKey; 100 // Cell log is displayed in. Log content is in div element that is 101 // initially hidden and empty. 102 cells[2].className = LOG_CELL_TEXT_CLASSNAME; 103 var logDiv = document.createElement('div'); 104 logDiv.textContent = ''; 105 logDiv.className = LOG_CELL_LOG_CLASSNAME; 106 logDiv.id = 'logs-view.log-cell.' + this.rows.length; 107 cells[2].appendChild(logDiv); 108 109 // Button that we use to show or hide div element with log content. Logs 110 // are not visible initially, so we initialize button accordingly. 111 var expandButton = document.createElement('button'); 112 expandButton.textContent = 'Show...'; 113 expandButton.className = LOG_BUTTON_CLASSNAME; 114 expandButton.addEventListener('click', 115 this.onButtonClicked_.bind(this, row)); 116 117 // Cell that contains show/hide button. 118 cells[1].appendChild(expandButton); 119 cells[1].className = LOG_TABLE_BUTTON_COLUMN_CLASSNAME; 120 121 // Initially, log is not visible. 122 row.className = LOG_ROW_COLLAPSED_CLASSNAME; 123 124 // We will need those to process row buttons' onclick events. 125 row.logKey = logKey; 126 row.expandButton = expandButton; 127 row.logDiv = logDiv; 128 row.logVisible = false; 129 this.rows.push(row); 130 131 return row; 132 }, 133 134 /** 135 * Initializes |tableDiv| to represent data from |logList| which should be 136 * of type LOG_FILTER_LIST. 137 */ 138 populateTable: function(tableDiv, logList) { 139 for (var i = 0; i < logList.length; i++) { 140 var logSource = this.createTableRow(logList[i].key); 141 tableDiv.appendChild(logSource); 142 } 143 }, 144 145 /** 146 * Processes clicks on buttons that show or hide log contents in log row. 147 * Row containing the clicked button is given to the method since it 148 * contains all data we need to process the click (unlike button object 149 * itself). 150 */ 151 onButtonClicked_: function(containingRow) { 152 if (!containingRow.logVisible) { 153 containingRow.className = LOG_ROW_EXPANDED_CLASSNAME; 154 containingRow.expandButton.textContent = 'Hide...'; 155 var logDiv = containingRow.logDiv; 156 if (logDiv.textContent == '') { 157 logDiv.textContent = 'Getting logs...'; 158 // Callback will be executed by g_browser. 159 g_browser.getSystemLog(containingRow.logKey, 160 containingRow.logDiv.id); 161 } 162 } else { 163 containingRow.className = LOG_ROW_COLLAPSED_CLASSNAME; 164 containingRow.expandButton.textContent = 'Show...'; 165 } 166 containingRow.logVisible = !containingRow.logVisible; 167 }, 168 169 /** 170 * Processes click on one of the buttons that are used to show or hide all 171 * logs we care about. 172 */ 173 onGlobalChangeVisibleClick_: function(isShowAll) { 174 for (var row in this.rows) { 175 if (isShowAll != this.rows[row].logVisible) { 176 this.onButtonClicked_(this.rows[row]); 177 } 178 } 179 }, 180 181 /** 182 * Processes click event on the button we use to refresh fetched logs. We 183 * get the newest logs from libcros, and refresh content of the visible log 184 * cells. 185 */ 186 onLogsRefresh_: function() { 187 g_browser.refreshSystemLogs(); 188 189 var visibleLogRows = []; 190 var hiddenLogRows = []; 191 for (var row in this.rows) { 192 if (this.rows[row].logVisible) { 193 visibleLogRows.push(this.rows[row]); 194 } else { 195 hiddenLogRows.push(this.rows[row]); 196 } 197 } 198 199 // We have to refresh text content in visible rows. 200 for (row in visibleLogRows) { 201 visibleLogRows[row].logDiv.textContent = 'Getting logs...'; 202 g_browser.getSystemLog(visibleLogRows[row].logKey, 203 visibleLogRows[row].logDiv.id); 204 } 205 206 // In hidden rows we just clear potential log text, so we know we have to 207 // get new contents when we show the row next time. 208 for (row in hiddenLogRows) { 209 hiddenLogRows[row].logDiv.textContent = ''; 210 } 211 } 212 }; 213 214 return LogsView; 215 })(); 216