dom/indexedDB/Key.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
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 #ifndef mozilla_dom_indexeddb_key_h__
michael@0 8 #define mozilla_dom_indexeddb_key_h__
michael@0 9
michael@0 10 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
michael@0 11
michael@0 12 #include "mozIStorageStatement.h"
michael@0 13
michael@0 14 #include "js/Value.h"
michael@0 15
michael@0 16 namespace IPC {
michael@0 17 template <typename T> struct ParamTraits;
michael@0 18 } // namespace IPC
michael@0 19
michael@0 20 BEGIN_INDEXEDDB_NAMESPACE
michael@0 21
michael@0 22 class Key
michael@0 23 {
michael@0 24 friend struct IPC::ParamTraits<Key>;
michael@0 25
michael@0 26 public:
michael@0 27 Key()
michael@0 28 {
michael@0 29 Unset();
michael@0 30 }
michael@0 31
michael@0 32 Key& operator=(const nsAString& aString)
michael@0 33 {
michael@0 34 SetFromString(aString);
michael@0 35 return *this;
michael@0 36 }
michael@0 37
michael@0 38 Key& operator=(int64_t aInt)
michael@0 39 {
michael@0 40 SetFromInteger(aInt);
michael@0 41 return *this;
michael@0 42 }
michael@0 43
michael@0 44 bool operator==(const Key& aOther) const
michael@0 45 {
michael@0 46 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
michael@0 47 "Don't compare unset keys!");
michael@0 48
michael@0 49 return mBuffer.Equals(aOther.mBuffer);
michael@0 50 }
michael@0 51
michael@0 52 bool operator!=(const Key& aOther) const
michael@0 53 {
michael@0 54 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
michael@0 55 "Don't compare unset keys!");
michael@0 56
michael@0 57 return !mBuffer.Equals(aOther.mBuffer);
michael@0 58 }
michael@0 59
michael@0 60 bool operator<(const Key& aOther) const
michael@0 61 {
michael@0 62 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
michael@0 63 "Don't compare unset keys!");
michael@0 64
michael@0 65 return Compare(mBuffer, aOther.mBuffer) < 0;
michael@0 66 }
michael@0 67
michael@0 68 bool operator>(const Key& aOther) const
michael@0 69 {
michael@0 70 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
michael@0 71 "Don't compare unset keys!");
michael@0 72
michael@0 73 return Compare(mBuffer, aOther.mBuffer) > 0;
michael@0 74 }
michael@0 75
michael@0 76 bool operator<=(const Key& aOther) const
michael@0 77 {
michael@0 78 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
michael@0 79 "Don't compare unset keys!");
michael@0 80
michael@0 81 return Compare(mBuffer, aOther.mBuffer) <= 0;
michael@0 82 }
michael@0 83
michael@0 84 bool operator>=(const Key& aOther) const
michael@0 85 {
michael@0 86 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
michael@0 87 "Don't compare unset keys!");
michael@0 88
michael@0 89 return Compare(mBuffer, aOther.mBuffer) >= 0;
michael@0 90 }
michael@0 91
michael@0 92 void
michael@0 93 Unset()
michael@0 94 {
michael@0 95 mBuffer.SetIsVoid(true);
michael@0 96 }
michael@0 97
michael@0 98 bool IsUnset() const
michael@0 99 {
michael@0 100 return mBuffer.IsVoid();
michael@0 101 }
michael@0 102
michael@0 103 bool IsFloat() const
michael@0 104 {
michael@0 105 return !IsUnset() && mBuffer.First() == eFloat;
michael@0 106 }
michael@0 107
michael@0 108 bool IsDate() const
michael@0 109 {
michael@0 110 return !IsUnset() && mBuffer.First() == eDate;
michael@0 111 }
michael@0 112
michael@0 113 bool IsString() const
michael@0 114 {
michael@0 115 return !IsUnset() && mBuffer.First() == eString;
michael@0 116 }
michael@0 117
michael@0 118 bool IsArray() const
michael@0 119 {
michael@0 120 return !IsUnset() && mBuffer.First() >= eArray;
michael@0 121 }
michael@0 122
michael@0 123 double ToFloat() const
michael@0 124 {
michael@0 125 NS_ASSERTION(IsFloat(), "Why'd you call this?");
michael@0 126 const unsigned char* pos = BufferStart();
michael@0 127 double res = DecodeNumber(pos, BufferEnd());
michael@0 128 NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
michael@0 129 return res;
michael@0 130 }
michael@0 131
michael@0 132 double ToDateMsec() const
michael@0 133 {
michael@0 134 NS_ASSERTION(IsDate(), "Why'd you call this?");
michael@0 135 const unsigned char* pos = BufferStart();
michael@0 136 double res = DecodeNumber(pos, BufferEnd());
michael@0 137 NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
michael@0 138 return res;
michael@0 139 }
michael@0 140
michael@0 141 void ToString(nsString& aString) const
michael@0 142 {
michael@0 143 NS_ASSERTION(IsString(), "Why'd you call this?");
michael@0 144 const unsigned char* pos = BufferStart();
michael@0 145 DecodeString(pos, BufferEnd(), aString);
michael@0 146 NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
michael@0 147 }
michael@0 148
michael@0 149 void SetFromString(const nsAString& aString)
michael@0 150 {
michael@0 151 mBuffer.Truncate();
michael@0 152 EncodeString(aString, 0);
michael@0 153 TrimBuffer();
michael@0 154 }
michael@0 155
michael@0 156 void SetFromInteger(int64_t aInt)
michael@0 157 {
michael@0 158 mBuffer.Truncate();
michael@0 159 EncodeNumber(double(aInt), eFloat);
michael@0 160 TrimBuffer();
michael@0 161 }
michael@0 162
michael@0 163 nsresult SetFromJSVal(JSContext* aCx,
michael@0 164 JS::Handle<JS::Value> aVal)
michael@0 165 {
michael@0 166 mBuffer.Truncate();
michael@0 167
michael@0 168 if (aVal.isNull() || aVal.isUndefined()) {
michael@0 169 Unset();
michael@0 170 return NS_OK;
michael@0 171 }
michael@0 172
michael@0 173 nsresult rv = EncodeJSVal(aCx, aVal, 0);
michael@0 174 if (NS_FAILED(rv)) {
michael@0 175 Unset();
michael@0 176 return rv;
michael@0 177 }
michael@0 178 TrimBuffer();
michael@0 179
michael@0 180 return NS_OK;
michael@0 181 }
michael@0 182
michael@0 183 nsresult ToJSVal(JSContext* aCx,
michael@0 184 JS::MutableHandle<JS::Value> aVal) const
michael@0 185 {
michael@0 186 if (IsUnset()) {
michael@0 187 aVal.setUndefined();
michael@0 188 return NS_OK;
michael@0 189 }
michael@0 190
michael@0 191 const unsigned char* pos = BufferStart();
michael@0 192 nsresult rv = DecodeJSVal(pos, BufferEnd(), aCx, 0, aVal);
michael@0 193 NS_ENSURE_SUCCESS(rv, rv);
michael@0 194
michael@0 195 NS_ASSERTION(pos >= BufferEnd(),
michael@0 196 "Didn't consume whole buffer");
michael@0 197
michael@0 198 return NS_OK;
michael@0 199 }
michael@0 200
michael@0 201 nsresult ToJSVal(JSContext* aCx,
michael@0 202 JS::Heap<JS::Value>& aVal) const
michael@0 203 {
michael@0 204 JS::Rooted<JS::Value> value(aCx);
michael@0 205 nsresult rv = ToJSVal(aCx, &value);
michael@0 206 if (NS_SUCCEEDED(rv)) {
michael@0 207 aVal = value;
michael@0 208 }
michael@0 209 return rv;
michael@0 210 }
michael@0 211
michael@0 212 nsresult AppendItem(JSContext* aCx,
michael@0 213 bool aFirstOfArray,
michael@0 214 JS::Handle<JS::Value> aVal)
michael@0 215 {
michael@0 216 nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
michael@0 217 if (NS_FAILED(rv)) {
michael@0 218 Unset();
michael@0 219 return rv;
michael@0 220 }
michael@0 221
michael@0 222 return NS_OK;
michael@0 223 }
michael@0 224
michael@0 225 void FinishArray()
michael@0 226 {
michael@0 227 TrimBuffer();
michael@0 228 }
michael@0 229
michael@0 230 const nsCString& GetBuffer() const
michael@0 231 {
michael@0 232 return mBuffer;
michael@0 233 }
michael@0 234
michael@0 235 nsresult BindToStatement(mozIStorageStatement* aStatement,
michael@0 236 const nsACString& aParamName) const
michael@0 237 {
michael@0 238 nsresult rv = aStatement->BindBlobByName(aParamName,
michael@0 239 reinterpret_cast<const uint8_t*>(mBuffer.get()), mBuffer.Length());
michael@0 240
michael@0 241 return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 242 }
michael@0 243
michael@0 244 nsresult SetFromStatement(mozIStorageStatement* aStatement,
michael@0 245 uint32_t aIndex)
michael@0 246 {
michael@0 247 uint8_t* data;
michael@0 248 uint32_t dataLength = 0;
michael@0 249
michael@0 250 nsresult rv = aStatement->GetBlob(aIndex, &dataLength, &data);
michael@0 251 NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 252
michael@0 253 mBuffer.Adopt(
michael@0 254 reinterpret_cast<char*>(const_cast<uint8_t*>(data)), dataLength);
michael@0 255
michael@0 256 return NS_OK;
michael@0 257 }
michael@0 258
michael@0 259 static
michael@0 260 int16_t CompareKeys(Key& aFirst, Key& aSecond)
michael@0 261 {
michael@0 262 int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
michael@0 263
michael@0 264 if (result < 0) {
michael@0 265 return -1;
michael@0 266 }
michael@0 267
michael@0 268 if (result > 0) {
michael@0 269 return 1;
michael@0 270 }
michael@0 271
michael@0 272 return 0;
michael@0 273 }
michael@0 274
michael@0 275 private:
michael@0 276 const unsigned char* BufferStart() const
michael@0 277 {
michael@0 278 return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading());
michael@0 279 }
michael@0 280
michael@0 281 const unsigned char* BufferEnd() const
michael@0 282 {
michael@0 283 return reinterpret_cast<const unsigned char*>(mBuffer.EndReading());
michael@0 284 }
michael@0 285
michael@0 286 enum {
michael@0 287 eTerminator = 0,
michael@0 288 eFloat = 1,
michael@0 289 eDate = 2,
michael@0 290 eString = 3,
michael@0 291 eArray = 4,
michael@0 292 eMaxType = eArray
michael@0 293 };
michael@0 294
michael@0 295 // Encoding helper. Trims trailing zeros off of mBuffer as a post-processing
michael@0 296 // step.
michael@0 297 void TrimBuffer()
michael@0 298 {
michael@0 299 const char* end = mBuffer.EndReading() - 1;
michael@0 300 while (!*end) {
michael@0 301 --end;
michael@0 302 }
michael@0 303
michael@0 304 mBuffer.Truncate(end + 1 - mBuffer.BeginReading());
michael@0 305 }
michael@0 306
michael@0 307 // Encoding functions. These append the encoded value to the end of mBuffer
michael@0 308 inline nsresult EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal,
michael@0 309 uint8_t aTypeOffset)
michael@0 310 {
michael@0 311 return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
michael@0 312 }
michael@0 313 void EncodeString(const nsAString& aString, uint8_t aTypeOffset);
michael@0 314 void EncodeNumber(double aFloat, uint8_t aType);
michael@0 315
michael@0 316 // Decoding functions. aPos points into mBuffer and is adjusted to point
michael@0 317 // past the consumed value.
michael@0 318 static inline nsresult DecodeJSVal(const unsigned char*& aPos,
michael@0 319 const unsigned char* aEnd, JSContext* aCx,
michael@0 320 uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal)
michael@0 321 {
michael@0 322 return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
michael@0 323 }
michael@0 324
michael@0 325 static void DecodeString(const unsigned char*& aPos,
michael@0 326 const unsigned char* aEnd,
michael@0 327 nsString& aString);
michael@0 328 static double DecodeNumber(const unsigned char*& aPos,
michael@0 329 const unsigned char* aEnd);
michael@0 330
michael@0 331 nsCString mBuffer;
michael@0 332
michael@0 333 private:
michael@0 334 nsresult EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
michael@0 335 uint8_t aTypeOffset, uint16_t aRecursionDepth);
michael@0 336
michael@0 337 static nsresult DecodeJSValInternal(const unsigned char*& aPos,
michael@0 338 const unsigned char* aEnd,
michael@0 339 JSContext* aCx, uint8_t aTypeOffset,
michael@0 340 JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth);
michael@0 341 };
michael@0 342
michael@0 343 END_INDEXEDDB_NAMESPACE
michael@0 344
michael@0 345 #endif /* mozilla_dom_indexeddb_key_h__ */

mercurial