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 var SourceTracker = (function() {
      6   'use strict';
      7 
      8   /**
      9    * This class keeps track of all NetLog events, grouped into per-source
     10    * streams. It receives events from EventsTracker, and passes
     11    * them on to all its observers.
     12    *
     13    * @constructor
     14    */
     15   function SourceTracker() {
     16     assertFirstConstructorCall(SourceTracker);
     17 
     18     // Observers that only want to receive lists of updated SourceEntries.
     19     this.sourceEntryObservers_ = [];
     20 
     21     // True when cookies and authentication information should be removed from
     22     // displayed events.  When true, such information should be hidden from
     23     // all pages.
     24     this.privacyStripping_ = true;
     25 
     26     // True when times should be displayed as milliseconds since the first
     27     // event, as opposed to milliseconds since January 1, 1970.
     28     this.useRelativeTimes_ = true;
     29 
     30     this.clearEntries_();
     31 
     32     EventsTracker.getInstance().addLogEntryObserver(this);
     33   }
     34 
     35   cr.addSingletonGetter(SourceTracker);
     36 
     37   SourceTracker.prototype = {
     38     /**
     39      * Clears all log entries and SourceEntries and related state.
     40      */
     41     clearEntries_: function() {
     42       // Used for sorting entries with automatically assigned IDs.
     43       this.maxReceivedSourceId_ = 0;
     44 
     45       // Next unique id to be assigned to a log entry without a source.
     46       // Needed to identify associated GUI elements, etc.
     47       this.nextSourcelessEventId_ = -1;
     48 
     49       // Ordered list of log entries.  Needed to maintain original order when
     50       // generating log dumps
     51       this.capturedEvents_ = [];
     52 
     53       this.sourceEntries_ = {};
     54     },
     55 
     56     /**
     57      * Returns a list of all SourceEntries.
     58      */
     59     getAllSourceEntries: function() {
     60       return this.sourceEntries_;
     61     },
     62 
     63     /**
     64      * Returns the description of the specified SourceEntry, or an empty string
     65      * if it doesn't exist.
     66      */
     67     getDescription: function(id) {
     68       var entry = this.getSourceEntry(id);
     69       if (entry)
     70         return entry.getDescription();
     71       return '';
     72     },
     73 
     74     /**
     75      * Returns the specified SourceEntry.
     76      */
     77     getSourceEntry: function(id) {
     78       return this.sourceEntries_[id];
     79     },
     80 
     81     /**
     82      * Sends each entry to all observers and updates |capturedEvents_|.
     83      * Also assigns unique ids to log entries without a source.
     84      */
     85     onReceivedLogEntries: function(logEntries) {
     86       // List source entries with new log entries.  Sorted chronologically, by
     87       // first new log entry.
     88       var updatedSourceEntries = [];
     89 
     90       var updatedSourceEntryIdMap = {};
     91 
     92       for (var e = 0; e < logEntries.length; ++e) {
     93         var logEntry = logEntries[e];
     94 
     95         // Assign unique ID, if needed.
     96         // TODO(mmenke):  Remove this, and all other code to handle 0 source
     97         //                IDs when M19 hits stable.
     98         if (logEntry.source.id == 0) {
     99           logEntry.source.id = this.nextSourcelessEventId_;
    100           --this.nextSourcelessEventId_;
    101         } else if (this.maxReceivedSourceId_ < logEntry.source.id) {
    102           this.maxReceivedSourceId_ = logEntry.source.id;
    103         }
    104 
    105         // Create/update SourceEntry object.
    106         var sourceEntry = this.sourceEntries_[logEntry.source.id];
    107         if (!sourceEntry) {
    108           sourceEntry = new SourceEntry(logEntry, this.maxReceivedSourceId_);
    109           this.sourceEntries_[logEntry.source.id] = sourceEntry;
    110         } else {
    111           sourceEntry.update(logEntry);
    112         }
    113 
    114         // Add to updated SourceEntry list, if not already in it.
    115         if (!updatedSourceEntryIdMap[logEntry.source.id]) {
    116           updatedSourceEntryIdMap[logEntry.source.id] = sourceEntry;
    117           updatedSourceEntries.push(sourceEntry);
    118         }
    119       }
    120 
    121       this.capturedEvents_ = this.capturedEvents_.concat(logEntries);
    122       for (var i = 0; i < this.sourceEntryObservers_.length; ++i) {
    123         this.sourceEntryObservers_[i].onSourceEntriesUpdated(
    124             updatedSourceEntries);
    125       }
    126     },
    127 
    128     /**
    129      * Called when all log events have been deleted.
    130      */
    131     onAllLogEntriesDeleted: function() {
    132       this.clearEntries_();
    133       for (var i = 0; i < this.sourceEntryObservers_.length; ++i)
    134         this.sourceEntryObservers_[i].onAllSourceEntriesDeleted();
    135     },
    136 
    137     /**
    138      * Sets the value of |privacyStripping_| and informs log observers
    139      * of the change.
    140      */
    141     setPrivacyStripping: function(privacyStripping) {
    142       this.privacyStripping_ = privacyStripping;
    143       for (var i = 0; i < this.sourceEntryObservers_.length; ++i) {
    144         if (this.sourceEntryObservers_[i].onPrivacyStrippingChanged)
    145           this.sourceEntryObservers_[i].onPrivacyStrippingChanged();
    146       }
    147     },
    148 
    149     /**
    150      * Returns whether or not cookies and authentication information should be
    151      * displayed for events that contain them.
    152      */
    153     getPrivacyStripping: function() {
    154       return this.privacyStripping_;
    155     },
    156 
    157     /**
    158      * Sets the value of |useRelativeTimes_| and informs log observers
    159      * of the change.
    160      */
    161     setUseRelativeTimes: function(useRelativeTimes) {
    162       this.useRelativeTimes_ = useRelativeTimes;
    163       for (var i = 0; i < this.sourceEntryObservers_.length; ++i) {
    164         if (this.sourceEntryObservers_[i].onUseRelativeTimesChanged)
    165           this.sourceEntryObservers_[i].onUseRelativeTimesChanged();
    166       }
    167     },
    168 
    169     /**
    170      * Returns true if times should be displayed as milliseconds since the first
    171      * event.
    172      */
    173     getUseRelativeTimes: function() {
    174       return this.useRelativeTimes_;
    175     },
    176 
    177     /**
    178      * Adds a listener of SourceEntries. |observer| will be called back when
    179      * SourceEntries are added or modified, source entries are deleted, or
    180      * privacy stripping changes:
    181      *
    182      *   observer.onSourceEntriesUpdated(sourceEntries)
    183      *   observer.onAllSourceEntriesDeleted()
    184      *   observer.onPrivacyStrippingChanged()
    185      */
    186     addSourceEntryObserver: function(observer) {
    187       this.sourceEntryObservers_.push(observer);
    188     }
    189   };
    190 
    191   return SourceTracker;
    192 })();
    193