summaryrefslogtreecommitdiffstats
path: root/chrome/browser/net/chrome_net_log.h
blob: a032c33abd6a8eb4d1d573865a875751a82ca27f (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
// Copyright (c) 2011 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.

#ifndef CHROME_BROWSER_NET_CHROME_NET_LOG_H_
#define CHROME_BROWSER_NET_CHROME_NET_LOG_H_
#pragma once

#include <vector>

#include "base/atomicops.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
#include "base/time.h"
#include "net/base/net_log.h"

class LoadTimingObserver;
class NetLogLogger;
class PassiveLogCollector;

// ChromeNetLog is an implementation of NetLog that dispatches network log
// messages to a list of observers.
//
// All methods are thread safe, with the exception that no ChromeNetLog or
// ChromeNetLog::ThreadSafeObserverImpl functions may be called by an observer's
// OnAddEntry() method.  Doing so will result in a deadlock.
//
// By default, ChromeNetLog will attach the observer PassiveLogCollector which
// will keep track of recent request information (which used when displaying
// the about:net-internals page).
//
class ChromeNetLog : public net::NetLog {
 public:
  // This structure encapsulates all of the parameters of an event,
  // including an "order" field that identifies when it was captured relative
  // to other events.
  struct Entry {
    Entry(uint32 order,
          net::NetLog::EventType type,
          const base::TimeTicks& time,
          net::NetLog::Source source,
          net::NetLog::EventPhase phase,
          net::NetLog::EventParameters* params);
    ~Entry();

    uint32 order;
    net::NetLog::EventType type;
    base::TimeTicks time;
    net::NetLog::Source source;
    net::NetLog::EventPhase phase;
    scoped_refptr<net::NetLog::EventParameters> params;
  };

  typedef std::vector<Entry> EntryList;

  // Base class for observing the events logged by the network
  // stack. This has some nice-to-have functionality for use by code
  // within chrome/, but any net::NetLog::ThreadSafeObserver may be
  // registered to observe the NetLog.
  //
  // This class uses composition rather than inheritance so that
  // certain invariants can be maintained when subclasses of it are
  // added as observers (through the AddAsObserver and
  // RemoveAsObserver methods on this class).
  class ThreadSafeObserverImpl {
   public:
    // Observers that need to see the full granularity of events can
    // specify LOG_ALL. However doing so will have performance consequences,
    // and may cause PassiveLogCollector to use more memory than anticipated.
    explicit ThreadSafeObserverImpl(LogLevel log_level);
    virtual ~ThreadSafeObserverImpl();

    virtual void OnAddEntry(EventType type,
                            const base::TimeTicks& time,
                            const Source& source,
                            EventPhase phase,
                            EventParameters* params) = 0;

    // These must be used instead of
    // ChromeNetLog::Add/RemoveThreadSafeObserver to manage the
    // association in this class with a given ChromeNetLog instance.
    void AddAsObserver(ChromeNetLog* net_log);
    void RemoveAsObserver();

    void SetLogLevel(LogLevel log_level);

    void AddAsObserverAndGetAllPassivelyCapturedEvents(
        ChromeNetLog *net_log,
        EntryList* passive_entries);

   protected:
    void AssertNetLogLockAcquired() const;

   private:
    class PassThroughObserver : public ThreadSafeObserver {
     public:
      PassThroughObserver(ThreadSafeObserverImpl* owner, LogLevel log_level);
      virtual ~PassThroughObserver() {}
      virtual void OnAddEntry(EventType type,
                              const base::TimeTicks& time,
                              const Source& source,
                              EventPhase phase,
                              EventParameters* params) OVERRIDE;

      // Can only be called when actively observing a ChromeNetLog.
      void SetLogLevel(LogLevel log_level);

     private:
      ThreadSafeObserverImpl* owner_;
    };

    friend class PassThroughObserver;

    // ChromeNetLog currently being observed. Set by
    // AddAsObserver/RemoveAsObserver.
    ChromeNetLog* net_log_;

    // The observer we register in AddAsObserver, that passes stuff
    // through to us.
    PassThroughObserver internal_observer_;

    DISALLOW_COPY_AND_ASSIGN(ThreadSafeObserverImpl);
  };

  ChromeNetLog();
  virtual ~ChromeNetLog();

  // NetLog implementation:
  virtual void AddEntry(EventType type,
                        const base::TimeTicks& time,
                        const Source& source,
                        EventPhase phase,
                        EventParameters* params) OVERRIDE;
  virtual uint32 NextID() OVERRIDE;
  virtual LogLevel GetLogLevel() const OVERRIDE;

  void GetAllPassivelyCapturedEvents(EntryList* passive_entries);

  void ClearAllPassivelyCapturedEvents();

  LoadTimingObserver* load_timing_observer() {
    return load_timing_observer_.get();
  }

 private:
  void AddObserverWhileLockHeld(ThreadSafeObserver* observer);

  // NetLog implementation
  virtual void AddThreadSafeObserver(ThreadSafeObserver* observer) OVERRIDE;
  virtual void RemoveThreadSafeObserver(ThreadSafeObserver* observer) OVERRIDE;

  // Adds |observer| and writes all passively captured events to
  // |passive_entries|. Guarantees that no events in |passive_entries| will be
  // sent to |observer| and all future events that have yet been sent to the
  // PassiveLogCollector will be sent to |observer|.
  void AddObserverAndGetAllPassivelyCapturedEvents(ThreadSafeObserver* observer,
                                                   EntryList* passive_entries);


  // Called whenever an observer is added or removed, or changes its log level.
  // Must have acquired |lock_| prior to calling.
  void UpdateLogLevel();

  // |lock_| protects access to |observers_| and, indirectly, to
  // |passive_collector_|.  Should not be acquired by observers.
  base::Lock lock_;

  // Last assigned source ID.  Incremented to get the next one.
  base::subtle::Atomic32 last_id_;

  // The lowest allowed log level, regardless of any ChromeNetLogObservers.
  // Normally defaults to LOG_BASIC, but can be changed with command line flags.
  LogLevel base_log_level_;

  // The current log level.
  base::subtle::Atomic32 effective_log_level_;

  // Not thread safe.  Must only be used when |lock_| is acquired.
  scoped_ptr<PassiveLogCollector> passive_collector_;

  scoped_ptr<LoadTimingObserver> load_timing_observer_;
  scoped_ptr<NetLogLogger> net_log_logger_;

  // |lock_| must be acquired whenever reading or writing to this.
  ObserverList<ThreadSafeObserver, true> observers_;

  DISALLOW_COPY_AND_ASSIGN(ChromeNetLog);
};

#endif  // CHROME_BROWSER_NET_CHROME_NET_LOG_H_