Index: chrome/browser/net/load_timing_observer.cc |
=================================================================== |
--- chrome/browser/net/load_timing_observer.cc (revision 190428) |
+++ chrome/browser/net/load_timing_observer.cc (working copy) |
@@ -1,401 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/net/load_timing_observer.h" |
- |
-#include "base/time.h" |
-#include "chrome/browser/net/chrome_net_log.h" |
-#include "content/public/common/resource_response.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "net/base/load_flags.h" |
-#include "net/url_request/url_request.h" |
-#include "net/url_request/url_request_netlog_params.h" |
- |
-using base::Time; |
-using base::TimeTicks; |
-using content::BrowserThread; |
-using webkit_glue::ResourceLoaderBridge; |
-using webkit_glue::ResourceLoadTimingInfo; |
- |
-const size_t kMaxNumEntries = 1000; |
- |
-namespace { |
- |
-const int64 kSyncPeriodMicroseconds = 1000 * 1000 * 10; |
- |
-// We know that this conversion is not solid and suffers from world clock |
-// changes, but given that we sync clock every 10 seconds, it should be good |
-// enough for the load timing info. |
-static Time TimeTicksToTime(const TimeTicks& time_ticks) { |
- static int64 tick_to_time_offset; |
- static int64 last_sync_ticks = 0; |
- if (time_ticks.ToInternalValue() - last_sync_ticks > |
- kSyncPeriodMicroseconds) { |
- int64 cur_time = (Time::Now() - Time()).InMicroseconds(); |
- int64 cur_time_ticks = (TimeTicks::Now() - TimeTicks()).InMicroseconds(); |
- // If we add this number to a time tick value, it gives the timestamp. |
- tick_to_time_offset = cur_time - cur_time_ticks; |
- last_sync_ticks = time_ticks.ToInternalValue(); |
- } |
- return Time::FromInternalValue(time_ticks.ToInternalValue() + |
- tick_to_time_offset); |
-} |
- |
-static int32 TimeTicksToOffset( |
- const TimeTicks& time_ticks, |
- LoadTimingObserver::URLRequestRecord* record) { |
- return static_cast<int32>( |
- (time_ticks - record->base_ticks).InMillisecondsRoundedUp()); |
-} |
- |
-} // namespace |
- |
-LoadTimingObserver::URLRequestRecord::URLRequestRecord() |
- : connect_job_id(net::NetLog::Source::kInvalidId), |
- socket_log_id(net::NetLog::Source::kInvalidId), |
- socket_reused(false) { |
-} |
- |
-LoadTimingObserver::HTTPStreamJobRecord::HTTPStreamJobRecord() |
- : socket_log_id(net::NetLog::Source::kInvalidId), |
- socket_reused(false) { |
-} |
- |
-LoadTimingObserver::LoadTimingObserver() |
- : last_connect_job_id_(net::NetLog::Source::kInvalidId) { |
-} |
- |
-LoadTimingObserver::~LoadTimingObserver() { |
-} |
- |
-void LoadTimingObserver::StartObserving(net::NetLog* net_log) { |
- net_log->AddThreadSafeObserver(this, net::NetLog::LOG_BASIC); |
-} |
- |
-LoadTimingObserver::URLRequestRecord* |
-LoadTimingObserver::GetURLRequestRecord(uint32 source_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- |
- URLRequestToRecordMap::iterator it = url_request_to_record_.find(source_id); |
- if (it != url_request_to_record_.end()) |
- return &it->second; |
- return NULL; |
-} |
- |
-void LoadTimingObserver::OnAddEntry(const net::NetLog::Entry& entry) { |
- // The events that the Observer is interested in only occur on the IO thread. |
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) |
- return; |
- if (entry.source().type == net::NetLog::SOURCE_URL_REQUEST) |
- OnAddURLRequestEntry(entry); |
- else if (entry.source().type == net::NetLog::SOURCE_HTTP_STREAM_JOB) |
- OnAddHTTPStreamJobEntry(entry); |
- else if (entry.source().type == net::NetLog::SOURCE_CONNECT_JOB) |
- OnAddConnectJobEntry(entry); |
- else if (entry.source().type == net::NetLog::SOURCE_SOCKET) |
- OnAddSocketEntry(entry); |
-} |
- |
-// static |
-void LoadTimingObserver::PopulateTimingInfo( |
- net::URLRequest* request, |
- content::ResourceResponse* response) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)) |
- return; |
- |
- ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>( |
- request->net_log().net_log()); |
- if (chrome_net_log == NULL) |
- return; |
- |
- uint32 source_id = request->net_log().source().id; |
- LoadTimingObserver* observer = chrome_net_log->load_timing_observer(); |
- LoadTimingObserver::URLRequestRecord* record = |
- observer->GetURLRequestRecord(source_id); |
- if (record) { |
- response->head.connection_id = record->socket_log_id; |
- response->head.connection_reused = record->socket_reused; |
-#if !defined(OS_IOS) |
- response->head.load_timing = record->timing; |
-#endif |
- } |
-} |
- |
-void LoadTimingObserver::OnAddURLRequestEntry(const net::NetLog::Entry& entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- |
- bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN; |
- bool is_end = entry.phase() == net::NetLog::PHASE_END; |
- |
- if (entry.type() == net::NetLog::TYPE_URL_REQUEST_START_JOB) { |
- if (is_begin) { |
- // Only record timing for entries with corresponding flag. |
- int load_flags; |
- scoped_ptr<Value> event_params(entry.ParametersToValue()); |
- if (!net::StartEventLoadFlagsFromEventParams(event_params.get(), |
- &load_flags)) { |
- NOTREACHED(); |
- return; |
- } |
- |
- if (!(load_flags & net::LOAD_ENABLE_LOAD_TIMING)) |
- return; |
- |
- // Prevents us from passively growing the memory unbounded in case |
- // something went wrong. Should not happen. |
- if (url_request_to_record_.size() > kMaxNumEntries) { |
- LOG(WARNING) << "The load timing observer url request count has grown " |
- "larger than expected, resetting"; |
- url_request_to_record_.clear(); |
- } |
- |
- URLRequestRecord& record = url_request_to_record_[entry.source().id]; |
- base::TimeTicks now = GetCurrentTime(); |
- record.base_ticks = now; |
-#if !defined(OS_IOS) |
- record.timing = ResourceLoadTimingInfo(); |
- record.timing.base_ticks = now; |
- record.timing.base_time = TimeTicksToTime(now); |
-#endif |
- } |
- return; |
- } else if (entry.type() == net::NetLog::TYPE_REQUEST_ALIVE) { |
- // Cleanup records based on the TYPE_REQUEST_ALIVE entry. |
- if (is_end) |
- url_request_to_record_.erase(entry.source().id); |
- return; |
- } |
- |
- URLRequestRecord* record = GetURLRequestRecord(entry.source().id); |
- if (!record) |
- return; |
- |
-#if !defined(OS_IOS) |
- ResourceLoadTimingInfo& timing = record->timing; |
- |
- switch (entry.type()) { |
- case net::NetLog::TYPE_PROXY_SERVICE: |
- if (is_begin) |
- timing.proxy_start = TimeTicksToOffset(GetCurrentTime(), record); |
- else if (is_end) |
- timing.proxy_end = TimeTicksToOffset(GetCurrentTime(), record); |
- break; |
- case net::NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB: { |
- net::NetLog::Source http_stream_job_source; |
- scoped_ptr<Value> event_params(entry.ParametersToValue()); |
- if (!net::NetLog::Source::FromEventParameters( |
- event_params.get(), |
- &http_stream_job_source)) { |
- NOTREACHED(); |
- return; |
- } |
- DCHECK_EQ(net::NetLog::SOURCE_HTTP_STREAM_JOB, |
- http_stream_job_source.type); |
- |
- HTTPStreamJobToRecordMap::iterator it = |
- http_stream_job_to_record_.find(http_stream_job_source.id); |
- if (it == http_stream_job_to_record_.end()) |
- return; |
- if (!it->second.connect_start.is_null()) { |
- timing.connect_start = TimeTicksToOffset(it->second.connect_start, |
- record); |
- } |
- if (!it->second.connect_end.is_null()) |
- timing.connect_end = TimeTicksToOffset(it->second.connect_end, record); |
- if (!it->second.dns_start.is_null()) |
- timing.dns_start = TimeTicksToOffset(it->second.dns_start, record); |
- if (!it->second.dns_end.is_null()) |
- timing.dns_end = TimeTicksToOffset(it->second.dns_end, record); |
- if (!it->second.ssl_start.is_null()) |
- timing.ssl_start = TimeTicksToOffset(it->second.ssl_start, record); |
- if (!it->second.ssl_end.is_null()) |
- timing.ssl_end = TimeTicksToOffset(it->second.ssl_end, record); |
- record->socket_reused = it->second.socket_reused; |
- record->socket_log_id = it->second.socket_log_id; |
- break; |
- } |
- case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST: |
- if (is_begin) |
- timing.send_start = TimeTicksToOffset(GetCurrentTime(), record); |
- else if (is_end) |
- timing.send_end = TimeTicksToOffset(GetCurrentTime(), record); |
- break; |
- case net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS: |
- if (is_begin) { |
- timing.receive_headers_start = |
- TimeTicksToOffset(GetCurrentTime(), record); |
- } else if (is_end) { |
- timing.receive_headers_end = |
- TimeTicksToOffset(GetCurrentTime(), record); |
- } |
- break; |
- default: |
- break; |
- } |
-#endif // !defined(OS_IOS) |
-} |
- |
-void LoadTimingObserver::OnAddHTTPStreamJobEntry( |
- const net::NetLog::Entry& entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- |
- bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN; |
- bool is_end = entry.phase() == net::NetLog::PHASE_END; |
- |
- if (entry.type() == net::NetLog::TYPE_HTTP_STREAM_JOB) { |
- if (is_begin) { |
- // Prevents us from passively growing the memory unbounded in |
- // case something went wrong. Should not happen. |
- if (http_stream_job_to_record_.size() > kMaxNumEntries) { |
- LOG(WARNING) << "The load timing observer http stream job count " |
- "has grown larger than expected, resetting"; |
- http_stream_job_to_record_.clear(); |
- } |
- |
- http_stream_job_to_record_.insert( |
- std::make_pair(entry.source().id, HTTPStreamJobRecord())); |
- } else if (is_end) { |
- http_stream_job_to_record_.erase(entry.source().id); |
- } |
- return; |
- } |
- |
- HTTPStreamJobToRecordMap::iterator it = |
- http_stream_job_to_record_.find(entry.source().id); |
- if (it == http_stream_job_to_record_.end()) |
- return; |
- |
- switch (entry.type()) { |
- case net::NetLog::TYPE_SOCKET_POOL: |
- if (is_begin) |
- it->second.connect_start = GetCurrentTime(); |
- else if (is_end) |
- it->second.connect_end = GetCurrentTime(); |
- break; |
- case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB: { |
- net::NetLog::Source connect_job_source; |
- scoped_ptr<Value> event_params(entry.ParametersToValue()); |
- if (!net::NetLog::Source::FromEventParameters(event_params.get(), |
- &connect_job_source)) { |
- NOTREACHED(); |
- return; |
- } |
- DCHECK_EQ(net::NetLog::SOURCE_CONNECT_JOB, connect_job_source.type); |
- |
- if (last_connect_job_id_ == connect_job_source.id && |
- !last_connect_job_record_.dns_start.is_null()) { |
- it->second.dns_start = last_connect_job_record_.dns_start; |
- it->second.dns_end = last_connect_job_record_.dns_end; |
- } |
- break; |
- } |
- case net::NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET: |
- it->second.socket_reused = true; |
- break; |
- case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET: { |
- net::NetLog::Source socket_source; |
- scoped_ptr<Value> event_params(entry.ParametersToValue()); |
- if (!net::NetLog::Source::FromEventParameters(event_params.get(), |
- &socket_source)) { |
- NOTREACHED(); |
- return; |
- } |
- |
- it->second.socket_log_id = socket_source.id; |
- if (!it->second.socket_reused) { |
- SocketToRecordMap::iterator socket_it = |
- socket_to_record_.find(it->second.socket_log_id); |
- if (socket_it != socket_to_record_.end() && |
- !socket_it->second.ssl_start.is_null()) { |
- it->second.ssl_start = socket_it->second.ssl_start; |
- it->second.ssl_end = socket_it->second.ssl_end; |
- } |
- } |
- break; |
- } |
- default: |
- break; |
- } |
-} |
- |
-void LoadTimingObserver::OnAddConnectJobEntry(const net::NetLog::Entry& entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- |
- bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN; |
- bool is_end = entry.phase() == net::NetLog::PHASE_END; |
- |
- // Manage record lifetime based on the SOCKET_POOL_CONNECT_JOB entry. |
- if (entry.type() == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB) { |
- if (is_begin) { |
- // Prevents us from passively growing the memory unbounded in case |
- // something went wrong. Should not happen. |
- if (connect_job_to_record_.size() > kMaxNumEntries) { |
- LOG(WARNING) << "The load timing observer connect job count has grown " |
- "larger than expected, resetting"; |
- connect_job_to_record_.clear(); |
- } |
- |
- connect_job_to_record_.insert( |
- std::make_pair(entry.source().id, ConnectJobRecord())); |
- } else if (is_end) { |
- ConnectJobToRecordMap::iterator it = |
- connect_job_to_record_.find(entry.source().id); |
- if (it != connect_job_to_record_.end()) { |
- last_connect_job_id_ = it->first; |
- last_connect_job_record_ = it->second; |
- connect_job_to_record_.erase(it); |
- } |
- } |
- } else if (entry.type() == net::NetLog::TYPE_HOST_RESOLVER_IMPL) { |
- ConnectJobToRecordMap::iterator it = |
- connect_job_to_record_.find(entry.source().id); |
- if (it != connect_job_to_record_.end()) { |
- if (is_begin) |
- it->second.dns_start = GetCurrentTime(); |
- else if (is_end) |
- it->second.dns_end = GetCurrentTime(); |
- } |
- } |
-} |
- |
-void LoadTimingObserver::OnAddSocketEntry(const net::NetLog::Entry& entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- |
- bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN; |
- bool is_end = entry.phase() == net::NetLog::PHASE_END; |
- |
- // Manage record lifetime based on the SOCKET_ALIVE entry. |
- if (entry.type() == net::NetLog::TYPE_SOCKET_ALIVE) { |
- if (is_begin) { |
- // Prevents us from passively growing the memory unbounded in case |
- // something went wrong. Should not happen. |
- if (socket_to_record_.size() > kMaxNumEntries) { |
- LOG(WARNING) << "The load timing observer socket count has grown " |
- "larger than expected, resetting"; |
- socket_to_record_.clear(); |
- } |
- |
- socket_to_record_.insert( |
- std::make_pair(entry.source().id, SocketRecord())); |
- } else if (is_end) { |
- socket_to_record_.erase(entry.source().id); |
- } |
- return; |
- } |
- SocketToRecordMap::iterator it = socket_to_record_.find(entry.source().id); |
- if (it == socket_to_record_.end()) |
- return; |
- |
- if (entry.type() == net::NetLog::TYPE_SSL_CONNECT) { |
- if (is_begin) |
- it->second.ssl_start = GetCurrentTime(); |
- else if (is_end) |
- it->second.ssl_end = GetCurrentTime(); |
- } |
-} |
- |
-base::TimeTicks LoadTimingObserver::GetCurrentTime() const { |
- return base::TimeTicks::Now(); |
-} |