Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_leveldb_coding.cc
blobdcb1081b315eacd6b3d658fae2296a0a171f7b53
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.
5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
7 #include <iterator>
8 #include <limits>
10 #include "base/logging.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/sys_byteorder.h"
14 #include "content/common/indexed_db/indexed_db_key.h"
15 #include "content/common/indexed_db/indexed_db_key_path.h"
17 // LevelDB Coding Scheme
18 // =====================
20 // LevelDB stores key/value pairs. Keys and values are strings of bytes,
21 // normally of type std::string.
23 // The keys in the backing store are variable-length tuples with different
24 // types of fields. Each key in the backing store starts with a ternary
25 // prefix: (database id, object store id, index id). For each, 0 is reserved
26 // for metadata. See KeyPrefix::Decode() for details of the prefix coding.
28 // The prefix makes sure that data for a specific database, object store, and
29 // index are grouped together. The locality is important for performance:
30 // common operations should only need a minimal number of seek operations. For
31 // example, all the metadata for a database is grouped together so that
32 // reading that metadata only requires one seek.
34 // Each key type has a class (in square brackets below) which knows how to
35 // encode, decode, and compare that key type.
37 // Strings (origins, names, etc) are encoded as UTF-16BE.
40 // Global metadata
41 // ---------------
42 // The prefix is <0, 0, 0>, followed by a metadata type byte:
44 // <0, 0, 0, 0> => backing store schema version [SchemaVersionKey]
45 // <0, 0, 0, 1> => maximum allocated database [MaxDatabaseIdKey]
46 // <0, 0, 0, 2> => SerializedScriptValue version [DataVersionKey]
47 // <0, 0, 0, 3>
48 // => Blob journal
49 // The format of the journal is:
50 // {database_id (var int), blobKey (var int)}*.
51 // If the blobKey is kAllBlobsKey, the whole database should be deleted.
52 // [BlobJournalKey]
53 // <0, 0, 0, 4> => Live blob journal; same format. [LiveBlobJournalKey]
54 // <0, 0, 0, 100, database id>
55 // => Existence implies the database id is in the free list
56 // [DatabaseFreeListKey]
57 // <0, 0, 0, 201, origin, database name> => Database id (int) [DatabaseNameKey]
60 // Database metadata: [DatabaseMetaDataKey]
61 // ----------------------------------------
62 // The prefix is <database id, 0, 0> followed by a metadata type byte:
64 // <database id, 0, 0, 0> => origin name
65 // <database id, 0, 0, 1> => database name
66 // <database id, 0, 0, 2> => IDB string version data (obsolete)
67 // <database id, 0, 0, 3> => maximum allocated object store id
68 // <database id, 0, 0, 4> => IDB integer version (var int)
69 // <database id, 0, 0, 5> => blob key generator current number
72 // Object store metadata: [ObjectStoreMetaDataKey]
73 // -----------------------------------------------
74 // The prefix is <database id, 0, 0>, followed by a type byte (50), then the
75 // object store id (var int), then a metadata type byte.
77 // <database id, 0, 0, 50, object store id, 0> => object store name
78 // <database id, 0, 0, 50, object store id, 1> => key path
79 // <database id, 0, 0, 50, object store id, 2> => auto increment flag
80 // <database id, 0, 0, 50, object store id, 3> => is evictable
81 // <database id, 0, 0, 50, object store id, 4> => last "version" number
82 // <database id, 0, 0, 50, object store id, 5> => maximum allocated index id
83 // <database id, 0, 0, 50, object store id, 6> => has key path flag (obsolete)
84 // <database id, 0, 0, 50, object store id, 7> => key generator current number
86 // The key path was originally just a string (#1) or null (identified by flag,
87 // #6). To support null, string, or array the coding is now identified by the
88 // leading bytes in #1 - see EncodeIDBKeyPath.
90 // The "version" field is used to weed out stale index data. Whenever new
91 // object store data is inserted, it gets a new "version" number, and new
92 // index data is written with this number. When the index is used for
93 // look-ups, entries are validated against the "exists" entries, and records
94 // with old "version" numbers are deleted when they are encountered in
95 // GetPrimaryKeyViaIndex, IndexCursorImpl::LoadCurrentRow and
96 // IndexKeyCursorImpl::LoadCurrentRow.
99 // Index metadata: [IndexMetaDataKey]
100 // ----------------------------------
101 // The prefix is <database id, 0, 0>, followed by a type byte (100), then the
102 // object store id (var int), then the index id (var int), then a metadata
103 // type byte.
105 // <database id, 0, 0, 100, object store id, index id, 0> => index name
106 // <database id, 0, 0, 100, object store id, index id, 1> => unique flag
107 // <database id, 0, 0, 100, object store id, index id, 2> => key path
108 // <database id, 0, 0, 100, object store id, index id, 3> => multi-entry flag
111 // Other object store and index metadata
112 // -------------------------------------
113 // The prefix is <database id, 0, 0> followed by a type byte. The object
114 // store and index id are variable length integers, the names are variable
115 // length strings.
117 // <database id, 0, 0, 150, object store id>
118 // => existence implies the object store id is in the free list
119 // [ObjectStoreFreeListKey]
120 // <database id, 0, 0, 151, object store id, index id>
121 // => existence implies the index id is in the free list [IndexFreeListKey]
122 // <database id, 0, 0, 200, object store name>
123 // => object store id [ObjectStoreNamesKey]
124 // <database id, 0, 0, 201, object store id, index name>
125 // => index id [IndexNamesKey]
128 // Object store data: [ObjectStoreDataKey]
129 // ---------------------------------------
130 // The prefix is followed by a type byte and the encoded IDB primary key. The
131 // data has a "version" prefix followed by the serialized script value.
133 // <database id, object store id, 1, user key>
134 // => "version", serialized script value
137 // "Exists" entry: [ExistsEntryKey]
138 // --------------------------------
139 // The prefix is followed by a type byte and the encoded IDB primary key.
141 // <database id, object store id, 2, user key> => "version"
144 // Blob entry table: [BlobEntryKey]
145 // --------------------------------
147 // The prefix is followed by a type byte and the encoded IDB primary key.
149 // <database id, object store id, 3, user key> => array of IndexedDBBlobInfo
152 // Index data
153 // ----------
154 // The prefix is followed by a type byte, the encoded IDB index key, a
155 // "sequence" number (obsolete; var int), and the encoded IDB primary key.
157 // <database id, object store id, index id, index key, sequence number,
158 // primary key> => "version", primary key [IndexDataKey]
160 // The sequence number is obsolete; it was used to allow two entries with the
161 // same user (index) key in non-unique indexes prior to the inclusion of the
162 // primary key in the data.
164 using base::StringPiece;
165 using blink::WebIDBKeyType;
166 using blink::WebIDBKeyTypeArray;
167 using blink::WebIDBKeyTypeBinary;
168 using blink::WebIDBKeyTypeDate;
169 using blink::WebIDBKeyTypeInvalid;
170 using blink::WebIDBKeyTypeMin;
171 using blink::WebIDBKeyTypeNull;
172 using blink::WebIDBKeyTypeNumber;
173 using blink::WebIDBKeyTypeString;
174 using blink::WebIDBKeyPathType;
175 using blink::WebIDBKeyPathTypeArray;
176 using blink::WebIDBKeyPathTypeNull;
177 using blink::WebIDBKeyPathTypeString;
179 namespace content {
181 // As most of the IndexedDBKeys and encoded values are short, we
182 // initialize some std::vectors with a default inline buffer size to reduce
183 // the memory re-allocations when the std::vectors are appended.
184 static const size_t kDefaultInlineBufferSize = 32;
186 static const unsigned char kIndexedDBKeyNullTypeByte = 0;
187 static const unsigned char kIndexedDBKeyStringTypeByte = 1;
188 static const unsigned char kIndexedDBKeyDateTypeByte = 2;
189 static const unsigned char kIndexedDBKeyNumberTypeByte = 3;
190 static const unsigned char kIndexedDBKeyArrayTypeByte = 4;
191 static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
192 static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
194 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
195 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
197 static const unsigned char kObjectStoreDataIndexId = 1;
198 static const unsigned char kExistsEntryIndexId = 2;
199 static const unsigned char kBlobEntryIndexId = 3;
201 static const unsigned char kSchemaVersionTypeByte = 0;
202 static const unsigned char kMaxDatabaseIdTypeByte = 1;
203 static const unsigned char kDataVersionTypeByte = 2;
204 static const unsigned char kBlobJournalTypeByte = 3;
205 static const unsigned char kLiveBlobJournalTypeByte = 4;
206 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte =
207 5; // Insert before this and increment.
208 static const unsigned char kDatabaseFreeListTypeByte = 100;
209 static const unsigned char kDatabaseNameTypeByte = 201;
211 static const unsigned char kObjectStoreMetaDataTypeByte = 50;
212 static const unsigned char kIndexMetaDataTypeByte = 100;
213 static const unsigned char kObjectStoreFreeListTypeByte = 150;
214 static const unsigned char kIndexFreeListTypeByte = 151;
215 static const unsigned char kObjectStoreNamesTypeByte = 200;
216 static const unsigned char kIndexNamesKeyTypeByte = 201;
218 static const unsigned char kObjectMetaDataTypeMaximum = 255;
219 static const unsigned char kIndexMetaDataTypeMaximum = 255;
221 const unsigned char kMinimumIndexId = 30;
223 inline void EncodeIntSafely(int64 nParam, int64 max, std::string* into) {
224 DCHECK_LE(nParam, max);
225 return EncodeInt(nParam, into);
228 std::string MaxIDBKey() {
229 std::string ret;
230 EncodeByte(kIndexedDBKeyNullTypeByte, &ret);
231 return ret;
234 std::string MinIDBKey() {
235 std::string ret;
236 EncodeByte(kIndexedDBKeyMinKeyTypeByte, &ret);
237 return ret;
240 void EncodeByte(unsigned char value, std::string* into) {
241 into->push_back(value);
244 void EncodeBool(bool value, std::string* into) {
245 into->push_back(value ? 1 : 0);
248 void EncodeInt(int64 value, std::string* into) {
249 #ifndef NDEBUG
250 // Exercised by unit tests in debug only.
251 DCHECK_GE(value, 0);
252 #endif
253 uint64 n = static_cast<uint64>(value);
255 do {
256 unsigned char c = n;
257 into->push_back(c);
258 n >>= 8;
259 } while (n);
262 void EncodeVarInt(int64 value, std::string* into) {
263 #ifndef NDEBUG
264 // Exercised by unit tests in debug only.
265 DCHECK_GE(value, 0);
266 #endif
267 uint64 n = static_cast<uint64>(value);
269 do {
270 unsigned char c = n & 0x7f;
271 n >>= 7;
272 if (n)
273 c |= 0x80;
274 into->push_back(c);
275 } while (n);
278 void EncodeString(const base::string16& value, std::string* into) {
279 if (value.empty())
280 return;
281 // Backing store is UTF-16BE, convert from host endianness.
282 size_t length = value.length();
283 size_t current = into->size();
284 into->resize(into->size() + length * sizeof(base::char16));
286 const base::char16* src = value.c_str();
287 base::char16* dst =
288 reinterpret_cast<base::char16*>(&*into->begin() + current);
289 for (unsigned i = 0; i < length; ++i)
290 *dst++ = htons(*src++);
293 void EncodeBinary(const std::string& value, std::string* into) {
294 EncodeVarInt(value.length(), into);
295 into->append(value.begin(), value.end());
296 DCHECK(into->size() >= value.size());
299 void EncodeStringWithLength(const base::string16& value, std::string* into) {
300 EncodeVarInt(value.length(), into);
301 EncodeString(value, into);
304 void EncodeDouble(double value, std::string* into) {
305 // This always has host endianness.
306 const char* p = reinterpret_cast<char*>(&value);
307 into->insert(into->end(), p, p + sizeof(value));
310 void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
311 size_t previous_size = into->size();
312 DCHECK(value.IsValid());
313 switch (value.type()) {
314 case WebIDBKeyTypeArray: {
315 EncodeByte(kIndexedDBKeyArrayTypeByte, into);
316 size_t length = value.array().size();
317 EncodeVarInt(length, into);
318 for (size_t i = 0; i < length; ++i)
319 EncodeIDBKey(value.array()[i], into);
320 DCHECK_GT(into->size(), previous_size);
321 return;
323 case WebIDBKeyTypeBinary:
324 EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
325 EncodeBinary(value.binary(), into);
326 DCHECK_GT(into->size(), previous_size);
327 return;
328 case WebIDBKeyTypeString:
329 EncodeByte(kIndexedDBKeyStringTypeByte, into);
330 EncodeStringWithLength(value.string(), into);
331 DCHECK_GT(into->size(), previous_size);
332 return;
333 case WebIDBKeyTypeDate:
334 EncodeByte(kIndexedDBKeyDateTypeByte, into);
335 EncodeDouble(value.date(), into);
336 DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
337 return;
338 case WebIDBKeyTypeNumber:
339 EncodeByte(kIndexedDBKeyNumberTypeByte, into);
340 EncodeDouble(value.number(), into);
341 DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
342 return;
343 case WebIDBKeyTypeNull:
344 case WebIDBKeyTypeInvalid:
345 case WebIDBKeyTypeMin:
346 default:
347 NOTREACHED();
348 EncodeByte(kIndexedDBKeyNullTypeByte, into);
349 return;
353 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
354 // May be typed, or may be a raw string. An invalid leading
355 // byte is used to identify typed coding. New records are
356 // always written as typed.
357 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
358 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
359 EncodeByte(static_cast<char>(value.type()), into);
360 switch (value.type()) {
361 case WebIDBKeyPathTypeNull:
362 break;
363 case WebIDBKeyPathTypeString: {
364 EncodeStringWithLength(value.string(), into);
365 break;
367 case WebIDBKeyPathTypeArray: {
368 const std::vector<base::string16>& array = value.array();
369 size_t count = array.size();
370 EncodeVarInt(count, into);
371 for (size_t i = 0; i < count; ++i) {
372 EncodeStringWithLength(array[i], into);
374 break;
379 void EncodeBlobJournal(const BlobJournalType& journal, std::string* into) {
380 BlobJournalType::const_iterator iter;
381 for (iter = journal.begin(); iter != journal.end(); ++iter) {
382 EncodeVarInt(iter->first, into);
383 EncodeVarInt(iter->second, into);
387 bool DecodeByte(StringPiece* slice, unsigned char* value) {
388 if (slice->empty())
389 return false;
391 *value = (*slice)[0];
392 slice->remove_prefix(1);
393 return true;
396 bool DecodeBool(StringPiece* slice, bool* value) {
397 if (slice->empty())
398 return false;
400 *value = !!(*slice)[0];
401 slice->remove_prefix(1);
402 return true;
405 bool DecodeInt(StringPiece* slice, int64* value) {
406 if (slice->empty())
407 return false;
409 StringPiece::const_iterator it = slice->begin();
410 int shift = 0;
411 int64 ret = 0;
412 while (it != slice->end()) {
413 unsigned char c = *it++;
414 ret |= static_cast<int64>(c) << shift;
415 shift += 8;
417 *value = ret;
418 slice->remove_prefix(it - slice->begin());
419 return true;
422 bool DecodeVarInt(StringPiece* slice, int64* value) {
423 if (slice->empty())
424 return false;
426 StringPiece::const_iterator it = slice->begin();
427 int shift = 0;
428 int64 ret = 0;
429 do {
430 if (it == slice->end())
431 return false;
433 unsigned char c = *it;
434 ret |= static_cast<int64>(c & 0x7f) << shift;
435 shift += 7;
436 } while (*it++ & 0x80);
437 *value = ret;
438 slice->remove_prefix(it - slice->begin());
439 return true;
442 bool DecodeString(StringPiece* slice, base::string16* value) {
443 if (slice->empty()) {
444 value->clear();
445 return true;
448 // Backing store is UTF-16BE, convert to host endianness.
449 DCHECK(!(slice->size() % sizeof(base::char16)));
450 size_t length = slice->size() / sizeof(base::char16);
451 base::string16 decoded;
452 decoded.reserve(length);
453 const base::char16* encoded =
454 reinterpret_cast<const base::char16*>(slice->begin());
455 for (unsigned i = 0; i < length; ++i)
456 decoded.push_back(ntohs(*encoded++));
458 *value = decoded;
459 slice->remove_prefix(length * sizeof(base::char16));
460 return true;
463 bool DecodeStringWithLength(StringPiece* slice, base::string16* value) {
464 if (slice->empty())
465 return false;
467 int64 length = 0;
468 if (!DecodeVarInt(slice, &length) || length < 0)
469 return false;
470 size_t bytes = length * sizeof(base::char16);
471 if (slice->size() < bytes)
472 return false;
474 StringPiece subpiece(slice->begin(), bytes);
475 slice->remove_prefix(bytes);
476 if (!DecodeString(&subpiece, value))
477 return false;
479 return true;
482 bool DecodeBinary(StringPiece* slice, std::string* value) {
483 if (slice->empty())
484 return false;
486 int64 length = 0;
487 if (!DecodeVarInt(slice, &length) || length < 0)
488 return false;
489 size_t size = length;
490 if (slice->size() < size)
491 return false;
493 value->assign(slice->begin(), size);
494 slice->remove_prefix(size);
495 return true;
498 bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
499 if (slice->empty())
500 return false;
502 unsigned char type = (*slice)[0];
503 slice->remove_prefix(1);
505 switch (type) {
506 case kIndexedDBKeyNullTypeByte:
507 *value = make_scoped_ptr(new IndexedDBKey());
508 return true;
510 case kIndexedDBKeyArrayTypeByte: {
511 int64 length = 0;
512 if (!DecodeVarInt(slice, &length) || length < 0)
513 return false;
514 IndexedDBKey::KeyArray array;
515 while (length--) {
516 scoped_ptr<IndexedDBKey> key;
517 if (!DecodeIDBKey(slice, &key))
518 return false;
519 array.push_back(*key);
521 *value = make_scoped_ptr(new IndexedDBKey(array));
522 return true;
524 case kIndexedDBKeyBinaryTypeByte: {
525 std::string binary;
526 if (!DecodeBinary(slice, &binary))
527 return false;
528 *value = make_scoped_ptr(new IndexedDBKey(binary));
529 return true;
531 case kIndexedDBKeyStringTypeByte: {
532 base::string16 s;
533 if (!DecodeStringWithLength(slice, &s))
534 return false;
535 *value = make_scoped_ptr(new IndexedDBKey(s));
536 return true;
538 case kIndexedDBKeyDateTypeByte: {
539 double d;
540 if (!DecodeDouble(slice, &d))
541 return false;
542 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeDate));
543 return true;
545 case kIndexedDBKeyNumberTypeByte: {
546 double d;
547 if (!DecodeDouble(slice, &d))
548 return false;
549 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeNumber));
550 return true;
554 NOTREACHED();
555 return false;
558 bool DecodeDouble(StringPiece* slice, double* value) {
559 if (slice->size() < sizeof(*value))
560 return false;
562 memcpy(value, slice->begin(), sizeof(*value));
563 slice->remove_prefix(sizeof(*value));
564 return true;
567 bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
568 // May be typed, or may be a raw string. An invalid leading
569 // byte sequence is used to identify typed coding. New records are
570 // always written as typed.
571 if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 ||
572 (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) {
573 base::string16 s;
574 if (!DecodeString(slice, &s))
575 return false;
576 *value = IndexedDBKeyPath(s);
577 return true;
580 slice->remove_prefix(2);
581 DCHECK(!slice->empty());
582 WebIDBKeyPathType type = static_cast<WebIDBKeyPathType>((*slice)[0]);
583 slice->remove_prefix(1);
585 switch (type) {
586 case WebIDBKeyPathTypeNull:
587 DCHECK(slice->empty());
588 *value = IndexedDBKeyPath();
589 return true;
590 case WebIDBKeyPathTypeString: {
591 base::string16 string;
592 if (!DecodeStringWithLength(slice, &string))
593 return false;
594 DCHECK(slice->empty());
595 *value = IndexedDBKeyPath(string);
596 return true;
598 case WebIDBKeyPathTypeArray: {
599 std::vector<base::string16> array;
600 int64 count;
601 if (!DecodeVarInt(slice, &count))
602 return false;
603 DCHECK_GE(count, 0);
604 while (count--) {
605 base::string16 string;
606 if (!DecodeStringWithLength(slice, &string))
607 return false;
608 array.push_back(string);
610 DCHECK(slice->empty());
611 *value = IndexedDBKeyPath(array);
612 return true;
615 NOTREACHED();
616 return false;
619 bool DecodeBlobJournal(StringPiece* slice, BlobJournalType* journal) {
620 BlobJournalType output;
621 while (!slice->empty()) {
622 int64 database_id = -1;
623 int64 blob_key = -1;
624 if (!DecodeVarInt(slice, &database_id))
625 return false;
626 if (!KeyPrefix::IsValidDatabaseId(database_id))
627 return false;
628 if (!DecodeVarInt(slice, &blob_key))
629 return false;
630 if (!DatabaseMetaDataKey::IsValidBlobKey(blob_key) &&
631 (blob_key != DatabaseMetaDataKey::kAllBlobsKey)) {
632 return false;
634 output.push_back(std::make_pair(database_id, blob_key));
636 journal->swap(output);
637 return true;
640 bool ConsumeEncodedIDBKey(StringPiece* slice) {
641 unsigned char type = (*slice)[0];
642 slice->remove_prefix(1);
644 switch (type) {
645 case kIndexedDBKeyNullTypeByte:
646 case kIndexedDBKeyMinKeyTypeByte:
647 return true;
648 case kIndexedDBKeyArrayTypeByte: {
649 int64 length;
650 if (!DecodeVarInt(slice, &length))
651 return false;
652 while (length--) {
653 if (!ConsumeEncodedIDBKey(slice))
654 return false;
656 return true;
658 case kIndexedDBKeyBinaryTypeByte: {
659 int64 length = 0;
660 if (!DecodeVarInt(slice, &length) || length < 0)
661 return false;
662 if (slice->size() < static_cast<size_t>(length))
663 return false;
664 slice->remove_prefix(length);
665 return true;
667 case kIndexedDBKeyStringTypeByte: {
668 int64 length = 0;
669 if (!DecodeVarInt(slice, &length) || length < 0)
670 return false;
671 if (slice->size() < static_cast<size_t>(length) * sizeof(base::char16))
672 return false;
673 slice->remove_prefix(length * sizeof(base::char16));
674 return true;
676 case kIndexedDBKeyDateTypeByte:
677 case kIndexedDBKeyNumberTypeByte:
678 if (slice->size() < sizeof(double))
679 return false;
680 slice->remove_prefix(sizeof(double));
681 return true;
683 NOTREACHED();
684 return false;
687 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) {
688 const char* start = slice->begin();
689 if (!ConsumeEncodedIDBKey(slice))
690 return false;
692 if (result)
693 result->assign(start, slice->begin());
694 return true;
697 static WebIDBKeyType KeyTypeByteToKeyType(unsigned char type) {
698 switch (type) {
699 case kIndexedDBKeyNullTypeByte:
700 return WebIDBKeyTypeInvalid;
701 case kIndexedDBKeyArrayTypeByte:
702 return WebIDBKeyTypeArray;
703 case kIndexedDBKeyBinaryTypeByte:
704 return WebIDBKeyTypeBinary;
705 case kIndexedDBKeyStringTypeByte:
706 return WebIDBKeyTypeString;
707 case kIndexedDBKeyDateTypeByte:
708 return WebIDBKeyTypeDate;
709 case kIndexedDBKeyNumberTypeByte:
710 return WebIDBKeyTypeNumber;
711 case kIndexedDBKeyMinKeyTypeByte:
712 return WebIDBKeyTypeMin;
715 NOTREACHED();
716 return WebIDBKeyTypeInvalid;
719 int CompareEncodedStringsWithLength(StringPiece* slice1,
720 StringPiece* slice2,
721 bool* ok) {
722 int64 len1, len2;
723 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
724 *ok = false;
725 return 0;
727 DCHECK_GE(len1, 0);
728 DCHECK_GE(len2, 0);
729 if (len1 < 0 || len2 < 0) {
730 *ok = false;
731 return 0;
733 DCHECK_GE(slice1->size(), len1 * sizeof(base::char16));
734 DCHECK_GE(slice2->size(), len2 * sizeof(base::char16));
735 if (slice1->size() < len1 * sizeof(base::char16) ||
736 slice2->size() < len2 * sizeof(base::char16)) {
737 *ok = false;
738 return 0;
741 // Extract the string data, and advance the passed slices.
742 StringPiece string1(slice1->begin(), len1 * sizeof(base::char16));
743 StringPiece string2(slice2->begin(), len2 * sizeof(base::char16));
744 slice1->remove_prefix(len1 * sizeof(base::char16));
745 slice2->remove_prefix(len2 * sizeof(base::char16));
747 *ok = true;
748 // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
749 return string1.compare(string2);
752 int CompareEncodedBinary(StringPiece* slice1,
753 StringPiece* slice2,
754 bool* ok) {
755 int64 len1, len2;
756 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
757 *ok = false;
758 return 0;
760 DCHECK_GE(len1, 0);
761 DCHECK_GE(len2, 0);
762 if (len1 < 0 || len2 < 0) {
763 *ok = false;
764 return 0;
766 size_t size1 = len1;
767 size_t size2 = len2;
769 DCHECK_GE(slice1->size(), size1);
770 DCHECK_GE(slice2->size(), size2);
771 if (slice1->size() < size1 || slice2->size() < size2) {
772 *ok = false;
773 return 0;
776 // Extract the binary data, and advance the passed slices.
777 StringPiece binary1(slice1->begin(), size1);
778 StringPiece binary2(slice2->begin(), size2);
779 slice1->remove_prefix(size1);
780 slice2->remove_prefix(size2);
782 *ok = true;
783 // This is the same as a memcmp()
784 return binary1.compare(binary2);
787 static int CompareInts(int64 a, int64 b) {
788 #ifndef NDEBUG
789 // Exercised by unit tests in debug only.
790 DCHECK_GE(a, 0);
791 DCHECK_GE(b, 0);
792 #endif
793 int64 diff = a - b;
794 if (diff < 0)
795 return -1;
796 if (diff > 0)
797 return 1;
798 return 0;
801 static inline int CompareSizes(size_t a, size_t b) {
802 if (a > b)
803 return 1;
804 if (b > a)
805 return -1;
806 return 0;
809 static int CompareTypes(WebIDBKeyType a, WebIDBKeyType b) { return b - a; }
811 int CompareEncodedIDBKeys(StringPiece* slice_a,
812 StringPiece* slice_b,
813 bool* ok) {
814 DCHECK(!slice_a->empty());
815 DCHECK(!slice_b->empty());
816 *ok = true;
817 unsigned char type_a = (*slice_a)[0];
818 unsigned char type_b = (*slice_b)[0];
819 slice_a->remove_prefix(1);
820 slice_b->remove_prefix(1);
822 if (int x = CompareTypes(KeyTypeByteToKeyType(type_a),
823 KeyTypeByteToKeyType(type_b)))
824 return x;
826 switch (type_a) {
827 case kIndexedDBKeyNullTypeByte:
828 case kIndexedDBKeyMinKeyTypeByte:
829 // Null type or max type; no payload to compare.
830 return 0;
831 case kIndexedDBKeyArrayTypeByte: {
832 int64 length_a, length_b;
833 if (!DecodeVarInt(slice_a, &length_a) ||
834 !DecodeVarInt(slice_b, &length_b)) {
835 *ok = false;
836 return 0;
838 for (int64 i = 0; i < length_a && i < length_b; ++i) {
839 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
840 if (!*ok || result)
841 return result;
843 return length_a - length_b;
845 case kIndexedDBKeyBinaryTypeByte:
846 return CompareEncodedBinary(slice_a, slice_b, ok);
847 case kIndexedDBKeyStringTypeByte:
848 return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
849 case kIndexedDBKeyDateTypeByte:
850 case kIndexedDBKeyNumberTypeByte: {
851 double d, e;
852 if (!DecodeDouble(slice_a, &d) || !DecodeDouble(slice_b, &e)) {
853 *ok = false;
854 return 0;
856 if (d < e)
857 return -1;
858 if (d > e)
859 return 1;
860 return 0;
864 NOTREACHED();
865 return 0;
868 namespace {
870 template <typename KeyType>
871 int Compare(const StringPiece& a,
872 const StringPiece& b,
873 bool only_compare_index_keys,
874 bool* ok) {
875 KeyType key_a;
876 KeyType key_b;
878 StringPiece slice_a(a);
879 if (!KeyType::Decode(&slice_a, &key_a)) {
880 *ok = false;
881 return 0;
883 StringPiece slice_b(b);
884 if (!KeyType::Decode(&slice_b, &key_b)) {
885 *ok = false;
886 return 0;
889 *ok = true;
890 return key_a.Compare(key_b);
893 template <typename KeyType>
894 int CompareSuffix(StringPiece* a,
895 StringPiece* b,
896 bool only_compare_index_keys,
897 bool* ok) {
898 NOTREACHED();
899 return 0;
902 template <>
903 int CompareSuffix<ExistsEntryKey>(StringPiece* slice_a,
904 StringPiece* slice_b,
905 bool only_compare_index_keys,
906 bool* ok) {
907 DCHECK(!slice_a->empty());
908 DCHECK(!slice_b->empty());
909 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
912 template <>
913 int CompareSuffix<ObjectStoreDataKey>(StringPiece* slice_a,
914 StringPiece* slice_b,
915 bool only_compare_index_keys,
916 bool* ok) {
917 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
920 template <>
921 int CompareSuffix<BlobEntryKey>(StringPiece* slice_a,
922 StringPiece* slice_b,
923 bool only_compare_index_keys,
924 bool* ok) {
925 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
928 template <>
929 int CompareSuffix<IndexDataKey>(StringPiece* slice_a,
930 StringPiece* slice_b,
931 bool only_compare_index_keys,
932 bool* ok) {
933 // index key
934 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
935 if (!*ok || result)
936 return result;
937 if (only_compare_index_keys)
938 return 0;
940 // sequence number [optional]
941 int64 sequence_number_a = -1;
942 int64 sequence_number_b = -1;
943 if (!slice_a->empty() && !DecodeVarInt(slice_a, &sequence_number_a))
944 return 0;
945 if (!slice_b->empty() && !DecodeVarInt(slice_b, &sequence_number_b))
946 return 0;
948 if (slice_a->empty() || slice_b->empty())
949 return CompareSizes(slice_a->size(), slice_b->size());
951 // primary key [optional]
952 result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
953 if (!*ok || result)
954 return result;
956 return CompareInts(sequence_number_a, sequence_number_b);
959 int Compare(const StringPiece& a,
960 const StringPiece& b,
961 bool only_compare_index_keys,
962 bool* ok) {
963 StringPiece slice_a(a);
964 StringPiece slice_b(b);
965 KeyPrefix prefix_a;
966 KeyPrefix prefix_b;
967 bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
968 bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
969 DCHECK(ok_a);
970 DCHECK(ok_b);
971 if (!ok_a || !ok_b) {
972 *ok = false;
973 return 0;
976 *ok = true;
977 if (int x = prefix_a.Compare(prefix_b))
978 return x;
980 switch (prefix_a.type()) {
981 case KeyPrefix::GLOBAL_METADATA: {
982 DCHECK(!slice_a.empty());
983 DCHECK(!slice_b.empty());
985 unsigned char type_byte_a;
986 if (!DecodeByte(&slice_a, &type_byte_a)) {
987 *ok = false;
988 return 0;
991 unsigned char type_byte_b;
992 if (!DecodeByte(&slice_b, &type_byte_b)) {
993 *ok = false;
994 return 0;
997 if (int x = type_byte_a - type_byte_b)
998 return x;
999 if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte)
1000 return 0;
1002 // Compare<> is used (which re-decodes the prefix) rather than an
1003 // specialized CompareSuffix<> because metadata is relatively uncommon
1004 // in the database.
1006 if (type_byte_a == kDatabaseFreeListTypeByte) {
1007 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1008 return Compare<DatabaseFreeListKey>(a, b, only_compare_index_keys, ok);
1010 if (type_byte_a == kDatabaseNameTypeByte) {
1011 return Compare<DatabaseNameKey>(
1012 a, b, /*only_compare_index_keys*/ false, ok);
1014 break;
1017 case KeyPrefix::DATABASE_METADATA: {
1018 DCHECK(!slice_a.empty());
1019 DCHECK(!slice_b.empty());
1021 unsigned char type_byte_a;
1022 if (!DecodeByte(&slice_a, &type_byte_a)) {
1023 *ok = false;
1024 return 0;
1027 unsigned char type_byte_b;
1028 if (!DecodeByte(&slice_b, &type_byte_b)) {
1029 *ok = false;
1030 return 0;
1033 if (int x = type_byte_a - type_byte_b)
1034 return x;
1035 if (type_byte_a < DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE)
1036 return 0;
1038 // Compare<> is used (which re-decodes the prefix) rather than an
1039 // specialized CompareSuffix<> because metadata is relatively uncommon
1040 // in the database.
1042 if (type_byte_a == kObjectStoreMetaDataTypeByte) {
1043 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1044 return Compare<ObjectStoreMetaDataKey>(
1045 a, b, only_compare_index_keys, ok);
1047 if (type_byte_a == kIndexMetaDataTypeByte) {
1048 return Compare<IndexMetaDataKey>(
1049 a, b, /*only_compare_index_keys*/ false, ok);
1051 if (type_byte_a == kObjectStoreFreeListTypeByte) {
1052 return Compare<ObjectStoreFreeListKey>(
1053 a, b, only_compare_index_keys, ok);
1055 if (type_byte_a == kIndexFreeListTypeByte) {
1056 return Compare<IndexFreeListKey>(
1057 a, b, /*only_compare_index_keys*/ false, ok);
1059 if (type_byte_a == kObjectStoreNamesTypeByte) {
1060 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1061 return Compare<ObjectStoreNamesKey>(
1062 a, b, only_compare_index_keys, ok);
1064 if (type_byte_a == kIndexNamesKeyTypeByte) {
1065 return Compare<IndexNamesKey>(
1066 a, b, /*only_compare_index_keys*/ false, ok);
1068 break;
1071 case KeyPrefix::OBJECT_STORE_DATA: {
1072 // Provide a stable ordering for invalid data.
1073 if (slice_a.empty() || slice_b.empty())
1074 return CompareSizes(slice_a.size(), slice_b.size());
1076 return CompareSuffix<ObjectStoreDataKey>(
1077 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1080 case KeyPrefix::EXISTS_ENTRY: {
1081 // Provide a stable ordering for invalid data.
1082 if (slice_a.empty() || slice_b.empty())
1083 return CompareSizes(slice_a.size(), slice_b.size());
1085 return CompareSuffix<ExistsEntryKey>(
1086 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1089 case KeyPrefix::BLOB_ENTRY: {
1090 // Provide a stable ordering for invalid data.
1091 if (slice_a.empty() || slice_b.empty())
1092 return CompareSizes(slice_a.size(), slice_b.size());
1094 return CompareSuffix<BlobEntryKey>(
1095 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1098 case KeyPrefix::INDEX_DATA: {
1099 // Provide a stable ordering for invalid data.
1100 if (slice_a.empty() || slice_b.empty())
1101 return CompareSizes(slice_a.size(), slice_b.size());
1103 return CompareSuffix<IndexDataKey>(
1104 &slice_a, &slice_b, only_compare_index_keys, ok);
1107 case KeyPrefix::INVALID_TYPE:
1108 break;
1111 NOTREACHED();
1112 *ok = false;
1113 return 0;
1116 } // namespace
1118 int Compare(const StringPiece& a,
1119 const StringPiece& b,
1120 bool only_compare_index_keys) {
1121 bool ok;
1122 int result = Compare(a, b, only_compare_index_keys, &ok);
1123 DCHECK(ok);
1124 if (!ok)
1125 return 0;
1126 return result;
1129 KeyPrefix::KeyPrefix()
1130 : database_id_(INVALID_TYPE),
1131 object_store_id_(INVALID_TYPE),
1132 index_id_(INVALID_TYPE) {}
1134 KeyPrefix::KeyPrefix(int64 database_id)
1135 : database_id_(database_id), object_store_id_(0), index_id_(0) {
1136 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1139 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id)
1140 : database_id_(database_id),
1141 object_store_id_(object_store_id),
1142 index_id_(0) {
1143 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1144 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1147 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id)
1148 : database_id_(database_id),
1149 object_store_id_(object_store_id),
1150 index_id_(index_id) {
1151 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1152 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1153 DCHECK(KeyPrefix::IsValidIndexId(index_id));
1156 KeyPrefix::KeyPrefix(enum Type type,
1157 int64 database_id,
1158 int64 object_store_id,
1159 int64 index_id)
1160 : database_id_(database_id),
1161 object_store_id_(object_store_id),
1162 index_id_(index_id) {
1163 DCHECK_EQ(type, INVALID_TYPE);
1164 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1165 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1168 KeyPrefix KeyPrefix::CreateWithSpecialIndex(int64 database_id,
1169 int64 object_store_id,
1170 int64 index_id) {
1171 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1172 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1173 DCHECK(index_id);
1174 return KeyPrefix(INVALID_TYPE, database_id, object_store_id, index_id);
1177 bool KeyPrefix::IsValidDatabaseId(int64 database_id) {
1178 return (database_id > 0) && (database_id < KeyPrefix::kMaxDatabaseId);
1181 bool KeyPrefix::IsValidObjectStoreId(int64 object_store_id) {
1182 return (object_store_id > 0) &&
1183 (object_store_id < KeyPrefix::kMaxObjectStoreId);
1186 bool KeyPrefix::IsValidIndexId(int64 index_id) {
1187 return (index_id >= kMinimumIndexId) && (index_id < KeyPrefix::kMaxIndexId);
1190 bool KeyPrefix::Decode(StringPiece* slice, KeyPrefix* result) {
1191 unsigned char first_byte;
1192 if (!DecodeByte(slice, &first_byte))
1193 return false;
1195 size_t database_id_bytes = ((first_byte >> 5) & 0x7) + 1;
1196 size_t object_store_id_bytes = ((first_byte >> 2) & 0x7) + 1;
1197 size_t index_id_bytes = (first_byte & 0x3) + 1;
1199 if (database_id_bytes + object_store_id_bytes + index_id_bytes >
1200 slice->size())
1201 return false;
1204 StringPiece tmp(slice->begin(), database_id_bytes);
1205 if (!DecodeInt(&tmp, &result->database_id_))
1206 return false;
1208 slice->remove_prefix(database_id_bytes);
1210 StringPiece tmp(slice->begin(), object_store_id_bytes);
1211 if (!DecodeInt(&tmp, &result->object_store_id_))
1212 return false;
1214 slice->remove_prefix(object_store_id_bytes);
1216 StringPiece tmp(slice->begin(), index_id_bytes);
1217 if (!DecodeInt(&tmp, &result->index_id_))
1218 return false;
1220 slice->remove_prefix(index_id_bytes);
1221 return true;
1224 std::string KeyPrefix::EncodeEmpty() {
1225 const std::string result(4, 0);
1226 DCHECK(EncodeInternal(0, 0, 0) == std::string(4, 0));
1227 return result;
1230 std::string KeyPrefix::Encode() const {
1231 DCHECK(database_id_ != kInvalidId);
1232 DCHECK(object_store_id_ != kInvalidId);
1233 DCHECK(index_id_ != kInvalidId);
1234 return EncodeInternal(database_id_, object_store_id_, index_id_);
1237 std::string KeyPrefix::EncodeInternal(int64 database_id,
1238 int64 object_store_id,
1239 int64 index_id) {
1240 std::string database_id_string;
1241 std::string object_store_id_string;
1242 std::string index_id_string;
1244 EncodeIntSafely(database_id, kMaxDatabaseId, &database_id_string);
1245 EncodeIntSafely(object_store_id, kMaxObjectStoreId, &object_store_id_string);
1246 EncodeIntSafely(index_id, kMaxIndexId, &index_id_string);
1248 DCHECK(database_id_string.size() <= kMaxDatabaseIdSizeBytes);
1249 DCHECK(object_store_id_string.size() <= kMaxObjectStoreIdSizeBytes);
1250 DCHECK(index_id_string.size() <= kMaxIndexIdSizeBytes);
1252 unsigned char first_byte =
1253 (database_id_string.size() - 1) << (kMaxObjectStoreIdSizeBits +
1254 kMaxIndexIdSizeBits) |
1255 (object_store_id_string.size() - 1) << kMaxIndexIdSizeBits |
1256 (index_id_string.size() - 1);
1257 COMPILE_ASSERT(kMaxDatabaseIdSizeBits + kMaxObjectStoreIdSizeBits +
1258 kMaxIndexIdSizeBits ==
1259 sizeof(first_byte) * 8,
1260 CANT_ENCODE_IDS);
1261 std::string ret;
1262 ret.reserve(kDefaultInlineBufferSize);
1263 ret.push_back(first_byte);
1264 ret.append(database_id_string);
1265 ret.append(object_store_id_string);
1266 ret.append(index_id_string);
1268 DCHECK_LE(ret.size(), kDefaultInlineBufferSize);
1269 return ret;
1272 int KeyPrefix::Compare(const KeyPrefix& other) const {
1273 DCHECK(database_id_ != kInvalidId);
1274 DCHECK(object_store_id_ != kInvalidId);
1275 DCHECK(index_id_ != kInvalidId);
1277 if (database_id_ != other.database_id_)
1278 return CompareInts(database_id_, other.database_id_);
1279 if (object_store_id_ != other.object_store_id_)
1280 return CompareInts(object_store_id_, other.object_store_id_);
1281 if (index_id_ != other.index_id_)
1282 return CompareInts(index_id_, other.index_id_);
1283 return 0;
1286 KeyPrefix::Type KeyPrefix::type() const {
1287 DCHECK(database_id_ != kInvalidId);
1288 DCHECK(object_store_id_ != kInvalidId);
1289 DCHECK(index_id_ != kInvalidId);
1291 if (!database_id_)
1292 return GLOBAL_METADATA;
1293 if (!object_store_id_)
1294 return DATABASE_METADATA;
1295 if (index_id_ == kObjectStoreDataIndexId)
1296 return OBJECT_STORE_DATA;
1297 if (index_id_ == kExistsEntryIndexId)
1298 return EXISTS_ENTRY;
1299 if (index_id_ == kBlobEntryIndexId)
1300 return BLOB_ENTRY;
1301 if (index_id_ >= kMinimumIndexId)
1302 return INDEX_DATA;
1304 NOTREACHED();
1305 return INVALID_TYPE;
1308 std::string SchemaVersionKey::Encode() {
1309 std::string ret = KeyPrefix::EncodeEmpty();
1310 ret.push_back(kSchemaVersionTypeByte);
1311 return ret;
1314 std::string MaxDatabaseIdKey::Encode() {
1315 std::string ret = KeyPrefix::EncodeEmpty();
1316 ret.push_back(kMaxDatabaseIdTypeByte);
1317 return ret;
1320 std::string DataVersionKey::Encode() {
1321 std::string ret = KeyPrefix::EncodeEmpty();
1322 ret.push_back(kDataVersionTypeByte);
1323 return ret;
1326 std::string BlobJournalKey::Encode() {
1327 std::string ret = KeyPrefix::EncodeEmpty();
1328 ret.push_back(kBlobJournalTypeByte);
1329 return ret;
1332 std::string LiveBlobJournalKey::Encode() {
1333 std::string ret = KeyPrefix::EncodeEmpty();
1334 ret.push_back(kLiveBlobJournalTypeByte);
1335 return ret;
1338 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {}
1340 bool DatabaseFreeListKey::Decode(StringPiece* slice,
1341 DatabaseFreeListKey* result) {
1342 KeyPrefix prefix;
1343 if (!KeyPrefix::Decode(slice, &prefix))
1344 return false;
1345 DCHECK(!prefix.database_id_);
1346 DCHECK(!prefix.object_store_id_);
1347 DCHECK(!prefix.index_id_);
1348 unsigned char type_byte = 0;
1349 if (!DecodeByte(slice, &type_byte))
1350 return false;
1351 DCHECK_EQ(type_byte, kDatabaseFreeListTypeByte);
1352 if (!DecodeVarInt(slice, &result->database_id_))
1353 return false;
1354 return true;
1357 std::string DatabaseFreeListKey::Encode(int64 database_id) {
1358 std::string ret = KeyPrefix::EncodeEmpty();
1359 ret.push_back(kDatabaseFreeListTypeByte);
1360 EncodeVarInt(database_id, &ret);
1361 return ret;
1364 std::string DatabaseFreeListKey::EncodeMaxKey() {
1365 return Encode(std::numeric_limits<int64>::max());
1368 int64 DatabaseFreeListKey::DatabaseId() const {
1369 DCHECK_GE(database_id_, 0);
1370 return database_id_;
1373 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey& other) const {
1374 DCHECK_GE(database_id_, 0);
1375 return CompareInts(database_id_, other.database_id_);
1378 bool DatabaseNameKey::Decode(StringPiece* slice, DatabaseNameKey* result) {
1379 KeyPrefix prefix;
1380 if (!KeyPrefix::Decode(slice, &prefix))
1381 return false;
1382 DCHECK(!prefix.database_id_);
1383 DCHECK(!prefix.object_store_id_);
1384 DCHECK(!prefix.index_id_);
1385 unsigned char type_byte = 0;
1386 if (!DecodeByte(slice, &type_byte))
1387 return false;
1388 DCHECK_EQ(type_byte, kDatabaseNameTypeByte);
1389 if (!DecodeStringWithLength(slice, &result->origin_))
1390 return false;
1391 if (!DecodeStringWithLength(slice, &result->database_name_))
1392 return false;
1393 return true;
1396 std::string DatabaseNameKey::Encode(const std::string& origin_identifier,
1397 const base::string16& database_name) {
1398 std::string ret = KeyPrefix::EncodeEmpty();
1399 ret.push_back(kDatabaseNameTypeByte);
1400 EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier), &ret);
1401 EncodeStringWithLength(database_name, &ret);
1402 return ret;
1405 std::string DatabaseNameKey::EncodeMinKeyForOrigin(
1406 const std::string& origin_identifier) {
1407 return Encode(origin_identifier, base::string16());
1410 std::string DatabaseNameKey::EncodeStopKeyForOrigin(
1411 const std::string& origin_identifier) {
1412 // just after origin in collation order
1413 return EncodeMinKeyForOrigin(origin_identifier + '\x01');
1416 int DatabaseNameKey::Compare(const DatabaseNameKey& other) {
1417 if (int x = origin_.compare(other.origin_))
1418 return x;
1419 return database_name_.compare(other.database_name_);
1422 bool DatabaseMetaDataKey::IsValidBlobKey(int64 blob_key) {
1423 return blob_key >= kBlobKeyGeneratorInitialNumber;
1426 const int64 DatabaseMetaDataKey::kAllBlobsKey = 1;
1427 const int64 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber = 2;
1428 const int64 DatabaseMetaDataKey::kInvalidBlobKey = -1;
1430 std::string DatabaseMetaDataKey::Encode(int64 database_id,
1431 MetaDataType meta_data_type) {
1432 KeyPrefix prefix(database_id);
1433 std::string ret = prefix.Encode();
1434 ret.push_back(meta_data_type);
1435 return ret;
1438 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
1439 : object_store_id_(-1), meta_data_type_(0xFF) {}
1441 bool ObjectStoreMetaDataKey::Decode(StringPiece* slice,
1442 ObjectStoreMetaDataKey* result) {
1443 KeyPrefix prefix;
1444 if (!KeyPrefix::Decode(slice, &prefix))
1445 return false;
1446 DCHECK(prefix.database_id_);
1447 DCHECK(!prefix.object_store_id_);
1448 DCHECK(!prefix.index_id_);
1449 unsigned char type_byte = 0;
1450 if (!DecodeByte(slice, &type_byte))
1451 return false;
1452 DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte);
1453 if (!DecodeVarInt(slice, &result->object_store_id_))
1454 return false;
1455 DCHECK(result->object_store_id_);
1456 if (!DecodeByte(slice, &result->meta_data_type_))
1457 return false;
1458 return true;
1461 std::string ObjectStoreMetaDataKey::Encode(int64 database_id,
1462 int64 object_store_id,
1463 unsigned char meta_data_type) {
1464 KeyPrefix prefix(database_id);
1465 std::string ret = prefix.Encode();
1466 ret.push_back(kObjectStoreMetaDataTypeByte);
1467 EncodeVarInt(object_store_id, &ret);
1468 ret.push_back(meta_data_type);
1469 return ret;
1472 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id) {
1473 return Encode(database_id,
1474 std::numeric_limits<int64>::max(),
1475 kObjectMetaDataTypeMaximum);
1478 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id,
1479 int64 object_store_id) {
1480 return Encode(database_id, object_store_id, kObjectMetaDataTypeMaximum);
1483 int64 ObjectStoreMetaDataKey::ObjectStoreId() const {
1484 DCHECK_GE(object_store_id_, 0);
1485 return object_store_id_;
1487 unsigned char ObjectStoreMetaDataKey::MetaDataType() const {
1488 return meta_data_type_;
1491 int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey& other) {
1492 DCHECK_GE(object_store_id_, 0);
1493 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1494 return x;
1495 return meta_data_type_ - other.meta_data_type_;
1498 IndexMetaDataKey::IndexMetaDataKey()
1499 : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {}
1501 bool IndexMetaDataKey::Decode(StringPiece* slice, IndexMetaDataKey* result) {
1502 KeyPrefix prefix;
1503 if (!KeyPrefix::Decode(slice, &prefix))
1504 return false;
1505 DCHECK(prefix.database_id_);
1506 DCHECK(!prefix.object_store_id_);
1507 DCHECK(!prefix.index_id_);
1508 unsigned char type_byte = 0;
1509 if (!DecodeByte(slice, &type_byte))
1510 return false;
1511 DCHECK_EQ(type_byte, kIndexMetaDataTypeByte);
1512 if (!DecodeVarInt(slice, &result->object_store_id_))
1513 return false;
1514 if (!DecodeVarInt(slice, &result->index_id_))
1515 return false;
1516 if (!DecodeByte(slice, &result->meta_data_type_))
1517 return false;
1518 return true;
1521 std::string IndexMetaDataKey::Encode(int64 database_id,
1522 int64 object_store_id,
1523 int64 index_id,
1524 unsigned char meta_data_type) {
1525 KeyPrefix prefix(database_id);
1526 std::string ret = prefix.Encode();
1527 ret.push_back(kIndexMetaDataTypeByte);
1528 EncodeVarInt(object_store_id, &ret);
1529 EncodeVarInt(index_id, &ret);
1530 EncodeByte(meta_data_type, &ret);
1531 return ret;
1534 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1535 int64 object_store_id) {
1536 return Encode(database_id,
1537 object_store_id,
1538 std::numeric_limits<int64>::max(),
1539 kIndexMetaDataTypeMaximum);
1542 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1543 int64 object_store_id,
1544 int64 index_id) {
1545 return Encode(
1546 database_id, object_store_id, index_id, kIndexMetaDataTypeMaximum);
1549 int IndexMetaDataKey::Compare(const IndexMetaDataKey& other) {
1550 DCHECK_GE(object_store_id_, 0);
1551 DCHECK_GE(index_id_, 0);
1553 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1554 return x;
1555 if (int x = CompareInts(index_id_, other.index_id_))
1556 return x;
1557 return meta_data_type_ - other.meta_data_type_;
1560 int64 IndexMetaDataKey::IndexId() const {
1561 DCHECK_GE(index_id_, 0);
1562 return index_id_;
1565 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {}
1567 bool ObjectStoreFreeListKey::Decode(StringPiece* slice,
1568 ObjectStoreFreeListKey* result) {
1569 KeyPrefix prefix;
1570 if (!KeyPrefix::Decode(slice, &prefix))
1571 return false;
1572 DCHECK(prefix.database_id_);
1573 DCHECK(!prefix.object_store_id_);
1574 DCHECK(!prefix.index_id_);
1575 unsigned char type_byte = 0;
1576 if (!DecodeByte(slice, &type_byte))
1577 return false;
1578 DCHECK_EQ(type_byte, kObjectStoreFreeListTypeByte);
1579 if (!DecodeVarInt(slice, &result->object_store_id_))
1580 return false;
1581 return true;
1584 std::string ObjectStoreFreeListKey::Encode(int64 database_id,
1585 int64 object_store_id) {
1586 KeyPrefix prefix(database_id);
1587 std::string ret = prefix.Encode();
1588 ret.push_back(kObjectStoreFreeListTypeByte);
1589 EncodeVarInt(object_store_id, &ret);
1590 return ret;
1593 std::string ObjectStoreFreeListKey::EncodeMaxKey(int64 database_id) {
1594 return Encode(database_id, std::numeric_limits<int64>::max());
1597 int64 ObjectStoreFreeListKey::ObjectStoreId() const {
1598 DCHECK_GE(object_store_id_, 0);
1599 return object_store_id_;
1602 int ObjectStoreFreeListKey::Compare(const ObjectStoreFreeListKey& other) {
1603 // TODO(jsbell): It may seem strange that we're not comparing database id's,
1604 // but that comparison will have been made earlier.
1605 // We should probably make this more clear, though...
1606 DCHECK_GE(object_store_id_, 0);
1607 return CompareInts(object_store_id_, other.object_store_id_);
1610 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {}
1612 bool IndexFreeListKey::Decode(StringPiece* slice, IndexFreeListKey* result) {
1613 KeyPrefix prefix;
1614 if (!KeyPrefix::Decode(slice, &prefix))
1615 return false;
1616 DCHECK(prefix.database_id_);
1617 DCHECK(!prefix.object_store_id_);
1618 DCHECK(!prefix.index_id_);
1619 unsigned char type_byte = 0;
1620 if (!DecodeByte(slice, &type_byte))
1621 return false;
1622 DCHECK_EQ(type_byte, kIndexFreeListTypeByte);
1623 if (!DecodeVarInt(slice, &result->object_store_id_))
1624 return false;
1625 if (!DecodeVarInt(slice, &result->index_id_))
1626 return false;
1627 return true;
1630 std::string IndexFreeListKey::Encode(int64 database_id,
1631 int64 object_store_id,
1632 int64 index_id) {
1633 KeyPrefix prefix(database_id);
1634 std::string ret = prefix.Encode();
1635 ret.push_back(kIndexFreeListTypeByte);
1636 EncodeVarInt(object_store_id, &ret);
1637 EncodeVarInt(index_id, &ret);
1638 return ret;
1641 std::string IndexFreeListKey::EncodeMaxKey(int64 database_id,
1642 int64 object_store_id) {
1643 return Encode(
1644 database_id, object_store_id, std::numeric_limits<int64>::max());
1647 int IndexFreeListKey::Compare(const IndexFreeListKey& other) {
1648 DCHECK_GE(object_store_id_, 0);
1649 DCHECK_GE(index_id_, 0);
1650 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1651 return x;
1652 return CompareInts(index_id_, other.index_id_);
1655 int64 IndexFreeListKey::ObjectStoreId() const {
1656 DCHECK_GE(object_store_id_, 0);
1657 return object_store_id_;
1660 int64 IndexFreeListKey::IndexId() const {
1661 DCHECK_GE(index_id_, 0);
1662 return index_id_;
1665 // TODO(jsbell): We never use this to look up object store ids,
1666 // because a mapping is kept in the IndexedDBDatabase. Can the
1667 // mapping become unreliable? Can we remove this?
1668 bool ObjectStoreNamesKey::Decode(StringPiece* slice,
1669 ObjectStoreNamesKey* result) {
1670 KeyPrefix prefix;
1671 if (!KeyPrefix::Decode(slice, &prefix))
1672 return false;
1673 DCHECK(prefix.database_id_);
1674 DCHECK(!prefix.object_store_id_);
1675 DCHECK(!prefix.index_id_);
1676 unsigned char type_byte = 0;
1677 if (!DecodeByte(slice, &type_byte))
1678 return false;
1679 DCHECK_EQ(type_byte, kObjectStoreNamesTypeByte);
1680 if (!DecodeStringWithLength(slice, &result->object_store_name_))
1681 return false;
1682 return true;
1685 std::string ObjectStoreNamesKey::Encode(
1686 int64 database_id,
1687 const base::string16& object_store_name) {
1688 KeyPrefix prefix(database_id);
1689 std::string ret = prefix.Encode();
1690 ret.push_back(kObjectStoreNamesTypeByte);
1691 EncodeStringWithLength(object_store_name, &ret);
1692 return ret;
1695 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey& other) {
1696 return object_store_name_.compare(other.object_store_name_);
1699 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {}
1701 // TODO(jsbell): We never use this to look up index ids, because a mapping
1702 // is kept at a higher level.
1703 bool IndexNamesKey::Decode(StringPiece* slice, IndexNamesKey* result) {
1704 KeyPrefix prefix;
1705 if (!KeyPrefix::Decode(slice, &prefix))
1706 return false;
1707 DCHECK(prefix.database_id_);
1708 DCHECK(!prefix.object_store_id_);
1709 DCHECK(!prefix.index_id_);
1710 unsigned char type_byte = 0;
1711 if (!DecodeByte(slice, &type_byte))
1712 return false;
1713 DCHECK_EQ(type_byte, kIndexNamesKeyTypeByte);
1714 if (!DecodeVarInt(slice, &result->object_store_id_))
1715 return false;
1716 if (!DecodeStringWithLength(slice, &result->index_name_))
1717 return false;
1718 return true;
1721 std::string IndexNamesKey::Encode(int64 database_id,
1722 int64 object_store_id,
1723 const base::string16& index_name) {
1724 KeyPrefix prefix(database_id);
1725 std::string ret = prefix.Encode();
1726 ret.push_back(kIndexNamesKeyTypeByte);
1727 EncodeVarInt(object_store_id, &ret);
1728 EncodeStringWithLength(index_name, &ret);
1729 return ret;
1732 int IndexNamesKey::Compare(const IndexNamesKey& other) {
1733 DCHECK_GE(object_store_id_, 0);
1734 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1735 return x;
1736 return index_name_.compare(other.index_name_);
1739 ObjectStoreDataKey::ObjectStoreDataKey() {}
1740 ObjectStoreDataKey::~ObjectStoreDataKey() {}
1742 bool ObjectStoreDataKey::Decode(StringPiece* slice,
1743 ObjectStoreDataKey* result) {
1744 KeyPrefix prefix;
1745 if (!KeyPrefix::Decode(slice, &prefix))
1746 return false;
1747 DCHECK(prefix.database_id_);
1748 DCHECK(prefix.object_store_id_);
1749 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1750 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1751 return false;
1752 return true;
1755 std::string ObjectStoreDataKey::Encode(int64 database_id,
1756 int64 object_store_id,
1757 const std::string encoded_user_key) {
1758 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1759 database_id, object_store_id, kSpecialIndexNumber));
1760 std::string ret = prefix.Encode();
1761 ret.append(encoded_user_key);
1763 return ret;
1766 std::string ObjectStoreDataKey::Encode(int64 database_id,
1767 int64 object_store_id,
1768 const IndexedDBKey& user_key) {
1769 std::string encoded_key;
1770 EncodeIDBKey(user_key, &encoded_key);
1771 return Encode(database_id, object_store_id, encoded_key);
1774 scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const {
1775 scoped_ptr<IndexedDBKey> key;
1776 StringPiece slice(encoded_user_key_);
1777 if (!DecodeIDBKey(&slice, &key)) {
1778 // TODO(jsbell): Return error.
1780 return key.Pass();
1783 const int64 ObjectStoreDataKey::kSpecialIndexNumber = kObjectStoreDataIndexId;
1785 ExistsEntryKey::ExistsEntryKey() {}
1786 ExistsEntryKey::~ExistsEntryKey() {}
1788 bool ExistsEntryKey::Decode(StringPiece* slice, ExistsEntryKey* result) {
1789 KeyPrefix prefix;
1790 if (!KeyPrefix::Decode(slice, &prefix))
1791 return false;
1792 DCHECK(prefix.database_id_);
1793 DCHECK(prefix.object_store_id_);
1794 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1795 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1796 return false;
1797 return true;
1800 std::string ExistsEntryKey::Encode(int64 database_id,
1801 int64 object_store_id,
1802 const std::string& encoded_key) {
1803 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1804 database_id, object_store_id, kSpecialIndexNumber));
1805 std::string ret = prefix.Encode();
1806 ret.append(encoded_key);
1807 return ret;
1810 std::string ExistsEntryKey::Encode(int64 database_id,
1811 int64 object_store_id,
1812 const IndexedDBKey& user_key) {
1813 std::string encoded_key;
1814 EncodeIDBKey(user_key, &encoded_key);
1815 return Encode(database_id, object_store_id, encoded_key);
1818 scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const {
1819 scoped_ptr<IndexedDBKey> key;
1820 StringPiece slice(encoded_user_key_);
1821 if (!DecodeIDBKey(&slice, &key)) {
1822 // TODO(jsbell): Return error.
1824 return key.Pass();
1827 const int64 ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId;
1829 bool BlobEntryKey::Decode(StringPiece* slice, BlobEntryKey* result) {
1830 KeyPrefix prefix;
1831 if (!KeyPrefix::Decode(slice, &prefix))
1832 return false;
1833 DCHECK(prefix.database_id_);
1834 DCHECK(prefix.object_store_id_);
1835 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1837 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1838 return false;
1839 result->database_id_ = prefix.database_id_;
1840 result->object_store_id_ = prefix.object_store_id_;
1842 return true;
1845 bool BlobEntryKey::FromObjectStoreDataKey(StringPiece* slice,
1846 BlobEntryKey* result) {
1847 KeyPrefix prefix;
1848 if (!KeyPrefix::Decode(slice, &prefix))
1849 return false;
1850 DCHECK(prefix.database_id_);
1851 DCHECK(prefix.object_store_id_);
1852 DCHECK_EQ(prefix.index_id_, ObjectStoreDataKey::kSpecialIndexNumber);
1854 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1855 return false;
1856 result->database_id_ = prefix.database_id_;
1857 result->object_store_id_ = prefix.object_store_id_;
1858 return true;
1861 std::string BlobEntryKey::ReencodeToObjectStoreDataKey(StringPiece* slice) {
1862 // TODO(ericu): We could be more efficient here, since the suffix is the same.
1863 BlobEntryKey key;
1864 if (!Decode(slice, &key))
1865 return std::string();
1867 return ObjectStoreDataKey::Encode(
1868 key.database_id_, key.object_store_id_, key.encoded_user_key_);
1871 std::string BlobEntryKey::EncodeMinKeyForObjectStore(int64 database_id,
1872 int64 object_store_id) {
1873 // Our implied encoded_user_key_ here is empty, the lowest possible key.
1874 return Encode(database_id, object_store_id, std::string());
1877 std::string BlobEntryKey::EncodeStopKeyForObjectStore(int64 database_id,
1878 int64 object_store_id) {
1879 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
1880 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1881 database_id, object_store_id, kSpecialIndexNumber + 1));
1882 return prefix.Encode();
1885 std::string BlobEntryKey::Encode() const {
1886 DCHECK(!encoded_user_key_.empty());
1887 return Encode(database_id_, object_store_id_, encoded_user_key_);
1890 std::string BlobEntryKey::Encode(int64 database_id,
1891 int64 object_store_id,
1892 const IndexedDBKey& user_key) {
1893 std::string encoded_key;
1894 EncodeIDBKey(user_key, &encoded_key);
1895 return Encode(database_id, object_store_id, encoded_key);
1898 std::string BlobEntryKey::Encode(int64 database_id,
1899 int64 object_store_id,
1900 const std::string& encoded_user_key) {
1901 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
1902 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1903 database_id, object_store_id, kSpecialIndexNumber));
1904 return prefix.Encode() + encoded_user_key;
1907 const int64 BlobEntryKey::kSpecialIndexNumber = kBlobEntryIndexId;
1909 IndexDataKey::IndexDataKey()
1910 : database_id_(-1),
1911 object_store_id_(-1),
1912 index_id_(-1),
1913 sequence_number_(-1) {}
1915 IndexDataKey::~IndexDataKey() {}
1917 bool IndexDataKey::Decode(StringPiece* slice, IndexDataKey* result) {
1918 KeyPrefix prefix;
1919 if (!KeyPrefix::Decode(slice, &prefix))
1920 return false;
1921 DCHECK(prefix.database_id_);
1922 DCHECK(prefix.object_store_id_);
1923 DCHECK_GE(prefix.index_id_, kMinimumIndexId);
1924 result->database_id_ = prefix.database_id_;
1925 result->object_store_id_ = prefix.object_store_id_;
1926 result->index_id_ = prefix.index_id_;
1927 result->sequence_number_ = -1;
1928 result->encoded_primary_key_ = MinIDBKey();
1930 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1931 return false;
1933 // [optional] sequence number
1934 if (slice->empty())
1935 return true;
1936 if (!DecodeVarInt(slice, &result->sequence_number_))
1937 return false;
1939 // [optional] primary key
1940 if (slice->empty())
1941 return true;
1942 if (!ExtractEncodedIDBKey(slice, &result->encoded_primary_key_))
1943 return false;
1944 return true;
1947 std::string IndexDataKey::Encode(int64 database_id,
1948 int64 object_store_id,
1949 int64 index_id,
1950 const std::string& encoded_user_key,
1951 const std::string& encoded_primary_key,
1952 int64 sequence_number) {
1953 KeyPrefix prefix(database_id, object_store_id, index_id);
1954 std::string ret = prefix.Encode();
1955 ret.append(encoded_user_key);
1956 EncodeVarInt(sequence_number, &ret);
1957 ret.append(encoded_primary_key);
1958 return ret;
1961 std::string IndexDataKey::Encode(int64 database_id,
1962 int64 object_store_id,
1963 int64 index_id,
1964 const IndexedDBKey& user_key) {
1965 std::string encoded_key;
1966 EncodeIDBKey(user_key, &encoded_key);
1967 return Encode(
1968 database_id, object_store_id, index_id, encoded_key, MinIDBKey(), 0);
1971 std::string IndexDataKey::Encode(int64 database_id,
1972 int64 object_store_id,
1973 int64 index_id,
1974 const IndexedDBKey& user_key,
1975 const IndexedDBKey& user_primary_key) {
1976 std::string encoded_key;
1977 EncodeIDBKey(user_key, &encoded_key);
1978 std::string encoded_primary_key;
1979 EncodeIDBKey(user_primary_key, &encoded_primary_key);
1980 return Encode(database_id,
1981 object_store_id,
1982 index_id,
1983 encoded_key,
1984 encoded_primary_key,
1988 std::string IndexDataKey::EncodeMinKey(int64 database_id,
1989 int64 object_store_id,
1990 int64 index_id) {
1991 return Encode(
1992 database_id, object_store_id, index_id, MinIDBKey(), MinIDBKey(), 0);
1995 std::string IndexDataKey::EncodeMaxKey(int64 database_id,
1996 int64 object_store_id,
1997 int64 index_id) {
1998 return Encode(database_id,
1999 object_store_id,
2000 index_id,
2001 MaxIDBKey(),
2002 MaxIDBKey(),
2003 std::numeric_limits<int64>::max());
2006 int64 IndexDataKey::DatabaseId() const {
2007 DCHECK_GE(database_id_, 0);
2008 return database_id_;
2011 int64 IndexDataKey::ObjectStoreId() const {
2012 DCHECK_GE(object_store_id_, 0);
2013 return object_store_id_;
2016 int64 IndexDataKey::IndexId() const {
2017 DCHECK_GE(index_id_, 0);
2018 return index_id_;
2021 scoped_ptr<IndexedDBKey> IndexDataKey::user_key() const {
2022 scoped_ptr<IndexedDBKey> key;
2023 StringPiece slice(encoded_user_key_);
2024 if (!DecodeIDBKey(&slice, &key)) {
2025 // TODO(jsbell): Return error.
2027 return key.Pass();
2030 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const {
2031 scoped_ptr<IndexedDBKey> key;
2032 StringPiece slice(encoded_primary_key_);
2033 if (!DecodeIDBKey(&slice, &key)) {
2034 // TODO(jsbell): Return error.
2036 return key.Pass();
2039 } // namespace content