| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/net/passive_log_collector.h" | 5 #include "chrome/browser/net/passive_log_collector.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "chrome/browser/chrome_thread.h" | 10 #include "chrome/browser/chrome_thread.h" |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 const size_t kMaxNumEntriesPerLog = 50; | 13 const size_t kMaxNumEntriesPerLog = 50; |
| 14 const size_t kMaxConnectJobGraveyardSize = 3; | 14 const size_t kMaxConnectJobGraveyardSize = 3; |
| 15 const size_t kMaxRequestGraveyardSize = 25; | 15 const size_t kMaxRequestGraveyardSize = 25; |
| 16 const size_t kMaxLiveRequests = 200; | 16 const size_t kMaxLiveRequests = 200; |
| 17 | 17 |
| 18 // Sort function on source ID. | 18 // Sort function on source ID. |
| 19 bool OrderBySourceID(const PassiveLogCollector::RequestInfo& a, | 19 bool OrderBySourceID(const PassiveLogCollector::RequestInfo& a, |
| 20 const PassiveLogCollector::RequestInfo& b) { | 20 const PassiveLogCollector::RequestInfo& b) { |
| 21 return a.entries[0].source.id < b.entries[0].source.id; | 21 return a.entries[0].source.id < b.entries[0].source.id; |
| 22 } | 22 } |
| 23 | 23 |
| 24 void AddEntryToRequestInfo(const net::CapturingNetLog::Entry& entry, | 24 void AddEntryToRequestInfo(const PassiveLogCollector::Entry& entry, |
| 25 bool is_unbounded, | 25 bool is_unbounded, |
| 26 PassiveLogCollector::RequestInfo* out_info) { | 26 PassiveLogCollector::RequestInfo* out_info) { |
| 27 // Start dropping new entries when the log has gotten too big. | 27 // Start dropping new entries when the log has gotten too big. |
| 28 if (out_info->entries.size() + 1 <= kMaxNumEntriesPerLog || is_unbounded) { | 28 if (out_info->entries.size() + 1 <= kMaxNumEntriesPerLog || is_unbounded) { |
| 29 out_info->entries.push_back(entry); | 29 out_info->entries.push_back(entry); |
| 30 } else { | 30 } else { |
| 31 out_info->num_entries_truncated += 1; | 31 out_info->num_entries_truncated += 1; |
| 32 out_info->entries[kMaxNumEntriesPerLog - 1] = entry; | 32 out_info->entries[kMaxNumEntriesPerLog - 1] = entry; |
| 33 } | 33 } |
| 34 } | 34 } |
| 35 | 35 |
| 36 void AppendToRequestInfo(const PassiveLogCollector::RequestInfo& info, | 36 void AppendToRequestInfo(const PassiveLogCollector::RequestInfo& info, |
| 37 bool is_unbounded, | 37 bool is_unbounded, |
| 38 PassiveLogCollector::RequestInfo* out_info) { | 38 PassiveLogCollector::RequestInfo* out_info) { |
| 39 for (size_t i = 0; i < info.entries.size(); ++i) | 39 for (size_t i = 0; i < info.entries.size(); ++i) |
| 40 AddEntryToRequestInfo(info.entries[i], is_unbounded, out_info); | 40 AddEntryToRequestInfo(info.entries[i], is_unbounded, out_info); |
| 41 } | 41 } |
| 42 | 42 |
| 43 // Appends all of the logged events in |input| to |out|. |
| 44 void AppendAllEntriesFromRequests( |
| 45 const PassiveLogCollector::RequestInfoList& input, |
| 46 PassiveLogCollector::EntryList* out) { |
| 47 for (size_t i = 0; i < input.size(); ++i) { |
| 48 const PassiveLogCollector::EntryList& entries = input[i].entries; |
| 49 out->insert(out->end(), entries.begin(), entries.end()); |
| 50 } |
| 51 } |
| 52 |
| 53 // Comparator to sort entries by their |order| property, ascending. |
| 54 bool SortByOrderComparator(const PassiveLogCollector::Entry& a, |
| 55 const PassiveLogCollector::Entry& b) { |
| 56 return a.order < b.order; |
| 57 } |
| 58 |
| 43 } // namespace | 59 } // namespace |
| 44 | 60 |
| 45 //---------------------------------------------------------------------------- | 61 //---------------------------------------------------------------------------- |
| 46 // PassiveLogCollector | 62 // PassiveLogCollector |
| 47 //---------------------------------------------------------------------------- | 63 //---------------------------------------------------------------------------- |
| 48 | 64 |
| 49 PassiveLogCollector::PassiveLogCollector() | 65 PassiveLogCollector::PassiveLogCollector() |
| 50 : url_request_tracker_(&connect_job_tracker_), | 66 : url_request_tracker_(&connect_job_tracker_), |
| 51 socket_stream_tracker_(&connect_job_tracker_) { | 67 socket_stream_tracker_(&connect_job_tracker_), |
| 68 num_events_seen_(0) { |
| 52 } | 69 } |
| 53 | 70 |
| 54 PassiveLogCollector::~PassiveLogCollector() { | 71 PassiveLogCollector::~PassiveLogCollector() { |
| 55 } | 72 } |
| 56 | 73 |
| 57 void PassiveLogCollector::OnAddEntry( | 74 void PassiveLogCollector::OnAddEntry( |
| 58 net::NetLog::EventType type, | 75 net::NetLog::EventType type, |
| 59 const base::TimeTicks& time, | 76 const base::TimeTicks& time, |
| 60 const net::NetLog::Source& source, | 77 const net::NetLog::Source& source, |
| 61 net::NetLog::EventPhase phase, | 78 net::NetLog::EventPhase phase, |
| 62 net::NetLog::EventParameters* extra_parameters) { | 79 net::NetLog::EventParameters* extra_parameters) { |
| 63 // Package the parameters into a single struct for convenience. | 80 // Package the parameters into a single struct for convenience. |
| 64 net::CapturingNetLog::Entry entry(type, time, source, phase, | 81 Entry entry(num_events_seen_++, type, time, source, phase, extra_parameters); |
| 65 extra_parameters); | |
| 66 | 82 |
| 67 switch (entry.source.type) { | 83 switch (entry.source.type) { |
| 68 case net::NetLog::SOURCE_URL_REQUEST: | 84 case net::NetLog::SOURCE_URL_REQUEST: |
| 69 url_request_tracker_.OnAddEntry(entry); | 85 url_request_tracker_.OnAddEntry(entry); |
| 70 break; | 86 break; |
| 71 case net::NetLog::SOURCE_SOCKET_STREAM: | 87 case net::NetLog::SOURCE_SOCKET_STREAM: |
| 72 socket_stream_tracker_.OnAddEntry(entry); | 88 socket_stream_tracker_.OnAddEntry(entry); |
| 73 break; | 89 break; |
| 74 case net::NetLog::SOURCE_CONNECT_JOB: | 90 case net::NetLog::SOURCE_CONNECT_JOB: |
| 75 connect_job_tracker_.OnAddEntry(entry); | 91 connect_job_tracker_.OnAddEntry(entry); |
| 76 break; | 92 break; |
| 77 case net::NetLog::SOURCE_INIT_PROXY_RESOLVER: | 93 case net::NetLog::SOURCE_INIT_PROXY_RESOLVER: |
| 78 init_proxy_resolver_tracker_.OnAddEntry(entry); | 94 init_proxy_resolver_tracker_.OnAddEntry(entry); |
| 79 break; | 95 break; |
| 80 default: | 96 default: |
| 81 // Drop all other logged events. | 97 // Drop all other logged events. |
| 82 break; | 98 break; |
| 83 } | 99 } |
| 84 } | 100 } |
| 85 | 101 |
| 86 void PassiveLogCollector::Clear() { | 102 void PassiveLogCollector::Clear() { |
| 87 connect_job_tracker_.Clear(); | 103 connect_job_tracker_.Clear(); |
| 88 url_request_tracker_.Clear(); | 104 url_request_tracker_.Clear(); |
| 89 socket_stream_tracker_.Clear(); | 105 socket_stream_tracker_.Clear(); |
| 90 } | 106 } |
| 91 | 107 |
| 108 void PassiveLogCollector::GetAllCapturedEvents(EntryList* out) const { |
| 109 out->clear(); |
| 110 |
| 111 // Append all of the captured entries held by the various trackers to |
| 112 // |out|. |
| 113 socket_stream_tracker_.AppendAllEntries(out); |
| 114 url_request_tracker_.AppendAllEntries(out); |
| 115 |
| 116 const EntryList& proxy_entries = |
| 117 init_proxy_resolver_tracker_.entries(); |
| 118 out->insert(out->end(), proxy_entries.begin(), proxy_entries.end()); |
| 119 |
| 120 // Now sort the list of entries by their insertion time (ascending). |
| 121 std::sort(out->begin(), out->end(), &SortByOrderComparator); |
| 122 } |
| 123 |
| 92 //---------------------------------------------------------------------------- | 124 //---------------------------------------------------------------------------- |
| 93 // RequestTrackerBase | 125 // RequestTrackerBase |
| 94 //---------------------------------------------------------------------------- | 126 //---------------------------------------------------------------------------- |
| 95 | 127 |
| 96 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase( | 128 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase( |
| 97 size_t max_graveyard_size) | 129 size_t max_graveyard_size) |
| 98 : max_graveyard_size_(max_graveyard_size), | 130 : max_graveyard_size_(max_graveyard_size), |
| 99 next_graveyard_index_(0), | 131 next_graveyard_index_(0), |
| 100 is_unbounded_(false) { | 132 is_unbounded_(false) { |
| 101 } | 133 } |
| 102 | 134 |
| 103 void PassiveLogCollector::RequestTrackerBase::OnAddEntry( | 135 void PassiveLogCollector::RequestTrackerBase::OnAddEntry(const Entry& entry) { |
| 104 const net::CapturingNetLog::Entry& entry) { | |
| 105 RequestInfo& info = live_requests_[entry.source.id]; | 136 RequestInfo& info = live_requests_[entry.source.id]; |
| 106 Action result = DoAddEntry(entry, &info); | 137 Action result = DoAddEntry(entry, &info); |
| 107 | 138 |
| 108 switch (result) { | 139 switch (result) { |
| 109 case ACTION_MOVE_TO_GRAVEYARD: | 140 case ACTION_MOVE_TO_GRAVEYARD: |
| 110 InsertIntoGraveyard(info); | 141 InsertIntoGraveyard(info); |
| 111 // (fall-through) | 142 // (fall-through) |
| 112 case ACTION_DELETE: | 143 case ACTION_DELETE: |
| 113 RemoveFromLiveRequests(entry.source.id); | 144 RemoveFromLiveRequests(entry.source.id); |
| 114 break; | 145 break; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 ClearRecentlyDeceased(); | 223 ClearRecentlyDeceased(); |
| 193 | 224 |
| 194 is_unbounded_ = unbounded; | 225 is_unbounded_ = unbounded; |
| 195 } | 226 } |
| 196 | 227 |
| 197 void PassiveLogCollector::RequestTrackerBase::Clear() { | 228 void PassiveLogCollector::RequestTrackerBase::Clear() { |
| 198 ClearRecentlyDeceased(); | 229 ClearRecentlyDeceased(); |
| 199 live_requests_.clear(); | 230 live_requests_.clear(); |
| 200 } | 231 } |
| 201 | 232 |
| 233 void PassiveLogCollector::RequestTrackerBase::AppendAllEntries( |
| 234 EntryList* out) const { |
| 235 AppendAllEntriesFromRequests(GetLiveRequests(), out); |
| 236 AppendAllEntriesFromRequests(GetRecentlyDeceased(), out); |
| 237 } |
| 238 |
| 202 void PassiveLogCollector::RequestTrackerBase::InsertIntoGraveyard( | 239 void PassiveLogCollector::RequestTrackerBase::InsertIntoGraveyard( |
| 203 const RequestInfo& info) { | 240 const RequestInfo& info) { |
| 204 if (is_unbounded_) { | 241 if (is_unbounded_) { |
| 205 graveyard_.push_back(info); | 242 graveyard_.push_back(info); |
| 206 return; | 243 return; |
| 207 } | 244 } |
| 208 | 245 |
| 209 // Otherwise enforce a bound on the graveyard size, by treating it as a | 246 // Otherwise enforce a bound on the graveyard size, by treating it as a |
| 210 // circular buffer. | 247 // circular buffer. |
| 211 if (graveyard_.size() < max_graveyard_size_) { | 248 if (graveyard_.size() < max_graveyard_size_) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 223 // ConnectJobTracker | 260 // ConnectJobTracker |
| 224 //---------------------------------------------------------------------------- | 261 //---------------------------------------------------------------------------- |
| 225 | 262 |
| 226 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 3; | 263 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 3; |
| 227 | 264 |
| 228 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker() | 265 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker() |
| 229 : RequestTrackerBase(kMaxGraveyardSize) { | 266 : RequestTrackerBase(kMaxGraveyardSize) { |
| 230 } | 267 } |
| 231 | 268 |
| 232 PassiveLogCollector::RequestTrackerBase::Action | 269 PassiveLogCollector::RequestTrackerBase::Action |
| 233 PassiveLogCollector::ConnectJobTracker::DoAddEntry( | 270 PassiveLogCollector::ConnectJobTracker::DoAddEntry(const Entry& entry, |
| 234 const net::CapturingNetLog::Entry& entry, | 271 RequestInfo* out_info) { |
| 235 RequestInfo* out_info) { | |
| 236 // Save the entry (possibly truncating). | 272 // Save the entry (possibly truncating). |
| 237 AddEntryToRequestInfo(entry, is_unbounded(), out_info); | 273 AddEntryToRequestInfo(entry, is_unbounded(), out_info); |
| 238 | 274 |
| 239 // If this is the end of the connect job, move the request to the graveyard. | 275 // If this is the end of the connect job, move the request to the graveyard. |
| 240 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB && | 276 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB && |
| 241 entry.phase == net::NetLog::PHASE_END) { | 277 entry.phase == net::NetLog::PHASE_END) { |
| 242 return ACTION_MOVE_TO_GRAVEYARD; | 278 return ACTION_MOVE_TO_GRAVEYARD; |
| 243 } | 279 } |
| 244 | 280 |
| 245 return ACTION_NONE; | 281 return ACTION_NONE; |
| 246 } | 282 } |
| 247 | 283 |
| 248 //---------------------------------------------------------------------------- | 284 //---------------------------------------------------------------------------- |
| 249 // RequestTracker | 285 // RequestTracker |
| 250 //---------------------------------------------------------------------------- | 286 //---------------------------------------------------------------------------- |
| 251 | 287 |
| 252 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25; | 288 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25; |
| 253 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardURLSize = 1000; | 289 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardURLSize = 1000; |
| 254 | 290 |
| 255 PassiveLogCollector::RequestTracker::RequestTracker( | 291 PassiveLogCollector::RequestTracker::RequestTracker( |
| 256 ConnectJobTracker* connect_job_tracker) | 292 ConnectJobTracker* connect_job_tracker) |
| 257 : RequestTrackerBase(kMaxGraveyardSize), | 293 : RequestTrackerBase(kMaxGraveyardSize), |
| 258 connect_job_tracker_(connect_job_tracker) { | 294 connect_job_tracker_(connect_job_tracker) { |
| 259 } | 295 } |
| 260 | 296 |
| 261 PassiveLogCollector::RequestTrackerBase::Action | 297 PassiveLogCollector::RequestTrackerBase::Action |
| 262 PassiveLogCollector::RequestTracker::DoAddEntry( | 298 PassiveLogCollector::RequestTracker::DoAddEntry(const Entry& entry, |
| 263 const net::CapturingNetLog::Entry& entry, | 299 RequestInfo* out_info) { |
| 264 RequestInfo* out_info) { | |
| 265 | 300 |
| 266 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) { | 301 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) { |
| 267 // If this was notification that a ConnectJob was bound to the request, | 302 // If this was notification that a ConnectJob was bound to the request, |
| 268 // copy all the logged data for that ConnectJob. | 303 // copy all the logged data for that ConnectJob. |
| 269 AddConnectJobInfo(entry, out_info); | 304 AddConnectJobInfo(entry, out_info); |
| 270 } else { | 305 } else { |
| 271 // Otherwise just append this entry to the request info. | 306 // Otherwise just append this entry to the request info. |
| 272 AddEntryToRequestInfo(entry, is_unbounded(), out_info); | 307 AddEntryToRequestInfo(entry, is_unbounded(), out_info); |
| 273 } | 308 } |
| 274 | 309 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 291 // adds to clutter. | 326 // adds to clutter. |
| 292 return ACTION_DELETE; | 327 return ACTION_DELETE; |
| 293 } | 328 } |
| 294 return ACTION_MOVE_TO_GRAVEYARD; | 329 return ACTION_MOVE_TO_GRAVEYARD; |
| 295 } | 330 } |
| 296 | 331 |
| 297 return ACTION_NONE; | 332 return ACTION_NONE; |
| 298 } | 333 } |
| 299 | 334 |
| 300 void PassiveLogCollector::RequestTracker::AddConnectJobInfo( | 335 void PassiveLogCollector::RequestTracker::AddConnectJobInfo( |
| 301 const net::CapturingNetLog::Entry& entry, | 336 const Entry& entry, |
| 302 RequestInfo* live_entry) { | 337 RequestInfo* live_entry) { |
| 303 // We have just been notified of which ConnectJob the | 338 // We have just been notified of which ConnectJob the |
| 304 // URLRequest/SocketStream was assigned. Lookup all the data we captured | 339 // URLRequest/SocketStream was assigned. Lookup all the data we captured |
| 305 // for the ConnectJob, and append it to the URLRequest/SocketStream's | 340 // for the ConnectJob, and append it to the URLRequest/SocketStream's |
| 306 // RequestInfo. | 341 // RequestInfo. |
| 307 | 342 |
| 308 int connect_job_id = static_cast<net::NetLogIntegerParameter*>( | 343 int connect_job_id = static_cast<net::NetLogIntegerParameter*>( |
| 309 entry.extra_parameters.get())->value(); | 344 entry.extra_parameters.get())->value(); |
| 310 | 345 |
| 311 const RequestInfo* connect_job_info = | 346 const RequestInfo* connect_job_info = |
| 312 connect_job_tracker_->GetRequestInfoFromGraveyard(connect_job_id); | 347 connect_job_tracker_->GetRequestInfoFromGraveyard(connect_job_id); |
| 313 | 348 |
| 314 if (connect_job_info) { | 349 if (connect_job_info) { |
| 315 // Append the ConnectJob information we found. | 350 // Append the ConnectJob information we found. |
| 316 AppendToRequestInfo(*connect_job_info, is_unbounded(), live_entry); | 351 AppendToRequestInfo(*connect_job_info, is_unbounded(), live_entry); |
| 317 } else { | 352 } else { |
| 318 // If we couldn't find the information for the ConnectJob, append a | 353 // If we couldn't find the information for the ConnectJob, append a |
| 319 // generic message instead. | 354 // generic message instead. |
| 320 net::CapturingNetLog::Entry e(entry); | 355 Entry e(entry); |
| 321 e.type = net::NetLog::TYPE_TODO_STRING; | 356 e.type = net::NetLog::TYPE_TODO_STRING; |
| 322 e.extra_parameters = new net::NetLogStringParameter( | 357 e.extra_parameters = new net::NetLogStringParameter( |
| 323 StringPrintf("Used ConnectJob id=%d", connect_job_id)); | 358 StringPrintf("Used ConnectJob id=%d", connect_job_id)); |
| 324 AddEntryToRequestInfo(e, is_unbounded(), live_entry); | 359 AddEntryToRequestInfo(e, is_unbounded(), live_entry); |
| 325 } | 360 } |
| 326 } | 361 } |
| 327 | 362 |
| 328 //---------------------------------------------------------------------------- | 363 //---------------------------------------------------------------------------- |
| 329 // InitProxyResolverTracker | 364 // InitProxyResolverTracker |
| 330 //---------------------------------------------------------------------------- | 365 //---------------------------------------------------------------------------- |
| 331 | 366 |
| 332 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker() {} | 367 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker() {} |
| 333 | 368 |
| 334 void PassiveLogCollector::InitProxyResolverTracker::OnAddEntry( | 369 void PassiveLogCollector::InitProxyResolverTracker::OnAddEntry( |
| 335 const net::CapturingNetLog::Entry& entry) { | 370 const Entry& entry) { |
| 336 if (entry.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER && | 371 if (entry.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER && |
| 337 entry.phase == net::NetLog::PHASE_BEGIN) { | 372 entry.phase == net::NetLog::PHASE_BEGIN) { |
| 338 // If this is the start of a new InitProxyResolver, overwrite the old data. | 373 // If this is the start of a new InitProxyResolver, overwrite the old data. |
| 339 entries_.clear(); | 374 entries_.clear(); |
| 340 entries_.push_back(entry); | 375 entries_.push_back(entry); |
| 341 } else { | 376 } else { |
| 342 // Otherwise append it to the log for the latest InitProxyResolver. | 377 // Otherwise append it to the log for the latest InitProxyResolver. |
| 343 if (!entries_.empty() && entries_[0].source.id != entry.source.id) { | 378 if (!entries_.empty() && entries_[0].source.id != entry.source.id) { |
| 344 // If this entry doesn't match what we think was the latest | 379 // If this entry doesn't match what we think was the latest |
| 345 // InitProxyResolver, drop it. (This shouldn't happen, but we will guard | 380 // InitProxyResolver, drop it. (This shouldn't happen, but we will guard |
| 346 // against it). | 381 // against it). |
| 347 return; | 382 return; |
| 348 } | 383 } |
| 349 entries_.push_back(entry); | 384 entries_.push_back(entry); |
| 350 } | 385 } |
| 351 | 386 |
| 352 // Safety net: INIT_PROXY_RESOLVER shouldn't generate many messages, but in | 387 // Safety net: INIT_PROXY_RESOLVER shouldn't generate many messages, but in |
| 353 // case something goes wrong, avoid exploding the memory usage. | 388 // case something goes wrong, avoid exploding the memory usage. |
| 354 if (entries_.size() > kMaxNumEntriesPerLog) | 389 if (entries_.size() > kMaxNumEntriesPerLog) |
| 355 entries_.clear(); | 390 entries_.clear(); |
| 356 } | 391 } |
| 357 | 392 |
| OLD | NEW |