15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var EventsTracker = (function() {
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'use strict';
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * This class keeps track of all NetLog events.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * It receives events from the browser and when loading a log file, and passes
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * them on to all its observers.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @constructor
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function EventsTracker() {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assertFirstConstructorCall(EventsTracker);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.capturedEvents_ = [];
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.observers_ = [];
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Controls how large |capturedEvents_| can grow.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.softLimit_ = Infinity;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.hardLimit_ = Infinity;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cr.addSingletonGetter(EventsTracker);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventsTracker.prototype = {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Returns a list of all captured events.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    getAllCapturedEvents: function() {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return this.capturedEvents_;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Returns the number of events that were captured.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    getNumCapturedEvents: function() {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return this.capturedEvents_.length;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Deletes all the tracked events, and notifies any observers.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deleteAllLogEntries: function() {
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      timeutil.clearBaseTime();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this.capturedEvents_ = [];
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (var i = 0; i < this.observers_.length; ++i)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.observers_[i].onAllLogEntriesDeleted();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Adds captured events, and broadcasts them to any observers.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addLogEntries: function(logEntries) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // When reloading a page, it's possible to receive events before
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Constants.  Discard those events, as they can cause the fake
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // "REQUEST_ALIVE" events for pre-existing requests not be the first
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // events for those requests.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (Constants == null)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // This can happen when loading logs with no events.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!logEntries.length)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!timeutil.isBaseTimeSet()) {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        timeutil.setBaseTime(
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            timeutil.convertTimeTicksToTime(logEntries[0].time));
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this.capturedEvents_ = this.capturedEvents_.concat(logEntries);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (var i = 0; i < this.observers_.length; ++i) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.observers_[i].onReceivedLogEntries(logEntries);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Check that we haven't grown too big. If so, toss out older events.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (this.getNumCapturedEvents() > this.hardLimit_) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var originalEvents = this.capturedEvents_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.deleteAllLogEntries();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Delete the oldest events until we reach the soft limit.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        originalEvents.splice(0, originalEvents.length - this.softLimit_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.addLogEntries(originalEvents);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Adds a listener of log entries. |observer| will be called back when new
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * log data arrives or all entries are deleted:
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *   observer.onReceivedLogEntries(entries)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *   observer.onAllLogEntriesDeleted()
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addLogEntryObserver: function(observer) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this.observers_.push(observer);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Set bounds on the maximum number of events that will be tracked. This
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * helps to bound the total amount of memory usage, since otherwise
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * long-running capture sessions can exhaust the renderer's memory and
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * crash.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Once |hardLimit| number of events have been captured we do a garbage
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * collection and toss out old events, bringing our count down to
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * |softLimit|.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * To log observers this will look like all the events got deleted, and
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * then subsequently a bunch of new events were received. In other words, it
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * behaves the same as if the user had simply started logging a bit later
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * in time!
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setLimits: function(softLimit, hardLimit) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (hardLimit != Infinity && softLimit >= hardLimit)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        throw 'hardLimit must be greater than softLimit';
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this.softLimit_ = softLimit;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this.hardLimit_ = hardLimit;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EventsTracker;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})();
124