• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/net_log.h"
6 
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/time/time.h"
12 #include "base/values.h"
13 #include "net/base/net_errors.h"
14 
15 namespace net {
16 
17 namespace {
18 
19 // Returns parameters for logging data transferred events. Includes number of
20 // bytes transferred and, if the log level indicates bytes should be logged and
21 // |byte_count| > 0, the bytes themselves.  The bytes are hex-encoded, since
22 // base::StringValue only supports UTF-8.
BytesTransferredCallback(int byte_count,const char * bytes,NetLog::LogLevel log_level)23 base::Value* BytesTransferredCallback(int byte_count,
24                                       const char* bytes,
25                                       NetLog::LogLevel log_level) {
26   base::DictionaryValue* dict = new base::DictionaryValue();
27   dict->SetInteger("byte_count", byte_count);
28   if (NetLog::IsLoggingBytes(log_level) && byte_count > 0)
29     dict->SetString("hex_encoded_bytes", base::HexEncode(bytes, byte_count));
30   return dict;
31 }
32 
SourceEventParametersCallback(const NetLog::Source source,NetLog::LogLevel)33 base::Value* SourceEventParametersCallback(const NetLog::Source source,
34                                            NetLog::LogLevel /* log_level */) {
35   if (!source.IsValid())
36     return NULL;
37   base::DictionaryValue* event_params = new base::DictionaryValue();
38   source.AddToEventParameters(event_params);
39   return event_params;
40 }
41 
NetLogIntegerCallback(const char * name,int value,NetLog::LogLevel)42 base::Value* NetLogIntegerCallback(const char* name,
43                                    int value,
44                                    NetLog::LogLevel /* log_level */) {
45   base::DictionaryValue* event_params = new base::DictionaryValue();
46   event_params->SetInteger(name, value);
47   return event_params;
48 }
49 
NetLogInt64Callback(const char * name,int64 value,NetLog::LogLevel)50 base::Value* NetLogInt64Callback(const char* name,
51                                  int64 value,
52                                  NetLog::LogLevel /* log_level */) {
53   base::DictionaryValue* event_params = new base::DictionaryValue();
54   event_params->SetString(name, base::Int64ToString(value));
55   return event_params;
56 }
57 
NetLogStringCallback(const char * name,const std::string * value,NetLog::LogLevel)58 base::Value* NetLogStringCallback(const char* name,
59                                   const std::string* value,
60                                   NetLog::LogLevel /* log_level */) {
61   base::DictionaryValue* event_params = new base::DictionaryValue();
62   event_params->SetString(name, *value);
63   return event_params;
64 }
65 
NetLogString16Callback(const char * name,const base::string16 * value,NetLog::LogLevel)66 base::Value* NetLogString16Callback(const char* name,
67                                     const base::string16* value,
68                                     NetLog::LogLevel /* log_level */) {
69   base::DictionaryValue* event_params = new base::DictionaryValue();
70   event_params->SetString(name, *value);
71   return event_params;
72 }
73 
74 }  // namespace
75 
76 // LoadTimingInfo requires this be 0.
77 const uint32 NetLog::Source::kInvalidId = 0;
78 
Source()79 NetLog::Source::Source() : type(SOURCE_NONE), id(kInvalidId) {
80 }
81 
Source(SourceType type,uint32 id)82 NetLog::Source::Source(SourceType type, uint32 id) : type(type), id(id) {
83 }
84 
IsValid() const85 bool NetLog::Source::IsValid() const {
86   return id != kInvalidId;
87 }
88 
AddToEventParameters(base::DictionaryValue * event_params) const89 void NetLog::Source::AddToEventParameters(
90     base::DictionaryValue* event_params) const {
91   base::DictionaryValue* dict = new base::DictionaryValue();
92   dict->SetInteger("type", static_cast<int>(type));
93   dict->SetInteger("id", static_cast<int>(id));
94   event_params->Set("source_dependency", dict);
95 }
96 
ToEventParametersCallback() const97 NetLog::ParametersCallback NetLog::Source::ToEventParametersCallback() const {
98   return base::Bind(&SourceEventParametersCallback, *this);
99 }
100 
101 // static
FromEventParameters(base::Value * event_params,Source * source)102 bool NetLog::Source::FromEventParameters(base::Value* event_params,
103                                          Source* source) {
104   base::DictionaryValue* dict = NULL;
105   base::DictionaryValue* source_dict = NULL;
106   int source_id = -1;
107   int source_type = NetLog::SOURCE_COUNT;
108   if (!event_params ||
109       !event_params->GetAsDictionary(&dict) ||
110       !dict->GetDictionary("source_dependency", &source_dict) ||
111       !source_dict->GetInteger("id", &source_id) ||
112       !source_dict->GetInteger("type", &source_type)) {
113     *source = Source();
114     return false;
115   }
116 
117   DCHECK_GE(source_id, 0);
118   DCHECK_LT(source_type, NetLog::SOURCE_COUNT);
119   *source = Source(static_cast<SourceType>(source_type), source_id);
120   return true;
121 }
122 
ToValue() const123 base::Value* NetLog::Entry::ToValue() const {
124   base::DictionaryValue* entry_dict(new base::DictionaryValue());
125 
126   entry_dict->SetString("time", TickCountToString(data_->time));
127 
128   // Set the entry source.
129   base::DictionaryValue* source_dict = new base::DictionaryValue();
130   source_dict->SetInteger("id", data_->source.id);
131   source_dict->SetInteger("type", static_cast<int>(data_->source.type));
132   entry_dict->Set("source", source_dict);
133 
134   // Set the event info.
135   entry_dict->SetInteger("type", static_cast<int>(data_->type));
136   entry_dict->SetInteger("phase", static_cast<int>(data_->phase));
137 
138   // Set the event-specific parameters.
139   if (data_->parameters_callback) {
140     base::Value* value = data_->parameters_callback->Run(log_level_);
141     if (value)
142       entry_dict->Set("params", value);
143   }
144 
145   return entry_dict;
146 }
147 
ParametersToValue() const148 base::Value* NetLog::Entry::ParametersToValue() const {
149   if (data_->parameters_callback)
150     return data_->parameters_callback->Run(log_level_);
151   return NULL;
152 }
153 
EntryData(EventType type,Source source,EventPhase phase,base::TimeTicks time,const ParametersCallback * parameters_callback)154 NetLog::EntryData::EntryData(
155     EventType type,
156     Source source,
157     EventPhase phase,
158     base::TimeTicks time,
159     const ParametersCallback* parameters_callback)
160     : type(type),
161       source(source),
162       phase(phase),
163       time(time),
164       parameters_callback(parameters_callback) {
165 }
166 
~EntryData()167 NetLog::EntryData::~EntryData() {
168 }
169 
Entry(const EntryData * data,LogLevel log_level)170 NetLog::Entry::Entry(const EntryData* data, LogLevel log_level)
171     : data_(data), log_level_(log_level) {
172 }
173 
~Entry()174 NetLog::Entry::~Entry() {
175 }
176 
ThreadSafeObserver()177 NetLog::ThreadSafeObserver::ThreadSafeObserver() : log_level_(LOG_NONE),
178                                                    net_log_(NULL) {
179 }
180 
~ThreadSafeObserver()181 NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
182   // Make sure we aren't watching a NetLog on destruction.  Because the NetLog
183   // may pass events to each observer on multiple threads, we cannot safely
184   // stop watching a NetLog automatically from a parent class.
185   DCHECK(!net_log_);
186 }
187 
log_level() const188 NetLog::LogLevel NetLog::ThreadSafeObserver::log_level() const {
189   DCHECK(net_log_);
190   return log_level_;
191 }
192 
net_log() const193 NetLog* NetLog::ThreadSafeObserver::net_log() const {
194   return net_log_;
195 }
196 
OnAddEntryData(const EntryData & entry_data)197 void NetLog::ThreadSafeObserver::OnAddEntryData(const EntryData& entry_data) {
198   OnAddEntry(Entry(&entry_data, log_level()));
199 }
200 
NetLog()201 NetLog::NetLog()
202     : last_id_(0),
203       base_log_level_(LOG_NONE),
204       effective_log_level_(LOG_NONE) {
205 }
206 
~NetLog()207 NetLog::~NetLog() {
208 }
209 
AddGlobalEntry(EventType type)210 void NetLog::AddGlobalEntry(EventType type) {
211   AddEntry(type,
212            Source(net::NetLog::SOURCE_NONE, NextID()),
213            net::NetLog::PHASE_NONE,
214            NULL);
215 }
216 
AddGlobalEntry(EventType type,const NetLog::ParametersCallback & parameters_callback)217 void NetLog::AddGlobalEntry(
218     EventType type,
219     const NetLog::ParametersCallback& parameters_callback) {
220   AddEntry(type,
221            Source(net::NetLog::SOURCE_NONE, NextID()),
222            net::NetLog::PHASE_NONE,
223            &parameters_callback);
224 }
225 
NextID()226 uint32 NetLog::NextID() {
227   return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
228 }
229 
SetBaseLogLevel(LogLevel log_level)230 void NetLog::SetBaseLogLevel(LogLevel log_level) {
231   base::AutoLock lock(lock_);
232   base_log_level_ = log_level;
233 
234   UpdateLogLevel();
235 }
236 
GetLogLevel() const237 NetLog::LogLevel NetLog::GetLogLevel() const {
238   base::subtle::Atomic32 log_level =
239       base::subtle::NoBarrier_Load(&effective_log_level_);
240   return static_cast<net::NetLog::LogLevel>(log_level);
241 }
242 
AddThreadSafeObserver(net::NetLog::ThreadSafeObserver * observer,LogLevel log_level)243 void NetLog::AddThreadSafeObserver(
244     net::NetLog::ThreadSafeObserver* observer,
245     LogLevel log_level) {
246   DCHECK_NE(LOG_NONE, log_level);
247   base::AutoLock lock(lock_);
248 
249   DCHECK(!observer->net_log_);
250   DCHECK_EQ(LOG_NONE, observer->log_level_);
251   observers_.AddObserver(observer);
252   observer->net_log_ = this;
253   observer->log_level_ = log_level;
254   UpdateLogLevel();
255 }
256 
SetObserverLogLevel(net::NetLog::ThreadSafeObserver * observer,LogLevel log_level)257 void NetLog::SetObserverLogLevel(
258     net::NetLog::ThreadSafeObserver* observer,
259     LogLevel log_level) {
260   DCHECK_NE(LOG_NONE, log_level);
261   base::AutoLock lock(lock_);
262 
263   DCHECK(observers_.HasObserver(observer));
264   DCHECK_EQ(this, observer->net_log_);
265   DCHECK_NE(LOG_NONE, observer->log_level_);
266   observer->log_level_ = log_level;
267   UpdateLogLevel();
268 }
269 
RemoveThreadSafeObserver(net::NetLog::ThreadSafeObserver * observer)270 void NetLog::RemoveThreadSafeObserver(
271     net::NetLog::ThreadSafeObserver* observer) {
272   base::AutoLock lock(lock_);
273 
274   DCHECK(observers_.HasObserver(observer));
275   DCHECK_EQ(this, observer->net_log_);
276   DCHECK_NE(LOG_NONE, observer->log_level_);
277   observers_.RemoveObserver(observer);
278   observer->net_log_ = NULL;
279   observer->log_level_ = LOG_NONE;
280   UpdateLogLevel();
281 }
282 
UpdateLogLevel()283 void NetLog::UpdateLogLevel() {
284   lock_.AssertAcquired();
285 
286   // Look through all the observers and find the finest granularity
287   // log level (higher values of the enum imply *lower* log levels).
288   LogLevel new_effective_log_level = base_log_level_;
289   ObserverListBase<ThreadSafeObserver>::Iterator it(observers_);
290   ThreadSafeObserver* observer;
291   while ((observer = it.GetNext()) != NULL) {
292     new_effective_log_level =
293         std::min(new_effective_log_level, observer->log_level());
294   }
295   base::subtle::NoBarrier_Store(&effective_log_level_,
296                                 new_effective_log_level);
297 }
298 
299 // static
TickCountToString(const base::TimeTicks & time)300 std::string NetLog::TickCountToString(const base::TimeTicks& time) {
301   int64 delta_time = (time - base::TimeTicks()).InMilliseconds();
302   return base::Int64ToString(delta_time);
303 }
304 
305 // static
EventTypeToString(EventType event)306 const char* NetLog::EventTypeToString(EventType event) {
307   switch (event) {
308 #define EVENT_TYPE(label) case TYPE_ ## label: return #label;
309 #include "net/base/net_log_event_type_list.h"
310 #undef EVENT_TYPE
311     default:
312       NOTREACHED();
313       return NULL;
314   }
315 }
316 
317 // static
GetEventTypesAsValue()318 base::Value* NetLog::GetEventTypesAsValue() {
319   base::DictionaryValue* dict = new base::DictionaryValue();
320   for (int i = 0; i < EVENT_COUNT; ++i) {
321     dict->SetInteger(EventTypeToString(static_cast<EventType>(i)), i);
322   }
323   return dict;
324 }
325 
326 // static
SourceTypeToString(SourceType source)327 const char* NetLog::SourceTypeToString(SourceType source) {
328   switch (source) {
329 #define SOURCE_TYPE(label) case SOURCE_ ## label: return #label;
330 #include "net/base/net_log_source_type_list.h"
331 #undef SOURCE_TYPE
332     default:
333       NOTREACHED();
334       return NULL;
335   }
336 }
337 
338 // static
GetSourceTypesAsValue()339 base::Value* NetLog::GetSourceTypesAsValue() {
340   base::DictionaryValue* dict = new base::DictionaryValue();
341   for (int i = 0; i < SOURCE_COUNT; ++i) {
342     dict->SetInteger(SourceTypeToString(static_cast<SourceType>(i)), i);
343   }
344   return dict;
345 }
346 
347 // static
EventPhaseToString(EventPhase phase)348 const char* NetLog::EventPhaseToString(EventPhase phase) {
349   switch (phase) {
350     case PHASE_BEGIN:
351       return "PHASE_BEGIN";
352     case PHASE_END:
353       return "PHASE_END";
354     case PHASE_NONE:
355       return "PHASE_NONE";
356   }
357   NOTREACHED();
358   return NULL;
359 }
360 
361 // static
IsLoggingBytes(LogLevel log_level)362 bool NetLog::IsLoggingBytes(LogLevel log_level) {
363   return log_level == NetLog::LOG_ALL;
364 }
365 
366 // static
IsLogging(LogLevel log_level)367 bool NetLog::IsLogging(LogLevel log_level) {
368   return log_level < NetLog::LOG_NONE;
369 }
370 
371 // static
IntegerCallback(const char * name,int value)372 NetLog::ParametersCallback NetLog::IntegerCallback(const char* name,
373                                                    int value) {
374   return base::Bind(&NetLogIntegerCallback, name, value);
375 }
376 
377 // static
Int64Callback(const char * name,int64 value)378 NetLog::ParametersCallback NetLog::Int64Callback(const char* name,
379                                                  int64 value) {
380   return base::Bind(&NetLogInt64Callback, name, value);
381 }
382 
383 // static
StringCallback(const char * name,const std::string * value)384 NetLog::ParametersCallback NetLog::StringCallback(const char* name,
385                                                   const std::string* value) {
386   DCHECK(value);
387   return base::Bind(&NetLogStringCallback, name, value);
388 }
389 
390 // static
StringCallback(const char * name,const base::string16 * value)391 NetLog::ParametersCallback NetLog::StringCallback(const char* name,
392                                                   const base::string16* value) {
393   DCHECK(value);
394   return base::Bind(&NetLogString16Callback, name, value);
395 }
396 
AddEntry(EventType type,const Source & source,EventPhase phase,const NetLog::ParametersCallback * parameters_callback)397 void NetLog::AddEntry(EventType type,
398                       const Source& source,
399                       EventPhase phase,
400                       const NetLog::ParametersCallback* parameters_callback) {
401   if (GetLogLevel() == LOG_NONE)
402     return;
403   EntryData entry_data(type, source, phase, base::TimeTicks::Now(),
404                        parameters_callback);
405 
406   // Notify all of the log observers.
407   base::AutoLock lock(lock_);
408   FOR_EACH_OBSERVER(ThreadSafeObserver, observers_, OnAddEntryData(entry_data));
409 }
410 
AddEntry(NetLog::EventType type,NetLog::EventPhase phase) const411 void BoundNetLog::AddEntry(NetLog::EventType type,
412                            NetLog::EventPhase phase) const {
413   if (!net_log_)
414     return;
415   net_log_->AddEntry(type, source_, phase, NULL);
416 }
417 
AddEntry(NetLog::EventType type,NetLog::EventPhase phase,const NetLog::ParametersCallback & get_parameters) const418 void BoundNetLog::AddEntry(
419     NetLog::EventType type,
420     NetLog::EventPhase phase,
421     const NetLog::ParametersCallback& get_parameters) const {
422   if (!net_log_)
423     return;
424   net_log_->AddEntry(type, source_, phase, &get_parameters);
425 }
426 
AddEvent(NetLog::EventType type) const427 void BoundNetLog::AddEvent(NetLog::EventType type) const {
428   AddEntry(type, NetLog::PHASE_NONE);
429 }
430 
AddEvent(NetLog::EventType type,const NetLog::ParametersCallback & get_parameters) const431 void BoundNetLog::AddEvent(
432     NetLog::EventType type,
433     const NetLog::ParametersCallback& get_parameters) const {
434   AddEntry(type, NetLog::PHASE_NONE, get_parameters);
435 }
436 
BeginEvent(NetLog::EventType type) const437 void BoundNetLog::BeginEvent(NetLog::EventType type) const {
438   AddEntry(type, NetLog::PHASE_BEGIN);
439 }
440 
BeginEvent(NetLog::EventType type,const NetLog::ParametersCallback & get_parameters) const441 void BoundNetLog::BeginEvent(
442     NetLog::EventType type,
443     const NetLog::ParametersCallback& get_parameters) const {
444   AddEntry(type, NetLog::PHASE_BEGIN, get_parameters);
445 }
446 
EndEvent(NetLog::EventType type) const447 void BoundNetLog::EndEvent(NetLog::EventType type) const {
448   AddEntry(type, NetLog::PHASE_END);
449 }
450 
EndEvent(NetLog::EventType type,const NetLog::ParametersCallback & get_parameters) const451 void BoundNetLog::EndEvent(
452     NetLog::EventType type,
453     const NetLog::ParametersCallback& get_parameters) const {
454   AddEntry(type, NetLog::PHASE_END, get_parameters);
455 }
456 
AddEventWithNetErrorCode(NetLog::EventType event_type,int net_error) const457 void BoundNetLog::AddEventWithNetErrorCode(NetLog::EventType event_type,
458                                            int net_error) const {
459   DCHECK_NE(ERR_IO_PENDING, net_error);
460   if (net_error >= 0) {
461     AddEvent(event_type);
462   } else {
463     AddEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
464   }
465 }
466 
EndEventWithNetErrorCode(NetLog::EventType event_type,int net_error) const467 void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type,
468                                            int net_error) const {
469   DCHECK_NE(ERR_IO_PENDING, net_error);
470   if (net_error >= 0) {
471     EndEvent(event_type);
472   } else {
473     EndEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
474   }
475 }
476 
AddByteTransferEvent(NetLog::EventType event_type,int byte_count,const char * bytes) const477 void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type,
478                                        int byte_count,
479                                        const char* bytes) const {
480   AddEvent(event_type, base::Bind(BytesTransferredCallback, byte_count, bytes));
481 }
482 
GetLogLevel() const483 NetLog::LogLevel BoundNetLog::GetLogLevel() const {
484   if (net_log_)
485     return net_log_->GetLogLevel();
486   return NetLog::LOG_NONE;
487 }
488 
IsLoggingBytes() const489 bool BoundNetLog::IsLoggingBytes() const {
490   return NetLog::IsLoggingBytes(GetLogLevel());
491 }
492 
IsLogging() const493 bool BoundNetLog::IsLogging() const {
494   return NetLog::IsLogging(GetLogLevel());
495 }
496 
497 // static
Make(NetLog * net_log,NetLog::SourceType source_type)498 BoundNetLog BoundNetLog::Make(NetLog* net_log,
499                               NetLog::SourceType source_type) {
500   if (!net_log)
501     return BoundNetLog();
502 
503   NetLog::Source source(source_type, net_log->NextID());
504   return BoundNetLog(source, net_log);
505 }
506 
507 }  // namespace net
508