// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var EventsTracker = (function() { 'use strict'; /** * This class keeps track of all NetLog events. * It receives events from the browser and when loading a log file, and passes * them on to all its observers. * * @constructor */ function EventsTracker() { assertFirstConstructorCall(EventsTracker); this.capturedEvents_ = []; this.observers_ = []; // Controls how large |capturedEvents_| can grow. this.softLimit_ = Infinity; this.hardLimit_ = Infinity; } cr.addSingletonGetter(EventsTracker); EventsTracker.prototype = { /** * Returns a list of all captured events. */ getAllCapturedEvents: function() { return this.capturedEvents_; }, /** * Returns the number of events that were captured. */ getNumCapturedEvents: function() { return this.capturedEvents_.length; }, /** * Deletes all the tracked events, and notifies any observers. */ deleteAllLogEntries: function() { timeutil.clearBaseTime(); this.capturedEvents_ = []; for (var i = 0; i < this.observers_.length; ++i) this.observers_[i].onAllLogEntriesDeleted(); }, /** * Adds captured events, and broadcasts them to any observers. */ addLogEntries: function(logEntries) { // When reloading a page, it's possible to receive events before // Constants. Discard those events, as they can cause the fake // "REQUEST_ALIVE" events for pre-existing requests not be the first // events for those requests. if (Constants == null) return; // This can happen when loading logs with no events. if (!logEntries.length) return; if (!timeutil.isBaseTimeSet()) { timeutil.setBaseTime( timeutil.convertTimeTicksToTime(logEntries[0].time)); } this.capturedEvents_ = this.capturedEvents_.concat(logEntries); for (var i = 0; i < this.observers_.length; ++i) { this.observers_[i].onReceivedLogEntries(logEntries); } // Check that we haven't grown too big. If so, toss out older events. if (this.getNumCapturedEvents() > this.hardLimit_) { var originalEvents = this.capturedEvents_; this.deleteAllLogEntries(); // Delete the oldest events until we reach the soft limit. originalEvents.splice(0, originalEvents.length - this.softLimit_); this.addLogEntries(originalEvents); } }, /** * Adds a listener of log entries. |observer| will be called back when new * log data arrives or all entries are deleted: * * observer.onReceivedLogEntries(entries) * observer.onAllLogEntriesDeleted() */ addLogEntryObserver: function(observer) { this.observers_.push(observer); }, /** * Set bounds on the maximum number of events that will be tracked. This * helps to bound the total amount of memory usage, since otherwise * long-running capture sessions can exhaust the renderer's memory and * crash. * * Once |hardLimit| number of events have been captured we do a garbage * collection and toss out old events, bringing our count down to * |softLimit|. * * To log observers this will look like all the events got deleted, and * then subsequently a bunch of new events were received. In other words, it * behaves the same as if the user had simply started logging a bit later * in time! */ setLimits: function(softLimit, hardLimit) { if (hardLimit != Infinity && softLimit >= hardLimit) throw 'hardLimit must be greater than softLimit'; this.softLimit_ = softLimit; this.hardLimit_ = hardLimit; } }; return EventsTracker; })();