281 lines
9.0 KiB
C++
281 lines
9.0 KiB
C++
// Copyright 2012 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/log/net_log.h"
|
|
|
|
#include "base/check_op.h"
|
|
#include "base/containers/contains.h"
|
|
#include "base/no_destructor.h"
|
|
#include "base/notreached.h"
|
|
#include "base/ranges/algorithm.h"
|
|
#include "base/strings/string_number_conversions.h"
|
|
#include "base/values.h"
|
|
#include "net/log/net_log_values.h"
|
|
|
|
namespace net {
|
|
|
|
NetLog::ThreadSafeObserver::ThreadSafeObserver() = default;
|
|
|
|
NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
|
|
// Make sure we aren't watching a NetLog on destruction. Because the NetLog
|
|
// may pass events to each observer on multiple threads, we cannot safely
|
|
// stop watching a NetLog automatically from a parent class.
|
|
DCHECK(!net_log_);
|
|
}
|
|
|
|
NetLogCaptureMode NetLog::ThreadSafeObserver::capture_mode() const {
|
|
DCHECK(net_log_);
|
|
return capture_mode_;
|
|
}
|
|
|
|
NetLog* NetLog::ThreadSafeObserver::net_log() const {
|
|
return net_log_;
|
|
}
|
|
|
|
NetLog::ThreadSafeCaptureModeObserver::ThreadSafeCaptureModeObserver() =
|
|
default;
|
|
NetLog::ThreadSafeCaptureModeObserver::~ThreadSafeCaptureModeObserver() =
|
|
default;
|
|
|
|
NetLogCaptureModeSet
|
|
NetLog::ThreadSafeCaptureModeObserver::GetObserverCaptureModes() const {
|
|
DCHECK(net_log_);
|
|
return net_log_->GetObserverCaptureModes();
|
|
}
|
|
|
|
void NetLog::ThreadSafeCaptureModeObserver::
|
|
AddEntryAtTimeWithMaterializedParams(NetLogEventType type,
|
|
const NetLogSource& source,
|
|
NetLogEventPhase phase,
|
|
base::TimeTicks time,
|
|
base::Value::Dict params) {
|
|
DCHECK(net_log_);
|
|
net_log_->AddEntryAtTimeWithMaterializedParams(type, source, phase, time,
|
|
std::move(params));
|
|
}
|
|
|
|
// static
|
|
NetLog* NetLog::Get() {
|
|
static base::NoDestructor<NetLog> instance{base::PassKey<NetLog>()};
|
|
return instance.get();
|
|
}
|
|
|
|
NetLog::NetLog(base::PassKey<NetLog>) {}
|
|
NetLog::NetLog(base::PassKey<NetLogWithSource>) {}
|
|
|
|
void NetLog::AddEntry(NetLogEventType type,
|
|
const NetLogSource& source,
|
|
NetLogEventPhase phase) {
|
|
AddEntry(type, source, phase, [] { return base::Value::Dict(); });
|
|
}
|
|
|
|
void NetLog::AddGlobalEntry(NetLogEventType type) {
|
|
AddEntry(type, NetLogSource(NetLogSourceType::NONE, NextID()),
|
|
NetLogEventPhase::NONE);
|
|
}
|
|
|
|
void NetLog::AddGlobalEntryWithStringParams(NetLogEventType type,
|
|
base::StringPiece name,
|
|
base::StringPiece value) {
|
|
AddGlobalEntry(type, [&] { return NetLogParamsWithString(name, value); });
|
|
}
|
|
|
|
uint32_t NetLog::NextID() {
|
|
return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
|
|
}
|
|
|
|
void NetLog::AddObserver(NetLog::ThreadSafeObserver* observer,
|
|
NetLogCaptureMode capture_mode) {
|
|
base::AutoLock lock(lock_);
|
|
|
|
DCHECK(!observer->net_log_);
|
|
DCHECK(!HasObserver(observer));
|
|
DCHECK_LT(observers_.size(), 20u); // Performance sanity check.
|
|
|
|
observers_.push_back(observer);
|
|
|
|
observer->net_log_ = this;
|
|
observer->capture_mode_ = capture_mode;
|
|
UpdateObserverCaptureModes();
|
|
}
|
|
|
|
void NetLog::RemoveObserver(NetLog::ThreadSafeObserver* observer) {
|
|
base::AutoLock lock(lock_);
|
|
|
|
DCHECK_EQ(this, observer->net_log_);
|
|
|
|
auto it = base::ranges::find(observers_, observer);
|
|
DCHECK(it != observers_.end());
|
|
observers_.erase(it);
|
|
|
|
observer->net_log_ = nullptr;
|
|
observer->capture_mode_ = NetLogCaptureMode::kDefault;
|
|
UpdateObserverCaptureModes();
|
|
}
|
|
|
|
void NetLog::AddCaptureModeObserver(
|
|
NetLog::ThreadSafeCaptureModeObserver* observer) {
|
|
base::AutoLock lock(lock_);
|
|
|
|
DCHECK(!observer->net_log_);
|
|
DCHECK(!HasCaptureModeObserver(observer));
|
|
DCHECK_LT(capture_mode_observers_.size(), 20u); // Performance sanity check.
|
|
|
|
observer->net_log_ = this;
|
|
capture_mode_observers_.push_back(observer);
|
|
}
|
|
|
|
void NetLog::RemoveCaptureModeObserver(
|
|
NetLog::ThreadSafeCaptureModeObserver* observer) {
|
|
base::AutoLock lock(lock_);
|
|
|
|
DCHECK_EQ(this, observer->net_log_);
|
|
DCHECK(HasCaptureModeObserver(observer));
|
|
|
|
auto it = base::ranges::find(capture_mode_observers_, observer);
|
|
DCHECK(it != capture_mode_observers_.end());
|
|
capture_mode_observers_.erase(it);
|
|
|
|
observer->net_log_ = nullptr;
|
|
}
|
|
|
|
void NetLog::UpdateObserverCaptureModes() {
|
|
lock_.AssertAcquired();
|
|
|
|
NetLogCaptureModeSet capture_mode_set = 0;
|
|
for (const auto* observer : observers_)
|
|
NetLogCaptureModeSetAdd(observer->capture_mode_, &capture_mode_set);
|
|
|
|
base::subtle::NoBarrier_Store(&observer_capture_modes_, capture_mode_set);
|
|
|
|
// Notify any capture mode observers with the new |capture_mode_set|.
|
|
for (auto* capture_mode_observer : capture_mode_observers_)
|
|
capture_mode_observer->OnCaptureModeUpdated(capture_mode_set);
|
|
}
|
|
|
|
bool NetLog::HasObserver(ThreadSafeObserver* observer) {
|
|
lock_.AssertAcquired();
|
|
return base::Contains(observers_, observer);
|
|
}
|
|
|
|
bool NetLog::HasCaptureModeObserver(ThreadSafeCaptureModeObserver* observer) {
|
|
lock_.AssertAcquired();
|
|
return base::Contains(capture_mode_observers_, observer);
|
|
}
|
|
|
|
// static
|
|
std::string NetLog::TickCountToString(const base::TimeTicks& time) {
|
|
int64_t delta_time = time.since_origin().InMilliseconds();
|
|
// TODO(https://crbug.com/915391): Use NetLogNumberValue().
|
|
return base::NumberToString(delta_time);
|
|
}
|
|
|
|
// static
|
|
std::string NetLog::TimeToString(const base::Time& time) {
|
|
// Convert the base::Time to its (approximate) equivalent in base::TimeTicks.
|
|
base::TimeTicks time_ticks =
|
|
base::TimeTicks::UnixEpoch() + (time - base::Time::UnixEpoch());
|
|
return TickCountToString(time_ticks);
|
|
}
|
|
|
|
// static
|
|
base::Value NetLog::GetEventTypesAsValue() {
|
|
base::Value::Dict dict;
|
|
for (int i = 0; i < static_cast<int>(NetLogEventType::COUNT); ++i) {
|
|
dict.Set(NetLogEventTypeToString(static_cast<NetLogEventType>(i)), i);
|
|
}
|
|
return base::Value(std::move(dict));
|
|
}
|
|
|
|
// static
|
|
const char* NetLog::SourceTypeToString(NetLogSourceType source) {
|
|
switch (source) {
|
|
#define SOURCE_TYPE(label) \
|
|
case NetLogSourceType::label: \
|
|
return #label;
|
|
#include "net/log/net_log_source_type_list.h"
|
|
#undef SOURCE_TYPE
|
|
default:
|
|
NOTREACHED();
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
// static
|
|
base::Value NetLog::GetSourceTypesAsValue() {
|
|
base::Value::Dict dict;
|
|
for (int i = 0; i < static_cast<int>(NetLogSourceType::COUNT); ++i) {
|
|
dict.Set(SourceTypeToString(static_cast<NetLogSourceType>(i)), i);
|
|
}
|
|
return base::Value(std::move(dict));
|
|
}
|
|
|
|
// static
|
|
const char* NetLog::EventPhaseToString(NetLogEventPhase phase) {
|
|
switch (phase) {
|
|
case NetLogEventPhase::BEGIN:
|
|
return "PHASE_BEGIN";
|
|
case NetLogEventPhase::END:
|
|
return "PHASE_END";
|
|
case NetLogEventPhase::NONE:
|
|
return "PHASE_NONE";
|
|
}
|
|
NOTREACHED();
|
|
return nullptr;
|
|
}
|
|
|
|
void NetLog::InitializeSourceIdPartition() {
|
|
int32_t old_value = base::subtle::NoBarrier_AtomicExchange(
|
|
&last_id_, std::numeric_limits<base::subtle::Atomic32>::min());
|
|
DCHECK_EQ(old_value, 0) << " NetLog::InitializeSourceIdPartition() called "
|
|
"after NextID() or called multiple times";
|
|
}
|
|
|
|
void NetLog::AddEntryInternal(NetLogEventType type,
|
|
const NetLogSource& source,
|
|
NetLogEventPhase phase,
|
|
const GetParamsInterface* get_params) {
|
|
NetLogCaptureModeSet observer_capture_modes = GetObserverCaptureModes();
|
|
|
|
for (int i = 0; i <= static_cast<int>(NetLogCaptureMode::kLast); ++i) {
|
|
NetLogCaptureMode capture_mode = static_cast<NetLogCaptureMode>(i);
|
|
if (!NetLogCaptureModeSetContains(capture_mode, observer_capture_modes))
|
|
continue;
|
|
|
|
NetLogEntry entry(type, source, phase, base::TimeTicks::Now(),
|
|
get_params->GetParams(capture_mode));
|
|
|
|
// Notify all of the log observers with |capture_mode|.
|
|
base::AutoLock lock(lock_);
|
|
for (auto* observer : observers_) {
|
|
if (observer->capture_mode() == capture_mode)
|
|
observer->OnAddEntry(entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NetLog::AddEntryWithMaterializedParams(NetLogEventType type,
|
|
const NetLogSource& source,
|
|
NetLogEventPhase phase,
|
|
base::Value::Dict params) {
|
|
AddEntryAtTimeWithMaterializedParams(
|
|
type, source, phase, base::TimeTicks::Now(), std::move(params));
|
|
}
|
|
|
|
void NetLog::AddEntryAtTimeWithMaterializedParams(NetLogEventType type,
|
|
const NetLogSource& source,
|
|
NetLogEventPhase phase,
|
|
base::TimeTicks time,
|
|
base::Value::Dict params) {
|
|
NetLogEntry entry(type, source, phase, time, std::move(params));
|
|
|
|
// Notify all of the log observers, regardless of capture mode.
|
|
base::AutoLock lock(lock_);
|
|
for (auto* observer : observers_) {
|
|
observer->OnAddEntry(entry);
|
|
}
|
|
}
|
|
|
|
} // namespace net
|