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