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