blob: 128abab37eb8a96535ef92ebf11a463e863cc485 [file] [log] [blame]
// 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 <algorithm>
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
namespace content {
InterProcessTimeTicksConverter::InterProcessTimeTicksConverter(
LocalTimeTicks local_lower_bound,
LocalTimeTicks local_upper_bound,
RemoteTimeTicks remote_lower_bound,
RemoteTimeTicks remote_upper_bound)
: local_range_(local_upper_bound - local_lower_bound),
remote_lower_bound_(remote_lower_bound),
remote_upper_bound_(remote_upper_bound) {
RemoteTimeDelta remote_range = remote_upper_bound - remote_lower_bound;
DCHECK_LE(LocalTimeDelta(), local_range_);
DCHECK_LE(RemoteTimeDelta(), remote_range);
if (remote_range.ToTimeDelta() <= local_range_.ToTimeDelta()) {
// We fit! Center the source range on the target range.
range_conversion_rate_ = 1.0;
base::TimeDelta diff =
local_range_.ToTimeDelta() - remote_range.ToTimeDelta();
local_base_time_ =
local_lower_bound + LocalTimeDelta::FromTimeDelta(diff / 2);
// When converting times, remote bounds should fall within local bounds.
DCHECK_LE(local_lower_bound, ToLocalTimeTicks(remote_lower_bound));
DCHECK_LE(ToLocalTimeTicks(remote_upper_bound), local_upper_bound);
return;
}
// Interpolate values so that remote range will be will exactly fit into the
// local range, if possible.
DCHECK_GT(remote_range.ToTimeDelta().InMicroseconds(), 0);
range_conversion_rate_ =
static_cast<double>(local_range_.ToTimeDelta().InMicroseconds()) /
remote_range.ToTimeDelta().InMicroseconds();
local_base_time_ = local_lower_bound;
}
LocalTimeTicks InterProcessTimeTicksConverter::ToLocalTimeTicks(
RemoteTimeTicks remote_time_ticks) const {
// If input time is "null", return another "null" time.
if (remote_time_ticks.is_null())
return LocalTimeTicks();
RemoteTimeDelta remote_delta = remote_time_ticks - remote_lower_bound_;
DCHECK_LE(remote_time_ticks, remote_upper_bound_);
return local_base_time_ + ToLocalTimeDelta(remote_delta);
}
LocalTimeDelta InterProcessTimeTicksConverter::ToLocalTimeDelta(
RemoteTimeDelta remote_delta) const {
DCHECK_LE(remote_lower_bound_ + remote_delta, remote_upper_bound_);
// For remote times that come before remote time range, apply just time
// offset and ignore scaling, so as to avoid extrapolation error for values
// long in the past.
if (remote_delta <= RemoteTimeDelta())
return LocalTimeDelta::FromTimeDelta(remote_delta.ToTimeDelta());
return std::min(local_range_,
LocalTimeDelta::FromTimeDelta(remote_delta.ToTimeDelta() *
range_conversion_rate_));
}
base::TimeDelta InterProcessTimeTicksConverter::GetSkewForMetrics() const {
return remote_lower_bound_.ToTimeTicks() - local_base_time_.ToTimeTicks();
}
} // namespace content