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 EventsTracker = (function() {
      6   'use strict';
      7 
      8   /**
      9    * This class keeps track of all NetLog events.
     10    * It receives events from the browser and when loading a log file, and passes
     11    * them on to all its observers.
     12    *
     13    * @constructor
     14    */
     15   function EventsTracker() {
     16     assertFirstConstructorCall(EventsTracker);
     17 
     18     this.capturedEvents_ = [];
     19     this.observers_ = [];
     20 
     21     // Controls how large |capturedEvents_| can grow.
     22     this.softLimit_ = Infinity;
     23     this.hardLimit_ = Infinity;
     24   }
     25 
     26   cr.addSingletonGetter(EventsTracker);
     27 
     28   EventsTracker.prototype = {
     29     /**
     30      * Returns a list of all captured events.
     31      */
     32     getAllCapturedEvents: function() {
     33       return this.capturedEvents_;
     34     },
     35 
     36     /**
     37      * Returns the number of events that were captured.
     38      */
     39     getNumCapturedEvents: function() {
     40       return this.capturedEvents_.length;
     41     },
     42 
     43     /**
     44      * Deletes all the tracked events, and notifies any observers.
     45      */
     46     deleteAllLogEntries: function() {
     47       timeutil.clearBaseTime();
     48       this.capturedEvents_ = [];
     49       for (var i = 0; i < this.observers_.length; ++i)
     50         this.observers_[i].onAllLogEntriesDeleted();
     51     },
     52 
     53     /**
     54      * Adds captured events, and broadcasts them to any observers.
     55      */
     56     addLogEntries: function(logEntries) {
     57       // When reloading a page, it's possible to receive events before
     58       // Constants.  Discard those events, as they can cause the fake
     59       // "REQUEST_ALIVE" events for pre-existing requests not be the first
     60       // events for those requests.
     61       if (Constants == null)
     62         return;
     63       // This can happen when loading logs with no events.
     64       if (!logEntries.length)
     65         return;
     66 
     67       if (!timeutil.isBaseTimeSet()) {
     68         timeutil.setBaseTime(
     69             timeutil.convertTimeTicksToTime(logEntries[0].time));
     70       }
     71 
     72       this.capturedEvents_ = this.capturedEvents_.concat(logEntries);
     73       for (var i = 0; i < this.observers_.length; ++i) {
     74         this.observers_[i].onReceivedLogEntries(logEntries);
     75       }
     76 
     77       // Check that we haven't grown too big. If so, toss out older events.
     78       if (this.getNumCapturedEvents() > this.hardLimit_) {
     79         var originalEvents = this.capturedEvents_;
     80         this.deleteAllLogEntries();
     81         // Delete the oldest events until we reach the soft limit.
     82         originalEvents.splice(0, originalEvents.length - this.softLimit_);
     83         this.addLogEntries(originalEvents);
     84       }
     85     },
     86 
     87     /**
     88      * Adds a listener of log entries. |observer| will be called back when new
     89      * log data arrives or all entries are deleted:
     90      *
     91      *   observer.onReceivedLogEntries(entries)
     92      *   observer.onAllLogEntriesDeleted()
     93      */
     94     addLogEntryObserver: function(observer) {
     95       this.observers_.push(observer);
     96     },
     97 
     98     /**
     99      * Set bounds on the maximum number of events that will be tracked. This
    100      * helps to bound the total amount of memory usage, since otherwise
    101      * long-running capture sessions can exhaust the renderer's memory and
    102      * crash.
    103      *
    104      * Once |hardLimit| number of events have been captured we do a garbage
    105      * collection and toss out old events, bringing our count down to
    106      * |softLimit|.
    107      *
    108      * To log observers this will look like all the events got deleted, and
    109      * then subsequently a bunch of new events were received. In other words, it
    110      * behaves the same as if the user had simply started logging a bit later
    111      * in time!
    112      */
    113     setLimits: function(softLimit, hardLimit) {
    114       if (hardLimit != Infinity && softLimit >= hardLimit)
    115         throw 'hardLimit must be greater than softLimit';
    116 
    117       this.softLimit_ = softLimit;
    118       this.hardLimit_ = hardLimit;
    119     }
    120   };
    121 
    122   return EventsTracker;
    123 })();
    124