Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | #include "base/time/time.h" |
michael@0 | 6 | |
michael@0 | 7 | #include <limits> |
michael@0 | 8 | #include <ostream> |
michael@0 | 9 | |
michael@0 | 10 | #include "base/float_util.h" |
michael@0 | 11 | #include "base/logging.h" |
michael@0 | 12 | #include "base/third_party/nspr/prtime.h" |
michael@0 | 13 | #include "base/third_party/nspr/prtypes.h" |
michael@0 | 14 | |
michael@0 | 15 | namespace base { |
michael@0 | 16 | |
michael@0 | 17 | // TimeDelta ------------------------------------------------------------------ |
michael@0 | 18 | |
michael@0 | 19 | int TimeDelta::InDays() const { |
michael@0 | 20 | return static_cast<int>(delta_ / Time::kMicrosecondsPerDay); |
michael@0 | 21 | } |
michael@0 | 22 | |
michael@0 | 23 | int TimeDelta::InHours() const { |
michael@0 | 24 | return static_cast<int>(delta_ / Time::kMicrosecondsPerHour); |
michael@0 | 25 | } |
michael@0 | 26 | |
michael@0 | 27 | int TimeDelta::InMinutes() const { |
michael@0 | 28 | return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute); |
michael@0 | 29 | } |
michael@0 | 30 | |
michael@0 | 31 | double TimeDelta::InSecondsF() const { |
michael@0 | 32 | return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; |
michael@0 | 33 | } |
michael@0 | 34 | |
michael@0 | 35 | int64 TimeDelta::InSeconds() const { |
michael@0 | 36 | return delta_ / Time::kMicrosecondsPerSecond; |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | double TimeDelta::InMillisecondsF() const { |
michael@0 | 40 | return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | int64 TimeDelta::InMilliseconds() const { |
michael@0 | 44 | return delta_ / Time::kMicrosecondsPerMillisecond; |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | int64 TimeDelta::InMillisecondsRoundedUp() const { |
michael@0 | 48 | return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / |
michael@0 | 49 | Time::kMicrosecondsPerMillisecond; |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | int64 TimeDelta::InMicroseconds() const { |
michael@0 | 53 | return delta_; |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | // Time ----------------------------------------------------------------------- |
michael@0 | 57 | |
michael@0 | 58 | // static |
michael@0 | 59 | Time Time::Max() { |
michael@0 | 60 | return Time(std::numeric_limits<int64>::max()); |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | // static |
michael@0 | 64 | Time Time::FromTimeT(time_t tt) { |
michael@0 | 65 | if (tt == 0) |
michael@0 | 66 | return Time(); // Preserve 0 so we can tell it doesn't exist. |
michael@0 | 67 | if (tt == std::numeric_limits<time_t>::max()) |
michael@0 | 68 | return Max(); |
michael@0 | 69 | return Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset); |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | time_t Time::ToTimeT() const { |
michael@0 | 73 | if (is_null()) |
michael@0 | 74 | return 0; // Preserve 0 so we can tell it doesn't exist. |
michael@0 | 75 | if (is_max()) { |
michael@0 | 76 | // Preserve max without offset to prevent overflow. |
michael@0 | 77 | return std::numeric_limits<time_t>::max(); |
michael@0 | 78 | } |
michael@0 | 79 | if (std::numeric_limits<int64>::max() - kTimeTToMicrosecondsOffset <= us_) { |
michael@0 | 80 | DLOG(WARNING) << "Overflow when converting base::Time with internal " << |
michael@0 | 81 | "value " << us_ << " to time_t."; |
michael@0 | 82 | return std::numeric_limits<time_t>::max(); |
michael@0 | 83 | } |
michael@0 | 84 | return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond; |
michael@0 | 85 | } |
michael@0 | 86 | |
michael@0 | 87 | // static |
michael@0 | 88 | Time Time::FromDoubleT(double dt) { |
michael@0 | 89 | if (dt == 0 || IsNaN(dt)) |
michael@0 | 90 | return Time(); // Preserve 0 so we can tell it doesn't exist. |
michael@0 | 91 | if (dt == std::numeric_limits<double>::max()) |
michael@0 | 92 | return Max(); |
michael@0 | 93 | return Time(static_cast<int64>((dt * |
michael@0 | 94 | static_cast<double>(kMicrosecondsPerSecond)) + |
michael@0 | 95 | kTimeTToMicrosecondsOffset)); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | double Time::ToDoubleT() const { |
michael@0 | 99 | if (is_null()) |
michael@0 | 100 | return 0; // Preserve 0 so we can tell it doesn't exist. |
michael@0 | 101 | if (is_max()) { |
michael@0 | 102 | // Preserve max without offset to prevent overflow. |
michael@0 | 103 | return std::numeric_limits<double>::max(); |
michael@0 | 104 | } |
michael@0 | 105 | return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / |
michael@0 | 106 | static_cast<double>(kMicrosecondsPerSecond)); |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | #if defined(OS_POSIX) |
michael@0 | 110 | // static |
michael@0 | 111 | Time Time::FromTimeSpec(const timespec& ts) { |
michael@0 | 112 | return FromDoubleT(ts.tv_sec + |
michael@0 | 113 | static_cast<double>(ts.tv_nsec) / |
michael@0 | 114 | base::Time::kNanosecondsPerSecond); |
michael@0 | 115 | } |
michael@0 | 116 | #endif |
michael@0 | 117 | |
michael@0 | 118 | // static |
michael@0 | 119 | Time Time::FromJsTime(double ms_since_epoch) { |
michael@0 | 120 | // The epoch is a valid time, so this constructor doesn't interpret |
michael@0 | 121 | // 0 as the null time. |
michael@0 | 122 | if (ms_since_epoch == std::numeric_limits<double>::max()) |
michael@0 | 123 | return Max(); |
michael@0 | 124 | return Time(static_cast<int64>(ms_since_epoch * kMicrosecondsPerMillisecond) + |
michael@0 | 125 | kTimeTToMicrosecondsOffset); |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | double Time::ToJsTime() const { |
michael@0 | 129 | if (is_null()) { |
michael@0 | 130 | // Preserve 0 so the invalid result doesn't depend on the platform. |
michael@0 | 131 | return 0; |
michael@0 | 132 | } |
michael@0 | 133 | if (is_max()) { |
michael@0 | 134 | // Preserve max without offset to prevent overflow. |
michael@0 | 135 | return std::numeric_limits<double>::max(); |
michael@0 | 136 | } |
michael@0 | 137 | return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / |
michael@0 | 138 | kMicrosecondsPerMillisecond); |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | int64 Time::ToJavaTime() const { |
michael@0 | 142 | if (is_null()) { |
michael@0 | 143 | // Preserve 0 so the invalid result doesn't depend on the platform. |
michael@0 | 144 | return 0; |
michael@0 | 145 | } |
michael@0 | 146 | if (is_max()) { |
michael@0 | 147 | // Preserve max without offset to prevent overflow. |
michael@0 | 148 | return std::numeric_limits<int64>::max(); |
michael@0 | 149 | } |
michael@0 | 150 | return ((us_ - kTimeTToMicrosecondsOffset) / |
michael@0 | 151 | kMicrosecondsPerMillisecond); |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | // static |
michael@0 | 155 | Time Time::UnixEpoch() { |
michael@0 | 156 | Time time; |
michael@0 | 157 | time.us_ = kTimeTToMicrosecondsOffset; |
michael@0 | 158 | return time; |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | Time Time::LocalMidnight() const { |
michael@0 | 162 | Exploded exploded; |
michael@0 | 163 | LocalExplode(&exploded); |
michael@0 | 164 | exploded.hour = 0; |
michael@0 | 165 | exploded.minute = 0; |
michael@0 | 166 | exploded.second = 0; |
michael@0 | 167 | exploded.millisecond = 0; |
michael@0 | 168 | return FromLocalExploded(exploded); |
michael@0 | 169 | } |
michael@0 | 170 | |
michael@0 | 171 | // static |
michael@0 | 172 | bool Time::FromStringInternal(const char* time_string, |
michael@0 | 173 | bool is_local, |
michael@0 | 174 | Time* parsed_time) { |
michael@0 | 175 | DCHECK((time_string != NULL) && (parsed_time != NULL)); |
michael@0 | 176 | |
michael@0 | 177 | if (time_string[0] == '\0') |
michael@0 | 178 | return false; |
michael@0 | 179 | |
michael@0 | 180 | PRTime result_time = 0; |
michael@0 | 181 | PRStatus result = PR_ParseTimeString(time_string, |
michael@0 | 182 | is_local ? PR_FALSE : PR_TRUE, |
michael@0 | 183 | &result_time); |
michael@0 | 184 | if (PR_SUCCESS != result) |
michael@0 | 185 | return false; |
michael@0 | 186 | |
michael@0 | 187 | result_time += kTimeTToMicrosecondsOffset; |
michael@0 | 188 | *parsed_time = Time(result_time); |
michael@0 | 189 | return true; |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | // Time::Exploded ------------------------------------------------------------- |
michael@0 | 193 | |
michael@0 | 194 | inline bool is_in_range(int value, int lo, int hi) { |
michael@0 | 195 | return lo <= value && value <= hi; |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | bool Time::Exploded::HasValidValues() const { |
michael@0 | 199 | return is_in_range(month, 1, 12) && |
michael@0 | 200 | is_in_range(day_of_week, 0, 6) && |
michael@0 | 201 | is_in_range(day_of_month, 1, 31) && |
michael@0 | 202 | is_in_range(hour, 0, 23) && |
michael@0 | 203 | is_in_range(minute, 0, 59) && |
michael@0 | 204 | is_in_range(second, 0, 60) && |
michael@0 | 205 | is_in_range(millisecond, 0, 999); |
michael@0 | 206 | } |
michael@0 | 207 | |
michael@0 | 208 | } // namespace base |