summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/net_internals/source_tracker.js
blob: 92d576d3d27a4f1ea509f57c46f2347b17d2b4db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// 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 SourceTracker = (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 SourceTracker() {
    // Observers that are sent all events as they happen.  This allows for easy
    // watching for particular events.
    this.logEntryObservers_ = [];

    // Observers that only want to receive lists of updated SourceEntries.
    this.sourceEntryObservers_ = [];

    // True when cookies and authentication information should be removed from
    // displayed events.  When true, such information should be hidden from
    // all pages.
    this.enableSecurityStripping_ = true;

    this.clearEntries_();
  }

  SourceTracker.prototype = {
    /**
     * Clears all log entries and SourceEntries and related state.
     */
    clearEntries_: function() {
      // Used for sorting entries with automatically assigned IDs.
      this.maxReceivedSourceId_ = 0;

      // Next unique id to be assigned to a log entry without a source.
      // Needed to identify associated GUI elements, etc.
      this.nextSourcelessEventId_ = -1;

      // Ordered list of log entries.  Needed to maintain original order when
      // generating log dumps
      this.capturedEvents_ = [];

      this.sourceEntries_ = {};
    },

    /**
     * Returns a list of all captured events.
     */
    getAllCapturedEvents: function() {
      return this.capturedEvents_;
    },

    /**
     * Returns a list of all SourceEntries.
     */
    getAllSourceEntries: function() {
      return this.sourceEntries_;
    },

    /**
     * Returns the number of events that were captured while we were
     * listening for events.
     */
    getNumCapturedEvents: function() {
      return this.capturedEvents_.length;
    },

    /**
     * Returns the description of the specified SourceEntry, or an empty string
     * if it doesn't exist.
     */
    getDescription: function(id) {
      var entry = this.getSourceEntry(id);
      if (entry)
        return entry.getDescription();
      return '';
    },

    /**
     * Returns the specified SourceEntry.
     */
    getSourceEntry: function(id) {
      return this.sourceEntries_[id];
    },

    /**
     * Sends each entry to all observers and updates |capturedEvents_|.
     * Also assigns unique ids to log entries without a source.
     */
    onReceivedLogEntries: function(logEntries) {
      // List source entries with new log entries.  Sorted chronologically, by
      // first new log entry.
      var updatedSourceEntries = [];

      var updatedSourceEntryIdMap = {};

      for (var e = 0; e < logEntries.length; ++e) {
        var logEntry = logEntries[e];

        // Assign unique ID, if needed.
        if (logEntry.source.id == 0) {
          logEntry.source.id = this.nextSourcelessEventId_;
          --this.nextSourcelessEventId_;
        } else if (this.maxReceivedSourceId_ < logEntry.source.id) {
          this.maxReceivedSourceId_ = logEntry.source.id;
        }

        // Create/update SourceEntry object.
        var sourceEntry = this.sourceEntries_[logEntry.source.id];
        if (!sourceEntry) {
          sourceEntry = new SourceEntry(logEntry, this.maxReceivedSourceId_);
          this.sourceEntries_[logEntry.source.id] = sourceEntry;
        } else {
          sourceEntry.update(logEntry);
        }

        // Add to updated SourceEntry list, if not already in it.
        if (!updatedSourceEntryIdMap[logEntry.source.id]) {
          updatedSourceEntryIdMap[logEntry.source.id] = sourceEntry;
          updatedSourceEntries.push(sourceEntry);
        }
      }

      this.capturedEvents_ = this.capturedEvents_.concat(logEntries);
      for (var i = 0; i < this.sourceEntryObservers_.length; ++i) {
        this.sourceEntryObservers_[i].onSourceEntriesUpdated(
            updatedSourceEntries);
      }
      for (var i = 0; i < this.logEntryObservers_.length; ++i)
        this.logEntryObservers_[i].onReceivedLogEntries(logEntries);
    },

    /**
     * Deletes all captured events.
     */
    deleteAllSourceEntries: function() {
      this.clearEntries_();
      for (var i = 0; i < this.sourceEntryObservers_.length; ++i)
        this.sourceEntryObservers_[i].onAllSourceEntriesDeleted();
      for (var i = 0; i < this.logEntryObservers_.length; ++i)
        this.logEntryObservers_[i].onAllLogEntriesDeleted();
    },

    /**
     * Sets the value of |enableSecurityStripping_| and informs log observers
     * of the change.
     */
    setSecurityStripping: function(enableSecurityStripping) {
      this.enableSecurityStripping_ = enableSecurityStripping;
      for (var i = 0; i < this.sourceEntryObservers_.length; ++i) {
        if (this.sourceEntryObservers_[i].onSecurityStrippingChanged)
          this.sourceEntryObservers_[i].onSecurityStrippingChanged();
      }
    },

    /**
     * Returns whether or not cookies and authentication information should be
     * displayed for events that contain them.
     */
    getSecurityStripping: function() {
      return this.enableSecurityStripping_;
    },

    /**
     * Adds a listener of SourceEntries. |observer| will be called back when
     * SourceEntries are added or modified, source entries are deleted, or
     * security stripping changes:
     *
     *   observer.onSourceEntriesUpdated(sourceEntries)
     *   ovserver.onAllSourceEntriesDeleted()
     *   observer.onSecurityStrippingChanged()
     */
    addSourceEntryObserver: function(observer) {
      this.sourceEntryObservers_.push(observer);
    },

    /**
     * Adds a listener of log entries. |observer| will be called back when new
     * log data arrives or all entries are deleted:
     *
     *   observer.onReceivedLogEntries(entries)
     *   ovserver.onAllLogEntriesDeleted()
     */
    addLogEntryObserver: function(observer) {
      this.logEntryObservers_.push(observer);
    }
  };

  return SourceTracker;
})();