• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_
6 #define CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_
7 
8 #include "base/time/time.h"
9 #include "content/common/content_export.h"
10 
11 namespace content {
12 
13 class LocalTimeDelta;
14 class LocalTimeTicks;
15 class RemoteTimeDelta;
16 class RemoteTimeTicks;
17 
18 // On Windows, TimeTicks are not consistent between processes. Often, the values
19 // on one process have a static offset relative to another. Occasionally, these
20 // offsets shift while running.
21 //
22 // To combat this, any TimeTicks values sent from the remote process to the
23 // local process must be tweaked in order to appear monotonic.
24 //
25 // In order to properly tweak ticks, we need 4 reference points:
26 //
27 // - |local_lower_bound|:  A known point, recorded on the local process, that
28 //                         occurs before any remote values that will be
29 //                         converted.
30 // - |remote_lower_bound|: The equivalent point on the remote process. This
31 //                         should be recorded immediately after
32 //                         |local_lower_bound|.
33 // - |local_upper_bound|:  A known point, recorded on the local process, that
34 //                         occurs after any remote values that will be
35 //                         converted.
36 // - |remote_upper_bound|: The equivalent point on the remote process. This
37 //                         should be recorded immediately before
38 //                         |local_upper_bound|.
39 //
40 // Once these bounds are determined, values within the remote process's range
41 // can be converted to the local process's range. The values are converted as
42 // follows:
43 //
44 // 1. If the remote's range exceeds the local's range, it is scaled to fit.
45 //    Any values converted will have the same scale factor applied.
46 //
47 // 2. The remote's range is shifted so that it is centered within the
48 //    local's range. Any values converted will be shifted the same amount.
49 class CONTENT_EXPORT InterProcessTimeTicksConverter {
50  public:
51   InterProcessTimeTicksConverter(const LocalTimeTicks& local_lower_bound,
52                                  const LocalTimeTicks& local_upper_bound,
53                                  const RemoteTimeTicks& remote_lower_bound,
54                                  const RemoteTimeTicks& remote_upper_bound);
55 
56   // Returns the value within the local's bounds that correlates to
57   // |remote_ms|.
58   LocalTimeTicks ToLocalTimeTicks(const RemoteTimeTicks& remote_ms) const;
59 
60   // Returns the equivalent delta after applying remote-to-local scaling to
61   // |remote_delta|.
62   LocalTimeDelta ToLocalTimeDelta(const RemoteTimeDelta& remote_delta) const;
63 
64  private:
65   int64 Convert(int64 value) const;
66 
67   // The local time which |remote_lower_bound_| is mapped to.
68   int64 local_base_time_;
69 
70   int64 numerator_;
71   int64 denominator_;
72 
73   int64 remote_lower_bound_;
74   int64 remote_upper_bound_;
75 };
76 
77 class CONTENT_EXPORT LocalTimeDelta {
78  public:
ToInt32()79   int ToInt32() const { return value_; }
80 
81  private:
82   friend class InterProcessTimeTicksConverter;
83   friend class LocalTimeTicks;
84 
LocalTimeDelta(int value)85   LocalTimeDelta(int value) : value_(value) {}
86 
87   int value_;
88 };
89 
90 class CONTENT_EXPORT LocalTimeTicks {
91  public:
FromTimeTicks(const base::TimeTicks & value)92   static LocalTimeTicks FromTimeTicks(const base::TimeTicks& value) {
93     return LocalTimeTicks(value.ToInternalValue());
94   }
95 
ToTimeTicks()96   base::TimeTicks ToTimeTicks() {
97     return base::TimeTicks::FromInternalValue(value_);
98   }
99 
100   LocalTimeTicks operator+(const LocalTimeDelta& delta) {
101     return LocalTimeTicks(value_ + delta.value_);
102   }
103 
104  private:
105   friend class InterProcessTimeTicksConverter;
106 
LocalTimeTicks(int64 value)107   LocalTimeTicks(int64 value) : value_(value) {}
108 
109   int64 value_;
110 };
111 
112 class CONTENT_EXPORT RemoteTimeDelta {
113  public:
FromRawDelta(int delta)114   static RemoteTimeDelta FromRawDelta(int delta) {
115     return RemoteTimeDelta(delta);
116   }
117 
118  private:
119   friend class InterProcessTimeTicksConverter;
120   friend class RemoteTimeTicks;
121 
RemoteTimeDelta(int value)122   RemoteTimeDelta(int value) : value_(value) {}
123 
124   int value_;
125 };
126 
127 class CONTENT_EXPORT RemoteTimeTicks {
128  public:
FromTimeTicks(const base::TimeTicks & ticks)129   static RemoteTimeTicks FromTimeTicks(const base::TimeTicks& ticks) {
130     return RemoteTimeTicks(ticks.ToInternalValue());
131   }
132 
133   RemoteTimeDelta operator-(const RemoteTimeTicks& rhs) const {
134     return RemoteTimeDelta(value_ - rhs.value_);
135   }
136 
137  private:
138   friend class InterProcessTimeTicksConverter;
139 
RemoteTimeTicks(int64 value)140   RemoteTimeTicks(int64 value) : value_(value) {}
141 
142   int64 value_;
143 };
144 
145 }  // namespace content
146 
147 #endif  // CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_
148