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