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: 79 int ToInt32() const { return value_; } 80 81 private: 82 friend class InterProcessTimeTicksConverter; 83 friend class LocalTimeTicks; 84 85 LocalTimeDelta(int value) : value_(value) {} 86 87 int value_; 88 }; 89 90 class CONTENT_EXPORT LocalTimeTicks { 91 public: 92 static LocalTimeTicks FromTimeTicks(const base::TimeTicks& value) { 93 return LocalTimeTicks(value.ToInternalValue()); 94 } 95 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 107 LocalTimeTicks(int64 value) : value_(value) {} 108 109 int64 value_; 110 }; 111 112 class CONTENT_EXPORT RemoteTimeDelta { 113 public: 114 static RemoteTimeDelta FromRawDelta(int delta) { 115 return RemoteTimeDelta(delta); 116 } 117 118 private: 119 friend class InterProcessTimeTicksConverter; 120 friend class RemoteTimeTicks; 121 122 RemoteTimeDelta(int value) : value_(value) {} 123 124 int value_; 125 }; 126 127 class CONTENT_EXPORT RemoteTimeTicks { 128 public: 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 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