1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/common/inter_process_time_ticks_converter.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11
12 namespace content {
13
InterProcessTimeTicksConverter(LocalTimeTicks local_lower_bound,LocalTimeTicks local_upper_bound,RemoteTimeTicks remote_lower_bound,RemoteTimeTicks remote_upper_bound)14 InterProcessTimeTicksConverter::InterProcessTimeTicksConverter(
15 LocalTimeTicks local_lower_bound,
16 LocalTimeTicks local_upper_bound,
17 RemoteTimeTicks remote_lower_bound,
18 RemoteTimeTicks remote_upper_bound)
19 : local_range_(local_upper_bound - local_lower_bound),
20 remote_lower_bound_(remote_lower_bound),
21 remote_upper_bound_(remote_upper_bound) {
22 RemoteTimeDelta remote_range = remote_upper_bound - remote_lower_bound;
23
24 DCHECK_LE(LocalTimeDelta(), local_range_);
25 DCHECK_LE(RemoteTimeDelta(), remote_range);
26
27 if (remote_range.ToTimeDelta() <= local_range_.ToTimeDelta()) {
28 // We fit! Center the source range on the target range.
29 range_conversion_rate_ = 1.0;
30 base::TimeDelta diff =
31 local_range_.ToTimeDelta() - remote_range.ToTimeDelta();
32
33 local_base_time_ =
34 local_lower_bound + LocalTimeDelta::FromTimeDelta(diff / 2);
35 // When converting times, remote bounds should fall within local bounds.
36 DCHECK_LE(local_lower_bound, ToLocalTimeTicks(remote_lower_bound));
37 DCHECK_LE(ToLocalTimeTicks(remote_upper_bound), local_upper_bound);
38 return;
39 }
40
41 // Interpolate values so that remote range will be will exactly fit into the
42 // local range, if possible.
43 DCHECK_GT(remote_range.ToTimeDelta().InMicroseconds(), 0);
44 range_conversion_rate_ =
45 static_cast<double>(local_range_.ToTimeDelta().InMicroseconds()) /
46 remote_range.ToTimeDelta().InMicroseconds();
47 local_base_time_ = local_lower_bound;
48 }
49
ToLocalTimeTicks(RemoteTimeTicks remote_time_ticks) const50 LocalTimeTicks InterProcessTimeTicksConverter::ToLocalTimeTicks(
51 RemoteTimeTicks remote_time_ticks) const {
52 // If input time is "null", return another "null" time.
53 if (remote_time_ticks.is_null())
54 return LocalTimeTicks();
55
56 RemoteTimeDelta remote_delta = remote_time_ticks - remote_lower_bound_;
57
58 DCHECK_LE(remote_time_ticks, remote_upper_bound_);
59 return local_base_time_ + ToLocalTimeDelta(remote_delta);
60 }
61
ToLocalTimeDelta(RemoteTimeDelta remote_delta) const62 LocalTimeDelta InterProcessTimeTicksConverter::ToLocalTimeDelta(
63 RemoteTimeDelta remote_delta) const {
64 DCHECK_LE(remote_lower_bound_ + remote_delta, remote_upper_bound_);
65
66 // For remote times that come before remote time range, apply just time
67 // offset and ignore scaling, so as to avoid extrapolation error for values
68 // long in the past.
69 if (remote_delta <= RemoteTimeDelta())
70 return LocalTimeDelta::FromTimeDelta(remote_delta.ToTimeDelta());
71
72 return std::min(local_range_,
73 LocalTimeDelta::FromTimeDelta(remote_delta.ToTimeDelta() *
74 range_conversion_rate_));
75 }
76
GetSkewForMetrics() const77 base::TimeDelta InterProcessTimeTicksConverter::GetSkewForMetrics() const {
78 return remote_lower_bound_.ToTimeTicks() - local_base_time_.ToTimeTicks();
79 }
80
81 } // namespace content
82