1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/chrome_net_log.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/values.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/load_timing_observer.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/net/net_log_logger.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/passive_log_collector.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/chrome_switches.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenChromeNetLog::ThreadSafeObserver::ThreadSafeObserver(LogLevel log_level)
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : net_log_(NULL),
2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      log_level_(log_level) {
2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenChromeNetLog::ThreadSafeObserver::~ThreadSafeObserver() {
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!net_log_);
2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennet::NetLog::LogLevel ChromeNetLog::ThreadSafeObserver::log_level() const {
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return log_level_;
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::ThreadSafeObserver::AssertNetLogLockAcquired() const {
3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (net_log_)
3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net_log_->lock_.AssertAcquired();
3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::ThreadSafeObserver::SetLogLevel(
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net::NetLog::LogLevel log_level) {
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(net_log_);
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(net_log_->lock_);
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  log_level_ = log_level;
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net_log_->UpdateLogLevel_();
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenChromeNetLog::Entry::Entry(uint32 order,
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                           net::NetLog::EventType type,
4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                           const base::TimeTicks& time,
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                           net::NetLog::Source source,
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                           net::NetLog::EventPhase phase,
4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                           net::NetLog::EventParameters* params)
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : order(order),
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      type(type),
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      time(time),
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      source(source),
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      phase(phase),
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      params(params) {
56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenChromeNetLog::Entry::~Entry() {}
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochChromeNetLog::ChromeNetLog()
6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : last_id_(0),
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      log_level_(LOG_BASIC),
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      passive_collector_(new PassiveLogCollector),
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      load_timing_observer_(new LoadTimingObserver) {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddObserver(passive_collector_.get());
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddObserver(load_timing_observer_.get());
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (command_line.HasSwitch(switches::kLogNetLog)) {
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_logger_.reset(new NetLogLogger(
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            command_line.GetSwitchValuePath(switches::kLogNetLog)));
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    AddObserver(net_log_logger_.get());
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochChromeNetLog::~ChromeNetLog() {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RemoveObserver(passive_collector_.get());
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RemoveObserver(load_timing_observer_.get());
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (net_log_logger_.get()) {
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    RemoveObserver(net_log_logger_.get());
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ChromeNetLog::AddEntry(EventType type,
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            const base::TimeTicks& time,
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            const Source& source,
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            EventPhase phase,
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            EventParameters* params) {
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Notify all of the log observers.
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  FOR_EACH_OBSERVER(ThreadSafeObserver, observers_,
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    OnAddEntry(type, time, source, phase, params));
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochuint32 ChromeNetLog::NextID() {
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknet::NetLog::LogLevel ChromeNetLog::GetLogLevel() const {
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  base::subtle::Atomic32 log_level = base::subtle::NoBarrier_Load(&log_level_);
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return static_cast<net::NetLog::LogLevel>(log_level);
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::AddObserver(ThreadSafeObserver* observer) {
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  AddObserverWhileLockHeld(observer);
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::RemoveObserver(ThreadSafeObserver* observer) {
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK_EQ(observer->net_log_, this);
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  observer->net_log_ = NULL;
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  observers_.RemoveObserver(observer);
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UpdateLogLevel_();
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::AddObserverAndGetAllPassivelyCapturedEvents(
11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    ThreadSafeObserver* observer, EntryList* passive_entries) {
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  AddObserverWhileLockHeld(observer);
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  passive_collector_->GetAllCapturedEvents(passive_entries);
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::GetAllPassivelyCapturedEvents(EntryList* passive_entries) {
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  passive_collector_->GetAllCapturedEvents(passive_entries);
12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::ClearAllPassivelyCapturedEvents() {
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  passive_collector_->Clear();
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::UpdateLogLevel_() {
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  lock_.AssertAcquired();
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Look through all the observers and find the finest granularity
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // log level (higher values of the enum imply *lower* log levels).
14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LogLevel new_log_level = LOG_BASIC;
14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ObserverListBase<ThreadSafeObserver>::Iterator it(observers_);
14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ThreadSafeObserver* observer;
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  while ((observer = it.GetNext()) != NULL) {
14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    new_log_level = std::min(new_log_level, observer->log_level());
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  base::subtle::NoBarrier_Store(&log_level_, new_log_level);
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ChromeNetLog::AddObserverWhileLockHeld(ThreadSafeObserver* observer) {
15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!observer->net_log_);
15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  observer->net_log_ = this;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observers_.AddObserver(observer);
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UpdateLogLevel_();
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
155