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 information on the host resolver:
      7  *
      8  *   - Shows the default address family.
      9  *   - Has a button to enable IPv6, if it is disabled.
     10  *   - Shows the current host cache contents.
     11  *   - Has a button to clear the host cache.
     12  *   - Shows the parameters used to construct the host cache (capacity, ttl).
     13  */
     14 
     15 // TODO(mmenke):  Add links for each address entry to the corresponding NetLog
     16 //                source.  This could either be done by adding NetLog source ids
     17 //                to cache entries, or tracking sources based on their type and
     18 //                description.  Former is simpler, latter may be useful
     19 //                elsewhere as well.
     20 var DnsView = (function() {
     21   'use strict';
     22 
     23   // We inherit from DivView.
     24   var superClass = DivView;
     25 
     26   /**
     27    *  @constructor
     28    */
     29   function DnsView() {
     30     assertFirstConstructorCall(DnsView);
     31 
     32     // Call superclass's constructor.
     33     superClass.call(this, DnsView.MAIN_BOX_ID);
     34 
     35     $(DnsView.ENABLE_IPV6_BUTTON_ID).onclick =
     36         g_browser.enableIPv6.bind(g_browser);
     37     $(DnsView.CLEAR_CACHE_BUTTON_ID).onclick =
     38         g_browser.sendClearHostResolverCache.bind(g_browser);
     39 
     40     // Register to receive changes to the host resolver info.
     41     g_browser.addHostResolverInfoObserver(this, false);
     42   }
     43 
     44   DnsView.TAB_ID = 'tab-handle-dns';
     45   DnsView.TAB_NAME = 'DNS';
     46   DnsView.TAB_HASH = '#dns';
     47 
     48   // IDs for special HTML elements in dns_view.html
     49   DnsView.MAIN_BOX_ID = 'dns-view-tab-content';
     50   DnsView.DEFAULT_FAMILY_SPAN_ID = 'dns-view-default-family';
     51   DnsView.IPV6_DISABLED_SPAN_ID = 'dns-view-ipv6-disabled';
     52   DnsView.ENABLE_IPV6_BUTTON_ID = 'dns-view-enable-ipv6';
     53 
     54   DnsView.INTERNAL_DNS_ENABLED_SPAN_ID = 'dns-view-internal-dns-enabled';
     55   DnsView.INTERNAL_DNS_INVALID_CONFIG_SPAN_ID =
     56       'dns-view-internal-dns-invalid-config';
     57   DnsView.INTERNAL_DNS_CONFIG_TBODY_ID = 'dns-view-internal-dns-config-tbody';
     58 
     59   DnsView.CLEAR_CACHE_BUTTON_ID = 'dns-view-clear-cache';
     60   DnsView.CAPACITY_SPAN_ID = 'dns-view-cache-capacity';
     61 
     62   DnsView.ACTIVE_SPAN_ID = 'dns-view-cache-active';
     63   DnsView.EXPIRED_SPAN_ID = 'dns-view-cache-expired';
     64   DnsView.CACHE_TBODY_ID = 'dns-view-cache-tbody';
     65 
     66   cr.addSingletonGetter(DnsView);
     67 
     68   DnsView.prototype = {
     69     // Inherit the superclass's methods.
     70     __proto__: superClass.prototype,
     71 
     72     onLoadLogFinish: function(data) {
     73       return this.onHostResolverInfoChanged(data.hostResolverInfo);
     74     },
     75 
     76     onHostResolverInfoChanged: function(hostResolverInfo) {
     77       // Clear the existing values.
     78       $(DnsView.DEFAULT_FAMILY_SPAN_ID).innerHTML = '';
     79       $(DnsView.CAPACITY_SPAN_ID).innerHTML = '';
     80       $(DnsView.CACHE_TBODY_ID).innerHTML = '';
     81       $(DnsView.ACTIVE_SPAN_ID).innerHTML = '0';
     82       $(DnsView.EXPIRED_SPAN_ID).innerHTML = '0';
     83 
     84       // Update fields containing async DNS configuration information.
     85       displayAsyncDnsConfig_(hostResolverInfo);
     86 
     87       // No info.
     88       if (!hostResolverInfo || !hostResolverInfo.cache)
     89         return false;
     90 
     91       var family = hostResolverInfo.default_address_family;
     92       addTextNode($(DnsView.DEFAULT_FAMILY_SPAN_ID),
     93                   addressFamilyToString(family));
     94 
     95       var ipv6Disabled = (family == AddressFamily.ADDRESS_FAMILY_IPV4);
     96       setNodeDisplay($(DnsView.IPV6_DISABLED_SPAN_ID), ipv6Disabled);
     97 
     98       // Fill in the basic cache information.
     99       var hostResolverCache = hostResolverInfo.cache;
    100       $(DnsView.CAPACITY_SPAN_ID).innerText = hostResolverCache.capacity;
    101 
    102       var expiredEntries = 0;
    103       // Date the cache was logged.  This will be either now, when actively
    104       // logging data, or the date the log dump was created.
    105       var logDate;
    106       if (MainView.isViewingLoadedLog()) {
    107         logDate = new Date(ClientInfo.numericDate);
    108       } else {
    109         logDate = new Date();
    110       }
    111 
    112       // Fill in the cache contents table.
    113       for (var i = 0; i < hostResolverCache.entries.length; ++i) {
    114         var e = hostResolverCache.entries[i];
    115         var tr = addNode($(DnsView.CACHE_TBODY_ID), 'tr');
    116 
    117         var hostnameCell = addNode(tr, 'td');
    118         addTextNode(hostnameCell, e.hostname);
    119 
    120         var familyCell = addNode(tr, 'td');
    121         addTextNode(familyCell,
    122                     addressFamilyToString(e.address_family));
    123 
    124         var addressesCell = addNode(tr, 'td');
    125 
    126         if (e.error != undefined) {
    127           var errorText =
    128               e.error + ' (' + netErrorToString(e.error) + ')';
    129           var errorNode = addTextNode(addressesCell, 'error: ' + errorText);
    130           addressesCell.classList.add('warning-text');
    131         } else {
    132           addListToNode_(addNode(addressesCell, 'div'), e.addresses);
    133         }
    134 
    135         var expiresDate = timeutil.convertTimeTicksToDate(e.expiration);
    136         var expiresCell = addNode(tr, 'td');
    137         timeutil.addNodeWithDate(expiresCell, expiresDate);
    138         if (logDate > timeutil.convertTimeTicksToDate(e.expiration)) {
    139           ++expiredEntries;
    140           var expiredSpan = addNode(expiresCell, 'span');
    141           expiredSpan.classList.add('warning-text');
    142           addTextNode(expiredSpan, ' [Expired]');
    143         }
    144       }
    145 
    146       $(DnsView.ACTIVE_SPAN_ID).innerText =
    147           hostResolverCache.entries.length - expiredEntries;
    148       $(DnsView.EXPIRED_SPAN_ID).innerText = expiredEntries;
    149       return true;
    150     },
    151   };
    152 
    153   /**
    154    * Displays information corresponding to the current async DNS configuration.
    155    * @param {Object} hostResolverInfo The host resolver information.
    156    */
    157   function displayAsyncDnsConfig_(hostResolverInfo) {
    158     // Clear the table.
    159     $(DnsView.INTERNAL_DNS_CONFIG_TBODY_ID).innerHTML = '';
    160 
    161     // Figure out if the internal DNS resolver is disabled or has no valid
    162     // configuration information, and update display accordingly.
    163     var enabled = hostResolverInfo &&
    164                   hostResolverInfo.dns_config !== undefined;
    165     var noConfig = enabled &&
    166                    hostResolverInfo.dns_config.nameservers === undefined;
    167     $(DnsView.INTERNAL_DNS_ENABLED_SPAN_ID).innerText = enabled;
    168     setNodeDisplay($(DnsView.INTERNAL_DNS_INVALID_CONFIG_SPAN_ID), noConfig);
    169 
    170     // If the internal DNS resolver is disabled or has no valid configuration,
    171     // we're done.
    172     if (!enabled || noConfig)
    173       return;
    174 
    175     var dnsConfig = hostResolverInfo.dns_config;
    176 
    177     // Display nameservers first.
    178     var nameserverRow = addNode($(DnsView.INTERNAL_DNS_CONFIG_TBODY_ID), 'tr');
    179     addNodeWithText(nameserverRow, 'th', 'nameservers');
    180     addListToNode_(addNode(nameserverRow, 'td'), dnsConfig.nameservers);
    181 
    182     // Add everything else in |dnsConfig| to the table.
    183     for (var key in dnsConfig) {
    184       if (key == 'nameservers')
    185         continue;
    186       var tr = addNode($(DnsView.INTERNAL_DNS_CONFIG_TBODY_ID), 'tr');
    187       addNodeWithText(tr, 'th', key);
    188       var td = addNode(tr, 'td');
    189 
    190       // For lists, display each list entry on a separate line.
    191       if (typeof dnsConfig[key] == 'object' &&
    192           dnsConfig[key].constructor == Array) {
    193         addListToNode_(td, dnsConfig[key]);
    194         continue;
    195       }
    196 
    197       addTextNode(td, dnsConfig[key]);
    198     }
    199   }
    200 
    201   /**
    202    * Takes a last of strings and adds them all to a DOM node, displaying them
    203    * on separate lines.
    204    * @param {DomNode} node The parent node.
    205    * @param {Array.<string>} list List of strings to add to the node.
    206    */
    207   function addListToNode_(node, list) {
    208     for (var i = 0; i < list.length; ++i)
    209       addNodeWithText(node, 'div', list[i]);
    210   }
    211 
    212   return DnsView;
    213 })();
    214