| 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::NetLog::Entry& entry, | 24 void AddEntryToRequestInfo(const net::CapturingNetLog::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 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 47 //---------------------------------------------------------------------------- | 47 //---------------------------------------------------------------------------- |
| 48 | 48 |
| 49 PassiveLogCollector::PassiveLogCollector() | 49 PassiveLogCollector::PassiveLogCollector() |
| 50 : url_request_tracker_(&connect_job_tracker_), | 50 : url_request_tracker_(&connect_job_tracker_), |
| 51 socket_stream_tracker_(&connect_job_tracker_) { | 51 socket_stream_tracker_(&connect_job_tracker_) { |
| 52 } | 52 } |
| 53 | 53 |
| 54 PassiveLogCollector::~PassiveLogCollector() { | 54 PassiveLogCollector::~PassiveLogCollector() { |
| 55 } | 55 } |
| 56 | 56 |
| 57 void PassiveLogCollector::OnAddEntry(const net::NetLog::Entry& entry) { | 57 void PassiveLogCollector::OnAddEntry( |
| 58 net::NetLog::EventType type, |
| 59 const base::TimeTicks& time, |
| 60 const net::NetLog::Source& source, |
| 61 net::NetLog::EventPhase phase, |
| 62 net::NetLog::EventParameters* extra_parameters) { |
| 63 // Package the parameters into a single struct for convenience. |
| 64 net::CapturingNetLog::Entry entry(type, time, source, phase, |
| 65 extra_parameters); |
| 66 |
| 58 switch (entry.source.type) { | 67 switch (entry.source.type) { |
| 59 case net::NetLog::SOURCE_URL_REQUEST: | 68 case net::NetLog::SOURCE_URL_REQUEST: |
| 60 url_request_tracker_.OnAddEntry(entry); | 69 url_request_tracker_.OnAddEntry(entry); |
| 61 break; | 70 break; |
| 62 case net::NetLog::SOURCE_SOCKET_STREAM: | 71 case net::NetLog::SOURCE_SOCKET_STREAM: |
| 63 socket_stream_tracker_.OnAddEntry(entry); | 72 socket_stream_tracker_.OnAddEntry(entry); |
| 64 break; | 73 break; |
| 65 case net::NetLog::SOURCE_CONNECT_JOB: | 74 case net::NetLog::SOURCE_CONNECT_JOB: |
| 66 connect_job_tracker_.OnAddEntry(entry); | 75 connect_job_tracker_.OnAddEntry(entry); |
| 67 break; | 76 break; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 85 //---------------------------------------------------------------------------- | 94 //---------------------------------------------------------------------------- |
| 86 | 95 |
| 87 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase( | 96 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase( |
| 88 size_t max_graveyard_size) | 97 size_t max_graveyard_size) |
| 89 : max_graveyard_size_(max_graveyard_size), | 98 : max_graveyard_size_(max_graveyard_size), |
| 90 next_graveyard_index_(0), | 99 next_graveyard_index_(0), |
| 91 is_unbounded_(false) { | 100 is_unbounded_(false) { |
| 92 } | 101 } |
| 93 | 102 |
| 94 void PassiveLogCollector::RequestTrackerBase::OnAddEntry( | 103 void PassiveLogCollector::RequestTrackerBase::OnAddEntry( |
| 95 const net::NetLog::Entry& entry) { | 104 const net::CapturingNetLog::Entry& entry) { |
| 96 RequestInfo& info = live_requests_[entry.source.id]; | 105 RequestInfo& info = live_requests_[entry.source.id]; |
| 97 Action result = DoAddEntry(entry, &info); | 106 Action result = DoAddEntry(entry, &info); |
| 98 | 107 |
| 99 switch (result) { | 108 switch (result) { |
| 100 case ACTION_MOVE_TO_GRAVEYARD: | 109 case ACTION_MOVE_TO_GRAVEYARD: |
| 101 InsertIntoGraveyard(info); | 110 InsertIntoGraveyard(info); |
| 102 // (fall-through) | 111 // (fall-through) |
| 103 case ACTION_DELETE: | 112 case ACTION_DELETE: |
| 104 RemoveFromLiveRequests(entry.source.id); | 113 RemoveFromLiveRequests(entry.source.id); |
| 105 break; | 114 break; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 //---------------------------------------------------------------------------- | 224 //---------------------------------------------------------------------------- |
| 216 | 225 |
| 217 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 3; | 226 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 3; |
| 218 | 227 |
| 219 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker() | 228 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker() |
| 220 : RequestTrackerBase(kMaxGraveyardSize) { | 229 : RequestTrackerBase(kMaxGraveyardSize) { |
| 221 } | 230 } |
| 222 | 231 |
| 223 PassiveLogCollector::RequestTrackerBase::Action | 232 PassiveLogCollector::RequestTrackerBase::Action |
| 224 PassiveLogCollector::ConnectJobTracker::DoAddEntry( | 233 PassiveLogCollector::ConnectJobTracker::DoAddEntry( |
| 225 const net::NetLog::Entry& entry, | 234 const net::CapturingNetLog::Entry& entry, |
| 226 RequestInfo* out_info) { | 235 RequestInfo* out_info) { |
| 227 // Save the entry (possibly truncating). | 236 // Save the entry (possibly truncating). |
| 228 AddEntryToRequestInfo(entry, is_unbounded(), out_info); | 237 AddEntryToRequestInfo(entry, is_unbounded(), out_info); |
| 229 | 238 |
| 230 // If this is the end of the connect job, move the request to the graveyard. | 239 // If this is the end of the connect job, move the request to the graveyard. |
| 231 if (entry.type == net::NetLog::Entry::TYPE_EVENT && | 240 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB && |
| 232 entry.event.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB && | 241 entry.phase == net::NetLog::PHASE_END) { |
| 233 entry.event.phase == net::NetLog::PHASE_END) { | |
| 234 return ACTION_MOVE_TO_GRAVEYARD; | 242 return ACTION_MOVE_TO_GRAVEYARD; |
| 235 } | 243 } |
| 236 | 244 |
| 237 return ACTION_NONE; | 245 return ACTION_NONE; |
| 238 } | 246 } |
| 239 | 247 |
| 240 //---------------------------------------------------------------------------- | 248 //---------------------------------------------------------------------------- |
| 241 // RequestTracker | 249 // RequestTracker |
| 242 //---------------------------------------------------------------------------- | 250 //---------------------------------------------------------------------------- |
| 243 | 251 |
| 244 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25; | 252 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25; |
| 245 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardURLSize = 1000; | 253 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardURLSize = 1000; |
| 246 | 254 |
| 247 PassiveLogCollector::RequestTracker::RequestTracker( | 255 PassiveLogCollector::RequestTracker::RequestTracker( |
| 248 ConnectJobTracker* connect_job_tracker) | 256 ConnectJobTracker* connect_job_tracker) |
| 249 : RequestTrackerBase(kMaxGraveyardSize), | 257 : RequestTrackerBase(kMaxGraveyardSize), |
| 250 connect_job_tracker_(connect_job_tracker) { | 258 connect_job_tracker_(connect_job_tracker) { |
| 251 } | 259 } |
| 252 | 260 |
| 253 PassiveLogCollector::RequestTrackerBase::Action | 261 PassiveLogCollector::RequestTrackerBase::Action |
| 254 PassiveLogCollector::RequestTracker::DoAddEntry( | 262 PassiveLogCollector::RequestTracker::DoAddEntry( |
| 255 const net::NetLog::Entry& entry, | 263 const net::CapturingNetLog::Entry& entry, |
| 256 RequestInfo* out_info) { | 264 RequestInfo* out_info) { |
| 257 | 265 |
| 258 if (entry.type == net::NetLog::Entry::TYPE_EVENT && | 266 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) { |
| 259 entry.event.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) { | |
| 260 // If this was notification that a ConnectJob was bound to the request, | 267 // If this was notification that a ConnectJob was bound to the request, |
| 261 // copy all the logged data for that ConnectJob. | 268 // copy all the logged data for that ConnectJob. |
| 262 AddConnectJobInfo(entry, out_info); | 269 AddConnectJobInfo(entry, out_info); |
| 263 } else { | 270 } else { |
| 264 // Otherwise just append this entry to the request info. | 271 // Otherwise just append this entry to the request info. |
| 265 AddEntryToRequestInfo(entry, is_unbounded(), out_info); | 272 AddEntryToRequestInfo(entry, is_unbounded(), out_info); |
| 266 } | 273 } |
| 267 | 274 |
| 268 // If this was the start of a URLRequest/SocketStream, extract the URL. | 275 // If this was the start of a URLRequest/SocketStream, extract the URL. |
| 269 if (out_info->entries.size() == 1 && | 276 // Note: we look at the first *two* entries, since the outer REQUEST_ALIVE |
| 270 entry.type == net::NetLog::Entry::TYPE_EVENT && | 277 // doesn't actually contain any data. |
| 271 entry.event.type == net::NetLog::TYPE_REQUEST_ALIVE && | 278 if (out_info->url.empty() && out_info->entries.size() <= 2 && |
| 272 entry.event.phase == net::NetLog::PHASE_BEGIN) { | 279 entry.phase == net::NetLog::PHASE_BEGIN && entry.extra_parameters && |
| 273 out_info->url = entry.string; | 280 (entry.type == net::NetLog::TYPE_URL_REQUEST_START || |
| 274 out_info->entries[0].string = std::string(); | 281 entry.type == net::NetLog::TYPE_SOCKET_STREAM_CONNECT)) { |
| 275 | 282 out_info->url = static_cast<net::NetLogStringParameter*>( |
| 276 // Paranoia check: truncate the URL if it is really big. | 283 entry.extra_parameters.get())->value(); |
| 277 if (out_info->url.size() > kMaxGraveyardURLSize) | |
| 278 out_info->url = out_info->url.substr(0, kMaxGraveyardURLSize); | |
| 279 } | 284 } |
| 280 | 285 |
| 281 // If the request has ended, move it to the graveyard. | 286 // If the request has ended, move it to the graveyard. |
| 282 if (entry.type == net::NetLog::Entry::TYPE_EVENT && | 287 if (entry.type == net::NetLog::TYPE_REQUEST_ALIVE && |
| 283 entry.event.type == net::NetLog::TYPE_REQUEST_ALIVE && | 288 entry.phase == net::NetLog::PHASE_END) { |
| 284 entry.event.phase == net::NetLog::PHASE_END) { | |
| 285 if (StartsWithASCII(out_info->url, "chrome://", false)) { | 289 if (StartsWithASCII(out_info->url, "chrome://", false)) { |
| 286 // Avoid sending "chrome://" requests to the graveyard, since it just | 290 // Avoid sending "chrome://" requests to the graveyard, since it just |
| 287 // adds to clutter. | 291 // adds to clutter. |
| 288 return ACTION_DELETE; | 292 return ACTION_DELETE; |
| 289 } | 293 } |
| 290 return ACTION_MOVE_TO_GRAVEYARD; | 294 return ACTION_MOVE_TO_GRAVEYARD; |
| 291 } | 295 } |
| 292 | 296 |
| 293 return ACTION_NONE; | 297 return ACTION_NONE; |
| 294 } | 298 } |
| 295 | 299 |
| 296 void PassiveLogCollector::RequestTracker::AddConnectJobInfo( | 300 void PassiveLogCollector::RequestTracker::AddConnectJobInfo( |
| 297 const net::NetLog::Entry& entry, | 301 const net::CapturingNetLog::Entry& entry, |
| 298 RequestInfo* live_entry) { | 302 RequestInfo* live_entry) { |
| 299 // We have just been notified of which ConnectJob the | 303 // We have just been notified of which ConnectJob the |
| 300 // URLRequest/SocketStream was assigned. Lookup all the data we captured | 304 // URLRequest/SocketStream was assigned. Lookup all the data we captured |
| 301 // for the ConnectJob, and append it to the URLRequest/SocketStream's | 305 // for the ConnectJob, and append it to the URLRequest/SocketStream's |
| 302 // RequestInfo. | 306 // RequestInfo. |
| 303 | 307 |
| 304 // TODO(eroman): This should NOT be plumbed through via |error_code| ! | 308 int connect_job_id = static_cast<net::NetLogIntegerParameter*>( |
| 305 int connect_job_id = entry.error_code; | 309 entry.extra_parameters.get())->value(); |
| 306 | 310 |
| 307 const RequestInfo* connect_job_info = | 311 const RequestInfo* connect_job_info = |
| 308 connect_job_tracker_->GetRequestInfoFromGraveyard(connect_job_id); | 312 connect_job_tracker_->GetRequestInfoFromGraveyard(connect_job_id); |
| 309 | 313 |
| 310 if (connect_job_info) { | 314 if (connect_job_info) { |
| 311 // Append the ConnectJob information we found. | 315 // Append the ConnectJob information we found. |
| 312 AppendToRequestInfo(*connect_job_info, is_unbounded(), live_entry); | 316 AppendToRequestInfo(*connect_job_info, is_unbounded(), live_entry); |
| 313 } else { | 317 } else { |
| 314 // If we couldn't find the information for the ConnectJob, append a | 318 // If we couldn't find the information for the ConnectJob, append a |
| 315 // generic message instead. | 319 // generic message instead. |
| 316 net::NetLog::Entry e(entry); | 320 net::CapturingNetLog::Entry e(entry); |
| 317 e.type = net::NetLog::Entry::TYPE_STRING; | 321 e.type = net::NetLog::TYPE_TODO_STRING; |
| 318 e.string = StringPrintf("Used ConnectJob id=%d", connect_job_id); | 322 e.extra_parameters = new net::NetLogStringParameter( |
| 323 StringPrintf("Used ConnectJob id=%d", connect_job_id)); |
| 319 AddEntryToRequestInfo(e, is_unbounded(), live_entry); | 324 AddEntryToRequestInfo(e, is_unbounded(), live_entry); |
| 320 } | 325 } |
| 321 } | 326 } |
| 322 | 327 |
| 323 //---------------------------------------------------------------------------- | 328 //---------------------------------------------------------------------------- |
| 324 // InitProxyResolverTracker | 329 // InitProxyResolverTracker |
| 325 //---------------------------------------------------------------------------- | 330 //---------------------------------------------------------------------------- |
| 326 | 331 |
| 327 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker() {} | 332 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker() {} |
| 328 | 333 |
| 329 void PassiveLogCollector::InitProxyResolverTracker::OnAddEntry( | 334 void PassiveLogCollector::InitProxyResolverTracker::OnAddEntry( |
| 330 const net::NetLog::Entry& entry) { | 335 const net::CapturingNetLog::Entry& entry) { |
| 331 if (entry.type == net::NetLog::Entry::TYPE_EVENT && | 336 if (entry.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER && |
| 332 entry.event.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER && | 337 entry.phase == net::NetLog::PHASE_BEGIN) { |
| 333 entry.event.phase == net::NetLog::PHASE_BEGIN) { | |
| 334 // If this is the start of a new InitProxyResolver, overwrite the old data. | 338 // If this is the start of a new InitProxyResolver, overwrite the old data. |
| 335 entries_.clear(); | 339 entries_.clear(); |
| 336 entries_.push_back(entry); | 340 entries_.push_back(entry); |
| 337 } else { | 341 } else { |
| 338 // Otherwise append it to the log for the latest InitProxyResolver. | 342 // Otherwise append it to the log for the latest InitProxyResolver. |
| 339 if (!entries_.empty() && entries_[0].source.id != entry.source.id) { | 343 if (!entries_.empty() && entries_[0].source.id != entry.source.id) { |
| 340 // If this entry doesn't match what we think was the latest | 344 // If this entry doesn't match what we think was the latest |
| 341 // InitProxyResolver, drop it. (This shouldn't happen, but we will guard | 345 // InitProxyResolver, drop it. (This shouldn't happen, but we will guard |
| 342 // against it). | 346 // against it). |
| 343 return; | 347 return; |
| 344 } | 348 } |
| 345 entries_.push_back(entry); | 349 entries_.push_back(entry); |
| 346 } | 350 } |
| 347 | 351 |
| 348 // Safety net: INIT_PROXY_RESOLVER shouldn't generate many messages, but in | 352 // Safety net: INIT_PROXY_RESOLVER shouldn't generate many messages, but in |
| 349 // case something goes wrong, avoid exploding the memory usage. | 353 // case something goes wrong, avoid exploding the memory usage. |
| 350 if (entries_.size() > kMaxNumEntriesPerLog) | 354 if (entries_.size() > kMaxNumEntriesPerLog) |
| 351 entries_.clear(); | 355 entries_.clear(); |
| 352 } | 356 } |
| 353 | 357 |
| OLD | NEW |