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.
5 #include "net/log/net_log.h"
8 #include "base/debug/alias.h"
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h"
13 #include "base/values.h"
14 #include "net/base/net_errors.h"
20 // Returns parameters for logging data transferred events. At a minimum includes
21 // the number of bytes transferred. If the capture mode allows logging byte
22 // contents and |byte_count| > 0, then will include the actual bytes. The
23 // bytes are hex-encoded, since base::StringValue only supports UTF-8.
24 scoped_ptr
<base::Value
> BytesTransferredCallback(
27 NetLogCaptureMode capture_mode
) {
28 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
29 dict
->SetInteger("byte_count", byte_count
);
30 if (capture_mode
.include_socket_bytes() && byte_count
> 0)
31 dict
->SetString("hex_encoded_bytes", base::HexEncode(bytes
, byte_count
));
35 scoped_ptr
<base::Value
> SourceEventParametersCallback(
36 const NetLog::Source source
,
37 NetLogCaptureMode
/* capture_mode */) {
38 if (!source
.IsValid())
39 return scoped_ptr
<base::Value
>();
40 scoped_ptr
<base::DictionaryValue
> event_params(new base::DictionaryValue());
41 source
.AddToEventParameters(event_params
.get());
42 return event_params
.Pass();
45 scoped_ptr
<base::Value
> NetLogBoolCallback(
48 NetLogCaptureMode
/* capture_mode */) {
49 scoped_ptr
<base::DictionaryValue
> event_params(new base::DictionaryValue());
50 event_params
->SetBoolean(name
, value
);
51 return event_params
.Pass();
54 scoped_ptr
<base::Value
> NetLogIntegerCallback(
57 NetLogCaptureMode
/* capture_mode */) {
58 scoped_ptr
<base::DictionaryValue
> event_params(new base::DictionaryValue());
59 event_params
->SetInteger(name
, value
);
60 return event_params
.Pass();
63 scoped_ptr
<base::Value
> NetLogInt64Callback(
66 NetLogCaptureMode
/* capture_mode */) {
67 scoped_ptr
<base::DictionaryValue
> event_params(new base::DictionaryValue());
68 event_params
->SetString(name
, base::Int64ToString(value
));
69 return event_params
.Pass();
72 scoped_ptr
<base::Value
> NetLogStringCallback(
74 const std::string
* value
,
75 NetLogCaptureMode
/* capture_mode */) {
76 scoped_ptr
<base::DictionaryValue
> event_params(new base::DictionaryValue());
77 event_params
->SetString(name
, *value
);
78 return event_params
.Pass();
81 scoped_ptr
<base::Value
> NetLogString16Callback(
83 const base::string16
* value
,
84 NetLogCaptureMode
/* capture_mode */) {
85 scoped_ptr
<base::DictionaryValue
> event_params(new base::DictionaryValue());
86 event_params
->SetString(name
, *value
);
87 return event_params
.Pass();
92 // LoadTimingInfo requires this be 0.
93 const uint32
NetLog::Source::kInvalidId
= 0;
95 NetLog::Source::Source() : type(SOURCE_NONE
), id(kInvalidId
) {
98 NetLog::Source::Source(SourceType type
, uint32 id
) : type(type
), id(id
) {
101 bool NetLog::Source::IsValid() const {
102 return id
!= kInvalidId
;
105 void NetLog::Source::AddToEventParameters(
106 base::DictionaryValue
* event_params
) const {
107 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
108 dict
->SetInteger("type", static_cast<int>(type
));
109 dict
->SetInteger("id", static_cast<int>(id
));
110 event_params
->Set("source_dependency", dict
.Pass());
113 NetLog::ParametersCallback
NetLog::Source::ToEventParametersCallback() const {
114 return base::Bind(&SourceEventParametersCallback
, *this);
118 bool NetLog::Source::FromEventParameters(base::Value
* event_params
,
120 base::DictionaryValue
* dict
= NULL
;
121 base::DictionaryValue
* source_dict
= NULL
;
123 int source_type
= NetLog::SOURCE_COUNT
;
124 if (!event_params
|| !event_params
->GetAsDictionary(&dict
) ||
125 !dict
->GetDictionary("source_dependency", &source_dict
) ||
126 !source_dict
->GetInteger("id", &source_id
) ||
127 !source_dict
->GetInteger("type", &source_type
)) {
132 DCHECK_GE(source_id
, 0);
133 DCHECK_LT(source_type
, NetLog::SOURCE_COUNT
);
134 *source
= Source(static_cast<SourceType
>(source_type
), source_id
);
138 base::Value
* NetLog::Entry::ToValue() const {
139 scoped_ptr
<base::DictionaryValue
> entry_dict(new base::DictionaryValue());
141 entry_dict
->SetString("time", TickCountToString(data_
->time
));
143 // Set the entry source.
144 scoped_ptr
<base::DictionaryValue
> source_dict(new base::DictionaryValue());
145 source_dict
->SetInteger("id", data_
->source
.id
);
146 source_dict
->SetInteger("type", static_cast<int>(data_
->source
.type
));
147 entry_dict
->Set("source", source_dict
.Pass());
149 // Set the event info.
150 entry_dict
->SetInteger("type", static_cast<int>(data_
->type
));
151 entry_dict
->SetInteger("phase", static_cast<int>(data_
->phase
));
153 // Set the event-specific parameters.
154 if (data_
->parameters_callback
) {
155 scoped_ptr
<base::Value
> value(
156 data_
->parameters_callback
->Run(capture_mode_
));
158 entry_dict
->Set("params", value
.Pass());
161 return entry_dict
.release();
164 base::Value
* NetLog::Entry::ParametersToValue() const {
165 if (data_
->parameters_callback
)
166 return data_
->parameters_callback
->Run(capture_mode_
).release();
170 NetLog::EntryData::EntryData(EventType type
,
173 base::TimeTicks time
,
174 const ParametersCallback
* parameters_callback
)
179 parameters_callback(parameters_callback
) {
182 NetLog::EntryData::~EntryData() {
185 NetLog::Entry::Entry(const EntryData
* data
, NetLogCaptureMode capture_mode
)
186 : data_(data
), capture_mode_(capture_mode
) {
189 NetLog::Entry::~Entry() {
192 NetLog::ThreadSafeObserver::ThreadSafeObserver() : net_log_(NULL
) {
195 NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
196 // Make sure we aren't watching a NetLog on destruction. Because the NetLog
197 // may pass events to each observer on multiple threads, we cannot safely
198 // stop watching a NetLog automatically from a parent class.
202 NetLogCaptureMode
NetLog::ThreadSafeObserver::capture_mode() const {
204 return capture_mode_
;
207 NetLog
* NetLog::ThreadSafeObserver::net_log() const {
211 void NetLog::ThreadSafeObserver::OnAddEntryData(const EntryData
& entry_data
) {
212 OnAddEntry(Entry(&entry_data
, capture_mode()));
215 NetLog::NetLog() : last_id_(0), is_capturing_(0) {
221 void NetLog::AddGlobalEntry(EventType type
) {
222 AddEntry(type
, Source(NetLog::SOURCE_NONE
, NextID()), NetLog::PHASE_NONE
,
226 void NetLog::AddGlobalEntry(
228 const NetLog::ParametersCallback
& parameters_callback
) {
229 AddEntry(type
, Source(NetLog::SOURCE_NONE
, NextID()), NetLog::PHASE_NONE
,
230 ¶meters_callback
);
233 uint32
NetLog::NextID() {
234 return base::subtle::NoBarrier_AtomicIncrement(&last_id_
, 1);
237 bool NetLog::IsCapturing() const {
238 return base::subtle::NoBarrier_Load(&is_capturing_
) != 0;
241 void NetLog::DeprecatedAddObserver(NetLog::ThreadSafeObserver
* observer
,
242 NetLogCaptureMode capture_mode
) {
243 base::AutoLock
lock(lock_
);
245 DCHECK(!observer
->net_log_
);
246 observers_
.AddObserver(observer
);
247 observer
->net_log_
= this;
248 observer
->capture_mode_
= capture_mode
;
252 void NetLog::SetObserverCaptureMode(NetLog::ThreadSafeObserver
* observer
,
253 NetLogCaptureMode capture_mode
) {
254 base::AutoLock
lock(lock_
);
256 DCHECK(observers_
.HasObserver(observer
));
257 DCHECK_EQ(this, observer
->net_log_
);
258 observer
->capture_mode_
= capture_mode
;
261 void NetLog::DeprecatedRemoveObserver(NetLog::ThreadSafeObserver
* observer
) {
262 base::AutoLock
lock(lock_
);
264 DCHECK(observers_
.HasObserver(observer
));
265 DCHECK_EQ(this, observer
->net_log_
);
266 observers_
.RemoveObserver(observer
);
267 observer
->net_log_
= NULL
;
268 observer
->capture_mode_
= NetLogCaptureMode();
272 void NetLog::UpdateIsCapturing() {
273 lock_
.AssertAcquired();
274 base::subtle::NoBarrier_Store(&is_capturing_
,
275 observers_
.might_have_observers() ? 1 : 0);
279 std::string
NetLog::TickCountToString(const base::TimeTicks
& time
) {
280 int64 delta_time
= (time
- base::TimeTicks()).InMilliseconds();
281 return base::Int64ToString(delta_time
);
285 const char* NetLog::EventTypeToString(EventType event
) {
287 #define EVENT_TYPE(label) \
290 #include "net/log/net_log_event_type_list.h"
299 base::Value
* NetLog::GetEventTypesAsValue() {
300 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
301 for (int i
= 0; i
< EVENT_COUNT
; ++i
) {
302 dict
->SetInteger(EventTypeToString(static_cast<EventType
>(i
)), i
);
304 return dict
.release();
308 const char* NetLog::SourceTypeToString(SourceType source
) {
310 #define SOURCE_TYPE(label) \
311 case SOURCE_##label: \
313 #include "net/log/net_log_source_type_list.h"
322 base::Value
* NetLog::GetSourceTypesAsValue() {
323 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
324 for (int i
= 0; i
< SOURCE_COUNT
; ++i
) {
325 dict
->SetInteger(SourceTypeToString(static_cast<SourceType
>(i
)), i
);
327 return dict
.release();
331 const char* NetLog::EventPhaseToString(EventPhase phase
) {
334 return "PHASE_BEGIN";
345 NetLog::ParametersCallback
NetLog::BoolCallback(const char* name
, bool value
) {
346 return base::Bind(&NetLogBoolCallback
, name
, value
);
350 NetLog::ParametersCallback
NetLog::IntegerCallback(const char* name
,
352 return base::Bind(&NetLogIntegerCallback
, name
, value
);
356 NetLog::ParametersCallback
NetLog::Int64Callback(const char* name
,
358 return base::Bind(&NetLogInt64Callback
, name
, value
);
362 NetLog::ParametersCallback
NetLog::StringCallback(const char* name
,
363 const std::string
* value
) {
365 return base::Bind(&NetLogStringCallback
, name
, value
);
369 NetLog::ParametersCallback
NetLog::StringCallback(const char* name
,
370 const base::string16
* value
) {
372 return base::Bind(&NetLogString16Callback
, name
, value
);
375 void NetLog::AddEntry(EventType type
,
376 const Source
& source
,
378 const NetLog::ParametersCallback
* parameters_callback
) {
381 EntryData
entry_data(type
, source
, phase
, base::TimeTicks::Now(),
382 parameters_callback
);
384 // Notify all of the log observers.
385 base::AutoLock
lock(lock_
);
386 FOR_EACH_OBSERVER(ThreadSafeObserver
, observers_
, OnAddEntryData(entry_data
));
389 BoundNetLog::~BoundNetLog() {
393 void BoundNetLog::AddEntry(NetLog::EventType type
,
394 NetLog::EventPhase phase
) const {
399 net_log_
->AddEntry(type
, source_
, phase
, NULL
);
402 void BoundNetLog::AddEntry(
403 NetLog::EventType type
,
404 NetLog::EventPhase phase
,
405 const NetLog::ParametersCallback
& get_parameters
) const {
410 net_log_
->AddEntry(type
, source_
, phase
, &get_parameters
);
413 void BoundNetLog::AddEvent(NetLog::EventType type
) const {
414 AddEntry(type
, NetLog::PHASE_NONE
);
417 void BoundNetLog::AddEvent(
418 NetLog::EventType type
,
419 const NetLog::ParametersCallback
& get_parameters
) const {
420 AddEntry(type
, NetLog::PHASE_NONE
, get_parameters
);
423 void BoundNetLog::BeginEvent(NetLog::EventType type
) const {
424 AddEntry(type
, NetLog::PHASE_BEGIN
);
427 void BoundNetLog::BeginEvent(
428 NetLog::EventType type
,
429 const NetLog::ParametersCallback
& get_parameters
) const {
430 AddEntry(type
, NetLog::PHASE_BEGIN
, get_parameters
);
433 void BoundNetLog::EndEvent(NetLog::EventType type
) const {
434 AddEntry(type
, NetLog::PHASE_END
);
437 void BoundNetLog::EndEvent(
438 NetLog::EventType type
,
439 const NetLog::ParametersCallback
& get_parameters
) const {
440 AddEntry(type
, NetLog::PHASE_END
, get_parameters
);
443 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
);
449 AddEvent(event_type
, NetLog::IntegerCallback("net_error", net_error
));
453 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
);
459 EndEvent(event_type
, NetLog::IntegerCallback("net_error", net_error
));
463 void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type
,
465 const char* bytes
) const {
466 AddEvent(event_type
, base::Bind(BytesTransferredCallback
, byte_count
, bytes
));
469 bool BoundNetLog::IsCapturing() const {
471 return net_log_
&& net_log_
->IsCapturing();
475 BoundNetLog
BoundNetLog::Make(NetLog
* net_log
, NetLog::SourceType source_type
) {
477 return BoundNetLog();
479 NetLog::Source
source(source_type
, net_log
->NextID());
480 return BoundNetLog(source
, net_log
);
483 void BoundNetLog::CrashIfInvalid() const {
484 Liveness liveness
= liveness_
;
486 if (liveness
== ALIVE
)
489 base::debug::Alias(&liveness
);
490 CHECK_EQ(ALIVE
, liveness
);