// 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::ThreadSafeObserver 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;
// Interface for observing the events logged by the network stack.
class ThreadSafeObserver {
public:
// Constructs an observer that wants to see network events, with
// the specified minimum event granularity. A ThreadSafeObserver can only
// observe a single ChromeNetLog at a time.
//
// Typical observers should specify LOG_BASIC.
//
// 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.
//
// Observers will be called on the same thread an entry is added on,
// and are responsible for ensuring their own thread safety.
explicit ThreadSafeObserver(LogLevel log_level);
virtual ~ThreadSafeObserver();
// This method will be called on the thread that the event occurs on. It
// is the responsibility of the observer to handle it in a thread safe
// manner.
//
// It is illegal for an Observer to call any ChromeNetLog or
// ChromeNetLog::ThreadSafeObserver functions in response to a call to
// OnAddEntry.
virtual void OnAddEntry(EventType type,
const base::TimeTicks& time,
const Source& source,
EventPhase phase,
EventParameters* params) = 0;
LogLevel log_level() const;
protected:
void AssertNetLogLockAcquired() const;
// Can only be called when actively observing a ChromeNetLog.
void SetLogLevel(LogLevel log_level);
// ChromeNetLog currently being observed, if any. Set by ChromeNetLog's
// AddObserver and RemoveObserver methods.
ChromeNetLog* net_log_;
private:
friend class ChromeNetLog;
LogLevel log_level_;
DISALLOW_COPY_AND_ASSIGN(ThreadSafeObserver);
};
ChromeNetLog();
~ChromeNetLog();
// NetLog implementation:
virtual void AddEntry(EventType type,
const base::TimeTicks& time,
const Source& source,
EventPhase phase,
EventParameters* params);
virtual uint32 NextID();
virtual LogLevel GetLogLevel() const;
void AddObserver(ThreadSafeObserver* observer);
void RemoveObserver(ThreadSafeObserver* observer);
// 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);
void GetAllPassivelyCapturedEvents(EntryList* passive_entries);
void ClearAllPassivelyCapturedEvents();
LoadTimingObserver* load_timing_observer() {
return load_timing_observer_.get();
}
private:
void AddObserverWhileLockHeld(ThreadSafeObserver* observer);
// 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_;
base::subtle::Atomic32 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_