Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | // |
michael@0 | 8 | // Implement TimeStamp::Now() with mach_absolute_time |
michael@0 | 9 | // |
michael@0 | 10 | // The "tick" unit for mach_absolute_time is defined using mach_timebase_info() which |
michael@0 | 11 | // gives a conversion ratio to nanoseconds. For more information see Apple's QA1398. |
michael@0 | 12 | // |
michael@0 | 13 | // This code is inspired by Chromium's time_mac.cc. The biggest |
michael@0 | 14 | // differences are that we explicitly initialize using |
michael@0 | 15 | // TimeStamp::Initialize() instead of lazily in Now() and that |
michael@0 | 16 | // we store the time value in ticks and convert when needed instead |
michael@0 | 17 | // of storing the time value in nanoseconds. |
michael@0 | 18 | |
michael@0 | 19 | #include <mach/mach_time.h> |
michael@0 | 20 | #include <sys/time.h> |
michael@0 | 21 | #include <sys/sysctl.h> |
michael@0 | 22 | #include <time.h> |
michael@0 | 23 | #include <unistd.h> |
michael@0 | 24 | |
michael@0 | 25 | #include "mozilla/TimeStamp.h" |
michael@0 | 26 | #include "nsDebug.h" |
michael@0 | 27 | |
michael@0 | 28 | // Estimate of the smallest duration of time we can measure. |
michael@0 | 29 | static uint64_t sResolution; |
michael@0 | 30 | static uint64_t sResolutionSigDigs; |
michael@0 | 31 | |
michael@0 | 32 | static const uint64_t kNsPerMs = 1000000; |
michael@0 | 33 | static const uint64_t kUsPerSec = 1000000; |
michael@0 | 34 | static const double kNsPerMsd = 1000000.0; |
michael@0 | 35 | static const double kNsPerSecd = 1000000000.0; |
michael@0 | 36 | |
michael@0 | 37 | static bool gInitialized = false; |
michael@0 | 38 | static double sNsPerTick; |
michael@0 | 39 | |
michael@0 | 40 | static uint64_t |
michael@0 | 41 | ClockTime() |
michael@0 | 42 | { |
michael@0 | 43 | // mach_absolute_time is it when it comes to ticks on the Mac. Other calls |
michael@0 | 44 | // with less precision (such as TickCount) just call through to |
michael@0 | 45 | // mach_absolute_time. |
michael@0 | 46 | // |
michael@0 | 47 | // At the time of writing mach_absolute_time returns the number of nanoseconds |
michael@0 | 48 | // since boot. This won't overflow 64bits for 500+ years so we aren't going |
michael@0 | 49 | // to worry about that possiblity |
michael@0 | 50 | return mach_absolute_time(); |
michael@0 | 51 | } |
michael@0 | 52 | |
michael@0 | 53 | static uint64_t |
michael@0 | 54 | ClockResolutionNs() |
michael@0 | 55 | { |
michael@0 | 56 | uint64_t start = ClockTime(); |
michael@0 | 57 | uint64_t end = ClockTime(); |
michael@0 | 58 | uint64_t minres = (end - start); |
michael@0 | 59 | |
michael@0 | 60 | // 10 total trials is arbitrary: what we're trying to avoid by |
michael@0 | 61 | // looping is getting unlucky and being interrupted by a context |
michael@0 | 62 | // switch or signal, or being bitten by paging/cache effects |
michael@0 | 63 | for (int i = 0; i < 9; ++i) { |
michael@0 | 64 | start = ClockTime(); |
michael@0 | 65 | end = ClockTime(); |
michael@0 | 66 | |
michael@0 | 67 | uint64_t candidate = (start - end); |
michael@0 | 68 | if (candidate < minres) |
michael@0 | 69 | minres = candidate; |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | if (0 == minres) { |
michael@0 | 73 | // measurable resolution is either incredibly low, ~1ns, or very |
michael@0 | 74 | // high. fall back on NSPR's resolution assumption |
michael@0 | 75 | minres = 1 * kNsPerMs; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | return minres; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | namespace mozilla { |
michael@0 | 82 | |
michael@0 | 83 | double |
michael@0 | 84 | TimeDuration::ToSeconds() const |
michael@0 | 85 | { |
michael@0 | 86 | NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early"); |
michael@0 | 87 | return (mValue * sNsPerTick) / kNsPerSecd; |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | double |
michael@0 | 91 | TimeDuration::ToSecondsSigDigits() const |
michael@0 | 92 | { |
michael@0 | 93 | NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early"); |
michael@0 | 94 | // don't report a value < mResolution ... |
michael@0 | 95 | int64_t valueSigDigs = sResolution * (mValue / sResolution); |
michael@0 | 96 | // and chop off insignificant digits |
michael@0 | 97 | valueSigDigs = sResolutionSigDigs * (valueSigDigs / sResolutionSigDigs); |
michael@0 | 98 | return (valueSigDigs * sNsPerTick) / kNsPerSecd; |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | TimeDuration |
michael@0 | 102 | TimeDuration::FromMilliseconds(double aMilliseconds) |
michael@0 | 103 | { |
michael@0 | 104 | NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early"); |
michael@0 | 105 | return TimeDuration::FromTicks(int64_t((aMilliseconds * kNsPerMsd) / sNsPerTick)); |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | TimeDuration |
michael@0 | 109 | TimeDuration::Resolution() |
michael@0 | 110 | { |
michael@0 | 111 | NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early"); |
michael@0 | 112 | return TimeDuration::FromTicks(int64_t(sResolution)); |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | nsresult |
michael@0 | 116 | TimeStamp::Startup() |
michael@0 | 117 | { |
michael@0 | 118 | if (gInitialized) |
michael@0 | 119 | return NS_OK; |
michael@0 | 120 | |
michael@0 | 121 | mach_timebase_info_data_t timebaseInfo; |
michael@0 | 122 | // Apple's QA1398 suggests that the output from mach_timebase_info |
michael@0 | 123 | // will not change while a program is running, so it should be safe |
michael@0 | 124 | // to cache the result. |
michael@0 | 125 | kern_return_t kr = mach_timebase_info(&timebaseInfo); |
michael@0 | 126 | if (kr != KERN_SUCCESS) |
michael@0 | 127 | NS_RUNTIMEABORT("mach_timebase_info failed"); |
michael@0 | 128 | |
michael@0 | 129 | sNsPerTick = double(timebaseInfo.numer) / timebaseInfo.denom; |
michael@0 | 130 | |
michael@0 | 131 | sResolution = ClockResolutionNs(); |
michael@0 | 132 | |
michael@0 | 133 | // find the number of significant digits in sResolution, for the |
michael@0 | 134 | // sake of ToSecondsSigDigits() |
michael@0 | 135 | for (sResolutionSigDigs = 1; |
michael@0 | 136 | !(sResolutionSigDigs == sResolution |
michael@0 | 137 | || 10*sResolutionSigDigs > sResolution); |
michael@0 | 138 | sResolutionSigDigs *= 10); |
michael@0 | 139 | |
michael@0 | 140 | gInitialized = true; |
michael@0 | 141 | |
michael@0 | 142 | return NS_OK; |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | void |
michael@0 | 146 | TimeStamp::Shutdown() |
michael@0 | 147 | { |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | TimeStamp |
michael@0 | 151 | TimeStamp::Now(bool aHighResolution) |
michael@0 | 152 | { |
michael@0 | 153 | return TimeStamp(ClockTime()); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | // Computes and returns the process uptime in microseconds. |
michael@0 | 157 | // Returns 0 if an error was encountered. |
michael@0 | 158 | |
michael@0 | 159 | uint64_t |
michael@0 | 160 | TimeStamp::ComputeProcessUptime() |
michael@0 | 161 | { |
michael@0 | 162 | struct timeval tv; |
michael@0 | 163 | int rv = gettimeofday(&tv, nullptr); |
michael@0 | 164 | |
michael@0 | 165 | if (rv == -1) { |
michael@0 | 166 | return 0; |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | int mib[] = { |
michael@0 | 170 | CTL_KERN, |
michael@0 | 171 | KERN_PROC, |
michael@0 | 172 | KERN_PROC_PID, |
michael@0 | 173 | getpid(), |
michael@0 | 174 | }; |
michael@0 | 175 | u_int mibLen = sizeof(mib) / sizeof(mib[0]); |
michael@0 | 176 | |
michael@0 | 177 | struct kinfo_proc proc; |
michael@0 | 178 | size_t bufferSize = sizeof(proc); |
michael@0 | 179 | rv = sysctl(mib, mibLen, &proc, &bufferSize, nullptr, 0); |
michael@0 | 180 | |
michael@0 | 181 | if (rv == -1) |
michael@0 | 182 | return 0; |
michael@0 | 183 | |
michael@0 | 184 | uint64_t startTime = |
michael@0 | 185 | ((uint64_t)proc.kp_proc.p_un.__p_starttime.tv_sec * kUsPerSec) + |
michael@0 | 186 | proc.kp_proc.p_un.__p_starttime.tv_usec; |
michael@0 | 187 | uint64_t now = (tv.tv_sec * kUsPerSec) + tv.tv_usec; |
michael@0 | 188 | |
michael@0 | 189 | if (startTime > now) |
michael@0 | 190 | return 0; |
michael@0 | 191 | |
michael@0 | 192 | return now - startTime; |
michael@0 | 193 | } |
michael@0 | 194 | |
michael@0 | 195 | } // namespace mozilla |