blob: 6efd2c836b510ad3db505f515155e9b5ea5c52f0 [file] [log] [blame]
// 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;
})();