diff options
27 files changed, 602 insertions, 77 deletions
@@ -5,7 +5,7 @@ vars = { "sourceforge_url": "http://%(repo)s.svn.sourceforge.net/svnroot/%(repo)s", "webkit_trunk": "http://svn.webkit.org/repository/webkit/trunk", "nacl_trunk": "http://src.chromium.org/native_client/trunk", - "webkit_revision": "102911", + "webkit_revision": "102988", "chromium_git": "http://git.chromium.org/git", "swig_revision": "69281", "nacl_revision": "7388", diff --git a/chrome/browser/net/load_timing_observer.cc b/chrome/browser/net/load_timing_observer.cc index f0d33e2..b3bd189 100644 --- a/chrome/browser/net/load_timing_observer.cc +++ b/chrome/browser/net/load_timing_observer.cc @@ -153,6 +153,7 @@ void LoadTimingObserver::OnAddURLRequestEntry( URLRequestRecord& record = url_request_to_record_[source.id]; record.base_ticks = time; record.timing = ResourceLoadTimingInfo(); + record.timing.base_ticks = time; record.timing.base_time = TimeTicksToTime(time); } return; diff --git a/chrome/common/extensions/extension_localization_peer.cc b/chrome/common/extensions/extension_localization_peer.cc index dfb4f1d..fa00999 100644 --- a/chrome/common/extensions/extension_localization_peer.cc +++ b/chrome/common/extensions/extension_localization_peer.cc @@ -68,7 +68,7 @@ void ExtensionLocalizationPeer::OnReceivedData(const char* data, void ExtensionLocalizationPeer::OnCompletedRequest( const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time) { + const base::TimeTicks& completion_time) { // Make sure we delete ourselves at the end of this call. scoped_ptr<ExtensionLocalizationPeer> this_deleter(this); diff --git a/chrome/common/extensions/extension_localization_peer.h b/chrome/common/extensions/extension_localization_peer.h index 1f88775..346d06e 100644 --- a/chrome/common/extensions/extension_localization_peer.h +++ b/chrome/common/extensions/extension_localization_peer.h @@ -42,9 +42,10 @@ class ExtensionLocalizationPeer virtual void OnReceivedData(const char* data, int data_length, int encoded_data_length) OVERRIDE; - virtual void OnCompletedRequest(const net::URLRequestStatus& status, - const std::string& security_info, - const base::Time& completion_time) OVERRIDE; + virtual void OnCompletedRequest( + const net::URLRequestStatus& status, + const std::string& security_info, + const base::TimeTicks& completion_time) OVERRIDE; private: friend class ExtensionLocalizationPeerTest; diff --git a/chrome/common/extensions/extension_localization_peer_unittest.cc b/chrome/common/extensions/extension_localization_peer_unittest.cc index df847ce..06bd74e 100644 --- a/chrome/common/extensions/extension_localization_peer_unittest.cc +++ b/chrome/common/extensions/extension_localization_peer_unittest.cc @@ -72,7 +72,7 @@ class MockResourceLoaderBridgePeer MOCK_METHOD3(OnCompletedRequest, void( const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time)); + const base::TimeTicks& completion_time)); private: DISALLOW_COPY_AND_ASSIGN(MockResourceLoaderBridgePeer); @@ -142,11 +142,11 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestBadURLRequestStatus) { EXPECT_CALL(*original_peer_, OnReceivedResponse(_)); EXPECT_CALL(*original_peer_, OnCompletedRequest( - IsURLRequestEqual(net::URLRequestStatus::CANCELED), "", base::Time())); + IsURLRequestEqual(net::URLRequestStatus::CANCELED), "", base::TimeTicks())); net::URLRequestStatus status; status.set_status(net::URLRequestStatus::FAILED); - filter_peer->OnCompletedRequest(status, "", base::Time()); + filter_peer->OnCompletedRequest(status, "", base::TimeTicks()); } TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) { @@ -158,11 +158,12 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) { EXPECT_CALL(*original_peer_, OnReceivedResponse(_)); EXPECT_CALL(*original_peer_, OnCompletedRequest( - IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time())); + IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", + base::TimeTicks())); net::URLRequestStatus status; status.set_status(net::URLRequestStatus::SUCCESS); - filter_peer->OnCompletedRequest(status, "", base::Time()); + filter_peer->OnCompletedRequest(status, "", base::TimeTicks()); } TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) { @@ -180,18 +181,18 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) { EXPECT_CALL(*original_peer_, OnReceivedResponse(_)).Times(2); EXPECT_CALL(*original_peer_, OnCompletedRequest( IsURLRequestEqual( - net::URLRequestStatus::SUCCESS), "", base::Time())).Times(2); + net::URLRequestStatus::SUCCESS), "", base::TimeTicks())).Times(2); net::URLRequestStatus status; status.set_status(net::URLRequestStatus::SUCCESS); - filter_peer->OnCompletedRequest(status, "", base::Time()); + filter_peer->OnCompletedRequest(status, "", base::TimeTicks()); // Test if Send gets called again (it shouldn't be) when first call returned // an empty dictionary. filter_peer = CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1)); SetData(filter_peer, "some text"); - filter_peer->OnCompletedRequest(status, "", base::Time()); + filter_peer->OnCompletedRequest(status, "", base::TimeTicks()); } TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) { @@ -217,11 +218,12 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) { EXPECT_CALL(*original_peer_, OnReceivedResponse(_)); EXPECT_CALL(*original_peer_, OnCompletedRequest( - IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time())); + IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", + base::TimeTicks())); net::URLRequestStatus status; status.set_status(net::URLRequestStatus::SUCCESS); - filter_peer->OnCompletedRequest(status, "", base::Time()); + filter_peer->OnCompletedRequest(status, "", base::TimeTicks()); } TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestReplaceMessagesFails) { @@ -247,9 +249,10 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestReplaceMessagesFails) { EXPECT_CALL(*original_peer_, OnReceivedResponse(_)); EXPECT_CALL(*original_peer_, OnCompletedRequest( - IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time())); + IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", + base::TimeTicks())); net::URLRequestStatus status; status.set_status(net::URLRequestStatus::SUCCESS); - filter_peer->OnCompletedRequest(status, "", base::Time()); + filter_peer->OnCompletedRequest(status, "", base::TimeTicks()); } diff --git a/chrome/renderer/security_filter_peer.cc b/chrome/renderer/security_filter_peer.cc index 7d98684..994543c 100644 --- a/chrome/renderer/security_filter_peer.cc +++ b/chrome/renderer/security_filter_peer.cc @@ -87,9 +87,10 @@ void SecurityFilterPeer::OnReceivedData(const char* data, NOTREACHED(); } -void SecurityFilterPeer::OnCompletedRequest(const net::URLRequestStatus& status, - const std::string& security_info, - const base::Time& completion_time) { +void SecurityFilterPeer::OnCompletedRequest( + const net::URLRequestStatus& status, + const std::string& security_info, + const base::TimeTicks& completion_time) { NOTREACHED(); } @@ -149,7 +150,7 @@ void BufferedPeer::OnReceivedData(const char* data, void BufferedPeer::OnCompletedRequest(const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time) { + const base::TimeTicks& completion_time) { // Make sure we delete ourselves at the end of this call. scoped_ptr<BufferedPeer> this_deleter(this); @@ -201,7 +202,7 @@ void ReplaceContentPeer::OnReceivedData(const char* data, void ReplaceContentPeer::OnCompletedRequest( const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time) { + const base::TimeTicks& completion_time) { webkit_glue::ResourceResponseInfo info; ProcessResponseInfo(info, &info, mime_type_); info.security_info = security_info; diff --git a/chrome/renderer/security_filter_peer.h b/chrome/renderer/security_filter_peer.h index c54705d..df499bd 100644 --- a/chrome/renderer/security_filter_peer.h +++ b/chrome/renderer/security_filter_peer.h @@ -41,9 +41,10 @@ class SecurityFilterPeer : public webkit_glue::ResourceLoaderBridge::Peer { virtual void OnReceivedData(const char* data, int data_length, int encoded_data_length) OVERRIDE; - virtual void OnCompletedRequest(const net::URLRequestStatus& status, - const std::string& security_info, - const base::Time& completion_time) OVERRIDE; + virtual void OnCompletedRequest( + const net::URLRequestStatus& status, + const std::string& security_info, + const base::TimeTicks& completion_time) OVERRIDE; protected: SecurityFilterPeer(webkit_glue::ResourceLoaderBridge* resource_loader_bridge, @@ -71,9 +72,10 @@ class BufferedPeer : public SecurityFilterPeer { virtual void OnReceivedData(const char* data, int data_length, int encoded_data_length) OVERRIDE; - virtual void OnCompletedRequest(const net::URLRequestStatus& status, - const std::string& security_info, - const base::Time& completion_time) OVERRIDE; + virtual void OnCompletedRequest( + const net::URLRequestStatus& status, + const std::string& security_info, + const base::TimeTicks& completion_time) OVERRIDE; protected: // Invoked when the entire request has been processed before the data is sent @@ -113,9 +115,10 @@ class ReplaceContentPeer : public SecurityFilterPeer { virtual void OnReceivedData(const char* data, int data_length, int encoded_data_length) OVERRIDE; - virtual void OnCompletedRequest(const net::URLRequestStatus& status, - const std::string& security_info, - const base::Time& completion_time) OVERRIDE; + virtual void OnCompletedRequest( + const net::URLRequestStatus& status, + const std::string& security_info, + const base::TimeTicks& completion_time) OVERRIDE; private: webkit_glue::ResourceResponseInfo response_info_; diff --git a/content/browser/renderer_host/async_resource_handler.cc b/content/browser/renderer_host/async_resource_handler.cc index 9f7577f..d4b5a15 100644 --- a/content/browser/renderer_host/async_resource_handler.cc +++ b/content/browser/renderer_host/async_resource_handler.cc @@ -26,7 +26,6 @@ #include "net/base/net_log.h" #include "webkit/glue/resource_loader_bridge.h" -using base::Time; using base::TimeTicks; namespace { @@ -110,6 +109,8 @@ bool AsyncResourceHandler::OnRequestRedirected( rdh_->delegate()->OnRequestRedirected(request, response, filter_); DevToolsNetLogObserver::PopulateResponseInfo(request, response); + response->request_start = request->creation_time(); + response->response_start = TimeTicks::Now(); return filter_->Send(new ResourceMsg_ReceivedRedirect( routing_id_, request_id, new_url, *response)); } @@ -143,6 +144,8 @@ bool AsyncResourceHandler::OnResponseStarted( request_url)))); } + response->request_start = request->creation_time(); + response->response_start = TimeTicks::Now(); filter_->Send(new ResourceMsg_ReceivedResponse( routing_id_, request_id, *response)); @@ -241,7 +244,7 @@ bool AsyncResourceHandler::OnResponseCompleted( int request_id, const net::URLRequestStatus& status, const std::string& security_info) { - Time completion_time = Time::Now(); + TimeTicks completion_time = TimeTicks::Now(); filter_->Send(new ResourceMsg_RequestComplete(routing_id_, request_id, status, diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc index 542b606..5bb26e3 100644 --- a/content/browser/renderer_host/resource_dispatcher_host.cc +++ b/content/browser/renderer_host/resource_dispatcher_host.cc @@ -137,8 +137,8 @@ void AbortRequestBeforeItStarts(ResourceMessageFilter* filter, route_id, request_id, status, - std::string(), // No security info needed, connection was not - base::Time())); // established. + std::string(), // No security info needed, connection not established. + base::TimeTicks())); } } diff --git a/content/common/inter_process_time_ticks_converter.cc b/content/common/inter_process_time_ticks_converter.cc new file mode 100644 index 0000000..09c14f0 --- /dev/null +++ b/content/common/inter_process_time_ticks_converter.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2011 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 "content/common/inter_process_time_ticks_converter.h" + +#include "base/logging.h" + +namespace content { + +InterProcessTimeTicksConverter::InterProcessTimeTicksConverter( + const LocalTimeTicks& local_lower_bound, + const LocalTimeTicks& local_upper_bound, + const RemoteTimeTicks& remote_lower_bound, + const RemoteTimeTicks& remote_upper_bound) + : remote_lower_bound_(remote_lower_bound.value_), + remote_upper_bound_(remote_upper_bound.value_) { + int64 target_range = local_upper_bound.value_ - local_lower_bound.value_; + int64 source_range = remote_upper_bound.value_ - remote_lower_bound.value_; + if (source_range <= target_range) { + // We fit! Just shift the midpoints to match. + numerator_ = 1; + denominator_ = 1; + offset_ = ((local_upper_bound.value_ + local_lower_bound.value_) - + (remote_upper_bound.value_ + remote_lower_bound.value_)) / 2; + return; + } + // Set up scaling factors, and then deduce shift. + numerator_ = target_range; + denominator_ = source_range; + // Find out what we need to shift by to make this really work. + offset_ = local_lower_bound.value_ - Convert(remote_lower_bound.value_); + DCHECK_GE(local_upper_bound.value_, Convert(remote_upper_bound.value_)); +} + +LocalTimeTicks InterProcessTimeTicksConverter::ToLocalTimeTicks( + const RemoteTimeTicks& remote_ms) { + DCHECK_LE(remote_lower_bound_, remote_ms.value_); + DCHECK_GE(remote_upper_bound_, remote_ms.value_); + RemoteTimeDelta remote_delta = remote_ms - remote_lower_bound_; + return LocalTimeTicks(remote_lower_bound_ + offset_ + + ToLocalTimeDelta(remote_delta).value_); +} + +LocalTimeDelta InterProcessTimeTicksConverter::ToLocalTimeDelta( + const RemoteTimeDelta& remote_delta) { + DCHECK_GE(remote_upper_bound_, remote_lower_bound_ + remote_delta.value_); + return LocalTimeDelta(Convert(remote_delta.value_)); +} + +int64 InterProcessTimeTicksConverter::Convert(int64 value) { + if (value <= 0) { + return value; + } + return numerator_ * value / denominator_; +} + +} // namespace content diff --git a/content/common/inter_process_time_ticks_converter.h b/content/common/inter_process_time_ticks_converter.h new file mode 100644 index 0000000..0377764 --- /dev/null +++ b/content/common/inter_process_time_ticks_converter.h @@ -0,0 +1,144 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_ +#define CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_ + +#include "base/time.h" + +namespace content { + +class LocalTimeDelta; +class LocalTimeTicks; +class RemoteTimeDelta; +class RemoteTimeTicks; + +// On Windows, TimeTicks are not consistent between processes. Often, the values +// on one process have a static offset relative to another. Occasionally, these +// offsets shift while running. +// +// To combat this, any TimeTicks values sent from the remote process to the +// local process must be tweaked in order to appear monotonic. +// +// In order to properly tweak ticks, we need 4 reference points: +// +// - |local_lower_bound|: A known point, recorded on the local process, that +// occurs before any remote values that will be +// converted. +// - |remote_lower_bound|: The equivalent point on the remote process. This +// should be recorded immediately after +// |local_lower_bound|. +// - |local_upper_bound|: A known point, recorded on the local process, that +// occurs after any remote values that will be +// converted. +// - |remote_upper_bound|: The equivalent point on the remote process. This +// should be recorded immediately before +// |local_upper_bound|. +// +// Once these bounds are determined, values within the remote process's range +// can be converted to the local process's range. The values are converted as +// follows: +// +// 1. If the remote's range exceeds the local's range, it is scaled to fit. +// Any values converted will have the same scale factor applied. +// +// 2. The remote's range is shifted so that it is centered within the +// local's range. Any values converted will be shifted the same amount. +class InterProcessTimeTicksConverter { + public: + InterProcessTimeTicksConverter(const LocalTimeTicks& local_lower_bound, + const LocalTimeTicks& local_upper_bound, + const RemoteTimeTicks& remote_lower_bound, + const RemoteTimeTicks& remote_upper_bound); + + // Returns the value within the local's bounds that correlates to + // |remote_ms|. + LocalTimeTicks ToLocalTimeTicks(const RemoteTimeTicks& remote_ms); + + // Returns the equivalent delta after applying remote-to-local scaling to + // |remote_delta|. + LocalTimeDelta ToLocalTimeDelta(const RemoteTimeDelta& remote_delta); + + private: + int64 Convert(int64 value); + + int64 offset_; + int64 numerator_; + int64 denominator_; + + int64 remote_lower_bound_; + int64 remote_upper_bound_; +}; + +class LocalTimeDelta { + public: + int ToInt32() const { return value_; } + + private: + friend class InterProcessTimeTicksConverter; + friend class LocalTimeTicks; + + LocalTimeDelta(int value) : value_(value) {} + + int value_; +}; + +class LocalTimeTicks { + public: + static LocalTimeTicks FromTimeTicks(const base::TimeTicks& value) { + return LocalTimeTicks(value.ToInternalValue()); + } + + base::TimeTicks ToTimeTicks() { + return base::TimeTicks::FromInternalValue(value_); + } + + LocalTimeTicks operator+(const LocalTimeDelta& delta) { + return LocalTimeTicks(value_ + delta.value_); + } + + private: + friend class InterProcessTimeTicksConverter; + + LocalTimeTicks(int64 value) : value_(value) {} + + int64 value_; +}; + +class RemoteTimeDelta { + public: + static RemoteTimeDelta FromRawDelta(int delta) { + return RemoteTimeDelta(delta); + } + + private: + friend class InterProcessTimeTicksConverter; + friend class RemoteTimeTicks; + + RemoteTimeDelta(int value) : value_(value) {} + + int value_; +}; + +class RemoteTimeTicks { + public: + static RemoteTimeTicks FromTimeTicks(const base::TimeTicks& ticks) { + return RemoteTimeTicks(ticks.ToInternalValue()); + } + + RemoteTimeDelta operator-(const RemoteTimeTicks& rhs) const { + return RemoteTimeDelta(value_ - rhs.value_); + } + + private: + friend class InterProcessTimeTicksConverter; + + RemoteTimeTicks(int64 value) : value_(value) {} + + int64 value_; +}; + +} // namespace content + +#endif // CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_ diff --git a/content/common/inter_process_time_ticks_converter_unittest.cc b/content/common/inter_process_time_ticks_converter_unittest.cc new file mode 100644 index 0000000..1d1f301 --- /dev/null +++ b/content/common/inter_process_time_ticks_converter_unittest.cc @@ -0,0 +1,206 @@ +// Copyright (c) 2011 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 "base/time.h" +#include "content/common/inter_process_time_ticks_converter.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::TimeTicks; + +namespace content { + +namespace { + +struct TestParams { + int64 local_lower_bound; + int64 remote_lower_bound; + int64 remote_upper_bound; + int64 local_upper_bound; + int64 test_time; + int64 test_delta; +}; + +struct TestResults { + int64 result_time; + int32 result_delta; +}; + +TestResults RunTest(const TestParams& params) { + TimeTicks local_lower_bound = TimeTicks::FromInternalValue( + params.local_lower_bound); + TimeTicks local_upper_bound = TimeTicks::FromInternalValue( + params.local_upper_bound); + TimeTicks remote_lower_bound = TimeTicks::FromInternalValue( + params.remote_lower_bound); + TimeTicks remote_upper_bound = TimeTicks::FromInternalValue( + params.remote_upper_bound); + TimeTicks test_time = TimeTicks::FromInternalValue(params.test_time); + + InterProcessTimeTicksConverter converter( + LocalTimeTicks::FromTimeTicks(local_lower_bound), + LocalTimeTicks::FromTimeTicks(local_upper_bound), + RemoteTimeTicks::FromTimeTicks(remote_lower_bound), + RemoteTimeTicks::FromTimeTicks(remote_upper_bound)); + + TestResults results; + results.result_time = converter.ToLocalTimeTicks( + RemoteTimeTicks::FromTimeTicks( + test_time)).ToTimeTicks().ToInternalValue(); + results.result_delta = converter.ToLocalTimeDelta( + RemoteTimeDelta::FromRawDelta(params.test_delta)).ToInt32(); + return results; +} + +TEST(InterProcessTimeTicksConverterTest, NoSkew) { + // All times are monotonic and centered, so no adjustment should occur. + TestParams p; + p.local_lower_bound = 0; + p.remote_lower_bound = 1; + p.remote_upper_bound = 4; + p.local_upper_bound = 5; + p.test_time = 2; + p.test_delta = 1; + TestResults results = RunTest(p); + EXPECT_EQ(2, results.result_time); + EXPECT_EQ(1, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, OffsetMidpoints) { + // All times are monotonic, but not centered. Adjust the |remote_*| times so + // they are centered within the |local_*| times. + TestParams p; + p.local_lower_bound = 0; + p.remote_lower_bound = 2; + p.remote_upper_bound = 5; + p.local_upper_bound = 5; + p.test_time = 3; + p.test_delta = 1; + TestResults results = RunTest(p); + EXPECT_EQ(2, results.result_time); + EXPECT_EQ(1, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, DoubleEndedSkew) { + // |remote_lower_bound| occurs before |local_lower_bound| and + // |remote_upper_bound| occurs after |local_upper_bound|. We must adjust both + // bounds and scale down the delta. |test_time| is on the midpoint, so it + // doesn't change. The ratio of local time to network time is 1:2, so we scale + // |test_delta| to half. + TestParams p; + p.local_lower_bound = 2; + p.remote_lower_bound = 0; + p.remote_upper_bound = 8; + p.local_upper_bound = 6; + p.test_time = 4; + p.test_delta = 2; + TestResults results = RunTest(p); + EXPECT_EQ(4, results.result_time); + EXPECT_EQ(1, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, FrontEndSkew) { + // |remote_upper_bound| is coherent, but |remote_lower_bound| is not. So we + // adjust the lower bound and move |test_time| out. The scale factor is 2:3, + // but since we use integers, the numbers truncate from 3.33 to 3 and 1.33 + // to 1. + TestParams p; + p.local_lower_bound = 2; + p.remote_lower_bound = 0; + p.remote_upper_bound = 6; + p.local_upper_bound = 6; + p.test_time = 2; + p.test_delta = 2; + TestResults results = RunTest(p); + EXPECT_EQ(3, results.result_time); + EXPECT_EQ(1, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, BackEndSkew) { + // Like the previous test, but |remote_lower_bound| is coherent and + // |remote_upper_bound| is skewed. + TestParams p; + p.local_lower_bound = 0; + p.remote_lower_bound = 0; + p.remote_upper_bound = 6; + p.local_upper_bound = 4; + p.test_time = 2; + p.test_delta = 2; + TestResults results = RunTest(p); + EXPECT_EQ(1, results.result_time); + EXPECT_EQ(1, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, Instantaneous) { + // The bounds are all okay, but the |remote_lower_bound| and + // |remote_upper_bound| have the same value. No adjustments should be made and + // no divide-by-zero errors should occur. + TestParams p; + p.local_lower_bound = 0; + p.remote_lower_bound = 1; + p.remote_upper_bound = 1; + p.local_upper_bound = 2; + p.test_time = 1; + p.test_delta = 0; + TestResults results = RunTest(p); + EXPECT_EQ(1, results.result_time); + EXPECT_EQ(0, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, OffsetInstantaneous) { + // The bounds are all okay, but the |remote_lower_bound| and + // |remote_upper_bound| have the same value and are offset from the midpoint + // of |local_lower_bound| and |local_upper_bound|. An offset should be applied + // to make the midpoints line up. + TestParams p; + p.local_lower_bound = 0; + p.remote_lower_bound = 2; + p.remote_upper_bound = 2; + p.local_upper_bound = 2; + p.test_time = 2; + p.test_delta = 0; + TestResults results = RunTest(p); + EXPECT_EQ(1, results.result_time); + EXPECT_EQ(0, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, DisjointInstantaneous) { + // |local_lower_bound| and |local_upper_bound| are the same. No matter what + // the other values are, they must fit within [local_lower_bound, + // local_upper_bound]. So, all of the values should be adjusted so they are + // exactly that value. + TestParams p; + p.local_lower_bound = 1; + p.remote_lower_bound = 2; + p.remote_upper_bound = 2; + p.local_upper_bound = 1; + p.test_time = 2; + p.test_delta = 0; + TestResults results = RunTest(p); + EXPECT_EQ(1, results.result_time); + EXPECT_EQ(0, results.result_delta); +} + +TEST(InterProcessTimeTicksConverterTest, RoundingNearEdges) { + // Verify that rounding never causes a value to appear outside the given + // |local_*| range. + const int kMaxRange = 100; + for (int i = 0; i < kMaxRange; ++i) { + for (int j = 0; j < kMaxRange; ++j) { + TestParams p; + p.local_lower_bound = 0; + p.remote_lower_bound = 0; + p.remote_upper_bound = j; + p.local_upper_bound = i; + p.test_time = 0; + p.test_delta = j; + TestResults results = RunTest(p); + EXPECT_LE(0, results.result_time); + EXPECT_GE(i, results.result_delta); + } + } +} + +} // anonymous namespace + +} // namespace content diff --git a/content/common/resource_dispatcher.cc b/content/common/resource_dispatcher.cc index 6094fc2..38bc014 100644 --- a/content/common/resource_dispatcher.cc +++ b/content/common/resource_dispatcher.cc @@ -13,6 +13,7 @@ #include "base/message_loop.h" #include "base/shared_memory.h" #include "base/string_util.h" +#include "content/common/inter_process_time_ticks_converter.h" #include "content/common/request_extra_data.h" #include "content/common/resource_messages.h" #include "content/public/common/resource_dispatcher_delegate.h" @@ -23,6 +24,12 @@ #include "net/http/http_response_headers.h" #include "webkit/glue/resource_type.h" +using content::InterProcessTimeTicksConverter; +using content::LocalTimeDelta; +using content::LocalTimeTicks; +using content::RemoteTimeDelta; +using content::RemoteTimeTicks; + // Each resource request is assigned an ID scoped to this process. static int MakeRequestID() { // NOTE: The resource_dispatcher_host also needs probably unique @@ -348,6 +355,7 @@ void ResourceDispatcher::OnReceivedResponse( PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); if (!request_info) return; + request_info->response_start = base::TimeTicks::Now(); if (delegate_) { webkit_glue::ResourceLoaderBridge::Peer* new_peer = @@ -357,7 +365,9 @@ void ResourceDispatcher::OnReceivedResponse( request_info->peer = new_peer; } - request_info->peer->OnReceivedResponse(response_head); + webkit_glue::ResourceResponseInfo renderer_response_info; + ToResourceResponseInfo(*request_info, response_head, &renderer_response_info); + request_info->peer->OnReceivedResponse(renderer_response_info); } void ResourceDispatcher::OnReceivedCachedMetadata( @@ -411,17 +421,20 @@ void ResourceDispatcher::OnReceivedRedirect( const IPC::Message& message, int request_id, const GURL& new_url, - const webkit_glue::ResourceResponseInfo& info) { + const content::ResourceResponseHead& response_head) { PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); if (!request_info) return; + request_info->response_start = base::TimeTicks::Now(); int32 routing_id = message.routing_id(); bool has_new_first_party_for_cookies = false; GURL new_first_party_for_cookies; - if (request_info->peer->OnReceivedRedirect(new_url, info, - &has_new_first_party_for_cookies, - &new_first_party_for_cookies)) { + webkit_glue::ResourceResponseInfo renderer_response_info; + ToResourceResponseInfo(*request_info, response_head, &renderer_response_info); + if (request_info->peer->OnReceivedRedirect(new_url, renderer_response_info, + &has_new_first_party_for_cookies, + &new_first_party_for_cookies)) { // Double-check if the request is still around. The call above could // potentially remove it. request_info = GetPendingRequestInfo(request_id); @@ -447,13 +460,15 @@ void ResourceDispatcher::FollowPendingRedirect( message_sender()->Send(msg); } -void ResourceDispatcher::OnRequestComplete(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info, - const base::Time& completion_time) { +void ResourceDispatcher::OnRequestComplete( + int request_id, + const net::URLRequestStatus& status, + const std::string& security_info, + const base::TimeTicks& browser_completion_time) { PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); if (!request_info) return; + request_info->completion_time = base::TimeTicks::Now(); webkit_glue::ResourceLoaderBridge::Peer* peer = request_info->peer; @@ -465,10 +480,12 @@ void ResourceDispatcher::OnRequestComplete(int request_id, request_info->peer = new_peer; } + base::TimeTicks renderer_completion_time = ToRendererCompletionTime( + *request_info, browser_completion_time); // The request ID will be removed from our pending list in the destructor. // Normally, dispatching this message causes the reference-counted request to // die immediately. - peer->OnCompletedRequest(status, security_info, completion_time); + peer->OnCompletedRequest(status, security_info, renderer_completion_time); } int ResourceDispatcher::AddPendingRequest( @@ -579,6 +596,65 @@ webkit_glue::ResourceLoaderBridge* ResourceDispatcher::CreateBridge( return new webkit_glue::IPCResourceLoaderBridge(this, request_info); } +void ResourceDispatcher::ToResourceResponseInfo( + const PendingRequestInfo& request_info, + const content::ResourceResponseHead& browser_info, + webkit_glue::ResourceResponseInfo* renderer_info) const { + *renderer_info = browser_info; + if (request_info.request_start.is_null() || + request_info.response_start.is_null() || + browser_info.request_start.is_null() || + browser_info.response_start.is_null()) { + return; + } + content::InterProcessTimeTicksConverter converter( + LocalTimeTicks::FromTimeTicks(request_info.request_start), + LocalTimeTicks::FromTimeTicks(request_info.response_start), + RemoteTimeTicks::FromTimeTicks(browser_info.request_start), + RemoteTimeTicks::FromTimeTicks(browser_info.response_start)); + + LocalTimeTicks renderer_base_ticks = converter.ToLocalTimeTicks( + RemoteTimeTicks::FromTimeTicks(browser_info.load_timing.base_ticks)); + renderer_info->load_timing.base_ticks = renderer_base_ticks.ToTimeTicks(); + +#define CONVERT(field) \ + LocalTimeDelta renderer_##field = converter.ToLocalTimeDelta( \ + RemoteTimeDelta::FromRawDelta(browser_info.load_timing.field)); \ + renderer_info->load_timing.field = renderer_##field.ToInt32() + + CONVERT(proxy_start); + CONVERT(dns_start); + CONVERT(dns_end); + CONVERT(connect_start); + CONVERT(connect_end); + CONVERT(ssl_start); + CONVERT(ssl_end); + CONVERT(send_start); + CONVERT(send_end); + CONVERT(receive_headers_start); + CONVERT(receive_headers_end); + +#undef CONVERT +} + +base::TimeTicks ResourceDispatcher::ToRendererCompletionTime( + const PendingRequestInfo& request_info, + const base::TimeTicks& browser_completion_time) const { + if (request_info.completion_time.is_null()) { + return browser_completion_time; + } + + // TODO(simonjam): The optimal lower bound should be the most recent value of + // TimeTicks::Now() returned to WebKit. Is it worth trying to cache that? + // Until then, |response_start| is used as it is the most recent value + // returned for this request. + int64 result = std::max(browser_completion_time.ToInternalValue(), + request_info.response_start.ToInternalValue()); + result = std::min(result, request_info.completion_time.ToInternalValue()); + return base::TimeTicks::FromInternalValue(result); +} + +// static bool ResourceDispatcher::IsResourceDispatcherMessage( const IPC::Message& message) { switch (message.type()) { diff --git a/content/common/resource_dispatcher.h b/content/common/resource_dispatcher.h index 1b8e3a3..7c5cdba 100644 --- a/content/common/resource_dispatcher.h +++ b/content/common/resource_dispatcher.h @@ -15,6 +15,7 @@ #include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "base/shared_memory.h" +#include "base/time.h" #include "content/common/content_export.h" #include "ipc/ipc_channel.h" #include "webkit/glue/resource_loader_bridge.h" @@ -79,7 +80,8 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Channel::Listener { : peer(peer), resource_type(resource_type), is_deferred(false), - url(request_url) { + url(request_url), + request_start(base::TimeTicks::Now()) { } ~PendingRequestInfo() { } webkit_glue::ResourceLoaderBridge::Peer* peer; @@ -88,6 +90,9 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Channel::Listener { bool is_deferred; GURL url; linked_ptr<IPC::Message> pending_redirect_message; + base::TimeTicks request_start; + base::TimeTicks response_start; + base::TimeTicks completion_time; }; typedef base::hash_map<int, PendingRequestInfo> PendingRequestList; @@ -110,7 +115,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Channel::Listener { const IPC::Message& message, int request_id, const GURL& new_url, - const webkit_glue::ResourceResponseInfo& info); + const content::ResourceResponseHead& response_head); void OnReceivedData( const IPC::Message& message, int request_id, @@ -125,7 +130,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Channel::Listener { int request_id, const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time); + const base::TimeTicks& completion_time); // Dispatch the message to one of the message response handlers. void DispatchMessage(const IPC::Message& message); @@ -134,6 +139,15 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Channel::Listener { // again in the deferred state. void FlushDeferredMessages(int request_id); + void ToResourceResponseInfo( + const PendingRequestInfo& request_info, + const content::ResourceResponseHead& browser_info, + webkit_glue::ResourceResponseInfo* renderer_info) const; + + base::TimeTicks ToRendererCompletionTime( + const PendingRequestInfo& request_info, + const base::TimeTicks& browser_completion_time) const; + // Returns true if the message passed in is a resource related message. static bool IsResourceDispatcherMessage(const IPC::Message& message); diff --git a/content/common/resource_dispatcher_unittest.cc b/content/common/resource_dispatcher_unittest.cc index d133bc1..2bc9ebb 100644 --- a/content/common/resource_dispatcher_unittest.cc +++ b/content/common/resource_dispatcher_unittest.cc @@ -67,7 +67,7 @@ class TestRequestCallback : public ResourceLoaderBridge::Peer { virtual void OnCompletedRequest(const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time) { + const base::TimeTicks& completion_time) { EXPECT_FALSE(complete_); complete_ = true; } @@ -298,7 +298,7 @@ class DeferredResourceLoadingTest : public ResourceDispatcherTest, virtual void OnCompletedRequest(const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time) { + const base::TimeTicks& completion_time) { } protected: diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h index 95c73ae..1771461 100644 --- a/content/common/resource_messages.h +++ b/content/common/resource_messages.h @@ -169,7 +169,7 @@ IPC_MESSAGE_ROUTED4(ResourceMsg_RequestComplete, int /* request_id */, net::URLRequestStatus /* status */, std::string /* security info */, - base::Time /* completion_time */) + base::TimeTicks /* completion_time */) // Resource messages sent from the renderer to the browser. diff --git a/content/content_common.gypi b/content/content_common.gypi index 7b073dc..7e30d23 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -173,6 +173,8 @@ 'common/indexed_db_messages.h', 'common/indexed_db_param_traits.cc', 'common/indexed_db_param_traits.h', + 'common/inter_process_time_ticks_converter.cc', + 'common/inter_process_time_ticks_converter.h', 'common/intents_messages.h', 'common/java_bridge_messages.h', 'common/mac/attributed_string_coder.h', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 673a089..e8e36c0 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -244,6 +244,7 @@ 'common/gpu/gpu_feature_flags_unittest.cc', 'common/gpu/gpu_info_unittest.cc', 'common/hi_res_timer_manager_unittest.cc', + 'common/inter_process_time_ticks_converter_unittest.cc', 'common/net/url_fetcher_impl_unittest.cc', 'common/page_zoom_unittest.cc', 'common/resource_dispatcher_unittest.cc', diff --git a/content/public/common/resource_response.h b/content/public/common/resource_response.h index 652ef34..9a8e3a8 100644 --- a/content/public/common/resource_response.h +++ b/content/public/common/resource_response.h @@ -23,6 +23,10 @@ namespace content { struct ResourceResponseHead : webkit_glue::ResourceResponseInfo { // The response status. net::URLRequestStatus status; + // TimeTicks::Now() when the browser received the request from the renderer. + base::TimeTicks request_start; + // TimeTicks::Now() when the browser sent the response to the renderer. + base::TimeTicks response_start; }; // Parameters for a synchronous resource response. diff --git a/content/public/common/webkit_param_traits.cc b/content/public/common/webkit_param_traits.cc index 555bd77..5d4e059 100644 --- a/content/public/common/webkit_param_traits.cc +++ b/content/public/common/webkit_param_traits.cc @@ -40,6 +40,7 @@ void ParamTraits<webkit_glue::ResourceLoadTimingInfo>::Write( WriteParam(m, p.base_time.is_null()); if (p.base_time.is_null()) return; + WriteParam(m, p.base_ticks); WriteParam(m, p.base_time); WriteParam(m, p.proxy_start); WriteParam(m, p.proxy_end); @@ -64,6 +65,7 @@ bool ParamTraits<webkit_glue::ResourceLoadTimingInfo>::Read( return true; return + ReadParam(m, iter, &r->base_ticks) && ReadParam(m, iter, &r->base_time) && ReadParam(m, iter, &r->proxy_start) && ReadParam(m, iter, &r->proxy_end) && @@ -82,6 +84,8 @@ bool ParamTraits<webkit_glue::ResourceLoadTimingInfo>::Read( void ParamTraits<webkit_glue::ResourceLoadTimingInfo>::Log(const param_type& p, std::string* l) { l->append("("); + LogParam(p.base_ticks, l); + l->append(", "); LogParam(p.base_time, l); l->append(", "); LogParam(p.proxy_start, l); diff --git a/content/test/render_view_fake_resources_test.cc b/content/test/render_view_fake_resources_test.cc index d8769c1..87d67a5 100644 --- a/content/test/render_view_fake_resources_test.cc +++ b/content/test/render_view_fake_resources_test.cc @@ -175,7 +175,7 @@ void RenderViewFakeResourcesTest::OnRequestResource( request_id, net::URLRequestStatus(), std::string(), - base::Time()))); + base::TimeTicks()))); } void RenderViewFakeResourcesTest::OnRenderViewReady() { diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index af405d7..0408757 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -152,7 +152,8 @@ URLRequest::URLRequest(const GURL& url, Delegate* delegate) ALLOW_THIS_IN_INITIALIZER_LIST(before_request_callback_( base::Bind(&URLRequest::BeforeRequestComplete, base::Unretained(this)))), - has_notified_completion_(false) { + has_notified_completion_(false), + creation_time_(base::TimeTicks::Now()) { SIMPLE_STATS_COUNTER("URLRequestCount"); // Sanity check out environment. diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 3deb198..5e3ca80 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h @@ -15,6 +15,7 @@ #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/string16.h" +#include "base/time.h" #include "base/threading/non_thread_safe.h" #include "googleurl/src/gurl.h" #include "net/base/auth.h" @@ -48,10 +49,6 @@ class AppCacheRequestHandlerTest; class AppCacheURLRequestJobTest; } -namespace base { -class Time; -} // namespace base - // Temporary layering violation to allow existing users of a deprecated // interface. namespace fileapi { @@ -456,6 +453,9 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { // the response status line. Restrictions on GetResponseHeaders apply. void GetAllResponseHeaders(std::string* headers); + // The time when |this| was constructed. + base::TimeTicks creation_time() const { return creation_time_; } + // The time at which the returned response was requested. For cached // responses, this is the last time the cache entry was validated. const base::Time& request_time() const { @@ -814,6 +814,8 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { AuthCredentials auth_credentials_; scoped_refptr<AuthChallengeInfo> auth_info_; + base::TimeTicks creation_time_; + DISALLOW_COPY_AND_ASSIGN(URLRequest); }; diff --git a/webkit/glue/resource_loader_bridge.h b/webkit/glue/resource_loader_bridge.h index 8976463..c86b998 100644 --- a/webkit/glue/resource_loader_bridge.h +++ b/webkit/glue/resource_loader_bridge.h @@ -53,8 +53,11 @@ struct ResourceLoadTimingInfo { WEBKIT_GLUE_EXPORT ResourceLoadTimingInfo(); WEBKIT_GLUE_EXPORT ~ResourceLoadTimingInfo(); - // All the values in this struct are given as offsets in milliseconds wrt - // this base time. + // All the values in this struct are given as offsets in ticks wrt + // this base tick count. + base::TimeTicks base_ticks; + + // The value of Time::Now() when base_ticks was set. base::Time base_time; // The time that proxy processing started. For requests with no proxy phase, @@ -329,9 +332,10 @@ class ResourceLoaderBridge { // Called when the response is complete. This method signals completion of // the resource load.ff - virtual void OnCompletedRequest(const net::URLRequestStatus& status, - const std::string& security_info, - const base::Time& completion_time) = 0; + virtual void OnCompletedRequest( + const net::URLRequestStatus& status, + const std::string& security_info, + const base::TimeTicks& completion_time) = 0; }; // use WebKitPlatformSupportImpl::CreateResourceLoader() for construction, but diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc index 7df6ace..8315b61 100644 --- a/webkit/glue/weburlloader_impl.cc +++ b/webkit/glue/weburlloader_impl.cc @@ -36,7 +36,7 @@ #include "webkit/glue/weburlrequest_extradata_impl.h" using base::Time; -using base::TimeDelta; +using base::TimeTicks; using WebKit::WebData; using WebKit::WebHTTPBody; using WebKit::WebHTTPHeaderVisitor; @@ -124,6 +124,7 @@ bool GetInfoFromDataURL(const GURL& url, // Assure same time for all time fields of data: URLs. Time now = Time::Now(); info->load_timing.base_time = now; + info->load_timing.base_ticks = TimeTicks::Now(); info->request_time = now; info->response_time = now; info->headers = NULL; @@ -173,7 +174,7 @@ void PopulateURLResponse( if (!timing_info.base_time.is_null()) { WebURLLoadTiming timing; timing.initialize(); - timing.setRequestTime(timing_info.base_time.ToDoubleT()); + timing.setRequestTime((timing_info.base_ticks - TimeTicks()).InSecondsF()); timing.setProxyStart(timing_info.proxy_start); timing.setProxyEnd(timing_info.proxy_end); timing.setDNSStart(timing_info.dns_start); @@ -284,7 +285,7 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context>, virtual void OnReceivedCachedMetadata(const char* data, int len); virtual void OnCompletedRequest(const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time); + const base::TimeTicks& completion_time); private: friend class base::RefCounted<Context>; @@ -610,7 +611,7 @@ void WebURLLoaderImpl::Context::OnReceivedCachedMetadata( void WebURLLoaderImpl::Context::OnCompletedRequest( const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& completion_time) { + const base::TimeTicks& completion_time) { if (ftp_listing_delegate_.get()) { ftp_listing_delegate_->OnCompletedRequest(); ftp_listing_delegate_.reset(NULL); @@ -642,7 +643,8 @@ void WebURLLoaderImpl::Context::OnCompletedRequest( error.unreachableURL = request_.url(); client_->didFail(loader_, error); } else { - client_->didFinishLoading(loader_, completion_time.ToDoubleT()); + client_->didFinishLoading( + loader_, (completion_time - TimeTicks()).InSecondsF()); } } @@ -686,7 +688,7 @@ void WebURLLoaderImpl::Context::HandleDataURL() { OnReceivedData(data.data(), data.size(), 0); } - OnCompletedRequest(status, info.security_info, base::Time::Now()); + OnCompletedRequest(status, info.security_info, base::TimeTicks::Now()); } // WebURLLoaderImpl ----------------------------------------------------------- diff --git a/webkit/tools/layout_tests/test_expectations.txt b/webkit/tools/layout_tests/test_expectations.txt index 668f5a9b..707c890 100644 --- a/webkit/tools/layout_tests/test_expectations.txt +++ b/webkit/tools/layout_tests/test_expectations.txt @@ -6,8 +6,3 @@ // until the changes can be landed upstream. // PLEASE DO NOT LEAVE ENTRIES IN THIS FILE FOR MORE THAN 24 HRS. - -BUGCR107668: fast/speech/input-appearance-numberandspeech.html = IMAGE -BUGCR107668: fast/speech/input-appearance-searchandspeech.html = IMAGE -BUGCR107668: fast/speech/input-appearance-speechbutton.html = IMAGE -BUGCR107668: fast/speech/speech-bidi-rendering.html = IMAGE diff --git a/webkit/tools/test_shell/simple_resource_loader_bridge.cc b/webkit/tools/test_shell/simple_resource_loader_bridge.cc index 6ce3e9c..958d662 100644 --- a/webkit/tools/test_shell/simple_resource_loader_bridge.cc +++ b/webkit/tools/test_shell/simple_resource_loader_bridge.cc @@ -288,7 +288,7 @@ class RequestProxy : public net::URLRequest::Delegate, void NotifyCompletedRequest(const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& complete_time) { + const base::TimeTicks& complete_time) { if (peer_) { peer_->OnCompletedRequest(status, security_info, complete_time); DropPeer(); // ensure no further notifications @@ -423,7 +423,7 @@ class RequestProxy : public net::URLRequest::Delegate, virtual void OnCompletedRequest(const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& complete_time) { + const base::TimeTicks& complete_time) { if (download_to_file_) file_stream_.Close(); owner_loop_->PostTask( @@ -519,7 +519,7 @@ class RequestProxy : public net::URLRequest::Delegate, // |failed_file_request_status_|. Otherwise use request_'s status. OnCompletedRequest(failed_file_request_status_.get() ? *failed_file_request_status_ : request_->status(), - std::string(), base::Time()); + std::string(), base::TimeTicks()); request_.reset(); // destroy on the io thread } @@ -729,7 +729,7 @@ class SyncRequestProxy : public RequestProxy { virtual void OnCompletedRequest(const net::URLRequestStatus& status, const std::string& security_info, - const base::Time& complete_time) { + const base::TimeTicks& complete_time) { if (download_to_file_) file_stream_.Close(); result_->status = status; |