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 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #ifndef mozilla_IOInterposer_h |
michael@0 | 6 | #define mozilla_IOInterposer_h |
michael@0 | 7 | |
michael@0 | 8 | #include "mozilla/Attributes.h" |
michael@0 | 9 | #include "mozilla/TimeStamp.h" |
michael@0 | 10 | #include "mozilla/XPCOM.h" |
michael@0 | 11 | |
michael@0 | 12 | namespace mozilla { |
michael@0 | 13 | |
michael@0 | 14 | /** |
michael@0 | 15 | * Interface for I/O interposer observers. This is separate from the |
michael@0 | 16 | * IOInterposer because we have multiple uses for these observations. |
michael@0 | 17 | */ |
michael@0 | 18 | class IOInterposeObserver |
michael@0 | 19 | { |
michael@0 | 20 | public: |
michael@0 | 21 | enum Operation |
michael@0 | 22 | { |
michael@0 | 23 | OpNone = 0, |
michael@0 | 24 | OpCreateOrOpen = (1 << 0), |
michael@0 | 25 | OpRead = (1 << 1), |
michael@0 | 26 | OpWrite = (1 << 2), |
michael@0 | 27 | OpFSync = (1 << 3), |
michael@0 | 28 | OpStat = (1 << 4), |
michael@0 | 29 | OpClose = (1 << 5), |
michael@0 | 30 | OpNextStage = (1 << 6), // Meta - used when leaving startup, entering shutdown |
michael@0 | 31 | OpWriteFSync = (OpWrite | OpFSync), |
michael@0 | 32 | OpAll = (OpCreateOrOpen | OpRead | OpWrite | OpFSync | OpStat | OpClose), |
michael@0 | 33 | OpAllWithStaging = (OpAll | OpNextStage) |
michael@0 | 34 | }; |
michael@0 | 35 | |
michael@0 | 36 | /** A representation of an I/O observation */ |
michael@0 | 37 | class Observation |
michael@0 | 38 | { |
michael@0 | 39 | protected: |
michael@0 | 40 | /** |
michael@0 | 41 | * This constructor is for use by subclasses that are intended to take |
michael@0 | 42 | * timing measurements via RAII. The |aShouldReport| parameter may be |
michael@0 | 43 | * used to make the measurement and reporting conditional on the |
michael@0 | 44 | * satisfaction of an arbitrary predicate that was evaluated |
michael@0 | 45 | * in the subclass. Note that IOInterposer::IsObservedOperation() is |
michael@0 | 46 | * always ANDed with aShouldReport, so the subclass does not need to |
michael@0 | 47 | * include a call to that function explicitly. |
michael@0 | 48 | */ |
michael@0 | 49 | Observation(Operation aOperation, const char* aReference, |
michael@0 | 50 | bool aShouldReport = true); |
michael@0 | 51 | |
michael@0 | 52 | public: |
michael@0 | 53 | /** |
michael@0 | 54 | * Since this constructor accepts start and end times, it does *not* take |
michael@0 | 55 | * its own timings, nor does it report itself. |
michael@0 | 56 | */ |
michael@0 | 57 | Observation(Operation aOperation, const TimeStamp& aStart, |
michael@0 | 58 | const TimeStamp& aEnd, const char* aReference); |
michael@0 | 59 | |
michael@0 | 60 | /** |
michael@0 | 61 | * Operation observed, this is one of the individual Operation values. |
michael@0 | 62 | * Combinations of these flags are only used when registering observers. |
michael@0 | 63 | */ |
michael@0 | 64 | Operation ObservedOperation() const |
michael@0 | 65 | { |
michael@0 | 66 | return mOperation; |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | /** |
michael@0 | 70 | * Return the observed operation as a human-readable string. |
michael@0 | 71 | */ |
michael@0 | 72 | const char* ObservedOperationString() const; |
michael@0 | 73 | |
michael@0 | 74 | /** Time at which the I/O operation was started */ |
michael@0 | 75 | TimeStamp Start() const |
michael@0 | 76 | { |
michael@0 | 77 | return mStart; |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | /** |
michael@0 | 81 | * Time at which the I/O operation ended, for asynchronous methods this is |
michael@0 | 82 | * the time at which the call initiating the asynchronous request returned. |
michael@0 | 83 | */ |
michael@0 | 84 | TimeStamp End() const |
michael@0 | 85 | { |
michael@0 | 86 | return mEnd; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | /** |
michael@0 | 90 | * Duration of the operation, for asynchronous I/O methods this is the |
michael@0 | 91 | * duration of the call initiating the asynchronous request. |
michael@0 | 92 | */ |
michael@0 | 93 | TimeDuration Duration() const |
michael@0 | 94 | { |
michael@0 | 95 | return mEnd - mStart; |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | /** |
michael@0 | 99 | * IO reference, function name or name of component (sqlite) that did IO |
michael@0 | 100 | * this is in addition the generic operation. This attribute may be platform |
michael@0 | 101 | * specific, but should only take a finite number of distinct values. |
michael@0 | 102 | * E.g. sqlite-commit, CreateFile, NtReadFile, fread, fsync, mmap, etc. |
michael@0 | 103 | * I.e. typically the platform specific function that did the IO. |
michael@0 | 104 | */ |
michael@0 | 105 | const char* Reference() const |
michael@0 | 106 | { |
michael@0 | 107 | return mReference; |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | /** Request filename associated with the I/O operation, null if unknown */ |
michael@0 | 111 | virtual const char16_t* Filename() |
michael@0 | 112 | { |
michael@0 | 113 | return nullptr; |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | virtual ~Observation() |
michael@0 | 117 | { |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | protected: |
michael@0 | 121 | void |
michael@0 | 122 | Report(); |
michael@0 | 123 | |
michael@0 | 124 | Operation mOperation; |
michael@0 | 125 | TimeStamp mStart; |
michael@0 | 126 | TimeStamp mEnd; |
michael@0 | 127 | const char* mReference; // Identifies the source of the Observation |
michael@0 | 128 | bool mShouldReport; // Measure and report if true |
michael@0 | 129 | }; |
michael@0 | 130 | |
michael@0 | 131 | /** |
michael@0 | 132 | * Invoked whenever an implementation of the IOInterposeObserver should |
michael@0 | 133 | * observe aObservation. Implement this and do your thing... |
michael@0 | 134 | * But do consider if it is wise to use IO functions in this method, they are |
michael@0 | 135 | * likely to cause recursion :) |
michael@0 | 136 | * At least, see PoisonIOInterposer.h and register your handle as a debug file |
michael@0 | 137 | * even, if you don't initialize the poison IO interposer, someone else might. |
michael@0 | 138 | * |
michael@0 | 139 | * Remark: Observations may occur on any thread. |
michael@0 | 140 | */ |
michael@0 | 141 | virtual void Observe(Observation& aObservation) = 0; |
michael@0 | 142 | |
michael@0 | 143 | virtual ~IOInterposeObserver() |
michael@0 | 144 | { |
michael@0 | 145 | } |
michael@0 | 146 | |
michael@0 | 147 | protected: |
michael@0 | 148 | /** |
michael@0 | 149 | * We don't use NS_IsMainThread() because we need to be able to determine the |
michael@0 | 150 | * main thread outside of XPCOM Initialization. IOInterposer observers should |
michael@0 | 151 | * call this function instead. |
michael@0 | 152 | */ |
michael@0 | 153 | static bool IsMainThread(); |
michael@0 | 154 | }; |
michael@0 | 155 | |
michael@0 | 156 | /** |
michael@0 | 157 | * These functions are responsible for ensuring that events are routed to the |
michael@0 | 158 | * appropriate observers. |
michael@0 | 159 | */ |
michael@0 | 160 | namespace IOInterposer |
michael@0 | 161 | { |
michael@0 | 162 | /** |
michael@0 | 163 | * This function must be called from the main-thread when no other threads are |
michael@0 | 164 | * running before any of the other methods on this class may be used. |
michael@0 | 165 | * |
michael@0 | 166 | * IO reports can however, safely assume that IsObservedOperation() will |
michael@0 | 167 | * return false until the IOInterposer is initialized. |
michael@0 | 168 | * |
michael@0 | 169 | * Remark, it's safe to call this method multiple times, so just call it when |
michael@0 | 170 | * you to utilize IO interposing. |
michael@0 | 171 | * |
michael@0 | 172 | * Using the IOInterposerInit class is preferred to calling this directly. |
michael@0 | 173 | */ |
michael@0 | 174 | bool Init(); |
michael@0 | 175 | |
michael@0 | 176 | /** |
michael@0 | 177 | * This function must be called from the main thread, and furthermore |
michael@0 | 178 | * it must be called when no other threads are executing. Effectively |
michael@0 | 179 | * restricting us to calling it only during shutdown. |
michael@0 | 180 | * |
michael@0 | 181 | * Callers should take care that no other consumers are subscribed to events, |
michael@0 | 182 | * as these events will stop when this function is called. |
michael@0 | 183 | * |
michael@0 | 184 | * In practice, we don't use this method as the IOInterposer is used for |
michael@0 | 185 | * late-write checks. |
michael@0 | 186 | */ |
michael@0 | 187 | void Clear(); |
michael@0 | 188 | |
michael@0 | 189 | /** |
michael@0 | 190 | * This function immediately disables IOInterposer functionality in a fast, |
michael@0 | 191 | * thread-safe manner. Primarily for use by the crash reporter. |
michael@0 | 192 | */ |
michael@0 | 193 | void Disable(); |
michael@0 | 194 | |
michael@0 | 195 | /** |
michael@0 | 196 | * Report IO to registered observers. |
michael@0 | 197 | * Notice that the reported operation must be either OpRead, OpWrite or |
michael@0 | 198 | * OpFSync. You are not allowed to report an observation with OpWriteFSync or |
michael@0 | 199 | * OpAll, these are just auxiliary values for use with Register(). |
michael@0 | 200 | * |
michael@0 | 201 | * If the IO call you're reporting does multiple things, write and fsync, you |
michael@0 | 202 | * can choose to call Report() twice once with write and once with FSync. You |
michael@0 | 203 | * may not call Report() with OpWriteFSync! The Observation::mOperation |
michael@0 | 204 | * attribute is meant to be generic, not perfect. |
michael@0 | 205 | * |
michael@0 | 206 | * Notice that there is no reason to report an observation with an operation |
michael@0 | 207 | * which is not being observed. Use IsObservedOperation() to check if the |
michael@0 | 208 | * operation you are about to report is being observed. This is especially |
michael@0 | 209 | * important if you are constructing expensive observations containing |
michael@0 | 210 | * filename and full-path. |
michael@0 | 211 | * |
michael@0 | 212 | * Remark: Init() must be called before any IO is reported. But |
michael@0 | 213 | * IsObservedOperation() will return false until Init() is called. |
michael@0 | 214 | */ |
michael@0 | 215 | void Report(IOInterposeObserver::Observation& aObservation); |
michael@0 | 216 | |
michael@0 | 217 | /** |
michael@0 | 218 | * Return whether or not an operation is observed. Reporters should not |
michael@0 | 219 | * report operations that are not being observed by anybody. This mechanism |
michael@0 | 220 | * allows us to avoid reporting I/O when no observers are registered. |
michael@0 | 221 | */ |
michael@0 | 222 | bool IsObservedOperation(IOInterposeObserver::Operation aOp); |
michael@0 | 223 | |
michael@0 | 224 | /** |
michael@0 | 225 | * Register IOInterposeObserver, the observer object will receive all |
michael@0 | 226 | * observations for the given operation aOp. |
michael@0 | 227 | * |
michael@0 | 228 | * Remark: Init() must be called before observers are registered. |
michael@0 | 229 | */ |
michael@0 | 230 | void Register(IOInterposeObserver::Operation aOp, |
michael@0 | 231 | IOInterposeObserver* aObserver); |
michael@0 | 232 | |
michael@0 | 233 | /** |
michael@0 | 234 | * Unregister an IOInterposeObserver for a given operation |
michael@0 | 235 | * Remark: It is always safe to unregister for all operations, even if yoú |
michael@0 | 236 | * didn't register for them all. |
michael@0 | 237 | * I.e. IOInterposer::Unregister(IOInterposeObserver::OpAll, aObserver) |
michael@0 | 238 | * |
michael@0 | 239 | * Remark: Init() must be called before observers are unregistered. |
michael@0 | 240 | */ |
michael@0 | 241 | void Unregister(IOInterposeObserver::Operation aOp, |
michael@0 | 242 | IOInterposeObserver* aObserver); |
michael@0 | 243 | |
michael@0 | 244 | /** |
michael@0 | 245 | * Registers the current thread with the IOInterposer. This must be done to |
michael@0 | 246 | * ensure that per-thread data is created in an orderly fashion. |
michael@0 | 247 | * We could have written this to initialize that data lazily, however this |
michael@0 | 248 | * could have unintended consequences if a thread that is not aware of |
michael@0 | 249 | * IOInterposer was implicitly registered: its per-thread data would never |
michael@0 | 250 | * be deleted because it would not know to unregister itself. |
michael@0 | 251 | * |
michael@0 | 252 | * @param aIsMainThread true if IOInterposer should treat the current thread |
michael@0 | 253 | * as the main thread. |
michael@0 | 254 | */ |
michael@0 | 255 | void |
michael@0 | 256 | RegisterCurrentThread(bool aIsMainThread = false); |
michael@0 | 257 | |
michael@0 | 258 | /** |
michael@0 | 259 | * Unregisters the current thread with the IOInterposer. This is important |
michael@0 | 260 | * to call when a thread is shutting down because it cleans up data that |
michael@0 | 261 | * is stored in a TLS slot. |
michael@0 | 262 | */ |
michael@0 | 263 | void |
michael@0 | 264 | UnregisterCurrentThread(); |
michael@0 | 265 | |
michael@0 | 266 | /** |
michael@0 | 267 | * Called to inform observers that the process has transitioned out of the |
michael@0 | 268 | * startup stage or into the shutdown stage. Main thread only. |
michael@0 | 269 | */ |
michael@0 | 270 | void |
michael@0 | 271 | EnteringNextStage(); |
michael@0 | 272 | } // namespace IOInterposer |
michael@0 | 273 | |
michael@0 | 274 | class IOInterposerInit |
michael@0 | 275 | { |
michael@0 | 276 | public: |
michael@0 | 277 | IOInterposerInit() |
michael@0 | 278 | { |
michael@0 | 279 | #if defined(MOZ_ENABLE_PROFILER_SPS) |
michael@0 | 280 | IOInterposer::Init(); |
michael@0 | 281 | #endif |
michael@0 | 282 | } |
michael@0 | 283 | |
michael@0 | 284 | // No destructor needed at the moment -- this stuff stays active for the |
michael@0 | 285 | // life of the process. This may change in the future. |
michael@0 | 286 | }; |
michael@0 | 287 | |
michael@0 | 288 | } // namespace mozilla |
michael@0 | 289 | |
michael@0 | 290 | #endif // mozilla_IOInterposer_h |