Home | History | Annotate | Download | only in net_internals
      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