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