Home | History | Annotate | Download | only in common
      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