1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
6 
7 #include <iterator>
8 #include <limits>
9 #include <sstream>
10 #include <utility>
11 
12 #include "base/big_endian.h"
13 #include "base/containers/span.h"
14 #include "base/logging.h"
15 #include "base/strings/string16.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/sys_byteorder.h"
18 #include "build/build_config.h"
19 #include "components/services/storage/indexed_db/scopes/leveldb_scopes_coding.h"
20 #include "components/services/storage/indexed_db/scopes/varint_coding.h"
21 
22 // See leveldb_coding_scheme.md for detailed documentation of the coding
23 // scheme implemented here.
24 
25 using base::StringPiece;
26 using blink::IndexedDBKey;
27 using blink::IndexedDBKeyPath;
28 
29 namespace content {
30 namespace {
ByteSwapToBE64(uint64_t x)31 inline uint64_t ByteSwapToBE64(uint64_t x) {
32 #if defined(ARCH_CPU_LITTLE_ENDIAN)
33   return base::ByteSwap(x);
34 #else
35   return x;
36 #endif
37 }
38 
39 // As most of the IndexedDBKeys and encoded values are short, we
40 // initialize some std::vectors with a default inline buffer size to reduce
41 // the memory re-allocations when the std::vectors are appended.
42 const size_t kDefaultInlineBufferSize = 32;
43 
44 constexpr unsigned char kIndexedDBKeyNullTypeByte = 0;
45 constexpr unsigned char kIndexedDBKeyStringTypeByte = 1;
46 constexpr unsigned char kIndexedDBKeyDateTypeByte = 2;
47 constexpr unsigned char kIndexedDBKeyNumberTypeByte = 3;
48 constexpr unsigned char kIndexedDBKeyArrayTypeByte = 4;
49 constexpr unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
50 constexpr unsigned char kIndexedDBKeyBinaryTypeByte = 6;
51 
52 constexpr unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
53 constexpr unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
54 
55 constexpr unsigned char kIndexedDBKeyPathNullTypeByte = 0;
56 constexpr unsigned char kIndexedDBKeyPathStringTypeByte = 1;
57 constexpr unsigned char kIndexedDBKeyPathArrayTypeByte = 2;
58 
59 constexpr unsigned char kObjectStoreDataIndexId = 1;
60 constexpr unsigned char kExistsEntryIndexId = 2;
61 constexpr unsigned char kBlobEntryIndexId = 3;
62 
63 constexpr unsigned char kSchemaVersionTypeByte = 0;
64 constexpr unsigned char kMaxDatabaseIdTypeByte = 1;
65 constexpr unsigned char kDataVersionTypeByte = 2;
66 constexpr unsigned char kRecoveryBlobJournalTypeByte = 3;
67 constexpr unsigned char kActiveBlobJournalTypeByte = 4;
68 constexpr unsigned char kEarliestSweepTimeTypeByte = 5;
69 constexpr unsigned char kMaxSimpleGlobalMetaDataTypeByte =
70     6;  // Insert before this and increment.
71 constexpr unsigned char kScopesPrefixByte = 50;
72 constexpr unsigned char kDatabaseFreeListTypeByte = 100;
73 constexpr unsigned char kDatabaseNameTypeByte = 201;
74 
75 constexpr unsigned char kObjectStoreMetaDataTypeByte = 50;
76 constexpr unsigned char kIndexMetaDataTypeByte = 100;
77 constexpr unsigned char kObjectStoreFreeListTypeByte = 150;
78 constexpr unsigned char kIndexFreeListTypeByte = 151;
79 constexpr unsigned char kObjectStoreNamesTypeByte = 200;
80 constexpr unsigned char kIndexNamesKeyTypeByte = 201;
81 
82 constexpr unsigned char kObjectMetaDataTypeMaximum = 255;
83 constexpr unsigned char kIndexMetaDataTypeMaximum = 255;
84 
EncodeIntSafely(int64_t value,int64_t max,std::string * into)85 inline void EncodeIntSafely(int64_t value, int64_t max, std::string* into) {
86   DCHECK_LE(value, max);
87   return EncodeInt(value, into);
88 }
89 
90 }  // namespace
91 
92 const unsigned char kMinimumIndexId = 30;
93 
MaxIDBKey()94 std::string MaxIDBKey() {
95   std::string ret;
96   EncodeByte(kIndexedDBKeyNullTypeByte, &ret);
97   return ret;
98 }
99 
MinIDBKey()100 std::string MinIDBKey() {
101   std::string ret;
102   EncodeByte(kIndexedDBKeyMinKeyTypeByte, &ret);
103   return ret;
104 }
105 
EncodeByte(unsigned char value,std::string * into)106 void EncodeByte(unsigned char value, std::string* into) {
107   into->push_back(value);
108 }
109 
EncodeBool(bool value,std::string * into)110 void EncodeBool(bool value, std::string* into) {
111   into->push_back(value ? 1 : 0);
112 }
113 
EncodeInt(int64_t value,std::string * into)114 void EncodeInt(int64_t value, std::string* into) {
115 #ifndef NDEBUG
116   // Exercised by unit tests in debug only.
117   DCHECK_GE(value, 0);
118 #endif
119   uint64_t n = static_cast<uint64_t>(value);
120 
121   do {
122     unsigned char c = n;
123     into->push_back(c);
124     n >>= 8;
125   } while (n);
126 }
127 
EncodeString(const base::string16 & value,std::string * into)128 void EncodeString(const base::string16& value, std::string* into) {
129   if (value.empty())
130     return;
131   // Backing store is UTF-16BE, convert from host endianness.
132   size_t length = value.length();
133   size_t current = into->size();
134   into->resize(into->size() + length * sizeof(base::char16));
135 
136   const base::char16* src = value.c_str();
137   base::char16* dst =
138       reinterpret_cast<base::char16*>(&*into->begin() + current);
139   for (unsigned i = 0; i < length; ++i)
140     *dst++ = base::HostToNet16(*src++);
141 }
142 
EncodeBinary(const std::string & value,std::string * into)143 void EncodeBinary(const std::string& value, std::string* into) {
144   EncodeVarInt(value.length(), into);
145   into->append(value.begin(), value.end());
146   DCHECK(into->size() >= value.size());
147 }
148 
EncodeBinary(base::span<const uint8_t> value,std::string * into)149 void EncodeBinary(base::span<const uint8_t> value, std::string* into) {
150   EncodeVarInt(value.size(), into);
151   into->append(value.begin(), value.end());
152   DCHECK(into->size() >= value.size());
153 }
154 
EncodeStringWithLength(const base::string16 & value,std::string * into)155 void EncodeStringWithLength(const base::string16& value, std::string* into) {
156   EncodeVarInt(value.length(), into);
157   EncodeString(value, into);
158 }
159 
EncodeDouble(double value,std::string * into)160 void EncodeDouble(double value, std::string* into) {
161   // This always has host endianness.
162   const char* p = reinterpret_cast<char*>(&value);
163   into->insert(into->end(), p, p + sizeof(value));
164 }
165 
EncodeIDBKey(const IndexedDBKey & value,std::string * into)166 void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
167   size_t previous_size = into->size();
168   DCHECK(value.IsValid());
169   switch (value.type()) {
170     case blink::mojom::IDBKeyType::Array: {
171       EncodeByte(kIndexedDBKeyArrayTypeByte, into);
172       size_t length = value.array().size();
173       EncodeVarInt(length, into);
174       for (size_t i = 0; i < length; ++i)
175         EncodeIDBKey(value.array()[i], into);
176       DCHECK_GT(into->size(), previous_size);
177       return;
178     }
179     case blink::mojom::IDBKeyType::Binary:
180       EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
181       EncodeBinary(value.binary(), into);
182       DCHECK_GT(into->size(), previous_size);
183       return;
184     case blink::mojom::IDBKeyType::String:
185       EncodeByte(kIndexedDBKeyStringTypeByte, into);
186       EncodeStringWithLength(value.string(), into);
187       DCHECK_GT(into->size(), previous_size);
188       return;
189     case blink::mojom::IDBKeyType::Date:
190       EncodeByte(kIndexedDBKeyDateTypeByte, into);
191       EncodeDouble(value.date(), into);
192       DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
193       return;
194     case blink::mojom::IDBKeyType::Number:
195       EncodeByte(kIndexedDBKeyNumberTypeByte, into);
196       EncodeDouble(value.number(), into);
197       DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
198       return;
199     case blink::mojom::IDBKeyType::None:
200     case blink::mojom::IDBKeyType::Invalid:
201     case blink::mojom::IDBKeyType::Min:
202     default:
203       NOTREACHED();
204       EncodeByte(kIndexedDBKeyNullTypeByte, into);
205       return;
206   }
207 }
208 
209 #define COMPILE_ASSERT_MATCHING_VALUES(a, b)                          \
210   static_assert(                                                      \
211       static_cast<unsigned char>(a) == static_cast<unsigned char>(b), \
212       "Blink enum and coding byte must match.")
213 
214 COMPILE_ASSERT_MATCHING_VALUES(blink::mojom::IDBKeyPathType::Null,
215                                kIndexedDBKeyPathNullTypeByte);
216 COMPILE_ASSERT_MATCHING_VALUES(blink::mojom::IDBKeyPathType::String,
217                                kIndexedDBKeyPathStringTypeByte);
218 COMPILE_ASSERT_MATCHING_VALUES(blink::mojom::IDBKeyPathType::Array,
219                                kIndexedDBKeyPathArrayTypeByte);
220 
EncodeIDBKeyPath(const IndexedDBKeyPath & value,std::string * into)221 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
222   // May be typed, or may be a raw string. An invalid leading
223   // byte is used to identify typed coding. New records are
224   // always written as typed.
225   EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
226   EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
227   EncodeByte(static_cast<char>(value.type()), into);
228   switch (value.type()) {
229     case blink::mojom::IDBKeyPathType::Null:
230       break;
231     case blink::mojom::IDBKeyPathType::String: {
232       EncodeStringWithLength(value.string(), into);
233       break;
234     }
235     case blink::mojom::IDBKeyPathType::Array: {
236       const std::vector<base::string16>& array = value.array();
237       size_t count = array.size();
238       EncodeVarInt(count, into);
239       for (size_t i = 0; i < count; ++i) {
240         EncodeStringWithLength(array[i], into);
241       }
242       break;
243     }
244   }
245 }
246 
EncodeBlobJournal(const BlobJournalType & journal,std::string * into)247 void EncodeBlobJournal(const BlobJournalType& journal, std::string* into) {
248   for (const auto& iter : journal) {
249     EncodeVarInt(iter.first, into);
250     EncodeVarInt(iter.second, into);
251   }
252 }
253 
DecodeByte(StringPiece * slice,unsigned char * value)254 bool DecodeByte(StringPiece* slice, unsigned char* value) {
255   if (slice->empty())
256     return false;
257 
258   *value = (*slice)[0];
259   slice->remove_prefix(1);
260   return true;
261 }
262 
DecodeBool(StringPiece * slice,bool * value)263 bool DecodeBool(StringPiece* slice, bool* value) {
264   if (slice->empty())
265     return false;
266 
267   *value = !!(*slice)[0];
268   slice->remove_prefix(1);
269   return true;
270 }
271 
DecodeInt(StringPiece * slice,int64_t * value)272 bool DecodeInt(StringPiece* slice, int64_t* value) {
273   if (slice->empty())
274     return false;
275 
276   StringPiece::const_iterator it = slice->begin();
277   int shift = 0;
278   int64_t ret = 0;
279   while (it != slice->end()) {
280     unsigned char c = *it++;
281     ret |= static_cast<int64_t>(c) << shift;
282     shift += 8;
283   }
284   *value = ret;
285   slice->remove_prefix(it - slice->begin());
286   return true;
287 }
288 
DecodeString(StringPiece * slice,base::string16 * value)289 bool DecodeString(StringPiece* slice, base::string16* value) {
290   if (slice->empty()) {
291     value->clear();
292     return true;
293   }
294 
295   // Backing store is UTF-16BE, convert to host endianness.
296   DCHECK(!(slice->size() % sizeof(base::char16)));
297   size_t length = slice->size() / sizeof(base::char16);
298   base::string16 decoded;
299   decoded.reserve(length);
300   const base::char16* encoded =
301       reinterpret_cast<const base::char16*>(slice->begin());
302   for (unsigned i = 0; i < length; ++i)
303     decoded.push_back(base::NetToHost16(*encoded++));
304 
305   *value = decoded;
306   slice->remove_prefix(length * sizeof(base::char16));
307   return true;
308 }
309 
DecodeStringWithLength(StringPiece * slice,base::string16 * value)310 bool DecodeStringWithLength(StringPiece* slice, base::string16* value) {
311   if (slice->empty())
312     return false;
313 
314   int64_t length = 0;
315   if (!DecodeVarInt(slice, &length) || length < 0)
316     return false;
317   size_t bytes = length * sizeof(base::char16);
318   if (slice->size() < bytes)
319     return false;
320 
321   StringPiece subpiece(slice->begin(), bytes);
322   slice->remove_prefix(bytes);
323   if (!DecodeString(&subpiece, value))
324     return false;
325 
326   return true;
327 }
328 
DecodeBinary(StringPiece * slice,std::string * value)329 bool DecodeBinary(StringPiece* slice, std::string* value) {
330   if (slice->empty())
331     return false;
332 
333   int64_t length = 0;
334   if (!DecodeVarInt(slice, &length) || length < 0)
335     return false;
336   size_t size = length;
337   if (slice->size() < size)
338     return false;
339 
340   value->assign(slice->begin(), size);
341   slice->remove_prefix(size);
342   return true;
343 }
344 
DecodeBinary(StringPiece * slice,base::span<const uint8_t> * value)345 bool DecodeBinary(StringPiece* slice, base::span<const uint8_t>* value) {
346   if (slice->empty())
347     return false;
348 
349   int64_t length = 0;
350   if (!DecodeVarInt(slice, &length) || length < 0)
351     return false;
352   size_t size = length;
353   if (slice->size() < size)
354     return false;
355 
356   *value = base::as_bytes(base::make_span(slice->substr(0, size)));
357   slice->remove_prefix(size);
358   return true;
359 }
360 
DecodeIDBKey(StringPiece * slice,std::unique_ptr<IndexedDBKey> * value)361 bool DecodeIDBKey(StringPiece* slice, std::unique_ptr<IndexedDBKey>* value) {
362   if (slice->empty())
363     return false;
364 
365   unsigned char type = (*slice)[0];
366   slice->remove_prefix(1);
367 
368   switch (type) {
369     case kIndexedDBKeyNullTypeByte:
370       *value = std::make_unique<IndexedDBKey>();
371       return true;
372 
373     case kIndexedDBKeyArrayTypeByte: {
374       int64_t length = 0;
375       if (!DecodeVarInt(slice, &length) || length < 0)
376         return false;
377       IndexedDBKey::KeyArray array;
378       while (length--) {
379         std::unique_ptr<IndexedDBKey> key;
380         if (!DecodeIDBKey(slice, &key))
381           return false;
382         array.push_back(*key);
383       }
384       *value = std::make_unique<IndexedDBKey>(std::move(array));
385       return true;
386     }
387     case kIndexedDBKeyBinaryTypeByte: {
388       std::string binary;
389       if (!DecodeBinary(slice, &binary))
390         return false;
391       *value = std::make_unique<IndexedDBKey>(std::move(binary));
392       return true;
393     }
394     case kIndexedDBKeyStringTypeByte: {
395       base::string16 s;
396       if (!DecodeStringWithLength(slice, &s))
397         return false;
398       *value = std::make_unique<IndexedDBKey>(std::move(s));
399       return true;
400     }
401     case kIndexedDBKeyDateTypeByte: {
402       double d;
403       if (!DecodeDouble(slice, &d))
404         return false;
405       *value =
406           std::make_unique<IndexedDBKey>(d, blink::mojom::IDBKeyType::Date);
407       return true;
408     }
409     case kIndexedDBKeyNumberTypeByte: {
410       double d;
411       if (!DecodeDouble(slice, &d))
412         return false;
413       *value =
414           std::make_unique<IndexedDBKey>(d, blink::mojom::IDBKeyType::Number);
415       return true;
416     }
417     case kIndexedDBKeyMinKeyTypeByte: {
418       *value = std::make_unique<IndexedDBKey>(blink::mojom::IDBKeyType::Min);
419       return true;
420     }
421   }
422 
423   NOTREACHED();
424   return false;
425 }
426 
DecodeDouble(StringPiece * slice,double * value)427 bool DecodeDouble(StringPiece* slice, double* value) {
428   if (slice->size() < sizeof(*value))
429     return false;
430 
431   memcpy(value, slice->begin(), sizeof(*value));
432   slice->remove_prefix(sizeof(*value));
433   return true;
434 }
435 
DecodeIDBKeyPath(StringPiece * slice,IndexedDBKeyPath * value)436 bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
437   // May be typed, or may be a raw string. An invalid leading
438   // byte sequence is used to identify typed coding. New records are
439   // always written as typed.
440   if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 ||
441       (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) {
442     base::string16 s;
443     if (!DecodeString(slice, &s))
444       return false;
445     *value = IndexedDBKeyPath(s);
446     return true;
447   }
448 
449   slice->remove_prefix(2);
450   DCHECK(!slice->empty());
451   blink::mojom::IDBKeyPathType type =
452       static_cast<blink::mojom::IDBKeyPathType>((*slice)[0]);
453   slice->remove_prefix(1);
454 
455   switch (type) {
456     case blink::mojom::IDBKeyPathType::Null:
457       DCHECK(slice->empty());
458       *value = IndexedDBKeyPath();
459       return true;
460     case blink::mojom::IDBKeyPathType::String: {
461       base::string16 string;
462       if (!DecodeStringWithLength(slice, &string))
463         return false;
464       DCHECK(slice->empty());
465       *value = IndexedDBKeyPath(string);
466       return true;
467     }
468     case blink::mojom::IDBKeyPathType::Array: {
469       std::vector<base::string16> array;
470       int64_t count;
471       if (!DecodeVarInt(slice, &count))
472         return false;
473       DCHECK_GE(count, 0);
474       while (count--) {
475         base::string16 string;
476         if (!DecodeStringWithLength(slice, &string))
477           return false;
478         array.push_back(string);
479       }
480       DCHECK(slice->empty());
481       *value = IndexedDBKeyPath(array);
482       return true;
483     }
484   }
485   NOTREACHED();
486   return false;
487 }
488 
DecodeBlobJournal(StringPiece * slice,BlobJournalType * journal)489 bool DecodeBlobJournal(StringPiece* slice, BlobJournalType* journal) {
490   BlobJournalType output;
491   while (!slice->empty()) {
492     int64_t database_id = -1;
493     int64_t blob_number = -1;
494     if (!DecodeVarInt(slice, &database_id))
495       return false;
496     if (!KeyPrefix::IsValidDatabaseId(database_id))
497       return false;
498     if (!DecodeVarInt(slice, &blob_number))
499       return false;
500     if (!DatabaseMetaDataKey::IsValidBlobNumber(blob_number) &&
501         (blob_number != DatabaseMetaDataKey::kAllBlobsNumber)) {
502       return false;
503     }
504     output.push_back({database_id, blob_number});
505   }
506   journal->swap(output);
507   return true;
508 }
509 
ConsumeEncodedIDBKey(StringPiece * slice)510 bool ConsumeEncodedIDBKey(StringPiece* slice) {
511   unsigned char type = (*slice)[0];
512   slice->remove_prefix(1);
513 
514   switch (type) {
515     case kIndexedDBKeyNullTypeByte:
516     case kIndexedDBKeyMinKeyTypeByte:
517       return true;
518     case kIndexedDBKeyArrayTypeByte: {
519       int64_t length;
520       if (!DecodeVarInt(slice, &length))
521         return false;
522       while (length--) {
523         if (!ConsumeEncodedIDBKey(slice))
524           return false;
525       }
526       return true;
527     }
528     case kIndexedDBKeyBinaryTypeByte: {
529       int64_t length = 0;
530       if (!DecodeVarInt(slice, &length) || length < 0)
531         return false;
532       if (slice->size() < static_cast<size_t>(length))
533         return false;
534       slice->remove_prefix(length);
535       return true;
536     }
537     case kIndexedDBKeyStringTypeByte: {
538       int64_t length = 0;
539       if (!DecodeVarInt(slice, &length) || length < 0)
540         return false;
541       if (slice->size() < static_cast<size_t>(length) * sizeof(base::char16))
542         return false;
543       slice->remove_prefix(length * sizeof(base::char16));
544       return true;
545     }
546     case kIndexedDBKeyDateTypeByte:
547     case kIndexedDBKeyNumberTypeByte:
548       if (slice->size() < sizeof(double))
549         return false;
550       slice->remove_prefix(sizeof(double));
551       return true;
552   }
553   NOTREACHED();
554   return false;
555 }
556 
ExtractEncodedIDBKey(StringPiece * slice,std::string * result)557 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) {
558   const char* start = slice->begin();
559   if (!ConsumeEncodedIDBKey(slice))
560     return false;
561 
562   if (result)
563     result->assign(start, slice->begin());
564   return true;
565 }
566 
KeyTypeByteToKeyType(unsigned char type)567 static blink::mojom::IDBKeyType KeyTypeByteToKeyType(unsigned char type) {
568   switch (type) {
569     case kIndexedDBKeyNullTypeByte:
570       return blink::mojom::IDBKeyType::Invalid;
571     case kIndexedDBKeyArrayTypeByte:
572       return blink::mojom::IDBKeyType::Array;
573     case kIndexedDBKeyBinaryTypeByte:
574       return blink::mojom::IDBKeyType::Binary;
575     case kIndexedDBKeyStringTypeByte:
576       return blink::mojom::IDBKeyType::String;
577     case kIndexedDBKeyDateTypeByte:
578       return blink::mojom::IDBKeyType::Date;
579     case kIndexedDBKeyNumberTypeByte:
580       return blink::mojom::IDBKeyType::Number;
581     case kIndexedDBKeyMinKeyTypeByte:
582       return blink::mojom::IDBKeyType::Min;
583   }
584 
585   NOTREACHED() << "Got invalid type " << type;
586   return blink::mojom::IDBKeyType::Invalid;
587 }
588 
CompareEncodedStringsWithLength(StringPiece * slice1,StringPiece * slice2,bool * ok)589 int CompareEncodedStringsWithLength(StringPiece* slice1,
590                                     StringPiece* slice2,
591                                     bool* ok) {
592   int64_t len1, len2;
593   if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
594     *ok = false;
595     return 0;
596   }
597   DCHECK_GE(len1, 0);
598   DCHECK_GE(len2, 0);
599   if (len1 < 0 || len2 < 0) {
600     *ok = false;
601     return 0;
602   }
603   DCHECK_GE(slice1->size(), len1 * sizeof(base::char16));
604   DCHECK_GE(slice2->size(), len2 * sizeof(base::char16));
605   if (slice1->size() < len1 * sizeof(base::char16) ||
606       slice2->size() < len2 * sizeof(base::char16)) {
607     *ok = false;
608     return 0;
609   }
610 
611   // Extract the string data, and advance the passed slices.
612   StringPiece string1(slice1->begin(), len1 * sizeof(base::char16));
613   StringPiece string2(slice2->begin(), len2 * sizeof(base::char16));
614   slice1->remove_prefix(len1 * sizeof(base::char16));
615   slice2->remove_prefix(len2 * sizeof(base::char16));
616 
617   *ok = true;
618   // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
619   return string1.compare(string2);
620 }
621 
CompareEncodedBinary(StringPiece * slice1,StringPiece * slice2,bool * ok)622 int CompareEncodedBinary(StringPiece* slice1, StringPiece* slice2, bool* ok) {
623   int64_t len1, len2;
624   if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
625     *ok = false;
626     return 0;
627   }
628   DCHECK_GE(len1, 0);
629   DCHECK_GE(len2, 0);
630   if (len1 < 0 || len2 < 0) {
631     *ok = false;
632     return 0;
633   }
634   size_t size1 = len1;
635   size_t size2 = len2;
636 
637   DCHECK_GE(slice1->size(), size1);
638   DCHECK_GE(slice2->size(), size2);
639   if (slice1->size() < size1 || slice2->size() < size2) {
640     *ok = false;
641     return 0;
642   }
643 
644   // Extract the binary data, and advance the passed slices.
645   StringPiece binary1(slice1->begin(), size1);
646   StringPiece binary2(slice2->begin(), size2);
647   slice1->remove_prefix(size1);
648   slice2->remove_prefix(size2);
649 
650   *ok = true;
651   // This is the same as a memcmp()
652   return binary1.compare(binary2);
653 }
654 
CompareInts(int64_t a,int64_t b)655 static int CompareInts(int64_t a, int64_t b) {
656 #ifndef NDEBUG
657   // Exercised by unit tests in debug only.
658   DCHECK_GE(a, 0);
659   DCHECK_GE(b, 0);
660 #endif
661   int64_t diff = a - b;
662   if (diff < 0)
663     return -1;
664   if (diff > 0)
665     return 1;
666   return 0;
667 }
668 
CompareSizes(size_t a,size_t b)669 static inline int CompareSizes(size_t a, size_t b) {
670   if (a > b)
671     return 1;
672   if (b > a)
673     return -1;
674   return 0;
675 }
676 
CompareTypes(blink::mojom::IDBKeyType a,blink::mojom::IDBKeyType b)677 static int CompareTypes(blink::mojom::IDBKeyType a,
678                         blink::mojom::IDBKeyType b) {
679   return static_cast<int32_t>(b) - static_cast<int32_t>(a);
680 }
681 
CompareEncodedIDBKeys(StringPiece * slice_a,StringPiece * slice_b,bool * ok)682 int CompareEncodedIDBKeys(StringPiece* slice_a,
683                           StringPiece* slice_b,
684                           bool* ok) {
685   DCHECK(!slice_a->empty());
686   DCHECK(!slice_b->empty());
687   *ok = true;
688   unsigned char type_a = (*slice_a)[0];
689   unsigned char type_b = (*slice_b)[0];
690   slice_a->remove_prefix(1);
691   slice_b->remove_prefix(1);
692 
693   if (int x = CompareTypes(KeyTypeByteToKeyType(type_a),
694                            KeyTypeByteToKeyType(type_b)))
695     return x;
696 
697   switch (type_a) {
698     case kIndexedDBKeyNullTypeByte:
699     case kIndexedDBKeyMinKeyTypeByte:
700       // Null type or max type; no payload to compare.
701       return 0;
702     case kIndexedDBKeyArrayTypeByte: {
703       int64_t length_a, length_b;
704       if (!DecodeVarInt(slice_a, &length_a) ||
705           !DecodeVarInt(slice_b, &length_b)) {
706         *ok = false;
707         return 0;
708       }
709       for (int64_t i = 0; i < length_a && i < length_b; ++i) {
710         int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
711         if (!*ok || result)
712           return result;
713       }
714       return length_a - length_b;
715     }
716     case kIndexedDBKeyBinaryTypeByte:
717       return CompareEncodedBinary(slice_a, slice_b, ok);
718     case kIndexedDBKeyStringTypeByte:
719       return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
720     case kIndexedDBKeyDateTypeByte:
721     case kIndexedDBKeyNumberTypeByte: {
722       double d, e;
723       if (!DecodeDouble(slice_a, &d) || !DecodeDouble(slice_b, &e)) {
724         *ok = false;
725         return 0;
726       }
727       if (d < e)
728         return -1;
729       if (d > e)
730         return 1;
731       return 0;
732     }
733   }
734 
735   NOTREACHED();
736   return 0;
737 }
738 
739 namespace {
740 
741 template <typename KeyType>
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys,bool * ok)742 int Compare(const StringPiece& a,
743             const StringPiece& b,
744             bool only_compare_index_keys,
745             bool* ok) {
746   KeyType key_a;
747   KeyType key_b;
748 
749   StringPiece slice_a(a);
750   if (!KeyType::Decode(&slice_a, &key_a)) {
751     *ok = false;
752     return 0;
753   }
754   StringPiece slice_b(b);
755   if (!KeyType::Decode(&slice_b, &key_b)) {
756     *ok = false;
757     return 0;
758   }
759 
760   *ok = true;
761   return key_a.Compare(key_b);
762 }
763 
764 template <typename KeyType>
CompareSuffix(StringPiece * a,StringPiece * b,bool only_compare_index_keys,bool * ok)765 int CompareSuffix(StringPiece* a,
766                   StringPiece* b,
767                   bool only_compare_index_keys,
768                   bool* ok) {
769   NOTREACHED();
770   return 0;
771 }
772 
773 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)774 int CompareSuffix<ExistsEntryKey>(StringPiece* slice_a,
775                                   StringPiece* slice_b,
776                                   bool only_compare_index_keys,
777                                   bool* ok) {
778   DCHECK(!slice_a->empty());
779   DCHECK(!slice_b->empty());
780   return CompareEncodedIDBKeys(slice_a, slice_b, ok);
781 }
782 
783 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)784 int CompareSuffix<ObjectStoreDataKey>(StringPiece* slice_a,
785                                       StringPiece* slice_b,
786                                       bool only_compare_index_keys,
787                                       bool* ok) {
788   return CompareEncodedIDBKeys(slice_a, slice_b, ok);
789 }
790 
791 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)792 int CompareSuffix<BlobEntryKey>(StringPiece* slice_a,
793                                 StringPiece* slice_b,
794                                 bool only_compare_index_keys,
795                                 bool* ok) {
796   return CompareEncodedIDBKeys(slice_a, slice_b, ok);
797 }
798 
799 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)800 int CompareSuffix<IndexDataKey>(StringPiece* slice_a,
801                                 StringPiece* slice_b,
802                                 bool only_compare_index_keys,
803                                 bool* ok) {
804   // index key
805   int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
806   if (!*ok || result)
807     return result;
808   if (only_compare_index_keys)
809     return 0;
810 
811   // sequence number [optional]
812   int64_t sequence_number_a = -1;
813   int64_t sequence_number_b = -1;
814   if (!slice_a->empty() && !DecodeVarInt(slice_a, &sequence_number_a))
815     return 0;
816   if (!slice_b->empty() && !DecodeVarInt(slice_b, &sequence_number_b))
817     return 0;
818 
819   if (slice_a->empty() || slice_b->empty())
820     return CompareSizes(slice_a->size(), slice_b->size());
821 
822   // primary key [optional]
823   result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
824   if (!*ok || result)
825     return result;
826 
827   return CompareInts(sequence_number_a, sequence_number_b);
828 }
829 
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys,bool * ok)830 int Compare(const StringPiece& a,
831             const StringPiece& b,
832             bool only_compare_index_keys,
833             bool* ok) {
834   StringPiece slice_a(a);
835   StringPiece slice_b(b);
836   KeyPrefix prefix_a;
837   KeyPrefix prefix_b;
838   bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
839   bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
840   DCHECK(ok_a);
841   DCHECK(ok_b);
842   if (!ok_a || !ok_b) {
843     *ok = false;
844     return 0;
845   }
846 
847   *ok = true;
848   if (int x = prefix_a.Compare(prefix_b))
849     return x;
850 
851   switch (prefix_a.type()) {
852     case KeyPrefix::GLOBAL_METADATA: {
853       DCHECK(!slice_a.empty());
854       DCHECK(!slice_b.empty());
855 
856       unsigned char type_byte_a;
857       if (!DecodeByte(&slice_a, &type_byte_a)) {
858         *ok = false;
859         return 0;
860       }
861 
862       unsigned char type_byte_b;
863       if (!DecodeByte(&slice_b, &type_byte_b)) {
864         *ok = false;
865         return 0;
866       }
867 
868       if (int x = type_byte_a - type_byte_b)
869         return x;
870       if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte)
871         return 0;
872 
873       if (type_byte_a == kScopesPrefixByte)
874         return slice_a.compare(slice_b);
875 
876       // Compare<> is used (which re-decodes the prefix) rather than an
877       // specialized CompareSuffix<> because metadata is relatively uncommon
878       // in the database.
879 
880       if (type_byte_a == kDatabaseFreeListTypeByte) {
881         // TODO(jsbell): No need to pass only_compare_index_keys through here.
882         return Compare<DatabaseFreeListKey>(a, b, only_compare_index_keys, ok);
883       }
884       if (type_byte_a == kDatabaseNameTypeByte) {
885         return Compare<DatabaseNameKey>(a, b, /*only_compare_index_keys*/ false,
886                                         ok);
887       }
888       break;
889     }
890 
891     case KeyPrefix::DATABASE_METADATA: {
892       DCHECK(!slice_a.empty());
893       DCHECK(!slice_b.empty());
894 
895       unsigned char type_byte_a;
896       if (!DecodeByte(&slice_a, &type_byte_a)) {
897         *ok = false;
898         return 0;
899       }
900 
901       unsigned char type_byte_b;
902       if (!DecodeByte(&slice_b, &type_byte_b)) {
903         *ok = false;
904         return 0;
905       }
906 
907       if (int x = type_byte_a - type_byte_b)
908         return x;
909       if (type_byte_a < DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE)
910         return 0;
911 
912       // Compare<> is used (which re-decodes the prefix) rather than an
913       // specialized CompareSuffix<> because metadata is relatively uncommon
914       // in the database.
915 
916       if (type_byte_a == kObjectStoreMetaDataTypeByte) {
917         // TODO(jsbell): No need to pass only_compare_index_keys through here.
918         return Compare<ObjectStoreMetaDataKey>(a, b, only_compare_index_keys,
919                                                ok);
920       }
921       if (type_byte_a == kIndexMetaDataTypeByte) {
922         return Compare<IndexMetaDataKey>(a, b,
923                                          /*only_compare_index_keys*/ false, ok);
924       }
925       if (type_byte_a == kObjectStoreFreeListTypeByte) {
926         return Compare<ObjectStoreFreeListKey>(a, b, only_compare_index_keys,
927                                                ok);
928       }
929       if (type_byte_a == kIndexFreeListTypeByte) {
930         return Compare<IndexFreeListKey>(a, b,
931                                          /*only_compare_index_keys*/ false, ok);
932       }
933       if (type_byte_a == kObjectStoreNamesTypeByte) {
934         // TODO(jsbell): No need to pass only_compare_index_keys through here.
935         return Compare<ObjectStoreNamesKey>(a, b, only_compare_index_keys, ok);
936       }
937       if (type_byte_a == kIndexNamesKeyTypeByte) {
938         return Compare<IndexNamesKey>(a, b, /*only_compare_index_keys*/ false,
939                                       ok);
940       }
941       break;
942     }
943 
944     case KeyPrefix::OBJECT_STORE_DATA: {
945       // Provide a stable ordering for invalid data.
946       if (slice_a.empty() || slice_b.empty())
947         return CompareSizes(slice_a.size(), slice_b.size());
948 
949       return CompareSuffix<ObjectStoreDataKey>(
950           &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
951     }
952 
953     case KeyPrefix::EXISTS_ENTRY: {
954       // Provide a stable ordering for invalid data.
955       if (slice_a.empty() || slice_b.empty())
956         return CompareSizes(slice_a.size(), slice_b.size());
957 
958       return CompareSuffix<ExistsEntryKey>(
959           &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
960     }
961 
962     case KeyPrefix::BLOB_ENTRY: {
963       // Provide a stable ordering for invalid data.
964       if (slice_a.empty() || slice_b.empty())
965         return CompareSizes(slice_a.size(), slice_b.size());
966 
967       return CompareSuffix<BlobEntryKey>(&slice_a, &slice_b,
968                                          /*only_compare_index_keys*/ false, ok);
969     }
970 
971     case KeyPrefix::INDEX_DATA: {
972       // Provide a stable ordering for invalid data.
973       if (slice_a.empty() || slice_b.empty())
974         return CompareSizes(slice_a.size(), slice_b.size());
975 
976       return CompareSuffix<IndexDataKey>(&slice_a, &slice_b,
977                                          only_compare_index_keys, ok);
978     }
979 
980     case KeyPrefix::INVALID_TYPE:
981       break;
982   }
983 
984   NOTREACHED();
985   *ok = false;
986   return 0;
987 }
988 
989 }  // namespace
990 
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys)991 int Compare(const StringPiece& a,
992             const StringPiece& b,
993             bool only_compare_index_keys) {
994   bool ok;
995   int result = Compare(a, b, only_compare_index_keys, &ok);
996   // TODO(dmurph): Report this somehow. https://crbug.com/913121
997   DCHECK(ok);
998   if (!ok)
999     return 0;
1000   return result;
1001 }
1002 
CompareKeys(const StringPiece & a,const StringPiece & b)1003 int CompareKeys(const StringPiece& a, const StringPiece& b) {
1004   return Compare(a, b, false /*index_keys*/);
1005 }
1006 
CompareIndexKeys(const StringPiece & a,const StringPiece & b)1007 int CompareIndexKeys(const StringPiece& a, const StringPiece& b) {
1008   return Compare(a, b, true /*index_keys*/);
1009 }
1010 
IndexedDBKeyToDebugString(base::StringPiece key)1011 std::string IndexedDBKeyToDebugString(base::StringPiece key) {
1012   base::StringPiece key_with_prefix_preserved = key;
1013   KeyPrefix prefix;
1014   std::stringstream result;
1015   if (!KeyPrefix::Decode(&key, &prefix)) {
1016     result << "<Error decoding key prefix>";
1017     return result.str();
1018   }
1019   result << prefix.DebugString() << ", ";
1020 
1021   switch (prefix.type()) {
1022     case KeyPrefix::GLOBAL_METADATA: {
1023       unsigned char type_byte;
1024       if (!DecodeByte(&key, &type_byte)) {
1025         result << "No_Type_Byte";
1026         break;
1027       }
1028       switch (type_byte) {
1029         case kSchemaVersionTypeByte:
1030           result << "kSchemaVersionTypeByte";
1031           break;
1032         case kMaxDatabaseIdTypeByte:
1033           result << "kMaxDatabaseIdTypeByte";
1034           break;
1035         case kDataVersionTypeByte:
1036           result << "kDataVersionTypeByte";
1037           break;
1038         case kRecoveryBlobJournalTypeByte:
1039           result << "kRecoveryBlobJournalTypeByte";
1040           break;
1041         case kActiveBlobJournalTypeByte:
1042           result << "kActiveBlobJournalTypeByte";
1043           break;
1044         case kEarliestSweepTimeTypeByte:
1045           result << "kEarliestSweepTimeTypeByte";
1046           break;
1047         case kScopesPrefixByte:
1048           result << "Scopes key: "
1049                  << leveldb_scopes::KeyToDebugString(base::make_span(
1050                         reinterpret_cast<const uint8_t*>(key.data()),
1051                         key.size()));
1052           break;
1053         case kDatabaseFreeListTypeByte: {
1054           DatabaseFreeListKey db_free_list_key;
1055           if (!DatabaseFreeListKey::Decode(&key_with_prefix_preserved,
1056                                            &db_free_list_key)) {
1057             result << "kDatabaseFreeListTypeByte, Invalid_Key";
1058             break;
1059           }
1060           result << db_free_list_key.DebugString();
1061           break;
1062         }
1063         case kDatabaseNameTypeByte: {
1064           DatabaseNameKey db_name_key;
1065           if (!DatabaseNameKey::Decode(&key_with_prefix_preserved,
1066                                        &db_name_key)) {
1067             result << "kDatabaseNameTypeByte, Invalid_Key";
1068             break;
1069           }
1070           result << db_name_key.DebugString();
1071           break;
1072         }
1073         default:
1074           result << "Invalid_metadata_type";
1075           break;
1076       }
1077       break;
1078     }
1079 
1080     case KeyPrefix::DATABASE_METADATA: {
1081       unsigned char type_byte;
1082       if (!DecodeByte(&key, &type_byte)) {
1083         result << "No_Type_Byte";
1084         break;
1085       }
1086       switch (type_byte) {
1087         case DatabaseMetaDataKey::ORIGIN_NAME:
1088           result << "ORIGIN_NAME";
1089           break;
1090         case DatabaseMetaDataKey::DATABASE_NAME:
1091           result << "DATABASE_NAME";
1092           break;
1093         case DatabaseMetaDataKey::USER_STRING_VERSION:
1094           result << "USER_STRING_VERSION";
1095           break;
1096         case DatabaseMetaDataKey::MAX_OBJECT_STORE_ID:
1097           result << "MAX_OBJECT_STORE_ID";
1098           break;
1099         case DatabaseMetaDataKey::USER_VERSION:
1100           result << "USER_VERSION";
1101           break;
1102         case DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER:
1103           result << "BLOB_KEY_GENERATOR_CURRENT_NUMBER";
1104           break;
1105         case kObjectStoreMetaDataTypeByte: {
1106           ObjectStoreMetaDataKey sub_key;
1107           if (!ObjectStoreMetaDataKey::Decode(&key_with_prefix_preserved,
1108                                               &sub_key)) {
1109             result << "Invalid_ObjectStoreMetaDataKey";
1110             break;
1111           }
1112           result << sub_key.DebugString();
1113           break;
1114         }
1115         case kIndexMetaDataTypeByte: {
1116           IndexMetaDataKey sub_key;
1117           if (!IndexMetaDataKey::Decode(&key_with_prefix_preserved, &sub_key)) {
1118             result << "Invalid_IndexMetaDataKey";
1119             break;
1120           }
1121           result << sub_key.DebugString();
1122           break;
1123         }
1124         case kObjectStoreFreeListTypeByte: {
1125           ObjectStoreFreeListKey sub_key;
1126           if (!ObjectStoreFreeListKey::Decode(&key_with_prefix_preserved,
1127                                               &sub_key)) {
1128             result << "Invalid_ObjectStoreFreeListKey";
1129             break;
1130           }
1131           result << sub_key.DebugString();
1132           break;
1133         }
1134         case kIndexFreeListTypeByte: {
1135           IndexFreeListKey sub_key;
1136           if (!IndexFreeListKey::Decode(&key_with_prefix_preserved, &sub_key)) {
1137             result << "Invalid_IndexFreeListKey";
1138             break;
1139           }
1140           result << sub_key.DebugString();
1141           break;
1142         }
1143         case kObjectStoreNamesTypeByte: {
1144           ObjectStoreNamesKey sub_key;
1145           if (!ObjectStoreNamesKey::Decode(&key_with_prefix_preserved,
1146                                            &sub_key)) {
1147             result << "Invalid_ObjectStoreNamesKey";
1148             break;
1149           }
1150           result << sub_key.DebugString();
1151           break;
1152         }  // namespace content
1153         case kIndexNamesKeyTypeByte: {
1154           IndexNamesKey sub_key;
1155           if (!IndexNamesKey::Decode(&key_with_prefix_preserved, &sub_key)) {
1156             result << "Invalid_IndexNamesKey";
1157             break;
1158           }
1159           result << sub_key.DebugString();
1160           break;
1161         }
1162       }
1163       break;
1164     }
1165     case KeyPrefix::OBJECT_STORE_DATA: {
1166       ObjectStoreDataKey sub_key;
1167       if (!ObjectStoreDataKey::Decode(&key_with_prefix_preserved, &sub_key)) {
1168         result << "Invalid_ObjectStoreDataKey";
1169         break;
1170       }
1171       result << sub_key.DebugString();
1172       break;
1173     }
1174 
1175     case KeyPrefix::EXISTS_ENTRY: {
1176       ExistsEntryKey sub_key;
1177       if (!ExistsEntryKey::Decode(&key_with_prefix_preserved, &sub_key)) {
1178         result << "Invalid_ExistsEntryKey";
1179         break;
1180       }
1181       result << sub_key.DebugString();
1182       break;
1183     }
1184 
1185     case KeyPrefix::BLOB_ENTRY: {
1186       BlobEntryKey sub_key;
1187       if (!BlobEntryKey::Decode(&key_with_prefix_preserved, &sub_key)) {
1188         result << "Invalid_BlobEntryKey";
1189         break;
1190       }
1191       result << sub_key.DebugString();
1192       break;
1193     }
1194 
1195     case KeyPrefix::INDEX_DATA: {
1196       IndexDataKey sub_key;
1197       if (!IndexDataKey::Decode(&key_with_prefix_preserved, &sub_key)) {
1198         result << "Invalid_IndexDataKey";
1199         break;
1200       }
1201       result << sub_key.DebugString();
1202       break;
1203     }
1204 
1205     case KeyPrefix::INVALID_TYPE:
1206       result << "InvalidKeyType";
1207       break;
1208   }
1209   result << "]";
1210   return result.str();
1211 }
1212 
GetDatabaseLockRange(int64_t database_id)1213 ScopeLockRange GetDatabaseLockRange(int64_t database_id) {
1214   // The numbers are transformed into big-endian to make them
1215   // bytewise-comparable. Eventually, these lock ranges should just match the
1216   // leveldb keys when they are bytewise-comparable.
1217   uint64_t first[1] = {ByteSwapToBE64(static_cast<uint64_t>(database_id))};
1218   uint64_t next[1] = {ByteSwapToBE64(static_cast<uint64_t>(database_id + 1))};
1219   return {std::string(reinterpret_cast<char*>(&first), sizeof(first)),
1220           std::string(reinterpret_cast<char*>(&next), sizeof(next))};
1221 }
1222 
GetObjectStoreLockRange(int64_t database_id,int64_t object_store_id)1223 ScopeLockRange GetObjectStoreLockRange(int64_t database_id,
1224                                        int64_t object_store_id) {
1225   // The numbers are transformed into big-endian to make them
1226   // bytewise-comparable. Eventually, these lock ranges should just match the
1227   // leveldb keys when they are bytewise-comparable.
1228   uint64_t first[2] = {ByteSwapToBE64(static_cast<uint64_t>(database_id)),
1229                        ByteSwapToBE64(static_cast<uint64_t>(object_store_id))};
1230   uint64_t next[2] = {
1231       ByteSwapToBE64(static_cast<uint64_t>(database_id)),
1232       ByteSwapToBE64(static_cast<uint64_t>(object_store_id + 1))};
1233   return {std::string(reinterpret_cast<char*>(&first), sizeof(first)),
1234           std::string(reinterpret_cast<char*>(&next), sizeof(next))};
1235 }
1236 
KeyPrefix()1237 KeyPrefix::KeyPrefix()
1238     : database_id_(INVALID_TYPE),
1239       object_store_id_(INVALID_TYPE),
1240       index_id_(INVALID_TYPE) {}
1241 
KeyPrefix(int64_t database_id)1242 KeyPrefix::KeyPrefix(int64_t database_id)
1243     : database_id_(database_id), object_store_id_(0), index_id_(0) {
1244   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1245 }
1246 
KeyPrefix(int64_t database_id,int64_t object_store_id)1247 KeyPrefix::KeyPrefix(int64_t database_id, int64_t object_store_id)
1248     : database_id_(database_id),
1249       object_store_id_(object_store_id),
1250       index_id_(0) {
1251   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1252   DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1253 }
1254 
KeyPrefix(int64_t database_id,int64_t object_store_id,int64_t index_id)1255 KeyPrefix::KeyPrefix(int64_t database_id,
1256                      int64_t object_store_id,
1257                      int64_t index_id)
1258     : database_id_(database_id),
1259       object_store_id_(object_store_id),
1260       index_id_(index_id) {
1261   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1262   DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1263   DCHECK(KeyPrefix::IsValidIndexId(index_id));
1264 }
1265 
KeyPrefix(enum Type type,int64_t database_id,int64_t object_store_id,int64_t index_id)1266 KeyPrefix::KeyPrefix(enum Type type,
1267                      int64_t database_id,
1268                      int64_t object_store_id,
1269                      int64_t index_id)
1270     : database_id_(database_id),
1271       object_store_id_(object_store_id),
1272       index_id_(index_id) {
1273   DCHECK_EQ(type, INVALID_TYPE);
1274   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1275   DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1276 }
1277 
CreateWithSpecialIndex(int64_t database_id,int64_t object_store_id,int64_t index_id)1278 KeyPrefix KeyPrefix::CreateWithSpecialIndex(int64_t database_id,
1279                                             int64_t object_store_id,
1280                                             int64_t index_id) {
1281   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1282   DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1283   DCHECK(index_id);
1284   return KeyPrefix(INVALID_TYPE, database_id, object_store_id, index_id);
1285 }
1286 
IsValidDatabaseId(int64_t database_id)1287 bool KeyPrefix::IsValidDatabaseId(int64_t database_id) {
1288   return (database_id > 0) && (database_id < KeyPrefix::kMaxDatabaseId);
1289 }
1290 
IsValidObjectStoreId(int64_t object_store_id)1291 bool KeyPrefix::IsValidObjectStoreId(int64_t object_store_id) {
1292   return (object_store_id > 0) &&
1293          (object_store_id < KeyPrefix::kMaxObjectStoreId);
1294 }
1295 
IsValidIndexId(int64_t index_id)1296 bool KeyPrefix::IsValidIndexId(int64_t index_id) {
1297   return (index_id >= kMinimumIndexId) && (index_id < KeyPrefix::kMaxIndexId);
1298 }
1299 
Decode(StringPiece * slice,KeyPrefix * result)1300 bool KeyPrefix::Decode(StringPiece* slice, KeyPrefix* result) {
1301   unsigned char first_byte;
1302   if (!DecodeByte(slice, &first_byte))
1303     return false;
1304 
1305   size_t database_id_bytes = ((first_byte >> 5) & 0x7) + 1;
1306   size_t object_store_id_bytes = ((first_byte >> 2) & 0x7) + 1;
1307   size_t index_id_bytes = (first_byte & 0x3) + 1;
1308 
1309   if (database_id_bytes + object_store_id_bytes + index_id_bytes >
1310       slice->size())
1311     return false;
1312 
1313   {
1314     StringPiece tmp(slice->begin(), database_id_bytes);
1315     if (!DecodeInt(&tmp, &result->database_id_))
1316       return false;
1317   }
1318   slice->remove_prefix(database_id_bytes);
1319   {
1320     StringPiece tmp(slice->begin(), object_store_id_bytes);
1321     if (!DecodeInt(&tmp, &result->object_store_id_))
1322       return false;
1323   }
1324   slice->remove_prefix(object_store_id_bytes);
1325   {
1326     StringPiece tmp(slice->begin(), index_id_bytes);
1327     if (!DecodeInt(&tmp, &result->index_id_))
1328       return false;
1329   }
1330   slice->remove_prefix(index_id_bytes);
1331   return true;
1332 }
1333 
EncodeEmpty()1334 std::string KeyPrefix::EncodeEmpty() {
1335   const std::string result(4, 0);
1336   DCHECK(EncodeInternal(0, 0, 0) == std::string(4, 0));
1337   return result;
1338 }
1339 
Encode() const1340 std::string KeyPrefix::Encode() const {
1341   DCHECK(database_id_ != kInvalidId);
1342   DCHECK(object_store_id_ != kInvalidId);
1343   DCHECK(index_id_ != kInvalidId);
1344   return EncodeInternal(database_id_, object_store_id_, index_id_);
1345 }
1346 
EncodeInternal(int64_t database_id,int64_t object_store_id,int64_t index_id)1347 std::string KeyPrefix::EncodeInternal(int64_t database_id,
1348                                       int64_t object_store_id,
1349                                       int64_t index_id) {
1350   std::string database_id_string;
1351   std::string object_store_id_string;
1352   std::string index_id_string;
1353 
1354   EncodeIntSafely(database_id, kMaxDatabaseId, &database_id_string);
1355   EncodeIntSafely(object_store_id, kMaxObjectStoreId, &object_store_id_string);
1356   EncodeIntSafely(index_id, kMaxIndexId, &index_id_string);
1357 
1358   DCHECK(database_id_string.size() <= kMaxDatabaseIdSizeBytes);
1359   DCHECK(object_store_id_string.size() <= kMaxObjectStoreIdSizeBytes);
1360   DCHECK(index_id_string.size() <= kMaxIndexIdSizeBytes);
1361 
1362   unsigned char first_byte =
1363       (database_id_string.size() - 1)
1364           << (kMaxObjectStoreIdSizeBits + kMaxIndexIdSizeBits) |
1365       (object_store_id_string.size() - 1) << kMaxIndexIdSizeBits |
1366       (index_id_string.size() - 1);
1367   static_assert(kMaxDatabaseIdSizeBits + kMaxObjectStoreIdSizeBits +
1368                         kMaxIndexIdSizeBits ==
1369                     sizeof(first_byte) * 8,
1370                 "cannot encode ids");
1371   std::string ret;
1372   ret.reserve(kDefaultInlineBufferSize);
1373   ret.push_back(first_byte);
1374   ret.append(database_id_string);
1375   ret.append(object_store_id_string);
1376   ret.append(index_id_string);
1377 
1378   DCHECK_LE(ret.size(), kDefaultInlineBufferSize);
1379   return ret;
1380 }
1381 
Compare(const KeyPrefix & other) const1382 int KeyPrefix::Compare(const KeyPrefix& other) const {
1383   DCHECK(database_id_ != kInvalidId);
1384   DCHECK(object_store_id_ != kInvalidId);
1385   DCHECK(index_id_ != kInvalidId);
1386 
1387   if (database_id_ != other.database_id_)
1388     return CompareInts(database_id_, other.database_id_);
1389   if (object_store_id_ != other.object_store_id_)
1390     return CompareInts(object_store_id_, other.object_store_id_);
1391   if (index_id_ != other.index_id_)
1392     return CompareInts(index_id_, other.index_id_);
1393   return 0;
1394 }
1395 
DebugString()1396 std::string KeyPrefix::DebugString() {
1397   std::stringstream result;
1398   result << "{";
1399   switch (type()) {
1400     case GLOBAL_METADATA:
1401       result << "GLOBAL_META";
1402       break;
1403     case DATABASE_METADATA:
1404       result << "DB_META, db: " << database_id_;
1405       break;
1406     case OBJECT_STORE_DATA:
1407       result << "OS_DATA, db: " << database_id_ << ", os: " << object_store_id_;
1408       break;
1409     case EXISTS_ENTRY:
1410       result << "EXISTS_ENTRY, db: " << database_id_
1411              << ", os: " << object_store_id_;
1412       break;
1413     case BLOB_ENTRY:
1414       result << "BLOB_ENTRY, db: " << database_id_
1415              << ", os: " << object_store_id_;
1416       break;
1417     case INDEX_DATA:
1418       result << "INDEX_DATA, db: " << database_id_
1419              << ", os: " << object_store_id_ << ", idx: " << index_id_;
1420       break;
1421     case INVALID_TYPE:
1422       result << "INVALID_TYPE";
1423       break;
1424   }
1425   result << "}";
1426   return result.str();
1427 }
1428 
type() const1429 KeyPrefix::Type KeyPrefix::type() const {
1430   DCHECK(database_id_ != kInvalidId);
1431   DCHECK(object_store_id_ != kInvalidId);
1432   DCHECK(index_id_ != kInvalidId);
1433 
1434   if (!database_id_)
1435     return GLOBAL_METADATA;
1436   if (!object_store_id_)
1437     return DATABASE_METADATA;
1438   if (index_id_ == kObjectStoreDataIndexId)
1439     return OBJECT_STORE_DATA;
1440   if (index_id_ == kExistsEntryIndexId)
1441     return EXISTS_ENTRY;
1442   if (index_id_ == kBlobEntryIndexId)
1443     return BLOB_ENTRY;
1444   if (index_id_ >= kMinimumIndexId)
1445     return INDEX_DATA;
1446 
1447   NOTREACHED();
1448   return INVALID_TYPE;
1449 }
1450 
Encode()1451 std::string SchemaVersionKey::Encode() {
1452   std::string ret = KeyPrefix::EncodeEmpty();
1453   ret.push_back(kSchemaVersionTypeByte);
1454   return ret;
1455 }
1456 
Encode()1457 std::string MaxDatabaseIdKey::Encode() {
1458   std::string ret = KeyPrefix::EncodeEmpty();
1459   ret.push_back(kMaxDatabaseIdTypeByte);
1460   return ret;
1461 }
1462 
Encode()1463 std::string DataVersionKey::Encode() {
1464   std::string ret = KeyPrefix::EncodeEmpty();
1465   ret.push_back(kDataVersionTypeByte);
1466   return ret;
1467 }
1468 
Encode()1469 std::string RecoveryBlobJournalKey::Encode() {
1470   std::string ret = KeyPrefix::EncodeEmpty();
1471   ret.push_back(kRecoveryBlobJournalTypeByte);
1472   return ret;
1473 }
1474 
Encode()1475 std::string ActiveBlobJournalKey::Encode() {
1476   std::string ret = KeyPrefix::EncodeEmpty();
1477   ret.push_back(kActiveBlobJournalTypeByte);
1478   return ret;
1479 }
1480 
Encode()1481 std::string EarliestSweepKey::Encode() {
1482   std::string ret = KeyPrefix::EncodeEmpty();
1483   ret.push_back(kEarliestSweepTimeTypeByte);
1484   return ret;
1485 }
1486 
Encode()1487 std::vector<uint8_t> ScopesPrefix::Encode() {
1488   std::string ret = KeyPrefix::EncodeEmpty();
1489   ret.push_back(kScopesPrefixByte);
1490   auto span = base::make_span(ret);
1491   return std::vector<uint8_t>(span.begin(), span.end());
1492 }
1493 
DatabaseFreeListKey()1494 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {}
1495 
Decode(StringPiece * slice,DatabaseFreeListKey * result)1496 bool DatabaseFreeListKey::Decode(StringPiece* slice,
1497                                  DatabaseFreeListKey* result) {
1498   KeyPrefix prefix;
1499   if (!KeyPrefix::Decode(slice, &prefix))
1500     return false;
1501   DCHECK(!prefix.database_id_);
1502   DCHECK(!prefix.object_store_id_);
1503   DCHECK(!prefix.index_id_);
1504   unsigned char type_byte = 0;
1505   if (!DecodeByte(slice, &type_byte))
1506     return false;
1507   DCHECK_EQ(type_byte, kDatabaseFreeListTypeByte);
1508   if (!DecodeVarInt(slice, &result->database_id_))
1509     return false;
1510   return true;
1511 }
1512 
Encode(int64_t database_id)1513 std::string DatabaseFreeListKey::Encode(int64_t database_id) {
1514   std::string ret = KeyPrefix::EncodeEmpty();
1515   ret.push_back(kDatabaseFreeListTypeByte);
1516   EncodeVarInt(database_id, &ret);
1517   return ret;
1518 }
1519 
EncodeMaxKey()1520 std::string DatabaseFreeListKey::EncodeMaxKey() {
1521   return Encode(std::numeric_limits<int64_t>::max());
1522 }
1523 
DatabaseId() const1524 int64_t DatabaseFreeListKey::DatabaseId() const {
1525   DCHECK_GE(database_id_, 0);
1526   return database_id_;
1527 }
1528 
Compare(const DatabaseFreeListKey & other) const1529 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey& other) const {
1530   DCHECK_GE(database_id_, 0);
1531   return CompareInts(database_id_, other.database_id_);
1532 }
1533 
DebugString() const1534 std::string DatabaseFreeListKey::DebugString() const {
1535   std::stringstream result;
1536   result << "DatabaseFreeListKey{db: " << database_id_ << "}";
1537   return result.str();
1538 }
1539 
Decode(StringPiece * slice,DatabaseNameKey * result)1540 bool DatabaseNameKey::Decode(StringPiece* slice, DatabaseNameKey* result) {
1541   KeyPrefix prefix;
1542   if (!KeyPrefix::Decode(slice, &prefix))
1543     return false;
1544   DCHECK(!prefix.database_id_);
1545   DCHECK(!prefix.object_store_id_);
1546   DCHECK(!prefix.index_id_);
1547   unsigned char type_byte = 0;
1548   if (!DecodeByte(slice, &type_byte))
1549     return false;
1550   DCHECK_EQ(type_byte, kDatabaseNameTypeByte);
1551   if (!DecodeStringWithLength(slice, &result->origin_))
1552     return false;
1553   if (!DecodeStringWithLength(slice, &result->database_name_))
1554     return false;
1555   return true;
1556 }
1557 
Encode(const std::string & origin_identifier,const base::string16 & database_name)1558 std::string DatabaseNameKey::Encode(const std::string& origin_identifier,
1559                                     const base::string16& database_name) {
1560   std::string ret = KeyPrefix::EncodeEmpty();
1561   ret.push_back(kDatabaseNameTypeByte);
1562   EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier), &ret);
1563   EncodeStringWithLength(database_name, &ret);
1564   return ret;
1565 }
1566 
EncodeMinKeyForOrigin(const std::string & origin_identifier)1567 std::string DatabaseNameKey::EncodeMinKeyForOrigin(
1568     const std::string& origin_identifier) {
1569   return Encode(origin_identifier, base::string16());
1570 }
1571 
EncodeStopKeyForOrigin(const std::string & origin_identifier)1572 std::string DatabaseNameKey::EncodeStopKeyForOrigin(
1573     const std::string& origin_identifier) {
1574   // just after origin in collation order
1575   return EncodeMinKeyForOrigin(origin_identifier + '\x01');
1576 }
1577 
Compare(const DatabaseNameKey & other)1578 int DatabaseNameKey::Compare(const DatabaseNameKey& other) {
1579   if (int x = origin_.compare(other.origin_))
1580     return x;
1581   return database_name_.compare(other.database_name_);
1582 }
1583 
DebugString() const1584 std::string DatabaseNameKey::DebugString() const {
1585   std::stringstream result;
1586   result << "DatabaseNameKey{origin: " << origin_
1587          << ", database_name: " << database_name_ << "}";
1588   return result.str();
1589 }
1590 
IsValidBlobNumber(int64_t blob_number)1591 bool DatabaseMetaDataKey::IsValidBlobNumber(int64_t blob_number) {
1592   return blob_number >= kBlobNumberGeneratorInitialNumber;
1593 }
1594 
1595 const int64_t DatabaseMetaDataKey::kAllBlobsNumber = 1;
1596 const int64_t DatabaseMetaDataKey::kBlobNumberGeneratorInitialNumber = 2;
1597 const int64_t DatabaseMetaDataKey::kInvalidBlobNumber = -1;
1598 
Encode(int64_t database_id,MetaDataType meta_data_type)1599 std::string DatabaseMetaDataKey::Encode(int64_t database_id,
1600                                         MetaDataType meta_data_type) {
1601   KeyPrefix prefix(database_id);
1602   std::string ret = prefix.Encode();
1603   ret.push_back(meta_data_type);
1604   return ret;
1605 }
1606 
1607 const int64_t ObjectStoreMetaDataKey::kKeyGeneratorInitialNumber = 1;
1608 
ObjectStoreMetaDataKey()1609 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
1610     : object_store_id_(-1), meta_data_type_(0xFF) {}
1611 
Decode(StringPiece * slice,ObjectStoreMetaDataKey * result)1612 bool ObjectStoreMetaDataKey::Decode(StringPiece* slice,
1613                                     ObjectStoreMetaDataKey* result) {
1614   KeyPrefix prefix;
1615   if (!KeyPrefix::Decode(slice, &prefix))
1616     return false;
1617   DCHECK(prefix.database_id_);
1618   DCHECK(!prefix.object_store_id_);
1619   DCHECK(!prefix.index_id_);
1620   unsigned char type_byte = 0;
1621   if (!DecodeByte(slice, &type_byte))
1622     return false;
1623   DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte);
1624   if (!DecodeVarInt(slice, &result->object_store_id_))
1625     return false;
1626   DCHECK(result->object_store_id_);
1627   if (!DecodeByte(slice, &result->meta_data_type_))
1628     return false;
1629   return true;
1630 }
1631 
Encode(int64_t database_id,int64_t object_store_id,unsigned char meta_data_type)1632 std::string ObjectStoreMetaDataKey::Encode(int64_t database_id,
1633                                            int64_t object_store_id,
1634                                            unsigned char meta_data_type) {
1635   KeyPrefix prefix(database_id);
1636   std::string ret = prefix.Encode();
1637   ret.push_back(kObjectStoreMetaDataTypeByte);
1638   EncodeVarInt(object_store_id, &ret);
1639   ret.push_back(meta_data_type);
1640   return ret;
1641 }
1642 
EncodeMaxKey(int64_t database_id)1643 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64_t database_id) {
1644   return Encode(database_id, std::numeric_limits<int64_t>::max(),
1645                 kObjectMetaDataTypeMaximum);
1646 }
1647 
EncodeMaxKey(int64_t database_id,int64_t object_store_id)1648 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64_t database_id,
1649                                                  int64_t object_store_id) {
1650   return Encode(database_id, object_store_id, kObjectMetaDataTypeMaximum);
1651 }
1652 
ObjectStoreId() const1653 int64_t ObjectStoreMetaDataKey::ObjectStoreId() const {
1654   DCHECK_GE(object_store_id_, 0);
1655   return object_store_id_;
1656 }
MetaDataType() const1657 unsigned char ObjectStoreMetaDataKey::MetaDataType() const {
1658   return meta_data_type_;
1659 }
1660 
Compare(const ObjectStoreMetaDataKey & other)1661 int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey& other) {
1662   DCHECK_GE(object_store_id_, 0);
1663   if (int x = CompareInts(object_store_id_, other.object_store_id_))
1664     return x;
1665   return meta_data_type_ - other.meta_data_type_;
1666 }
1667 
DebugString() const1668 std::string ObjectStoreMetaDataKey::DebugString() const {
1669   std::stringstream result;
1670   result << "ObjectStoreMetaDataKey{os: " << object_store_id_;
1671   switch (meta_data_type_) {
1672     case NAME:
1673       result << ", NAME";
1674       break;
1675     case KEY_PATH:
1676       result << ", KEY_PATH";
1677       break;
1678     case AUTO_INCREMENT:
1679       result << ", AUTO_INCREMENT";
1680       break;
1681     case EVICTABLE:
1682       result << ", EVICTABLE";
1683       break;
1684     case LAST_VERSION:
1685       result << ", LAST_VERSION";
1686       break;
1687     case MAX_INDEX_ID:
1688       result << ", MAX_INDEX_ID";
1689       break;
1690     case HAS_KEY_PATH:
1691       result << ", HAS_KEY_PATH";
1692       break;
1693     case KEY_GENERATOR_CURRENT_NUMBER:
1694       result << ", KEY_GENERATOR_CURRENT_NUMBER";
1695       break;
1696     default:
1697       result << ", INVALID_TYPE";
1698   }
1699   result << "}";
1700   return result.str();
1701 }
1702 
IndexMetaDataKey()1703 IndexMetaDataKey::IndexMetaDataKey()
1704     : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {}
1705 
Decode(StringPiece * slice,IndexMetaDataKey * result)1706 bool IndexMetaDataKey::Decode(StringPiece* slice, IndexMetaDataKey* result) {
1707   KeyPrefix prefix;
1708   if (!KeyPrefix::Decode(slice, &prefix))
1709     return false;
1710   DCHECK(prefix.database_id_);
1711   DCHECK(!prefix.object_store_id_);
1712   DCHECK(!prefix.index_id_);
1713   unsigned char type_byte = 0;
1714   if (!DecodeByte(slice, &type_byte))
1715     return false;
1716   DCHECK_EQ(type_byte, kIndexMetaDataTypeByte);
1717   if (!DecodeVarInt(slice, &result->object_store_id_))
1718     return false;
1719   if (!DecodeVarInt(slice, &result->index_id_))
1720     return false;
1721   if (!DecodeByte(slice, &result->meta_data_type_))
1722     return false;
1723   return true;
1724 }
1725 
Encode(int64_t database_id,int64_t object_store_id,int64_t index_id,unsigned char meta_data_type)1726 std::string IndexMetaDataKey::Encode(int64_t database_id,
1727                                      int64_t object_store_id,
1728                                      int64_t index_id,
1729                                      unsigned char meta_data_type) {
1730   KeyPrefix prefix(database_id);
1731   std::string ret = prefix.Encode();
1732   ret.push_back(kIndexMetaDataTypeByte);
1733   EncodeVarInt(object_store_id, &ret);
1734   EncodeVarInt(index_id, &ret);
1735   EncodeByte(meta_data_type, &ret);
1736   return ret;
1737 }
1738 
EncodeMaxKey(int64_t database_id,int64_t object_store_id)1739 std::string IndexMetaDataKey::EncodeMaxKey(int64_t database_id,
1740                                            int64_t object_store_id) {
1741   return Encode(database_id, object_store_id,
1742                 std::numeric_limits<int64_t>::max(), kIndexMetaDataTypeMaximum);
1743 }
1744 
EncodeMaxKey(int64_t database_id,int64_t object_store_id,int64_t index_id)1745 std::string IndexMetaDataKey::EncodeMaxKey(int64_t database_id,
1746                                            int64_t object_store_id,
1747                                            int64_t index_id) {
1748   return Encode(database_id, object_store_id, index_id,
1749                 kIndexMetaDataTypeMaximum);
1750 }
1751 
Compare(const IndexMetaDataKey & other)1752 int IndexMetaDataKey::Compare(const IndexMetaDataKey& other) {
1753   DCHECK_GE(object_store_id_, 0);
1754   DCHECK_GE(index_id_, 0);
1755 
1756   if (int x = CompareInts(object_store_id_, other.object_store_id_))
1757     return x;
1758   if (int x = CompareInts(index_id_, other.index_id_))
1759     return x;
1760   return meta_data_type_ - other.meta_data_type_;
1761 }
1762 
DebugString() const1763 std::string IndexMetaDataKey::DebugString() const {
1764   std::stringstream result;
1765   result << "IndexMetaDataKey{os: " << object_store_id_
1766          << ", idx: " << index_id_;
1767   switch (meta_data_type_) {
1768     case NAME:
1769       result << ", NAME";
1770       break;
1771     case UNIQUE:
1772       result << ", UNIQUE";
1773       break;
1774     case KEY_PATH:
1775       result << ", KEY_PATH";
1776       break;
1777     case MULTI_ENTRY:
1778       result << ", MULTI_ENTRY";
1779       break;
1780     default:
1781       result << ", INVALID_TYPE";
1782   }
1783   result << "}";
1784   return result.str();
1785 }
1786 
IndexId() const1787 int64_t IndexMetaDataKey::IndexId() const {
1788   DCHECK_GE(index_id_, 0);
1789   return index_id_;
1790 }
1791 
ObjectStoreFreeListKey()1792 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {}
1793 
Decode(StringPiece * slice,ObjectStoreFreeListKey * result)1794 bool ObjectStoreFreeListKey::Decode(StringPiece* slice,
1795                                     ObjectStoreFreeListKey* result) {
1796   KeyPrefix prefix;
1797   if (!KeyPrefix::Decode(slice, &prefix))
1798     return false;
1799   DCHECK(prefix.database_id_);
1800   DCHECK(!prefix.object_store_id_);
1801   DCHECK(!prefix.index_id_);
1802   unsigned char type_byte = 0;
1803   if (!DecodeByte(slice, &type_byte))
1804     return false;
1805   DCHECK_EQ(type_byte, kObjectStoreFreeListTypeByte);
1806   if (!DecodeVarInt(slice, &result->object_store_id_))
1807     return false;
1808   return true;
1809 }
1810 
Encode(int64_t database_id,int64_t object_store_id)1811 std::string ObjectStoreFreeListKey::Encode(int64_t database_id,
1812                                            int64_t object_store_id) {
1813   KeyPrefix prefix(database_id);
1814   std::string ret = prefix.Encode();
1815   ret.push_back(kObjectStoreFreeListTypeByte);
1816   EncodeVarInt(object_store_id, &ret);
1817   return ret;
1818 }
1819 
EncodeMaxKey(int64_t database_id)1820 std::string ObjectStoreFreeListKey::EncodeMaxKey(int64_t database_id) {
1821   return Encode(database_id, std::numeric_limits<int64_t>::max());
1822 }
1823 
ObjectStoreId() const1824 int64_t ObjectStoreFreeListKey::ObjectStoreId() const {
1825   DCHECK_GE(object_store_id_, 0);
1826   return object_store_id_;
1827 }
1828 
Compare(const ObjectStoreFreeListKey & other)1829 int ObjectStoreFreeListKey::Compare(const ObjectStoreFreeListKey& other) {
1830   // TODO(jsbell): It may seem strange that we're not comparing database id's,
1831   // but that comparison will have been made earlier.
1832   // We should probably make this more clear, though...
1833   DCHECK_GE(object_store_id_, 0);
1834   return CompareInts(object_store_id_, other.object_store_id_);
1835 }
1836 
DebugString() const1837 std::string ObjectStoreFreeListKey::DebugString() const {
1838   std::stringstream result;
1839   result << "ObjectStoreFreeListKey{os: " << object_store_id_ << "}";
1840   return result.str();
1841 }
1842 
IndexFreeListKey()1843 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {}
1844 
Decode(StringPiece * slice,IndexFreeListKey * result)1845 bool IndexFreeListKey::Decode(StringPiece* slice, IndexFreeListKey* result) {
1846   KeyPrefix prefix;
1847   if (!KeyPrefix::Decode(slice, &prefix))
1848     return false;
1849   DCHECK(prefix.database_id_);
1850   DCHECK(!prefix.object_store_id_);
1851   DCHECK(!prefix.index_id_);
1852   unsigned char type_byte = 0;
1853   if (!DecodeByte(slice, &type_byte))
1854     return false;
1855   DCHECK_EQ(type_byte, kIndexFreeListTypeByte);
1856   if (!DecodeVarInt(slice, &result->object_store_id_))
1857     return false;
1858   if (!DecodeVarInt(slice, &result->index_id_))
1859     return false;
1860   return true;
1861 }
1862 
Encode(int64_t database_id,int64_t object_store_id,int64_t index_id)1863 std::string IndexFreeListKey::Encode(int64_t database_id,
1864                                      int64_t object_store_id,
1865                                      int64_t index_id) {
1866   KeyPrefix prefix(database_id);
1867   std::string ret = prefix.Encode();
1868   ret.push_back(kIndexFreeListTypeByte);
1869   EncodeVarInt(object_store_id, &ret);
1870   EncodeVarInt(index_id, &ret);
1871   return ret;
1872 }
1873 
EncodeMaxKey(int64_t database_id,int64_t object_store_id)1874 std::string IndexFreeListKey::EncodeMaxKey(int64_t database_id,
1875                                            int64_t object_store_id) {
1876   return Encode(database_id, object_store_id,
1877                 std::numeric_limits<int64_t>::max());
1878 }
1879 
Compare(const IndexFreeListKey & other)1880 int IndexFreeListKey::Compare(const IndexFreeListKey& other) {
1881   DCHECK_GE(object_store_id_, 0);
1882   DCHECK_GE(index_id_, 0);
1883   if (int x = CompareInts(object_store_id_, other.object_store_id_))
1884     return x;
1885   return CompareInts(index_id_, other.index_id_);
1886 }
1887 
DebugString() const1888 std::string IndexFreeListKey::DebugString() const {
1889   std::stringstream result;
1890   result << "IndexFreeListKey{os: " << object_store_id_
1891          << ", idx: " << index_id_ << "}";
1892   return result.str();
1893 }
1894 
ObjectStoreId() const1895 int64_t IndexFreeListKey::ObjectStoreId() const {
1896   DCHECK_GE(object_store_id_, 0);
1897   return object_store_id_;
1898 }
1899 
IndexId() const1900 int64_t IndexFreeListKey::IndexId() const {
1901   DCHECK_GE(index_id_, 0);
1902   return index_id_;
1903 }
1904 
1905 // TODO(jsbell): We never use this to look up object store ids,
1906 // because a mapping is kept in the IndexedDBDatabase. Can the
1907 // mapping become unreliable?  Can we remove this?
Decode(StringPiece * slice,ObjectStoreNamesKey * result)1908 bool ObjectStoreNamesKey::Decode(StringPiece* slice,
1909                                  ObjectStoreNamesKey* result) {
1910   KeyPrefix prefix;
1911   if (!KeyPrefix::Decode(slice, &prefix))
1912     return false;
1913   DCHECK(prefix.database_id_);
1914   DCHECK(!prefix.object_store_id_);
1915   DCHECK(!prefix.index_id_);
1916   unsigned char type_byte = 0;
1917   if (!DecodeByte(slice, &type_byte))
1918     return false;
1919   DCHECK_EQ(type_byte, kObjectStoreNamesTypeByte);
1920   if (!DecodeStringWithLength(slice, &result->object_store_name_))
1921     return false;
1922   return true;
1923 }
1924 
Encode(int64_t database_id,const base::string16 & object_store_name)1925 std::string ObjectStoreNamesKey::Encode(
1926     int64_t database_id,
1927     const base::string16& object_store_name) {
1928   KeyPrefix prefix(database_id);
1929   std::string ret = prefix.Encode();
1930   ret.push_back(kObjectStoreNamesTypeByte);
1931   EncodeStringWithLength(object_store_name, &ret);
1932   return ret;
1933 }
1934 
Compare(const ObjectStoreNamesKey & other)1935 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey& other) {
1936   return object_store_name_.compare(other.object_store_name_);
1937 }
1938 
DebugString() const1939 std::string ObjectStoreNamesKey::DebugString() const {
1940   std::stringstream result;
1941   result << "ObjectStoreNamesKey{object_store_name: " << object_store_name_
1942          << "}";
1943   return result.str();
1944 }
1945 
IndexNamesKey()1946 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {}
1947 
1948 // TODO(jsbell): We never use this to look up index ids, because a mapping
1949 // is kept at a higher level.
Decode(StringPiece * slice,IndexNamesKey * result)1950 bool IndexNamesKey::Decode(StringPiece* slice, IndexNamesKey* result) {
1951   KeyPrefix prefix;
1952   if (!KeyPrefix::Decode(slice, &prefix))
1953     return false;
1954   DCHECK(prefix.database_id_);
1955   DCHECK(!prefix.object_store_id_);
1956   DCHECK(!prefix.index_id_);
1957   unsigned char type_byte = 0;
1958   if (!DecodeByte(slice, &type_byte))
1959     return false;
1960   DCHECK_EQ(type_byte, kIndexNamesKeyTypeByte);
1961   if (!DecodeVarInt(slice, &result->object_store_id_))
1962     return false;
1963   if (!DecodeStringWithLength(slice, &result->index_name_))
1964     return false;
1965   return true;
1966 }
1967 
Encode(int64_t database_id,int64_t object_store_id,const base::string16 & index_name)1968 std::string IndexNamesKey::Encode(int64_t database_id,
1969                                   int64_t object_store_id,
1970                                   const base::string16& index_name) {
1971   KeyPrefix prefix(database_id);
1972   std::string ret = prefix.Encode();
1973   ret.push_back(kIndexNamesKeyTypeByte);
1974   EncodeVarInt(object_store_id, &ret);
1975   EncodeStringWithLength(index_name, &ret);
1976   return ret;
1977 }
1978 
Compare(const IndexNamesKey & other)1979 int IndexNamesKey::Compare(const IndexNamesKey& other) {
1980   DCHECK_GE(object_store_id_, 0);
1981   if (int x = CompareInts(object_store_id_, other.object_store_id_))
1982     return x;
1983   return index_name_.compare(other.index_name_);
1984 }
1985 
DebugString() const1986 std::string IndexNamesKey::DebugString() const {
1987   std::stringstream result;
1988   result << "IndexNamesKey{os: " << object_store_id_
1989          << ", index_name: " << index_name_ << "}";
1990   return result.str();
1991 }
1992 
ObjectStoreDataKey()1993 ObjectStoreDataKey::ObjectStoreDataKey() {}
~ObjectStoreDataKey()1994 ObjectStoreDataKey::~ObjectStoreDataKey() {}
1995 
Decode(StringPiece * slice,ObjectStoreDataKey * result)1996 bool ObjectStoreDataKey::Decode(StringPiece* slice,
1997                                 ObjectStoreDataKey* result) {
1998   KeyPrefix prefix;
1999   if (!KeyPrefix::Decode(slice, &prefix))
2000     return false;
2001   DCHECK(prefix.database_id_);
2002   DCHECK(prefix.object_store_id_);
2003   DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
2004   if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
2005     return false;
2006   return true;
2007 }
2008 
Encode(int64_t database_id,int64_t object_store_id,const std::string encoded_user_key)2009 std::string ObjectStoreDataKey::Encode(int64_t database_id,
2010                                        int64_t object_store_id,
2011                                        const std::string encoded_user_key) {
2012   KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
2013       database_id, object_store_id, kSpecialIndexNumber));
2014   std::string ret = prefix.Encode();
2015   ret.append(encoded_user_key);
2016 
2017   return ret;
2018 }
2019 
Encode(int64_t database_id,int64_t object_store_id,const IndexedDBKey & user_key)2020 std::string ObjectStoreDataKey::Encode(int64_t database_id,
2021                                        int64_t object_store_id,
2022                                        const IndexedDBKey& user_key) {
2023   std::string encoded_key;
2024   EncodeIDBKey(user_key, &encoded_key);
2025   return Encode(database_id, object_store_id, encoded_key);
2026 }
2027 
DebugString() const2028 std::string ObjectStoreDataKey::DebugString() const {
2029   std::unique_ptr<blink::IndexedDBKey> key = user_key();
2030   std::stringstream result;
2031   result << "ObjectStoreDataKey{user_key: "
2032          << (key ? key->DebugString() : "Invalid") << "}";
2033   return result.str();
2034 }
2035 
user_key() const2036 std::unique_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const {
2037   std::unique_ptr<IndexedDBKey> key;
2038   StringPiece slice(encoded_user_key_);
2039   if (!DecodeIDBKey(&slice, &key)) {
2040     // TODO(jsbell): Return error.
2041   }
2042   return key;
2043 }
2044 
2045 const int64_t ObjectStoreDataKey::kSpecialIndexNumber = kObjectStoreDataIndexId;
2046 
ExistsEntryKey()2047 ExistsEntryKey::ExistsEntryKey() {}
~ExistsEntryKey()2048 ExistsEntryKey::~ExistsEntryKey() {}
2049 
Decode(StringPiece * slice,ExistsEntryKey * result)2050 bool ExistsEntryKey::Decode(StringPiece* slice, ExistsEntryKey* result) {
2051   KeyPrefix prefix;
2052   if (!KeyPrefix::Decode(slice, &prefix))
2053     return false;
2054   DCHECK(prefix.database_id_);
2055   DCHECK(prefix.object_store_id_);
2056   DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
2057   if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
2058     return false;
2059   return true;
2060 }
2061 
Encode(int64_t database_id,int64_t object_store_id,const std::string & encoded_key)2062 std::string ExistsEntryKey::Encode(int64_t database_id,
2063                                    int64_t object_store_id,
2064                                    const std::string& encoded_key) {
2065   KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
2066       database_id, object_store_id, kSpecialIndexNumber));
2067   std::string ret = prefix.Encode();
2068   ret.append(encoded_key);
2069   return ret;
2070 }
2071 
Encode(int64_t database_id,int64_t object_store_id,const IndexedDBKey & user_key)2072 std::string ExistsEntryKey::Encode(int64_t database_id,
2073                                    int64_t object_store_id,
2074                                    const IndexedDBKey& user_key) {
2075   std::string encoded_key;
2076   EncodeIDBKey(user_key, &encoded_key);
2077   return Encode(database_id, object_store_id, encoded_key);
2078 }
2079 
DebugString() const2080 std::string ExistsEntryKey::DebugString() const {
2081   std::unique_ptr<blink::IndexedDBKey> key = user_key();
2082   std::stringstream result;
2083   result << "ExistsEntryKey{user_key: "
2084          << (key ? key->DebugString() : "Invalid") << "}";
2085   return result.str();
2086 }
2087 
user_key() const2088 std::unique_ptr<IndexedDBKey> ExistsEntryKey::user_key() const {
2089   std::unique_ptr<IndexedDBKey> key;
2090   StringPiece slice(encoded_user_key_);
2091   if (!DecodeIDBKey(&slice, &key)) {
2092     // TODO(jsbell): Return error.
2093   }
2094   return key;
2095 }
2096 
2097 const int64_t ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId;
2098 
Decode(StringPiece * slice,BlobEntryKey * result)2099 bool BlobEntryKey::Decode(StringPiece* slice, BlobEntryKey* result) {
2100   KeyPrefix prefix;
2101   if (!KeyPrefix::Decode(slice, &prefix))
2102     return false;
2103   DCHECK(prefix.database_id_);
2104   DCHECK(prefix.object_store_id_);
2105   DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
2106 
2107   if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
2108     return false;
2109   result->database_id_ = prefix.database_id_;
2110   result->object_store_id_ = prefix.object_store_id_;
2111 
2112   return true;
2113 }
2114 
FromObjectStoreDataKey(StringPiece * slice,BlobEntryKey * result)2115 bool BlobEntryKey::FromObjectStoreDataKey(StringPiece* slice,
2116                                           BlobEntryKey* result) {
2117   KeyPrefix prefix;
2118   if (!KeyPrefix::Decode(slice, &prefix))
2119     return false;
2120   DCHECK(prefix.database_id_);
2121   DCHECK(prefix.object_store_id_);
2122   DCHECK_EQ(prefix.index_id_, ObjectStoreDataKey::kSpecialIndexNumber);
2123 
2124   if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
2125     return false;
2126   result->database_id_ = prefix.database_id_;
2127   result->object_store_id_ = prefix.object_store_id_;
2128   return true;
2129 }
2130 
ReencodeToObjectStoreDataKey(StringPiece * slice)2131 std::string BlobEntryKey::ReencodeToObjectStoreDataKey(StringPiece* slice) {
2132   // TODO(ericu): We could be more efficient here, since the suffix is the same.
2133   BlobEntryKey key;
2134   if (!Decode(slice, &key))
2135     return std::string();
2136 
2137   return ObjectStoreDataKey::Encode(key.database_id_, key.object_store_id_,
2138                                     key.encoded_user_key_);
2139 }
2140 
EncodeMinKeyForObjectStore(int64_t database_id,int64_t object_store_id)2141 std::string BlobEntryKey::EncodeMinKeyForObjectStore(int64_t database_id,
2142                                                      int64_t object_store_id) {
2143   // Our implied encoded_user_key_ here is empty, the lowest possible key.
2144   return Encode(database_id, object_store_id, std::string());
2145 }
2146 
EncodeStopKeyForObjectStore(int64_t database_id,int64_t object_store_id)2147 std::string BlobEntryKey::EncodeStopKeyForObjectStore(int64_t database_id,
2148                                                       int64_t object_store_id) {
2149   DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
2150   KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
2151       database_id, object_store_id, kSpecialIndexNumber + 1));
2152   return prefix.Encode();
2153 }
2154 
Encode() const2155 std::string BlobEntryKey::Encode() const {
2156   DCHECK(!encoded_user_key_.empty());
2157   return Encode(database_id_, object_store_id_, encoded_user_key_);
2158 }
2159 
Encode(int64_t database_id,int64_t object_store_id,const IndexedDBKey & user_key)2160 std::string BlobEntryKey::Encode(int64_t database_id,
2161                                  int64_t object_store_id,
2162                                  const IndexedDBKey& user_key) {
2163   std::string encoded_key;
2164   EncodeIDBKey(user_key, &encoded_key);
2165   return Encode(database_id, object_store_id, encoded_key);
2166 }
2167 
Encode(int64_t database_id,int64_t object_store_id,const std::string & encoded_user_key)2168 std::string BlobEntryKey::Encode(int64_t database_id,
2169                                  int64_t object_store_id,
2170                                  const std::string& encoded_user_key) {
2171   DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
2172   KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
2173       database_id, object_store_id, kSpecialIndexNumber));
2174   return prefix.Encode() + encoded_user_key;
2175 }
2176 
DebugString() const2177 std::string BlobEntryKey::DebugString() const {
2178   std::stringstream result;
2179   result << "BlobEntryKey{db: " << database_id_ << "os: " << object_store_id_
2180          << ", user_key: ";
2181   std::unique_ptr<blink::IndexedDBKey> key;
2182   StringPiece slice(encoded_user_key_);
2183   if (!DecodeIDBKey(&slice, &key)) {
2184     result << "Invalid";
2185   } else {
2186     result << key->DebugString();
2187   }
2188   result << "}";
2189   return result.str();
2190 }
2191 
2192 const int64_t BlobEntryKey::kSpecialIndexNumber = kBlobEntryIndexId;
2193 
IndexDataKey()2194 IndexDataKey::IndexDataKey()
2195     : database_id_(-1),
2196       object_store_id_(-1),
2197       index_id_(-1),
2198       sequence_number_(-1) {}
2199 
2200 IndexDataKey::IndexDataKey(IndexDataKey&& other) = default;
2201 
~IndexDataKey()2202 IndexDataKey::~IndexDataKey() {}
2203 
Decode(StringPiece * slice,IndexDataKey * result)2204 bool IndexDataKey::Decode(StringPiece* slice, IndexDataKey* result) {
2205   KeyPrefix prefix;
2206   if (!KeyPrefix::Decode(slice, &prefix))
2207     return false;
2208   if (prefix.database_id_ <= 0)
2209     return false;
2210   if (prefix.object_store_id_ <= 0)
2211     return false;
2212   if (prefix.index_id_ < kMinimumIndexId)
2213     return false;
2214   result->database_id_ = prefix.database_id_;
2215   result->object_store_id_ = prefix.object_store_id_;
2216   result->index_id_ = prefix.index_id_;
2217   result->sequence_number_ = -1;
2218   result->encoded_primary_key_ = MinIDBKey();
2219 
2220   if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
2221     return false;
2222 
2223   // [optional] sequence number
2224   if (slice->empty())
2225     return true;
2226   if (!DecodeVarInt(slice, &result->sequence_number_))
2227     return false;
2228 
2229   // [optional] primary key
2230   if (slice->empty())
2231     return true;
2232   if (!ExtractEncodedIDBKey(slice, &result->encoded_primary_key_))
2233     return false;
2234   return true;
2235 }
2236 
Encode(int64_t database_id,int64_t object_store_id,int64_t index_id,const std::string & encoded_user_key,const std::string & encoded_primary_key,int64_t sequence_number)2237 std::string IndexDataKey::Encode(int64_t database_id,
2238                                  int64_t object_store_id,
2239                                  int64_t index_id,
2240                                  const std::string& encoded_user_key,
2241                                  const std::string& encoded_primary_key,
2242                                  int64_t sequence_number) {
2243   KeyPrefix prefix(database_id, object_store_id, index_id);
2244   std::string ret = prefix.Encode();
2245   ret.append(encoded_user_key);
2246   EncodeVarInt(sequence_number, &ret);
2247   ret.append(encoded_primary_key);
2248   return ret;
2249 }
2250 
Encode(int64_t database_id,int64_t object_store_id,int64_t index_id,const IndexedDBKey & user_key)2251 std::string IndexDataKey::Encode(int64_t database_id,
2252                                  int64_t object_store_id,
2253                                  int64_t index_id,
2254                                  const IndexedDBKey& user_key) {
2255   std::string encoded_key;
2256   EncodeIDBKey(user_key, &encoded_key);
2257   return Encode(database_id, object_store_id, index_id, encoded_key,
2258                 MinIDBKey(), 0);
2259 }
2260 
Encode(int64_t database_id,int64_t object_store_id,int64_t index_id,const IndexedDBKey & user_key,const IndexedDBKey & user_primary_key)2261 std::string IndexDataKey::Encode(int64_t database_id,
2262                                  int64_t object_store_id,
2263                                  int64_t index_id,
2264                                  const IndexedDBKey& user_key,
2265                                  const IndexedDBKey& user_primary_key) {
2266   std::string encoded_key;
2267   EncodeIDBKey(user_key, &encoded_key);
2268   std::string encoded_primary_key;
2269   EncodeIDBKey(user_primary_key, &encoded_primary_key);
2270   return Encode(database_id, object_store_id, index_id, encoded_key,
2271                 encoded_primary_key, 0);
2272 }
2273 
EncodeMinKey(int64_t database_id,int64_t object_store_id,int64_t index_id)2274 std::string IndexDataKey::EncodeMinKey(int64_t database_id,
2275                                        int64_t object_store_id,
2276                                        int64_t index_id) {
2277   return Encode(database_id, object_store_id, index_id, MinIDBKey(),
2278                 MinIDBKey(), 0);
2279 }
2280 
EncodeMaxKey(int64_t database_id,int64_t object_store_id,int64_t index_id)2281 std::string IndexDataKey::EncodeMaxKey(int64_t database_id,
2282                                        int64_t object_store_id,
2283                                        int64_t index_id) {
2284   return Encode(database_id, object_store_id, index_id, MaxIDBKey(),
2285                 MaxIDBKey(), std::numeric_limits<int64_t>::max());
2286 }
2287 
Encode() const2288 std::string IndexDataKey::Encode() const {
2289   return Encode(database_id_, object_store_id_, index_id_, encoded_user_key_,
2290                 encoded_primary_key_, sequence_number_);
2291 }
2292 
DebugString() const2293 std::string IndexDataKey::DebugString() const {
2294   std::unique_ptr<blink::IndexedDBKey> user = user_key();
2295   std::unique_ptr<blink::IndexedDBKey> primary = primary_key();
2296   std::stringstream result;
2297   result << "IndexDataKey{db: " << database_id_ << ", os: " << object_store_id_
2298          << ", idx: " << index_id_ << ", sequence_number: " << sequence_number_
2299          << ", user_key: " << (user ? user->DebugString() : "Invalid")
2300          << ", primary_key: " << (primary ? primary->DebugString() : "Invalid")
2301          << "}";
2302   return result.str();
2303 }
2304 
DatabaseId() const2305 int64_t IndexDataKey::DatabaseId() const {
2306   DCHECK_GE(database_id_, 0);
2307   return database_id_;
2308 }
2309 
ObjectStoreId() const2310 int64_t IndexDataKey::ObjectStoreId() const {
2311   DCHECK_GE(object_store_id_, 0);
2312   return object_store_id_;
2313 }
2314 
IndexId() const2315 int64_t IndexDataKey::IndexId() const {
2316   DCHECK_GE(index_id_, 0);
2317   return index_id_;
2318 }
2319 
user_key() const2320 std::unique_ptr<IndexedDBKey> IndexDataKey::user_key() const {
2321   std::unique_ptr<IndexedDBKey> key;
2322   StringPiece slice(encoded_user_key_);
2323   if (!DecodeIDBKey(&slice, &key)) {
2324     // TODO(jsbell): Return error.
2325   }
2326   return key;
2327 }
2328 
primary_key() const2329 std::unique_ptr<IndexedDBKey> IndexDataKey::primary_key() const {
2330   std::unique_ptr<IndexedDBKey> key;
2331   StringPiece slice(encoded_primary_key_);
2332   if (!DecodeIDBKey(&slice, &key)) {
2333     // TODO(jsbell): Return error.
2334   }
2335   return key;
2336 }
2337 
2338 }  // namespace content
2339