• 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;
105   base::DictionaryValue* source_dict;
106   int source_id;
107   int source_type;
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_LE(0, source_id);
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(time_));
127 
128   // Set the entry source.
129   base::DictionaryValue* source_dict = new base::DictionaryValue();
130   source_dict->SetInteger("id", source_.id);
131   source_dict->SetInteger("type", static_cast<int>(source_.type));
132   entry_dict->Set("source", source_dict);
133 
134   // Set the event info.
135   entry_dict->SetInteger("type", static_cast<int>(type_));
136   entry_dict->SetInteger("phase", static_cast<int>(phase_));
137 
138   // Set the event-specific parameters.
139   if (parameters_callback_) {
140     base::Value* value = 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 (parameters_callback_)
150     return parameters_callback_->Run(log_level_);
151   return NULL;
152 }
153 
Entry(EventType type,Source source,EventPhase phase,base::TimeTicks time,const ParametersCallback * parameters_callback,LogLevel log_level)154 NetLog::Entry::Entry(
155     EventType type,
156     Source source,
157     EventPhase phase,
158     base::TimeTicks time,
159     const ParametersCallback* parameters_callback,
160     LogLevel log_level)
161     : type_(type),
162       source_(source),
163       phase_(phase),
164       time_(time),
165       parameters_callback_(parameters_callback),
166       log_level_(log_level) {
167 };
168 
~Entry()169 NetLog::Entry::~Entry() {
170 }
171 
ThreadSafeObserver()172 NetLog::ThreadSafeObserver::ThreadSafeObserver() : log_level_(LOG_BASIC),
173                                                    net_log_(NULL) {
174 }
175 
~ThreadSafeObserver()176 NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
177   // Make sure we aren't watching a NetLog on destruction.  Because the NetLog
178   // may pass events to each observer on multiple threads, we cannot safely
179   // stop watching a NetLog automatically from a parent class.
180   DCHECK(!net_log_);
181 }
182 
log_level() const183 NetLog::LogLevel NetLog::ThreadSafeObserver::log_level() const {
184   DCHECK(net_log_);
185   return log_level_;
186 }
187 
net_log() const188 NetLog* NetLog::ThreadSafeObserver::net_log() const {
189   return net_log_;
190 }
191 
NetLog()192 NetLog::NetLog()
193     : last_id_(0),
194       base_log_level_(LOG_NONE),
195       effective_log_level_(LOG_NONE) {
196 }
197 
~NetLog()198 NetLog::~NetLog() {
199 }
200 
AddGlobalEntry(EventType type)201 void NetLog::AddGlobalEntry(EventType type) {
202   AddEntry(type,
203            Source(net::NetLog::SOURCE_NONE, NextID()),
204            net::NetLog::PHASE_NONE,
205            NULL);
206 }
207 
AddGlobalEntry(EventType type,const NetLog::ParametersCallback & parameters_callback)208 void NetLog::AddGlobalEntry(
209     EventType type,
210     const NetLog::ParametersCallback& parameters_callback) {
211   AddEntry(type,
212            Source(net::NetLog::SOURCE_NONE, NextID()),
213            net::NetLog::PHASE_NONE,
214            &parameters_callback);
215 }
216 
NextID()217 uint32 NetLog::NextID() {
218   return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
219 }
220 
SetBaseLogLevel(LogLevel log_level)221 void NetLog::SetBaseLogLevel(LogLevel log_level) {
222   base::AutoLock lock(lock_);
223   base_log_level_ = log_level;
224 
225   UpdateLogLevel();
226 }
227 
GetLogLevel() const228 NetLog::LogLevel NetLog::GetLogLevel() const {
229   base::subtle::Atomic32 log_level =
230       base::subtle::NoBarrier_Load(&effective_log_level_);
231   return static_cast<net::NetLog::LogLevel>(log_level);
232 }
233 
AddThreadSafeObserver(net::NetLog::ThreadSafeObserver * observer,LogLevel log_level)234 void NetLog::AddThreadSafeObserver(
235     net::NetLog::ThreadSafeObserver* observer,
236     LogLevel log_level) {
237   base::AutoLock lock(lock_);
238 
239   DCHECK(!observer->net_log_);
240   observers_.AddObserver(observer);
241   observer->net_log_ = this;
242   observer->log_level_ = log_level;
243   UpdateLogLevel();
244 }
245 
SetObserverLogLevel(net::NetLog::ThreadSafeObserver * observer,LogLevel log_level)246 void NetLog::SetObserverLogLevel(
247     net::NetLog::ThreadSafeObserver* observer,
248     LogLevel log_level) {
249   base::AutoLock lock(lock_);
250 
251   DCHECK(observers_.HasObserver(observer));
252   DCHECK_EQ(this, observer->net_log_);
253   observer->log_level_ = log_level;
254   UpdateLogLevel();
255 }
256 
RemoveThreadSafeObserver(net::NetLog::ThreadSafeObserver * observer)257 void NetLog::RemoveThreadSafeObserver(
258     net::NetLog::ThreadSafeObserver* observer) {
259   base::AutoLock lock(lock_);
260 
261   DCHECK(observers_.HasObserver(observer));
262   DCHECK_EQ(this, observer->net_log_);
263   observers_.RemoveObserver(observer);
264   observer->net_log_ = NULL;
265   UpdateLogLevel();
266 }
267 
UpdateLogLevel()268 void NetLog::UpdateLogLevel() {
269   lock_.AssertAcquired();
270 
271   // Look through all the observers and find the finest granularity
272   // log level (higher values of the enum imply *lower* log levels).
273   LogLevel new_effective_log_level = base_log_level_;
274   ObserverListBase<ThreadSafeObserver>::Iterator it(observers_);
275   ThreadSafeObserver* observer;
276   while ((observer = it.GetNext()) != NULL) {
277     new_effective_log_level =
278         std::min(new_effective_log_level, observer->log_level());
279   }
280   base::subtle::NoBarrier_Store(&effective_log_level_,
281                                 new_effective_log_level);
282 }
283 
284 // static
TickCountToString(const base::TimeTicks & time)285 std::string NetLog::TickCountToString(const base::TimeTicks& time) {
286   int64 delta_time = (time - base::TimeTicks()).InMilliseconds();
287   return base::Int64ToString(delta_time);
288 }
289 
290 // static
EventTypeToString(EventType event)291 const char* NetLog::EventTypeToString(EventType event) {
292   switch (event) {
293 #define EVENT_TYPE(label) case TYPE_ ## label: return #label;
294 #include "net/base/net_log_event_type_list.h"
295 #undef EVENT_TYPE
296     default:
297       NOTREACHED();
298       return NULL;
299   }
300 }
301 
302 // static
GetEventTypesAsValue()303 base::Value* NetLog::GetEventTypesAsValue() {
304   base::DictionaryValue* dict = new base::DictionaryValue();
305   for (int i = 0; i < EVENT_COUNT; ++i) {
306     dict->SetInteger(EventTypeToString(static_cast<EventType>(i)), i);
307   }
308   return dict;
309 }
310 
311 // static
SourceTypeToString(SourceType source)312 const char* NetLog::SourceTypeToString(SourceType source) {
313   switch (source) {
314 #define SOURCE_TYPE(label) case SOURCE_ ## label: return #label;
315 #include "net/base/net_log_source_type_list.h"
316 #undef SOURCE_TYPE
317     default:
318       NOTREACHED();
319       return NULL;
320   }
321 }
322 
323 // static
GetSourceTypesAsValue()324 base::Value* NetLog::GetSourceTypesAsValue() {
325   base::DictionaryValue* dict = new base::DictionaryValue();
326   for (int i = 0; i < SOURCE_COUNT; ++i) {
327     dict->SetInteger(SourceTypeToString(static_cast<SourceType>(i)), i);
328   }
329   return dict;
330 }
331 
332 // static
EventPhaseToString(EventPhase phase)333 const char* NetLog::EventPhaseToString(EventPhase phase) {
334   switch (phase) {
335     case PHASE_BEGIN:
336       return "PHASE_BEGIN";
337     case PHASE_END:
338       return "PHASE_END";
339     case PHASE_NONE:
340       return "PHASE_NONE";
341   }
342   NOTREACHED();
343   return NULL;
344 }
345 
346 // static
IsLoggingBytes(LogLevel log_level)347 bool NetLog::IsLoggingBytes(LogLevel log_level) {
348   return log_level == NetLog::LOG_ALL;
349 }
350 
351 // static
IsLoggingAllEvents(LogLevel log_level)352 bool NetLog::IsLoggingAllEvents(LogLevel log_level) {
353   return log_level <= NetLog::LOG_ALL_BUT_BYTES;
354 }
355 
356 // static
IntegerCallback(const char * name,int value)357 NetLog::ParametersCallback NetLog::IntegerCallback(const char* name,
358                                                    int value) {
359   return base::Bind(&NetLogIntegerCallback, name, value);
360 }
361 
362 // static
Int64Callback(const char * name,int64 value)363 NetLog::ParametersCallback NetLog::Int64Callback(const char* name,
364                                                  int64 value) {
365   return base::Bind(&NetLogInt64Callback, name, value);
366 }
367 
368 // static
StringCallback(const char * name,const std::string * value)369 NetLog::ParametersCallback NetLog::StringCallback(const char* name,
370                                                   const std::string* value) {
371   DCHECK(value);
372   return base::Bind(&NetLogStringCallback, name, value);
373 }
374 
375 // static
StringCallback(const char * name,const base::string16 * value)376 NetLog::ParametersCallback NetLog::StringCallback(const char* name,
377                                                   const base::string16* value) {
378   DCHECK(value);
379   return base::Bind(&NetLogString16Callback, name, value);
380 }
381 
AddEntry(EventType type,const Source & source,EventPhase phase,const NetLog::ParametersCallback * parameters_callback)382 void NetLog::AddEntry(EventType type,
383                       const Source& source,
384                       EventPhase phase,
385                       const NetLog::ParametersCallback* parameters_callback) {
386   LogLevel log_level = GetLogLevel();
387   if (log_level == LOG_NONE)
388     return;
389   Entry entry(type, source, phase, base::TimeTicks::Now(),
390               parameters_callback, log_level);
391 
392   // Notify all of the log observers.
393   base::AutoLock lock(lock_);
394   FOR_EACH_OBSERVER(ThreadSafeObserver, observers_, OnAddEntry(entry));
395 }
396 
AddEntry(NetLog::EventType type,NetLog::EventPhase phase) const397 void BoundNetLog::AddEntry(NetLog::EventType type,
398                            NetLog::EventPhase phase) const {
399   if (!net_log_)
400     return;
401   net_log_->AddEntry(type, source_, phase, NULL);
402 }
403 
AddEntry(NetLog::EventType type,NetLog::EventPhase phase,const NetLog::ParametersCallback & get_parameters) const404 void BoundNetLog::AddEntry(
405     NetLog::EventType type,
406     NetLog::EventPhase phase,
407     const NetLog::ParametersCallback& get_parameters) const {
408   if (!net_log_)
409     return;
410   net_log_->AddEntry(type, source_, phase, &get_parameters);
411 }
412 
AddEvent(NetLog::EventType type) const413 void BoundNetLog::AddEvent(NetLog::EventType type) const {
414   AddEntry(type, NetLog::PHASE_NONE);
415 }
416 
AddEvent(NetLog::EventType type,const NetLog::ParametersCallback & get_parameters) const417 void BoundNetLog::AddEvent(
418     NetLog::EventType type,
419     const NetLog::ParametersCallback& get_parameters) const {
420   AddEntry(type, NetLog::PHASE_NONE, get_parameters);
421 }
422 
BeginEvent(NetLog::EventType type) const423 void BoundNetLog::BeginEvent(NetLog::EventType type) const {
424   AddEntry(type, NetLog::PHASE_BEGIN);
425 }
426 
BeginEvent(NetLog::EventType type,const NetLog::ParametersCallback & get_parameters) const427 void BoundNetLog::BeginEvent(
428     NetLog::EventType type,
429     const NetLog::ParametersCallback& get_parameters) const {
430   AddEntry(type, NetLog::PHASE_BEGIN, get_parameters);
431 }
432 
EndEvent(NetLog::EventType type) const433 void BoundNetLog::EndEvent(NetLog::EventType type) const {
434   AddEntry(type, NetLog::PHASE_END);
435 }
436 
EndEvent(NetLog::EventType type,const NetLog::ParametersCallback & get_parameters) const437 void BoundNetLog::EndEvent(
438     NetLog::EventType type,
439     const NetLog::ParametersCallback& get_parameters) const {
440   AddEntry(type, NetLog::PHASE_END, get_parameters);
441 }
442 
AddEventWithNetErrorCode(NetLog::EventType event_type,int net_error) const443 void BoundNetLog::AddEventWithNetErrorCode(NetLog::EventType event_type,
444                                            int net_error) const {
445   DCHECK_NE(ERR_IO_PENDING, net_error);
446   if (net_error >= 0) {
447     AddEvent(event_type);
448   } else {
449     AddEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
450   }
451 }
452 
EndEventWithNetErrorCode(NetLog::EventType event_type,int net_error) const453 void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type,
454                                            int net_error) const {
455   DCHECK_NE(ERR_IO_PENDING, net_error);
456   if (net_error >= 0) {
457     EndEvent(event_type);
458   } else {
459     EndEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
460   }
461 }
462 
AddByteTransferEvent(NetLog::EventType event_type,int byte_count,const char * bytes) const463 void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type,
464                                        int byte_count,
465                                        const char* bytes) const {
466   AddEvent(event_type, base::Bind(BytesTransferredCallback, byte_count, bytes));
467 }
468 
GetLogLevel() const469 NetLog::LogLevel BoundNetLog::GetLogLevel() const {
470   if (net_log_)
471     return net_log_->GetLogLevel();
472   return NetLog::LOG_BASIC;
473 }
474 
IsLoggingBytes() const475 bool BoundNetLog::IsLoggingBytes() const {
476   return NetLog::IsLoggingBytes(GetLogLevel());
477 }
478 
IsLoggingAllEvents() const479 bool BoundNetLog::IsLoggingAllEvents() const {
480   return NetLog::IsLoggingAllEvents(GetLogLevel());
481 }
482 
483 // static
Make(NetLog * net_log,NetLog::SourceType source_type)484 BoundNetLog BoundNetLog::Make(NetLog* net_log,
485                               NetLog::SourceType source_type) {
486   if (!net_log)
487     return BoundNetLog();
488 
489   NetLog::Source source(source_type, net_log->NextID());
490   return BoundNetLog(source, net_log);
491 }
492 
493 }  // namespace net
494