1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/log/net_log.h"
6
7 #include "base/check_op.h"
8 #include "base/no_destructor.h"
9 #include "base/notreached.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/values.h"
12 #include "net/log/net_log_values.h"
13
14 namespace net {
15
ThreadSafeObserver()16 NetLog::ThreadSafeObserver::ThreadSafeObserver()
17 : capture_mode_(NetLogCaptureMode::kDefault), net_log_(nullptr) {}
18
~ThreadSafeObserver()19 NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
20 // Make sure we aren't watching a NetLog on destruction. Because the NetLog
21 // may pass events to each observer on multiple threads, we cannot safely
22 // stop watching a NetLog automatically from a parent class.
23 DCHECK(!net_log_);
24 }
25
capture_mode() const26 NetLogCaptureMode NetLog::ThreadSafeObserver::capture_mode() const {
27 DCHECK(net_log_);
28 return capture_mode_;
29 }
30
net_log() const31 NetLog* NetLog::ThreadSafeObserver::net_log() const {
32 return net_log_;
33 }
34
35 NetLog::ThreadSafeCaptureModeObserver::ThreadSafeCaptureModeObserver() =
36 default;
37 NetLog::ThreadSafeCaptureModeObserver::~ThreadSafeCaptureModeObserver() =
38 default;
39
40 NetLogCaptureModeSet
GetObserverCaptureModes() const41 NetLog::ThreadSafeCaptureModeObserver::GetObserverCaptureModes() const {
42 DCHECK(net_log_);
43 return net_log_->GetObserverCaptureModes();
44 }
45
46 void NetLog::ThreadSafeCaptureModeObserver::
AddEntryAtTimeWithMaterializedParams(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,base::TimeTicks time,base::Value && params)47 AddEntryAtTimeWithMaterializedParams(NetLogEventType type,
48 const NetLogSource& source,
49 NetLogEventPhase phase,
50 base::TimeTicks time,
51 base::Value&& params) {
52 DCHECK(net_log_);
53 net_log_->AddEntryAtTimeWithMaterializedParams(type, source, phase, time,
54 std::move(params));
55 }
56
57 // static
Get()58 NetLog* NetLog::Get() {
59 static base::NoDestructor<NetLog> instance{util::PassKey<NetLog>()};
60 return instance.get();
61 }
62
NetLog(util::PassKey<NetLog>)63 NetLog::NetLog(util::PassKey<NetLog>) {}
NetLog(util::PassKey<NetLogWithSource>)64 NetLog::NetLog(util::PassKey<NetLogWithSource>) {}
NetLog(util::PassKey<TestNetLog>)65 NetLog::NetLog(util::PassKey<TestNetLog>) {}
66
67 NetLog::~NetLog() = default;
68
AddEntry(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase)69 void NetLog::AddEntry(NetLogEventType type,
70 const NetLogSource& source,
71 NetLogEventPhase phase) {
72 AddEntry(type, source, phase, [] { return base::Value(); });
73 }
74
AddGlobalEntry(NetLogEventType type)75 void NetLog::AddGlobalEntry(NetLogEventType type) {
76 AddEntry(type, NetLogSource(NetLogSourceType::NONE, NextID()),
77 NetLogEventPhase::NONE);
78 }
79
AddGlobalEntryWithStringParams(NetLogEventType type,base::StringPiece name,base::StringPiece value)80 void NetLog::AddGlobalEntryWithStringParams(NetLogEventType type,
81 base::StringPiece name,
82 base::StringPiece value) {
83 AddGlobalEntry(type, [&] { return NetLogParamsWithString(name, value); });
84 }
85
NextID()86 uint32_t NetLog::NextID() {
87 return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
88 }
89
AddObserver(NetLog::ThreadSafeObserver * observer,NetLogCaptureMode capture_mode)90 void NetLog::AddObserver(NetLog::ThreadSafeObserver* observer,
91 NetLogCaptureMode capture_mode) {
92 base::AutoLock lock(lock_);
93
94 DCHECK(!observer->net_log_);
95 DCHECK(!HasObserver(observer));
96 DCHECK_LT(observers_.size(), 20u); // Performance sanity check.
97
98 observers_.push_back(observer);
99
100 observer->net_log_ = this;
101 observer->capture_mode_ = capture_mode;
102 UpdateObserverCaptureModes();
103 }
104
RemoveObserver(NetLog::ThreadSafeObserver * observer)105 void NetLog::RemoveObserver(NetLog::ThreadSafeObserver* observer) {
106 base::AutoLock lock(lock_);
107
108 DCHECK_EQ(this, observer->net_log_);
109
110 auto it = std::find(observers_.begin(), observers_.end(), observer);
111 DCHECK(it != observers_.end());
112 observers_.erase(it);
113
114 observer->net_log_ = nullptr;
115 observer->capture_mode_ = NetLogCaptureMode::kDefault;
116 UpdateObserverCaptureModes();
117 }
118
AddCaptureModeObserver(NetLog::ThreadSafeCaptureModeObserver * observer)119 void NetLog::AddCaptureModeObserver(
120 NetLog::ThreadSafeCaptureModeObserver* observer) {
121 base::AutoLock lock(lock_);
122
123 DCHECK(!observer->net_log_);
124 DCHECK(!HasCaptureModeObserver(observer));
125 DCHECK_LT(capture_mode_observers_.size(), 20u); // Performance sanity check.
126
127 observer->net_log_ = this;
128 capture_mode_observers_.push_back(observer);
129 }
130
RemoveCaptureModeObserver(NetLog::ThreadSafeCaptureModeObserver * observer)131 void NetLog::RemoveCaptureModeObserver(
132 NetLog::ThreadSafeCaptureModeObserver* observer) {
133 base::AutoLock lock(lock_);
134
135 DCHECK_EQ(this, observer->net_log_);
136 DCHECK(HasCaptureModeObserver(observer));
137
138 auto it = std::find(capture_mode_observers_.begin(),
139 capture_mode_observers_.end(), observer);
140 DCHECK(it != capture_mode_observers_.end());
141 capture_mode_observers_.erase(it);
142
143 observer->net_log_ = nullptr;
144 }
145
UpdateObserverCaptureModes()146 void NetLog::UpdateObserverCaptureModes() {
147 lock_.AssertAcquired();
148
149 NetLogCaptureModeSet capture_mode_set = 0;
150 for (const auto* observer : observers_)
151 NetLogCaptureModeSetAdd(observer->capture_mode_, &capture_mode_set);
152
153 base::subtle::NoBarrier_Store(&observer_capture_modes_, capture_mode_set);
154
155 // Notify any capture mode observers with the new |capture_mode_set|.
156 for (auto* capture_mode_observer : capture_mode_observers_)
157 capture_mode_observer->OnCaptureModeUpdated(capture_mode_set);
158 }
159
HasObserver(ThreadSafeObserver * observer)160 bool NetLog::HasObserver(ThreadSafeObserver* observer) {
161 lock_.AssertAcquired();
162 return base::Contains(observers_, observer);
163 }
164
HasCaptureModeObserver(ThreadSafeCaptureModeObserver * observer)165 bool NetLog::HasCaptureModeObserver(ThreadSafeCaptureModeObserver* observer) {
166 lock_.AssertAcquired();
167 return base::Contains(capture_mode_observers_, observer);
168 }
169
170 // static
TickCountToString(const base::TimeTicks & time)171 std::string NetLog::TickCountToString(const base::TimeTicks& time) {
172 int64_t delta_time = time.since_origin().InMilliseconds();
173 // TODO(https://crbug.com/915391): Use NetLogNumberValue().
174 return base::NumberToString(delta_time);
175 }
176
177 // static
TimeToString(const base::Time & time)178 std::string NetLog::TimeToString(const base::Time& time) {
179 // Convert the base::Time to its (approximate) equivalent in base::TimeTicks.
180 base::TimeTicks time_ticks =
181 base::TimeTicks::UnixEpoch() + (time - base::Time::UnixEpoch());
182 return TickCountToString(time_ticks);
183 }
184
185 // static
EventTypeToString(NetLogEventType event)186 const char* NetLog::EventTypeToString(NetLogEventType event) {
187 switch (event) {
188 #define EVENT_TYPE(label) \
189 case NetLogEventType::label: \
190 return #label;
191 #include "net/log/net_log_event_type_list.h"
192 #undef EVENT_TYPE
193 default:
194 NOTREACHED();
195 return nullptr;
196 }
197 }
198
199 // static
GetEventTypesAsValue()200 base::Value NetLog::GetEventTypesAsValue() {
201 base::Value dict(base::Value::Type::DICTIONARY);
202 for (int i = 0; i < static_cast<int>(NetLogEventType::COUNT); ++i) {
203 dict.SetIntKey(EventTypeToString(static_cast<NetLogEventType>(i)), i);
204 }
205 return dict;
206 }
207
208 // static
SourceTypeToString(NetLogSourceType source)209 const char* NetLog::SourceTypeToString(NetLogSourceType source) {
210 switch (source) {
211 #define SOURCE_TYPE(label) \
212 case NetLogSourceType::label: \
213 return #label;
214 #include "net/log/net_log_source_type_list.h"
215 #undef SOURCE_TYPE
216 default:
217 NOTREACHED();
218 return nullptr;
219 }
220 }
221
222 // static
GetSourceTypesAsValue()223 base::Value NetLog::GetSourceTypesAsValue() {
224 base::Value dict(base::Value::Type::DICTIONARY);
225 for (int i = 0; i < static_cast<int>(NetLogSourceType::COUNT); ++i) {
226 dict.SetIntKey(SourceTypeToString(static_cast<NetLogSourceType>(i)), i);
227 }
228 return dict;
229 }
230
231 // static
EventPhaseToString(NetLogEventPhase phase)232 const char* NetLog::EventPhaseToString(NetLogEventPhase phase) {
233 switch (phase) {
234 case NetLogEventPhase::BEGIN:
235 return "PHASE_BEGIN";
236 case NetLogEventPhase::END:
237 return "PHASE_END";
238 case NetLogEventPhase::NONE:
239 return "PHASE_NONE";
240 }
241 NOTREACHED();
242 return nullptr;
243 }
244
InitializeSourceIdPartition()245 void NetLog::InitializeSourceIdPartition() {
246 int32_t old_value = base::subtle::NoBarrier_AtomicExchange(
247 &last_id_, std::numeric_limits<base::subtle::Atomic32>::min());
248 DCHECK_EQ(old_value, 0) << " NetLog::InitializeSourceIdPartition() called "
249 "after NextID() or called multiple times";
250 }
251
AddEntryInternal(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,const GetParamsInterface * get_params)252 void NetLog::AddEntryInternal(NetLogEventType type,
253 const NetLogSource& source,
254 NetLogEventPhase phase,
255 const GetParamsInterface* get_params) {
256 NetLogCaptureModeSet observer_capture_modes = GetObserverCaptureModes();
257
258 for (int i = 0; i <= static_cast<int>(NetLogCaptureMode::kLast); ++i) {
259 NetLogCaptureMode capture_mode = static_cast<NetLogCaptureMode>(i);
260 if (!NetLogCaptureModeSetContains(capture_mode, observer_capture_modes))
261 continue;
262
263 NetLogEntry entry(type, source, phase, base::TimeTicks::Now(),
264 get_params->GetParams(capture_mode));
265
266 // Notify all of the log observers with |capture_mode|.
267 base::AutoLock lock(lock_);
268 for (auto* observer : observers_) {
269 if (observer->capture_mode() == capture_mode)
270 observer->OnAddEntry(entry);
271 }
272 }
273 }
274
AddEntryWithMaterializedParams(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,base::Value && params)275 void NetLog::AddEntryWithMaterializedParams(NetLogEventType type,
276 const NetLogSource& source,
277 NetLogEventPhase phase,
278 base::Value&& params) {
279 AddEntryAtTimeWithMaterializedParams(
280 type, source, phase, base::TimeTicks::Now(), std::move(params));
281 }
282
AddEntryAtTimeWithMaterializedParams(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,base::TimeTicks time,base::Value && params)283 void NetLog::AddEntryAtTimeWithMaterializedParams(NetLogEventType type,
284 const NetLogSource& source,
285 NetLogEventPhase phase,
286 base::TimeTicks time,
287 base::Value&& params) {
288 NetLogEntry entry(type, source, phase, time, std::move(params));
289
290 // Notify all of the log observers, regardless of capture mode.
291 base::AutoLock lock(lock_);
292 for (auto* observer : observers_) {
293 observer->OnAddEntry(entry);
294 }
295 }
296
297 } // namespace net
298