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 SourceTracker = (function() { 6 'use strict'; 7 8 /** 9 * This class keeps track of all NetLog events, grouped into per-source 10 * streams. It receives events from EventsTracker, and passes 11 * them on to all its observers. 12 * 13 * @constructor 14 */ 15 function SourceTracker() { 16 assertFirstConstructorCall(SourceTracker); 17 18 // Observers that only want to receive lists of updated SourceEntries. 19 this.sourceEntryObservers_ = []; 20 21 // True when cookies and authentication information should be removed from 22 // displayed events. When true, such information should be hidden from 23 // all pages. 24 this.privacyStripping_ = true; 25 26 this.clearEntries_(); 27 28 EventsTracker.getInstance().addLogEntryObserver(this); 29 } 30 31 cr.addSingletonGetter(SourceTracker); 32 33 SourceTracker.prototype = { 34 /** 35 * Clears all log entries and SourceEntries and related state. 36 */ 37 clearEntries_: function() { 38 // Used for sorting entries with automatically assigned IDs. 39 this.maxReceivedSourceId_ = 0; 40 41 // Next unique id to be assigned to a log entry without a source. 42 // Needed to identify associated GUI elements, etc. 43 this.nextSourcelessEventId_ = -1; 44 45 // Ordered list of log entries. Needed to maintain original order when 46 // generating log dumps 47 this.capturedEvents_ = []; 48 49 this.sourceEntries_ = {}; 50 }, 51 52 /** 53 * Returns a list of all SourceEntries. 54 */ 55 getAllSourceEntries: function() { 56 return this.sourceEntries_; 57 }, 58 59 /** 60 * Returns the description of the specified SourceEntry, or an empty string 61 * if it doesn't exist. 62 */ 63 getDescription: function(id) { 64 var entry = this.getSourceEntry(id); 65 if (entry) 66 return entry.getDescription(); 67 return ''; 68 }, 69 70 /** 71 * Returns the specified SourceEntry. 72 */ 73 getSourceEntry: function(id) { 74 return this.sourceEntries_[id]; 75 }, 76 77 /** 78 * Sends each entry to all observers and updates |capturedEvents_|. 79 * Also assigns unique ids to log entries without a source. 80 */ 81 onReceivedLogEntries: function(logEntries) { 82 // List source entries with new log entries. Sorted chronologically, by 83 // first new log entry. 84 var updatedSourceEntries = []; 85 86 var updatedSourceEntryIdMap = {}; 87 88 for (var e = 0; e < logEntries.length; ++e) { 89 var logEntry = logEntries[e]; 90 91 // Assign unique ID, if needed. 92 // TODO(mmenke): Remove this, and all other code to handle 0 source 93 // IDs when M19 hits stable. 94 if (logEntry.source.id == 0) { 95 logEntry.source.id = this.nextSourcelessEventId_; 96 --this.nextSourcelessEventId_; 97 } else if (this.maxReceivedSourceId_ < logEntry.source.id) { 98 this.maxReceivedSourceId_ = logEntry.source.id; 99 } 100 101 // Create/update SourceEntry object. 102 var sourceEntry = this.sourceEntries_[logEntry.source.id]; 103 if (!sourceEntry) { 104 sourceEntry = new SourceEntry(logEntry, this.maxReceivedSourceId_); 105 this.sourceEntries_[logEntry.source.id] = sourceEntry; 106 } else { 107 sourceEntry.update(logEntry); 108 } 109 110 // Add to updated SourceEntry list, if not already in it. 111 if (!updatedSourceEntryIdMap[logEntry.source.id]) { 112 updatedSourceEntryIdMap[logEntry.source.id] = sourceEntry; 113 updatedSourceEntries.push(sourceEntry); 114 } 115 } 116 117 this.capturedEvents_ = this.capturedEvents_.concat(logEntries); 118 for (var i = 0; i < this.sourceEntryObservers_.length; ++i) { 119 this.sourceEntryObservers_[i].onSourceEntriesUpdated( 120 updatedSourceEntries); 121 } 122 }, 123 124 /** 125 * Called when all log events have been deleted. 126 */ 127 onAllLogEntriesDeleted: function() { 128 this.clearEntries_(); 129 for (var i = 0; i < this.sourceEntryObservers_.length; ++i) 130 this.sourceEntryObservers_[i].onAllSourceEntriesDeleted(); 131 }, 132 133 /** 134 * Sets the value of |privacyStripping_| and informs log observers 135 * of the change. 136 */ 137 setPrivacyStripping: function(privacyStripping) { 138 this.privacyStripping_ = privacyStripping; 139 for (var i = 0; i < this.sourceEntryObservers_.length; ++i) { 140 if (this.sourceEntryObservers_[i].onPrivacyStrippingChanged) 141 this.sourceEntryObservers_[i].onPrivacyStrippingChanged(); 142 } 143 }, 144 145 /** 146 * Returns whether or not cookies and authentication information should be 147 * displayed for events that contain them. 148 */ 149 getPrivacyStripping: function() { 150 return this.privacyStripping_; 151 }, 152 153 /** 154 * Adds a listener of SourceEntries. |observer| will be called back when 155 * SourceEntries are added or modified, source entries are deleted, or 156 * privacy stripping changes: 157 * 158 * observer.onSourceEntriesUpdated(sourceEntries) 159 * observer.onAllSourceEntriesDeleted() 160 * observer.onPrivacyStrippingChanged() 161 */ 162 addSourceEntryObserver: function(observer) { 163 this.sourceEntryObservers_.push(observer); 164 } 165 }; 166 167 return SourceTracker; 168 })(); 169