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
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"
16
17 // LevelDB Coding Scheme
18 // =====================
19 //
20 // LevelDB stores key/value pairs. Keys and values are strings of bytes,
21 // normally of type std::string.
22 //
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.
27 //
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.
33 //
34 // Each key type has a class (in square brackets below) which knows how to
35 // encode, decode, and compare that key type.
36 //
37 // Strings (origins, names, etc) are encoded as UTF-16BE.
38 //
39 //
40 // Global metadata
41 // ---------------
42 // The prefix is <0, 0, 0>, followed by a metadata type byte:
43 //
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, 100, database id>
48 // => Existence implies the database id is in the free list
49 // [DatabaseFreeListKey]
50 // <0, 0, 0, 201, origin, database name> => Database id [DatabaseNameKey]
51 //
52 //
53 // Database metadata: [DatabaseMetaDataKey]
54 // ----------------------------------------
55 // The prefix is <database id, 0, 0> followed by a metadata type byte:
56 //
57 // <database id, 0, 0, 0> => origin name
58 // <database id, 0, 0, 1> => database name
59 // <database id, 0, 0, 2> => IDB string version data (obsolete)
60 // <database id, 0, 0, 3> => maximum allocated object store id
61 // <database id, 0, 0, 4> => IDB integer version (var int)
62 //
63 //
64 // Object store metadata: [ObjectStoreMetaDataKey]
65 // -----------------------------------------------
66 // The prefix is <database id, 0, 0>, followed by a type byte (50), then the
67 // object store id (var int), then a metadata type byte.
68 //
69 // <database id, 0, 0, 50, object store id, 0> => object store name
70 // <database id, 0, 0, 50, object store id, 1> => key path
71 // <database id, 0, 0, 50, object store id, 2> => auto increment flag
72 // <database id, 0, 0, 50, object store id, 3> => is evictable
73 // <database id, 0, 0, 50, object store id, 4> => last "version" number
74 // <database id, 0, 0, 50, object store id, 5> => maximum allocated index id
75 // <database id, 0, 0, 50, object store id, 6> => has key path flag (obsolete)
76 // <database id, 0, 0, 50, object store id, 7> => key generator current number
77 //
78 // The key path was originally just a string (#1) or null (identified by flag,
79 // #6). To support null, string, or array the coding is now identified by the
80 // leading bytes in #1 - see EncodeIDBKeyPath.
81 //
82 // The "version" field is used to weed out stale index data. Whenever new
83 // object store data is inserted, it gets a new "version" number, and new
84 // index data is written with this number. When the index is used for
85 // look-ups, entries are validated against the "exists" entries, and records
86 // with old "version" numbers are deleted when they are encountered in
87 // GetPrimaryKeyViaIndex, IndexCursorImpl::LoadCurrentRow and
88 // IndexKeyCursorImpl::LoadCurrentRow.
89 //
90 //
91 // Index metadata: [IndexMetaDataKey]
92 // ----------------------------------
93 // The prefix is <database id, 0, 0>, followed by a type byte (100), then the
94 // object store id (var int), then the index id (var int), then a metadata
95 // type byte.
96 //
97 // <database id, 0, 0, 100, object store id, index id, 0> => index name
98 // <database id, 0, 0, 100, object store id, index id, 1> => unique flag
99 // <database id, 0, 0, 100, object store id, index id, 2> => key path
100 // <database id, 0, 0, 100, object store id, index id, 3> => multi-entry flag
101 //
102 //
103 // Other object store and index metadata
104 // -------------------------------------
105 // The prefix is <database id, 0, 0> followed by a type byte. The object
106 // store and index id are variable length integers, the names are variable
107 // length strings.
108 //
109 // <database id, 0, 0, 150, object store id>
110 // => existence implies the object store id is in the free list
111 // [ObjectStoreFreeListKey]
112 // <database id, 0, 0, 151, object store id, index id>
113 // => existence implies the index id is in the free list [IndexFreeListKey]
114 // <database id, 0, 0, 200, object store name>
115 // => object store id [ObjectStoreNamesKey]
116 // <database id, 0, 0, 201, object store id, index name>
117 // => index id [IndexNamesKey]
118 //
119 //
120 // Object store data: [ObjectStoreDataKey]
121 // ---------------------------------------
122 // The prefix is followed by a type byte and the encoded IDB primary key. The
123 // data has a "version" prefix followed by the serialized script value.
124 //
125 // <database id, object store id, 1, user key>
126 // => "version", serialized script value
127 //
128 //
129 // "Exists" entry: [ExistsEntryKey]
130 // --------------------------------
131 // The prefix is followed by a type byte and the encoded IDB primary key.
132 //
133 // <database id, object store id, 2, user key> => "version"
134 //
135 //
136 // Index data
137 // ----------
138 // The prefix is followed by a type byte, the encoded IDB index key, a
139 // "sequence" number (obsolete; var int), and the encoded IDB primary key.
140 //
141 // <database id, object store id, index id, index key, sequence number,
142 // primary key> => "version", primary key [IndexDataKey]
143 //
144 // The sequence number is obsolete; it was used to allow two entries with the
145 // same user (index) key in non-unique indexes prior to the inclusion of the
146 // primary key in the data.
147
148
149 using base::StringPiece;
150 using blink::WebIDBKeyType;
151 using blink::WebIDBKeyTypeArray;
152 using blink::WebIDBKeyTypeBinary;
153 using blink::WebIDBKeyTypeDate;
154 using blink::WebIDBKeyTypeInvalid;
155 using blink::WebIDBKeyTypeMin;
156 using blink::WebIDBKeyTypeNull;
157 using blink::WebIDBKeyTypeNumber;
158 using blink::WebIDBKeyTypeString;
159 using blink::WebIDBKeyPathType;
160 using blink::WebIDBKeyPathTypeArray;
161 using blink::WebIDBKeyPathTypeNull;
162 using blink::WebIDBKeyPathTypeString;
163
164 namespace content {
165
166 // As most of the IndexedDBKeys and encoded values are short, we
167 // initialize some Vectors with a default inline buffer size to reduce
168 // the memory re-allocations when the Vectors are appended.
169 static const size_t kDefaultInlineBufferSize = 32;
170
171 static const unsigned char kIndexedDBKeyNullTypeByte = 0;
172 static const unsigned char kIndexedDBKeyStringTypeByte = 1;
173 static const unsigned char kIndexedDBKeyDateTypeByte = 2;
174 static const unsigned char kIndexedDBKeyNumberTypeByte = 3;
175 static const unsigned char kIndexedDBKeyArrayTypeByte = 4;
176 static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
177 static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
178
179 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
180 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
181
182 static const unsigned char kObjectStoreDataIndexId = 1;
183 static const unsigned char kExistsEntryIndexId = 2;
184
185 static const unsigned char kSchemaVersionTypeByte = 0;
186 static const unsigned char kMaxDatabaseIdTypeByte = 1;
187 static const unsigned char kDataVersionTypeByte = 2;
188 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte =
189 3; // Insert before this and increment.
190 static const unsigned char kDatabaseFreeListTypeByte = 100;
191 static const unsigned char kDatabaseNameTypeByte = 201;
192
193 static const unsigned char kObjectStoreMetaDataTypeByte = 50;
194 static const unsigned char kIndexMetaDataTypeByte = 100;
195 static const unsigned char kObjectStoreFreeListTypeByte = 150;
196 static const unsigned char kIndexFreeListTypeByte = 151;
197 static const unsigned char kObjectStoreNamesTypeByte = 200;
198 static const unsigned char kIndexNamesKeyTypeByte = 201;
199
200 static const unsigned char kObjectMetaDataTypeMaximum = 255;
201 static const unsigned char kIndexMetaDataTypeMaximum = 255;
202
203 const unsigned char kMinimumIndexId = 30;
204
EncodeIntSafely(int64 nParam,int64 max,std::string * into)205 inline void EncodeIntSafely(int64 nParam, int64 max, std::string* into) {
206 DCHECK_LE(nParam, max);
207 return EncodeInt(nParam, into);
208 }
209
MaxIDBKey()210 std::string MaxIDBKey() {
211 std::string ret;
212 EncodeByte(kIndexedDBKeyNullTypeByte, &ret);
213 return ret;
214 }
215
MinIDBKey()216 std::string MinIDBKey() {
217 std::string ret;
218 EncodeByte(kIndexedDBKeyMinKeyTypeByte, &ret);
219 return ret;
220 }
221
EncodeByte(unsigned char value,std::string * into)222 void EncodeByte(unsigned char value, std::string* into) {
223 into->push_back(value);
224 }
225
EncodeBool(bool value,std::string * into)226 void EncodeBool(bool value, std::string* into) {
227 into->push_back(value ? 1 : 0);
228 }
229
EncodeInt(int64 value,std::string * into)230 void EncodeInt(int64 value, std::string* into) {
231 #ifndef NDEBUG
232 // Exercised by unit tests in debug only.
233 DCHECK_GE(value, 0);
234 #endif
235 uint64 n = static_cast<uint64>(value);
236
237 do {
238 unsigned char c = n;
239 into->push_back(c);
240 n >>= 8;
241 } while (n);
242 }
243
EncodeVarInt(int64 value,std::string * into)244 void EncodeVarInt(int64 value, std::string* into) {
245 #ifndef NDEBUG
246 // Exercised by unit tests in debug only.
247 DCHECK_GE(value, 0);
248 #endif
249 uint64 n = static_cast<uint64>(value);
250
251 do {
252 unsigned char c = n & 0x7f;
253 n >>= 7;
254 if (n)
255 c |= 0x80;
256 into->push_back(c);
257 } while (n);
258 }
259
EncodeString(const base::string16 & value,std::string * into)260 void EncodeString(const base::string16& value, std::string* into) {
261 if (value.empty())
262 return;
263 // Backing store is UTF-16BE, convert from host endianness.
264 size_t length = value.length();
265 size_t current = into->size();
266 into->resize(into->size() + length * sizeof(char16));
267
268 const char16* src = value.c_str();
269 char16* dst = reinterpret_cast<char16*>(&*into->begin() + current);
270 for (unsigned i = 0; i < length; ++i)
271 *dst++ = htons(*src++);
272 }
273
EncodeBinary(const std::string & value,std::string * into)274 void EncodeBinary(const std::string& value, std::string* into) {
275 EncodeVarInt(value.length(), into);
276 into->append(value.begin(), value.end());
277 DCHECK(into->size() >= value.size());
278 }
279
EncodeStringWithLength(const base::string16 & value,std::string * into)280 void EncodeStringWithLength(const base::string16& value, std::string* into) {
281 EncodeVarInt(value.length(), into);
282 EncodeString(value, into);
283 }
284
EncodeDouble(double value,std::string * into)285 void EncodeDouble(double value, std::string* into) {
286 // This always has host endianness.
287 const char* p = reinterpret_cast<char*>(&value);
288 into->insert(into->end(), p, p + sizeof(value));
289 }
290
EncodeIDBKey(const IndexedDBKey & value,std::string * into)291 void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
292 size_t previous_size = into->size();
293 DCHECK(value.IsValid());
294 switch (value.type()) {
295 case WebIDBKeyTypeNull:
296 case WebIDBKeyTypeInvalid:
297 case WebIDBKeyTypeMin:
298 default: {
299 NOTREACHED();
300 EncodeByte(kIndexedDBKeyNullTypeByte, into);
301 return;
302 }
303 case WebIDBKeyTypeArray: {
304 EncodeByte(kIndexedDBKeyArrayTypeByte, into);
305 size_t length = value.array().size();
306 EncodeVarInt(length, into);
307 for (size_t i = 0; i < length; ++i)
308 EncodeIDBKey(value.array()[i], into);
309 DCHECK_GT(into->size(), previous_size);
310 return;
311 }
312 case WebIDBKeyTypeBinary: {
313 EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
314 EncodeBinary(value.binary(), into);
315 DCHECK_GT(into->size(), previous_size);
316 return;
317 }
318 case WebIDBKeyTypeString: {
319 EncodeByte(kIndexedDBKeyStringTypeByte, into);
320 EncodeStringWithLength(value.string(), into);
321 DCHECK_GT(into->size(), previous_size);
322 return;
323 }
324 case WebIDBKeyTypeDate: {
325 EncodeByte(kIndexedDBKeyDateTypeByte, into);
326 EncodeDouble(value.date(), into);
327 DCHECK_EQ(static_cast<size_t>(9),
328 static_cast<size_t>(into->size() - previous_size));
329 return;
330 }
331 case WebIDBKeyTypeNumber: {
332 EncodeByte(kIndexedDBKeyNumberTypeByte, into);
333 EncodeDouble(value.number(), into);
334 DCHECK_EQ(static_cast<size_t>(9),
335 static_cast<size_t>(into->size() - previous_size));
336 return;
337 }
338 }
339
340 NOTREACHED();
341 }
342
EncodeIDBKeyPath(const IndexedDBKeyPath & value,std::string * into)343 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
344 // May be typed, or may be a raw string. An invalid leading
345 // byte is used to identify typed coding. New records are
346 // always written as typed.
347 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
348 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
349 EncodeByte(static_cast<char>(value.type()), into);
350 switch (value.type()) {
351 case WebIDBKeyPathTypeNull:
352 break;
353 case WebIDBKeyPathTypeString: {
354 EncodeStringWithLength(value.string(), into);
355 break;
356 }
357 case WebIDBKeyPathTypeArray: {
358 const std::vector<base::string16>& array = value.array();
359 size_t count = array.size();
360 EncodeVarInt(count, into);
361 for (size_t i = 0; i < count; ++i) {
362 EncodeStringWithLength(array[i], into);
363 }
364 break;
365 }
366 }
367 }
368
DecodeByte(StringPiece * slice,unsigned char * value)369 bool DecodeByte(StringPiece* slice, unsigned char* value) {
370 if (slice->empty())
371 return false;
372
373 *value = (*slice)[0];
374 slice->remove_prefix(1);
375 return true;
376 }
377
DecodeBool(StringPiece * slice,bool * value)378 bool DecodeBool(StringPiece* slice, bool* value) {
379 if (slice->empty())
380 return false;
381
382 *value = !!(*slice)[0];
383 slice->remove_prefix(1);
384 return true;
385 }
386
DecodeInt(StringPiece * slice,int64 * value)387 bool DecodeInt(StringPiece* slice, int64* value) {
388 if (slice->empty())
389 return false;
390
391 StringPiece::const_iterator it = slice->begin();
392 int shift = 0;
393 int64 ret = 0;
394 while (it != slice->end()) {
395 unsigned char c = *it++;
396 ret |= static_cast<int64>(c) << shift;
397 shift += 8;
398 }
399 *value = ret;
400 slice->remove_prefix(it - slice->begin());
401 return true;
402 }
403
DecodeVarInt(StringPiece * slice,int64 * value)404 bool DecodeVarInt(StringPiece* slice, int64* value) {
405 if (slice->empty())
406 return false;
407
408 StringPiece::const_iterator it = slice->begin();
409 int shift = 0;
410 int64 ret = 0;
411 do {
412 if (it == slice->end())
413 return false;
414
415 unsigned char c = *it;
416 ret |= static_cast<int64>(c & 0x7f) << shift;
417 shift += 7;
418 } while (*it++ & 0x80);
419 *value = ret;
420 slice->remove_prefix(it - slice->begin());
421 return true;
422 }
423
DecodeString(StringPiece * slice,base::string16 * value)424 bool DecodeString(StringPiece* slice, base::string16* value) {
425 if (slice->empty()) {
426 value->clear();
427 return true;
428 }
429
430 // Backing store is UTF-16BE, convert to host endianness.
431 DCHECK(!(slice->size() % sizeof(char16)));
432 size_t length = slice->size() / sizeof(char16);
433 base::string16 decoded;
434 decoded.reserve(length);
435 const char16* encoded = reinterpret_cast<const char16*>(slice->begin());
436 for (unsigned i = 0; i < length; ++i)
437 decoded.push_back(ntohs(*encoded++));
438
439 *value = decoded;
440 slice->remove_prefix(length * sizeof(char16));
441 return true;
442 }
443
DecodeStringWithLength(StringPiece * slice,base::string16 * value)444 bool DecodeStringWithLength(StringPiece* slice, base::string16* value) {
445 if (slice->empty())
446 return false;
447
448 int64 length = 0;
449 if (!DecodeVarInt(slice, &length) || length < 0)
450 return false;
451 size_t bytes = length * sizeof(char16);
452 if (slice->size() < bytes)
453 return false;
454
455 StringPiece subpiece(slice->begin(), bytes);
456 slice->remove_prefix(bytes);
457 if (!DecodeString(&subpiece, value))
458 return false;
459
460 return true;
461 }
462
DecodeBinary(StringPiece * slice,std::string * value)463 bool DecodeBinary(StringPiece* slice, std::string* value) {
464 if (slice->empty())
465 return false;
466
467 int64 length = 0;
468 if (!DecodeVarInt(slice, &length) || length < 0)
469 return false;
470 size_t size = length;
471 if (slice->size() < size)
472 return false;
473
474 value->assign(slice->begin(), size);
475 slice->remove_prefix(size);
476 return true;
477 }
478
DecodeIDBKey(StringPiece * slice,scoped_ptr<IndexedDBKey> * value)479 bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
480 if (slice->empty())
481 return false;
482
483 unsigned char type = (*slice)[0];
484 slice->remove_prefix(1);
485
486 switch (type) {
487 case kIndexedDBKeyNullTypeByte:
488 *value = make_scoped_ptr(new IndexedDBKey());
489 return true;
490
491 case kIndexedDBKeyArrayTypeByte: {
492 int64 length = 0;
493 if (!DecodeVarInt(slice, &length) || length < 0)
494 return false;
495 IndexedDBKey::KeyArray array;
496 while (length--) {
497 scoped_ptr<IndexedDBKey> key;
498 if (!DecodeIDBKey(slice, &key))
499 return false;
500 array.push_back(*key);
501 }
502 *value = make_scoped_ptr(new IndexedDBKey(array));
503 return true;
504 }
505 case kIndexedDBKeyBinaryTypeByte: {
506 std::string binary;
507 if (!DecodeBinary(slice, &binary))
508 return false;
509 *value = make_scoped_ptr(new IndexedDBKey(binary));
510 return true;
511 }
512 case kIndexedDBKeyStringTypeByte: {
513 base::string16 s;
514 if (!DecodeStringWithLength(slice, &s))
515 return false;
516 *value = make_scoped_ptr(new IndexedDBKey(s));
517 return true;
518 }
519 case kIndexedDBKeyDateTypeByte: {
520 double d;
521 if (!DecodeDouble(slice, &d))
522 return false;
523 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeDate));
524 return true;
525 }
526 case kIndexedDBKeyNumberTypeByte: {
527 double d;
528 if (!DecodeDouble(slice, &d))
529 return false;
530 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeNumber));
531 return true;
532 }
533 }
534
535 NOTREACHED();
536 return false;
537 }
538
DecodeDouble(StringPiece * slice,double * value)539 bool DecodeDouble(StringPiece* slice, double* value) {
540 if (slice->size() < sizeof(*value))
541 return false;
542
543 memcpy(value, slice->begin(), sizeof(*value));
544 slice->remove_prefix(sizeof(*value));
545 return true;
546 }
547
DecodeIDBKeyPath(StringPiece * slice,IndexedDBKeyPath * value)548 bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
549 // May be typed, or may be a raw string. An invalid leading
550 // byte sequence is used to identify typed coding. New records are
551 // always written as typed.
552 if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 ||
553 (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) {
554 base::string16 s;
555 if (!DecodeString(slice, &s))
556 return false;
557 *value = IndexedDBKeyPath(s);
558 return true;
559 }
560
561 slice->remove_prefix(2);
562 DCHECK(!slice->empty());
563 WebIDBKeyPathType type = static_cast<WebIDBKeyPathType>((*slice)[0]);
564 slice->remove_prefix(1);
565
566 switch (type) {
567 case WebIDBKeyPathTypeNull:
568 DCHECK(slice->empty());
569 *value = IndexedDBKeyPath();
570 return true;
571 case WebIDBKeyPathTypeString: {
572 base::string16 string;
573 if (!DecodeStringWithLength(slice, &string))
574 return false;
575 DCHECK(slice->empty());
576 *value = IndexedDBKeyPath(string);
577 return true;
578 }
579 case WebIDBKeyPathTypeArray: {
580 std::vector<base::string16> array;
581 int64 count;
582 if (!DecodeVarInt(slice, &count))
583 return false;
584 DCHECK_GE(count, 0);
585 while (count--) {
586 base::string16 string;
587 if (!DecodeStringWithLength(slice, &string))
588 return false;
589 array.push_back(string);
590 }
591 DCHECK(slice->empty());
592 *value = IndexedDBKeyPath(array);
593 return true;
594 }
595 }
596 NOTREACHED();
597 return false;
598 }
599
ConsumeEncodedIDBKey(StringPiece * slice)600 bool ConsumeEncodedIDBKey(StringPiece* slice) {
601 unsigned char type = (*slice)[0];
602 slice->remove_prefix(1);
603
604 switch (type) {
605 case kIndexedDBKeyNullTypeByte:
606 case kIndexedDBKeyMinKeyTypeByte:
607 return true;
608 case kIndexedDBKeyArrayTypeByte: {
609 int64 length;
610 if (!DecodeVarInt(slice, &length))
611 return false;
612 while (length--) {
613 if (!ConsumeEncodedIDBKey(slice))
614 return false;
615 }
616 return true;
617 }
618 case kIndexedDBKeyBinaryTypeByte: {
619 int64 length = 0;
620 if (!DecodeVarInt(slice, &length) || length < 0)
621 return false;
622 if (slice->size() < static_cast<size_t>(length))
623 return false;
624 slice->remove_prefix(length);
625 return true;
626 }
627 case kIndexedDBKeyStringTypeByte: {
628 int64 length = 0;
629 if (!DecodeVarInt(slice, &length) || length < 0)
630 return false;
631 if (slice->size() < static_cast<size_t>(length) * sizeof(char16))
632 return false;
633 slice->remove_prefix(length * sizeof(char16));
634 return true;
635 }
636 case kIndexedDBKeyDateTypeByte:
637 case kIndexedDBKeyNumberTypeByte:
638 if (slice->size() < sizeof(double))
639 return false;
640 slice->remove_prefix(sizeof(double));
641 return true;
642 }
643 NOTREACHED();
644 return false;
645 }
646
ExtractEncodedIDBKey(StringPiece * slice,std::string * result)647 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) {
648 const char* start = slice->begin();
649 if (!ConsumeEncodedIDBKey(slice))
650 return false;
651
652 if (result)
653 result->assign(start, slice->begin());
654 return true;
655 }
656
KeyTypeByteToKeyType(unsigned char type)657 static WebIDBKeyType KeyTypeByteToKeyType(unsigned char type) {
658 switch (type) {
659 case kIndexedDBKeyNullTypeByte:
660 return WebIDBKeyTypeInvalid;
661 case kIndexedDBKeyArrayTypeByte:
662 return WebIDBKeyTypeArray;
663 case kIndexedDBKeyBinaryTypeByte:
664 return WebIDBKeyTypeBinary;
665 case kIndexedDBKeyStringTypeByte:
666 return WebIDBKeyTypeString;
667 case kIndexedDBKeyDateTypeByte:
668 return WebIDBKeyTypeDate;
669 case kIndexedDBKeyNumberTypeByte:
670 return WebIDBKeyTypeNumber;
671 case kIndexedDBKeyMinKeyTypeByte:
672 return WebIDBKeyTypeMin;
673 }
674
675 NOTREACHED();
676 return WebIDBKeyTypeInvalid;
677 }
678
CompareEncodedStringsWithLength(StringPiece * slice1,StringPiece * slice2,bool * ok)679 int CompareEncodedStringsWithLength(StringPiece* slice1,
680 StringPiece* slice2,
681 bool* ok) {
682 int64 len1, len2;
683 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
684 *ok = false;
685 return 0;
686 }
687 DCHECK_GE(len1, 0);
688 DCHECK_GE(len2, 0);
689 if (len1 < 0 || len2 < 0) {
690 *ok = false;
691 return 0;
692 }
693 DCHECK_GE(slice1->size(), len1 * sizeof(char16));
694 DCHECK_GE(slice2->size(), len2 * sizeof(char16));
695 if (slice1->size() < len1 * sizeof(char16) ||
696 slice2->size() < len2 * sizeof(char16)) {
697 *ok = false;
698 return 0;
699 }
700
701 // Extract the string data, and advance the passed slices.
702 StringPiece string1(slice1->begin(), len1 * sizeof(char16));
703 StringPiece string2(slice2->begin(), len2 * sizeof(char16));
704 slice1->remove_prefix(len1 * sizeof(char16));
705 slice2->remove_prefix(len2 * sizeof(char16));
706
707 *ok = true;
708 // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
709 return string1.compare(string2);
710 }
711
CompareEncodedBinary(StringPiece * slice1,StringPiece * slice2,bool * ok)712 int CompareEncodedBinary(StringPiece* slice1,
713 StringPiece* slice2,
714 bool* ok) {
715 int64 len1, len2;
716 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
717 *ok = false;
718 return 0;
719 }
720 DCHECK_GE(len1, 0);
721 DCHECK_GE(len2, 0);
722 if (len1 < 0 || len2 < 0) {
723 *ok = false;
724 return 0;
725 }
726 size_t size1 = len1;
727 size_t size2 = len2;
728
729 DCHECK_GE(slice1->size(), size1);
730 DCHECK_GE(slice2->size(), size2);
731 if (slice1->size() < size1 || slice2->size() < size2) {
732 *ok = false;
733 return 0;
734 }
735
736 // Extract the binary data, and advance the passed slices.
737 StringPiece binary1(slice1->begin(), size1);
738 StringPiece binary2(slice2->begin(), size2);
739 slice1->remove_prefix(size1);
740 slice2->remove_prefix(size2);
741
742 *ok = true;
743 // This is the same as a memcmp()
744 return binary1.compare(binary2);
745 }
746
CompareInts(int64 a,int64 b)747 static int CompareInts(int64 a, int64 b) {
748 #ifndef NDEBUG
749 // Exercised by unit tests in debug only.
750 DCHECK_GE(a, 0);
751 DCHECK_GE(b, 0);
752 #endif
753 int64 diff = a - b;
754 if (diff < 0)
755 return -1;
756 if (diff > 0)
757 return 1;
758 return 0;
759 }
760
CompareSizes(size_t a,size_t b)761 static inline int CompareSizes(size_t a, size_t b) {
762 if (a > b)
763 return 1;
764 if (b > a)
765 return -1;
766 return 0;
767 }
768
CompareTypes(WebIDBKeyType a,WebIDBKeyType b)769 static int CompareTypes(WebIDBKeyType a, WebIDBKeyType b) { return b - a; }
770
CompareEncodedIDBKeys(StringPiece * slice_a,StringPiece * slice_b,bool * ok)771 int CompareEncodedIDBKeys(StringPiece* slice_a,
772 StringPiece* slice_b,
773 bool* ok) {
774 DCHECK(!slice_a->empty());
775 DCHECK(!slice_b->empty());
776 *ok = true;
777 unsigned char type_a = (*slice_a)[0];
778 unsigned char type_b = (*slice_b)[0];
779 slice_a->remove_prefix(1);
780 slice_b->remove_prefix(1);
781
782 if (int x = CompareTypes(KeyTypeByteToKeyType(type_a),
783 KeyTypeByteToKeyType(type_b)))
784 return x;
785
786 switch (type_a) {
787 case kIndexedDBKeyNullTypeByte:
788 case kIndexedDBKeyMinKeyTypeByte:
789 // Null type or max type; no payload to compare.
790 return 0;
791 case kIndexedDBKeyArrayTypeByte: {
792 int64 length_a, length_b;
793 if (!DecodeVarInt(slice_a, &length_a) ||
794 !DecodeVarInt(slice_b, &length_b)) {
795 *ok = false;
796 return 0;
797 }
798 for (int64 i = 0; i < length_a && i < length_b; ++i) {
799 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
800 if (!*ok || result)
801 return result;
802 }
803 return length_a - length_b;
804 }
805 case kIndexedDBKeyBinaryTypeByte:
806 return CompareEncodedBinary(slice_a, slice_b, ok);
807 case kIndexedDBKeyStringTypeByte:
808 return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
809 case kIndexedDBKeyDateTypeByte:
810 case kIndexedDBKeyNumberTypeByte: {
811 double d, e;
812 if (!DecodeDouble(slice_a, &d) || !DecodeDouble(slice_b, &e)) {
813 *ok = false;
814 return 0;
815 }
816 if (d < e)
817 return -1;
818 if (d > e)
819 return 1;
820 return 0;
821 }
822 }
823
824 NOTREACHED();
825 return 0;
826 }
827
828 namespace {
829
830 template <typename KeyType>
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys,bool * ok)831 int Compare(const StringPiece& a,
832 const StringPiece& b,
833 bool only_compare_index_keys,
834 bool* ok) {
835 KeyType key_a;
836 KeyType key_b;
837
838 StringPiece slice_a(a);
839 if (!KeyType::Decode(&slice_a, &key_a)) {
840 *ok = false;
841 return 0;
842 }
843 StringPiece slice_b(b);
844 if (!KeyType::Decode(&slice_b, &key_b)) {
845 *ok = false;
846 return 0;
847 }
848
849 *ok = true;
850 return key_a.Compare(key_b);
851 }
852
853 template <typename KeyType>
CompareSuffix(StringPiece * a,StringPiece * b,bool only_compare_index_keys,bool * ok)854 int CompareSuffix(StringPiece* a,
855 StringPiece* b,
856 bool only_compare_index_keys,
857 bool* ok) {
858 NOTREACHED();
859 return 0;
860 }
861
862 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)863 int CompareSuffix<ExistsEntryKey>(StringPiece* slice_a,
864 StringPiece* slice_b,
865 bool only_compare_index_keys,
866 bool* ok) {
867 DCHECK(!slice_a->empty());
868 DCHECK(!slice_b->empty());
869 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
870 }
871
872 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)873 int CompareSuffix<ObjectStoreDataKey>(StringPiece* slice_a,
874 StringPiece* slice_b,
875 bool only_compare_index_keys,
876 bool* ok) {
877 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
878 }
879
880 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)881 int CompareSuffix<IndexDataKey>(StringPiece* slice_a,
882 StringPiece* slice_b,
883 bool only_compare_index_keys,
884 bool* ok) {
885 // index key
886 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
887 if (!*ok || result)
888 return result;
889 if (only_compare_index_keys)
890 return 0;
891
892 // sequence number [optional]
893 int64 sequence_number_a = -1;
894 int64 sequence_number_b = -1;
895 if (!slice_a->empty() && !DecodeVarInt(slice_a, &sequence_number_a))
896 return 0;
897 if (!slice_b->empty() && !DecodeVarInt(slice_b, &sequence_number_b))
898 return 0;
899
900 if (slice_a->empty() || slice_b->empty())
901 return CompareSizes(slice_a->size(), slice_b->size());
902
903 // primary key [optional]
904 result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
905 if (!*ok || result)
906 return result;
907
908 return CompareInts(sequence_number_a, sequence_number_b);
909 }
910
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys,bool * ok)911 int Compare(const StringPiece& a,
912 const StringPiece& b,
913 bool only_compare_index_keys,
914 bool* ok) {
915 StringPiece slice_a(a);
916 StringPiece slice_b(b);
917 KeyPrefix prefix_a;
918 KeyPrefix prefix_b;
919 bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
920 bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
921 DCHECK(ok_a);
922 DCHECK(ok_b);
923 if (!ok_a || !ok_b) {
924 *ok = false;
925 return 0;
926 }
927
928 *ok = true;
929 if (int x = prefix_a.Compare(prefix_b))
930 return x;
931
932 switch (prefix_a.type()) {
933 case KeyPrefix::GLOBAL_METADATA: {
934 DCHECK(!slice_a.empty());
935 DCHECK(!slice_b.empty());
936
937 unsigned char type_byte_a;
938 if (!DecodeByte(&slice_a, &type_byte_a)) {
939 *ok = false;
940 return 0;
941 }
942
943 unsigned char type_byte_b;
944 if (!DecodeByte(&slice_b, &type_byte_b)) {
945 *ok = false;
946 return 0;
947 }
948
949 if (int x = type_byte_a - type_byte_b)
950 return x;
951 if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte)
952 return 0;
953
954 // Compare<> is used (which re-decodes the prefix) rather than an
955 // specialized CompareSuffix<> because metadata is relatively uncommon
956 // in the database.
957
958 if (type_byte_a == kDatabaseFreeListTypeByte) {
959 // TODO(jsbell): No need to pass only_compare_index_keys through here.
960 return Compare<DatabaseFreeListKey>(a, b, only_compare_index_keys, ok);
961 }
962 if (type_byte_a == kDatabaseNameTypeByte) {
963 return Compare<DatabaseNameKey>(
964 a, b, /*only_compare_index_keys*/ false, ok);
965 }
966 break;
967 }
968
969 case KeyPrefix::DATABASE_METADATA: {
970 DCHECK(!slice_a.empty());
971 DCHECK(!slice_b.empty());
972
973 unsigned char type_byte_a;
974 if (!DecodeByte(&slice_a, &type_byte_a)) {
975 *ok = false;
976 return 0;
977 }
978
979 unsigned char type_byte_b;
980 if (!DecodeByte(&slice_b, &type_byte_b)) {
981 *ok = false;
982 return 0;
983 }
984
985 if (int x = type_byte_a - type_byte_b)
986 return x;
987 if (type_byte_a < DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE)
988 return 0;
989
990 // Compare<> is used (which re-decodes the prefix) rather than an
991 // specialized CompareSuffix<> because metadata is relatively uncommon
992 // in the database.
993
994 if (type_byte_a == kObjectStoreMetaDataTypeByte) {
995 // TODO(jsbell): No need to pass only_compare_index_keys through here.
996 return Compare<ObjectStoreMetaDataKey>(
997 a, b, only_compare_index_keys, ok);
998 }
999 if (type_byte_a == kIndexMetaDataTypeByte) {
1000 return Compare<IndexMetaDataKey>(
1001 a, b, /*only_compare_index_keys*/ false, ok);
1002 }
1003 if (type_byte_a == kObjectStoreFreeListTypeByte) {
1004 return Compare<ObjectStoreFreeListKey>(
1005 a, b, only_compare_index_keys, ok);
1006 }
1007 if (type_byte_a == kIndexFreeListTypeByte) {
1008 return Compare<IndexFreeListKey>(
1009 a, b, /*only_compare_index_keys*/ false, ok);
1010 }
1011 if (type_byte_a == kObjectStoreNamesTypeByte) {
1012 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1013 return Compare<ObjectStoreNamesKey>(
1014 a, b, only_compare_index_keys, ok);
1015 }
1016 if (type_byte_a == kIndexNamesKeyTypeByte) {
1017 return Compare<IndexNamesKey>(
1018 a, b, /*only_compare_index_keys*/ false, ok);
1019 }
1020 break;
1021 }
1022
1023 case KeyPrefix::OBJECT_STORE_DATA: {
1024 // Provide a stable ordering for invalid data.
1025 if (slice_a.empty() || slice_b.empty())
1026 return CompareSizes(slice_a.size(), slice_b.size());
1027
1028 return CompareSuffix<ObjectStoreDataKey>(
1029 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1030 }
1031
1032 case KeyPrefix::EXISTS_ENTRY: {
1033 // Provide a stable ordering for invalid data.
1034 if (slice_a.empty() || slice_b.empty())
1035 return CompareSizes(slice_a.size(), slice_b.size());
1036
1037 return CompareSuffix<ExistsEntryKey>(
1038 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1039 }
1040
1041 case KeyPrefix::INDEX_DATA: {
1042 // Provide a stable ordering for invalid data.
1043 if (slice_a.empty() || slice_b.empty())
1044 return CompareSizes(slice_a.size(), slice_b.size());
1045
1046 return CompareSuffix<IndexDataKey>(
1047 &slice_a, &slice_b, only_compare_index_keys, ok);
1048 }
1049
1050 case KeyPrefix::INVALID_TYPE:
1051 break;
1052 }
1053
1054 NOTREACHED();
1055 *ok = false;
1056 return 0;
1057 }
1058
1059 } // namespace
1060
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys)1061 int Compare(const StringPiece& a,
1062 const StringPiece& b,
1063 bool only_compare_index_keys) {
1064 bool ok;
1065 int result = Compare(a, b, only_compare_index_keys, &ok);
1066 DCHECK(ok);
1067 if (!ok)
1068 return 0;
1069 return result;
1070 }
1071
KeyPrefix()1072 KeyPrefix::KeyPrefix()
1073 : database_id_(INVALID_TYPE),
1074 object_store_id_(INVALID_TYPE),
1075 index_id_(INVALID_TYPE) {}
1076
KeyPrefix(int64 database_id)1077 KeyPrefix::KeyPrefix(int64 database_id)
1078 : database_id_(database_id), object_store_id_(0), index_id_(0) {
1079 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1080 }
1081
KeyPrefix(int64 database_id,int64 object_store_id)1082 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id)
1083 : database_id_(database_id),
1084 object_store_id_(object_store_id),
1085 index_id_(0) {
1086 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1087 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1088 }
1089
KeyPrefix(int64 database_id,int64 object_store_id,int64 index_id)1090 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id)
1091 : database_id_(database_id),
1092 object_store_id_(object_store_id),
1093 index_id_(index_id) {
1094 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1095 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1096 DCHECK(KeyPrefix::IsValidIndexId(index_id));
1097 }
1098
KeyPrefix(enum Type type,int64 database_id,int64 object_store_id,int64 index_id)1099 KeyPrefix::KeyPrefix(enum Type type,
1100 int64 database_id,
1101 int64 object_store_id,
1102 int64 index_id)
1103 : database_id_(database_id),
1104 object_store_id_(object_store_id),
1105 index_id_(index_id) {
1106 DCHECK_EQ(type, INVALID_TYPE);
1107 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1108 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1109 }
1110
CreateWithSpecialIndex(int64 database_id,int64 object_store_id,int64 index_id)1111 KeyPrefix KeyPrefix::CreateWithSpecialIndex(int64 database_id,
1112 int64 object_store_id,
1113 int64 index_id) {
1114 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1115 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1116 DCHECK(index_id);
1117 return KeyPrefix(INVALID_TYPE, database_id, object_store_id, index_id);
1118 }
1119
IsValidDatabaseId(int64 database_id)1120 bool KeyPrefix::IsValidDatabaseId(int64 database_id) {
1121 return (database_id > 0) && (database_id < KeyPrefix::kMaxDatabaseId);
1122 }
1123
IsValidObjectStoreId(int64 object_store_id)1124 bool KeyPrefix::IsValidObjectStoreId(int64 object_store_id) {
1125 return (object_store_id > 0) &&
1126 (object_store_id < KeyPrefix::kMaxObjectStoreId);
1127 }
1128
IsValidIndexId(int64 index_id)1129 bool KeyPrefix::IsValidIndexId(int64 index_id) {
1130 return (index_id >= kMinimumIndexId) && (index_id < KeyPrefix::kMaxIndexId);
1131 }
1132
Decode(StringPiece * slice,KeyPrefix * result)1133 bool KeyPrefix::Decode(StringPiece* slice, KeyPrefix* result) {
1134 unsigned char first_byte;
1135 if (!DecodeByte(slice, &first_byte))
1136 return false;
1137
1138 size_t database_id_bytes = ((first_byte >> 5) & 0x7) + 1;
1139 size_t object_store_id_bytes = ((first_byte >> 2) & 0x7) + 1;
1140 size_t index_id_bytes = (first_byte & 0x3) + 1;
1141
1142 if (database_id_bytes + object_store_id_bytes + index_id_bytes >
1143 slice->size())
1144 return false;
1145
1146 {
1147 StringPiece tmp(slice->begin(), database_id_bytes);
1148 if (!DecodeInt(&tmp, &result->database_id_))
1149 return false;
1150 }
1151 slice->remove_prefix(database_id_bytes);
1152 {
1153 StringPiece tmp(slice->begin(), object_store_id_bytes);
1154 if (!DecodeInt(&tmp, &result->object_store_id_))
1155 return false;
1156 }
1157 slice->remove_prefix(object_store_id_bytes);
1158 {
1159 StringPiece tmp(slice->begin(), index_id_bytes);
1160 if (!DecodeInt(&tmp, &result->index_id_))
1161 return false;
1162 }
1163 slice->remove_prefix(index_id_bytes);
1164 return true;
1165 }
1166
EncodeEmpty()1167 std::string KeyPrefix::EncodeEmpty() {
1168 const std::string result(4, 0);
1169 DCHECK(EncodeInternal(0, 0, 0) == std::string(4, 0));
1170 return result;
1171 }
1172
Encode() const1173 std::string KeyPrefix::Encode() const {
1174 DCHECK(database_id_ != kInvalidId);
1175 DCHECK(object_store_id_ != kInvalidId);
1176 DCHECK(index_id_ != kInvalidId);
1177 return EncodeInternal(database_id_, object_store_id_, index_id_);
1178 }
1179
EncodeInternal(int64 database_id,int64 object_store_id,int64 index_id)1180 std::string KeyPrefix::EncodeInternal(int64 database_id,
1181 int64 object_store_id,
1182 int64 index_id) {
1183 std::string database_id_string;
1184 std::string object_store_id_string;
1185 std::string index_id_string;
1186
1187 EncodeIntSafely(database_id, kMaxDatabaseId, &database_id_string);
1188 EncodeIntSafely(object_store_id, kMaxObjectStoreId, &object_store_id_string);
1189 EncodeIntSafely(index_id, kMaxIndexId, &index_id_string);
1190
1191 DCHECK(database_id_string.size() <= kMaxDatabaseIdSizeBytes);
1192 DCHECK(object_store_id_string.size() <= kMaxObjectStoreIdSizeBytes);
1193 DCHECK(index_id_string.size() <= kMaxIndexIdSizeBytes);
1194
1195 unsigned char first_byte =
1196 (database_id_string.size() - 1) << (kMaxObjectStoreIdSizeBits +
1197 kMaxIndexIdSizeBits) |
1198 (object_store_id_string.size() - 1) << kMaxIndexIdSizeBits |
1199 (index_id_string.size() - 1);
1200 COMPILE_ASSERT(kMaxDatabaseIdSizeBits + kMaxObjectStoreIdSizeBits +
1201 kMaxIndexIdSizeBits ==
1202 sizeof(first_byte) * 8,
1203 CANT_ENCODE_IDS);
1204 std::string ret;
1205 ret.reserve(kDefaultInlineBufferSize);
1206 ret.push_back(first_byte);
1207 ret.append(database_id_string);
1208 ret.append(object_store_id_string);
1209 ret.append(index_id_string);
1210
1211 DCHECK_LE(ret.size(), kDefaultInlineBufferSize);
1212 return ret;
1213 }
1214
Compare(const KeyPrefix & other) const1215 int KeyPrefix::Compare(const KeyPrefix& other) const {
1216 DCHECK(database_id_ != kInvalidId);
1217 DCHECK(object_store_id_ != kInvalidId);
1218 DCHECK(index_id_ != kInvalidId);
1219
1220 if (database_id_ != other.database_id_)
1221 return CompareInts(database_id_, other.database_id_);
1222 if (object_store_id_ != other.object_store_id_)
1223 return CompareInts(object_store_id_, other.object_store_id_);
1224 if (index_id_ != other.index_id_)
1225 return CompareInts(index_id_, other.index_id_);
1226 return 0;
1227 }
1228
type() const1229 KeyPrefix::Type KeyPrefix::type() const {
1230 DCHECK(database_id_ != kInvalidId);
1231 DCHECK(object_store_id_ != kInvalidId);
1232 DCHECK(index_id_ != kInvalidId);
1233
1234 if (!database_id_)
1235 return GLOBAL_METADATA;
1236 if (!object_store_id_)
1237 return DATABASE_METADATA;
1238 if (index_id_ == kObjectStoreDataIndexId)
1239 return OBJECT_STORE_DATA;
1240 if (index_id_ == kExistsEntryIndexId)
1241 return EXISTS_ENTRY;
1242 if (index_id_ >= kMinimumIndexId)
1243 return INDEX_DATA;
1244
1245 NOTREACHED();
1246 return INVALID_TYPE;
1247 }
1248
Encode()1249 std::string SchemaVersionKey::Encode() {
1250 std::string ret = KeyPrefix::EncodeEmpty();
1251 ret.push_back(kSchemaVersionTypeByte);
1252 return ret;
1253 }
1254
Encode()1255 std::string MaxDatabaseIdKey::Encode() {
1256 std::string ret = KeyPrefix::EncodeEmpty();
1257 ret.push_back(kMaxDatabaseIdTypeByte);
1258 return ret;
1259 }
1260
Encode()1261 std::string DataVersionKey::Encode() {
1262 std::string ret = KeyPrefix::EncodeEmpty();
1263 ret.push_back(kDataVersionTypeByte);
1264 return ret;
1265 }
1266
DatabaseFreeListKey()1267 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {}
1268
Decode(StringPiece * slice,DatabaseFreeListKey * result)1269 bool DatabaseFreeListKey::Decode(StringPiece* slice,
1270 DatabaseFreeListKey* result) {
1271 KeyPrefix prefix;
1272 if (!KeyPrefix::Decode(slice, &prefix))
1273 return false;
1274 DCHECK(!prefix.database_id_);
1275 DCHECK(!prefix.object_store_id_);
1276 DCHECK(!prefix.index_id_);
1277 unsigned char type_byte = 0;
1278 if (!DecodeByte(slice, &type_byte))
1279 return false;
1280 DCHECK_EQ(type_byte, kDatabaseFreeListTypeByte);
1281 if (!DecodeVarInt(slice, &result->database_id_))
1282 return false;
1283 return true;
1284 }
1285
Encode(int64 database_id)1286 std::string DatabaseFreeListKey::Encode(int64 database_id) {
1287 std::string ret = KeyPrefix::EncodeEmpty();
1288 ret.push_back(kDatabaseFreeListTypeByte);
1289 EncodeVarInt(database_id, &ret);
1290 return ret;
1291 }
1292
EncodeMaxKey()1293 std::string DatabaseFreeListKey::EncodeMaxKey() {
1294 return Encode(std::numeric_limits<int64>::max());
1295 }
1296
DatabaseId() const1297 int64 DatabaseFreeListKey::DatabaseId() const {
1298 DCHECK_GE(database_id_, 0);
1299 return database_id_;
1300 }
1301
Compare(const DatabaseFreeListKey & other) const1302 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey& other) const {
1303 DCHECK_GE(database_id_, 0);
1304 return CompareInts(database_id_, other.database_id_);
1305 }
1306
Decode(StringPiece * slice,DatabaseNameKey * result)1307 bool DatabaseNameKey::Decode(StringPiece* slice, DatabaseNameKey* result) {
1308 KeyPrefix prefix;
1309 if (!KeyPrefix::Decode(slice, &prefix))
1310 return false;
1311 DCHECK(!prefix.database_id_);
1312 DCHECK(!prefix.object_store_id_);
1313 DCHECK(!prefix.index_id_);
1314 unsigned char type_byte = 0;
1315 if (!DecodeByte(slice, &type_byte))
1316 return false;
1317 DCHECK_EQ(type_byte, kDatabaseNameTypeByte);
1318 if (!DecodeStringWithLength(slice, &result->origin_))
1319 return false;
1320 if (!DecodeStringWithLength(slice, &result->database_name_))
1321 return false;
1322 return true;
1323 }
1324
Encode(const std::string & origin_identifier,const base::string16 & database_name)1325 std::string DatabaseNameKey::Encode(const std::string& origin_identifier,
1326 const base::string16& database_name) {
1327 std::string ret = KeyPrefix::EncodeEmpty();
1328 ret.push_back(kDatabaseNameTypeByte);
1329 EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier), &ret);
1330 EncodeStringWithLength(database_name, &ret);
1331 return ret;
1332 }
1333
EncodeMinKeyForOrigin(const std::string & origin_identifier)1334 std::string DatabaseNameKey::EncodeMinKeyForOrigin(
1335 const std::string& origin_identifier) {
1336 return Encode(origin_identifier, base::string16());
1337 }
1338
EncodeStopKeyForOrigin(const std::string & origin_identifier)1339 std::string DatabaseNameKey::EncodeStopKeyForOrigin(
1340 const std::string& origin_identifier) {
1341 // just after origin in collation order
1342 return EncodeMinKeyForOrigin(origin_identifier + '\x01');
1343 }
1344
Compare(const DatabaseNameKey & other)1345 int DatabaseNameKey::Compare(const DatabaseNameKey& other) {
1346 if (int x = origin_.compare(other.origin_))
1347 return x;
1348 return database_name_.compare(other.database_name_);
1349 }
1350
Encode(int64 database_id,MetaDataType meta_data_type)1351 std::string DatabaseMetaDataKey::Encode(int64 database_id,
1352 MetaDataType meta_data_type) {
1353 KeyPrefix prefix(database_id);
1354 std::string ret = prefix.Encode();
1355 ret.push_back(meta_data_type);
1356 return ret;
1357 }
1358
ObjectStoreMetaDataKey()1359 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
1360 : object_store_id_(-1), meta_data_type_(-1) {}
1361
Decode(StringPiece * slice,ObjectStoreMetaDataKey * result)1362 bool ObjectStoreMetaDataKey::Decode(StringPiece* slice,
1363 ObjectStoreMetaDataKey* result) {
1364 KeyPrefix prefix;
1365 if (!KeyPrefix::Decode(slice, &prefix))
1366 return false;
1367 DCHECK(prefix.database_id_);
1368 DCHECK(!prefix.object_store_id_);
1369 DCHECK(!prefix.index_id_);
1370 unsigned char type_byte = 0;
1371 if (!DecodeByte(slice, &type_byte))
1372 return false;
1373 DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte);
1374 if (!DecodeVarInt(slice, &result->object_store_id_))
1375 return false;
1376 DCHECK(result->object_store_id_);
1377 if (!DecodeByte(slice, &result->meta_data_type_))
1378 return false;
1379 return true;
1380 }
1381
Encode(int64 database_id,int64 object_store_id,unsigned char meta_data_type)1382 std::string ObjectStoreMetaDataKey::Encode(int64 database_id,
1383 int64 object_store_id,
1384 unsigned char meta_data_type) {
1385 KeyPrefix prefix(database_id);
1386 std::string ret = prefix.Encode();
1387 ret.push_back(kObjectStoreMetaDataTypeByte);
1388 EncodeVarInt(object_store_id, &ret);
1389 ret.push_back(meta_data_type);
1390 return ret;
1391 }
1392
EncodeMaxKey(int64 database_id)1393 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id) {
1394 return Encode(database_id,
1395 std::numeric_limits<int64>::max(),
1396 kObjectMetaDataTypeMaximum);
1397 }
1398
EncodeMaxKey(int64 database_id,int64 object_store_id)1399 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id,
1400 int64 object_store_id) {
1401 return Encode(database_id, object_store_id, kObjectMetaDataTypeMaximum);
1402 }
1403
ObjectStoreId() const1404 int64 ObjectStoreMetaDataKey::ObjectStoreId() const {
1405 DCHECK_GE(object_store_id_, 0);
1406 return object_store_id_;
1407 }
MetaDataType() const1408 unsigned char ObjectStoreMetaDataKey::MetaDataType() const {
1409 return meta_data_type_;
1410 }
1411
Compare(const ObjectStoreMetaDataKey & other)1412 int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey& other) {
1413 DCHECK_GE(object_store_id_, 0);
1414 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1415 return x;
1416 return meta_data_type_ - other.meta_data_type_;
1417 }
1418
IndexMetaDataKey()1419 IndexMetaDataKey::IndexMetaDataKey()
1420 : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {}
1421
Decode(StringPiece * slice,IndexMetaDataKey * result)1422 bool IndexMetaDataKey::Decode(StringPiece* slice, IndexMetaDataKey* result) {
1423 KeyPrefix prefix;
1424 if (!KeyPrefix::Decode(slice, &prefix))
1425 return false;
1426 DCHECK(prefix.database_id_);
1427 DCHECK(!prefix.object_store_id_);
1428 DCHECK(!prefix.index_id_);
1429 unsigned char type_byte = 0;
1430 if (!DecodeByte(slice, &type_byte))
1431 return false;
1432 DCHECK_EQ(type_byte, kIndexMetaDataTypeByte);
1433 if (!DecodeVarInt(slice, &result->object_store_id_))
1434 return false;
1435 if (!DecodeVarInt(slice, &result->index_id_))
1436 return false;
1437 if (!DecodeByte(slice, &result->meta_data_type_))
1438 return false;
1439 return true;
1440 }
1441
Encode(int64 database_id,int64 object_store_id,int64 index_id,unsigned char meta_data_type)1442 std::string IndexMetaDataKey::Encode(int64 database_id,
1443 int64 object_store_id,
1444 int64 index_id,
1445 unsigned char meta_data_type) {
1446 KeyPrefix prefix(database_id);
1447 std::string ret = prefix.Encode();
1448 ret.push_back(kIndexMetaDataTypeByte);
1449 EncodeVarInt(object_store_id, &ret);
1450 EncodeVarInt(index_id, &ret);
1451 EncodeByte(meta_data_type, &ret);
1452 return ret;
1453 }
1454
EncodeMaxKey(int64 database_id,int64 object_store_id)1455 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1456 int64 object_store_id) {
1457 return Encode(database_id,
1458 object_store_id,
1459 std::numeric_limits<int64>::max(),
1460 kIndexMetaDataTypeMaximum);
1461 }
1462
EncodeMaxKey(int64 database_id,int64 object_store_id,int64 index_id)1463 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1464 int64 object_store_id,
1465 int64 index_id) {
1466 return Encode(
1467 database_id, object_store_id, index_id, kIndexMetaDataTypeMaximum);
1468 }
1469
Compare(const IndexMetaDataKey & other)1470 int IndexMetaDataKey::Compare(const IndexMetaDataKey& other) {
1471 DCHECK_GE(object_store_id_, 0);
1472 DCHECK_GE(index_id_, 0);
1473
1474 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1475 return x;
1476 if (int x = CompareInts(index_id_, other.index_id_))
1477 return x;
1478 return meta_data_type_ - other.meta_data_type_;
1479 }
1480
IndexId() const1481 int64 IndexMetaDataKey::IndexId() const {
1482 DCHECK_GE(index_id_, 0);
1483 return index_id_;
1484 }
1485
ObjectStoreFreeListKey()1486 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {}
1487
Decode(StringPiece * slice,ObjectStoreFreeListKey * result)1488 bool ObjectStoreFreeListKey::Decode(StringPiece* slice,
1489 ObjectStoreFreeListKey* result) {
1490 KeyPrefix prefix;
1491 if (!KeyPrefix::Decode(slice, &prefix))
1492 return false;
1493 DCHECK(prefix.database_id_);
1494 DCHECK(!prefix.object_store_id_);
1495 DCHECK(!prefix.index_id_);
1496 unsigned char type_byte = 0;
1497 if (!DecodeByte(slice, &type_byte))
1498 return false;
1499 DCHECK_EQ(type_byte, kObjectStoreFreeListTypeByte);
1500 if (!DecodeVarInt(slice, &result->object_store_id_))
1501 return false;
1502 return true;
1503 }
1504
Encode(int64 database_id,int64 object_store_id)1505 std::string ObjectStoreFreeListKey::Encode(int64 database_id,
1506 int64 object_store_id) {
1507 KeyPrefix prefix(database_id);
1508 std::string ret = prefix.Encode();
1509 ret.push_back(kObjectStoreFreeListTypeByte);
1510 EncodeVarInt(object_store_id, &ret);
1511 return ret;
1512 }
1513
EncodeMaxKey(int64 database_id)1514 std::string ObjectStoreFreeListKey::EncodeMaxKey(int64 database_id) {
1515 return Encode(database_id, std::numeric_limits<int64>::max());
1516 }
1517
ObjectStoreId() const1518 int64 ObjectStoreFreeListKey::ObjectStoreId() const {
1519 DCHECK_GE(object_store_id_, 0);
1520 return object_store_id_;
1521 }
1522
Compare(const ObjectStoreFreeListKey & other)1523 int ObjectStoreFreeListKey::Compare(const ObjectStoreFreeListKey& other) {
1524 // TODO(jsbell): It may seem strange that we're not comparing database id's,
1525 // but that comparison will have been made earlier.
1526 // We should probably make this more clear, though...
1527 DCHECK_GE(object_store_id_, 0);
1528 return CompareInts(object_store_id_, other.object_store_id_);
1529 }
1530
IndexFreeListKey()1531 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {}
1532
Decode(StringPiece * slice,IndexFreeListKey * result)1533 bool IndexFreeListKey::Decode(StringPiece* slice, IndexFreeListKey* result) {
1534 KeyPrefix prefix;
1535 if (!KeyPrefix::Decode(slice, &prefix))
1536 return false;
1537 DCHECK(prefix.database_id_);
1538 DCHECK(!prefix.object_store_id_);
1539 DCHECK(!prefix.index_id_);
1540 unsigned char type_byte = 0;
1541 if (!DecodeByte(slice, &type_byte))
1542 return false;
1543 DCHECK_EQ(type_byte, kIndexFreeListTypeByte);
1544 if (!DecodeVarInt(slice, &result->object_store_id_))
1545 return false;
1546 if (!DecodeVarInt(slice, &result->index_id_))
1547 return false;
1548 return true;
1549 }
1550
Encode(int64 database_id,int64 object_store_id,int64 index_id)1551 std::string IndexFreeListKey::Encode(int64 database_id,
1552 int64 object_store_id,
1553 int64 index_id) {
1554 KeyPrefix prefix(database_id);
1555 std::string ret = prefix.Encode();
1556 ret.push_back(kIndexFreeListTypeByte);
1557 EncodeVarInt(object_store_id, &ret);
1558 EncodeVarInt(index_id, &ret);
1559 return ret;
1560 }
1561
EncodeMaxKey(int64 database_id,int64 object_store_id)1562 std::string IndexFreeListKey::EncodeMaxKey(int64 database_id,
1563 int64 object_store_id) {
1564 return Encode(
1565 database_id, object_store_id, std::numeric_limits<int64>::max());
1566 }
1567
Compare(const IndexFreeListKey & other)1568 int IndexFreeListKey::Compare(const IndexFreeListKey& other) {
1569 DCHECK_GE(object_store_id_, 0);
1570 DCHECK_GE(index_id_, 0);
1571 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1572 return x;
1573 return CompareInts(index_id_, other.index_id_);
1574 }
1575
ObjectStoreId() const1576 int64 IndexFreeListKey::ObjectStoreId() const {
1577 DCHECK_GE(object_store_id_, 0);
1578 return object_store_id_;
1579 }
1580
IndexId() const1581 int64 IndexFreeListKey::IndexId() const {
1582 DCHECK_GE(index_id_, 0);
1583 return index_id_;
1584 }
1585
1586 // TODO(jsbell): We never use this to look up object store ids,
1587 // because a mapping is kept in the IndexedDBDatabase. Can the
1588 // mapping become unreliable? Can we remove this?
Decode(StringPiece * slice,ObjectStoreNamesKey * result)1589 bool ObjectStoreNamesKey::Decode(StringPiece* slice,
1590 ObjectStoreNamesKey* result) {
1591 KeyPrefix prefix;
1592 if (!KeyPrefix::Decode(slice, &prefix))
1593 return false;
1594 DCHECK(prefix.database_id_);
1595 DCHECK(!prefix.object_store_id_);
1596 DCHECK(!prefix.index_id_);
1597 unsigned char type_byte = 0;
1598 if (!DecodeByte(slice, &type_byte))
1599 return false;
1600 DCHECK_EQ(type_byte, kObjectStoreNamesTypeByte);
1601 if (!DecodeStringWithLength(slice, &result->object_store_name_))
1602 return false;
1603 return true;
1604 }
1605
Encode(int64 database_id,const base::string16 & object_store_name)1606 std::string ObjectStoreNamesKey::Encode(
1607 int64 database_id,
1608 const base::string16& object_store_name) {
1609 KeyPrefix prefix(database_id);
1610 std::string ret = prefix.Encode();
1611 ret.push_back(kObjectStoreNamesTypeByte);
1612 EncodeStringWithLength(object_store_name, &ret);
1613 return ret;
1614 }
1615
Compare(const ObjectStoreNamesKey & other)1616 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey& other) {
1617 return object_store_name_.compare(other.object_store_name_);
1618 }
1619
IndexNamesKey()1620 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {}
1621
1622 // TODO(jsbell): We never use this to look up index ids, because a mapping
1623 // is kept at a higher level.
Decode(StringPiece * slice,IndexNamesKey * result)1624 bool IndexNamesKey::Decode(StringPiece* slice, IndexNamesKey* result) {
1625 KeyPrefix prefix;
1626 if (!KeyPrefix::Decode(slice, &prefix))
1627 return false;
1628 DCHECK(prefix.database_id_);
1629 DCHECK(!prefix.object_store_id_);
1630 DCHECK(!prefix.index_id_);
1631 unsigned char type_byte = 0;
1632 if (!DecodeByte(slice, &type_byte))
1633 return false;
1634 DCHECK_EQ(type_byte, kIndexNamesKeyTypeByte);
1635 if (!DecodeVarInt(slice, &result->object_store_id_))
1636 return false;
1637 if (!DecodeStringWithLength(slice, &result->index_name_))
1638 return false;
1639 return true;
1640 }
1641
Encode(int64 database_id,int64 object_store_id,const base::string16 & index_name)1642 std::string IndexNamesKey::Encode(int64 database_id,
1643 int64 object_store_id,
1644 const base::string16& index_name) {
1645 KeyPrefix prefix(database_id);
1646 std::string ret = prefix.Encode();
1647 ret.push_back(kIndexNamesKeyTypeByte);
1648 EncodeVarInt(object_store_id, &ret);
1649 EncodeStringWithLength(index_name, &ret);
1650 return ret;
1651 }
1652
Compare(const IndexNamesKey & other)1653 int IndexNamesKey::Compare(const IndexNamesKey& other) {
1654 DCHECK_GE(object_store_id_, 0);
1655 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1656 return x;
1657 return index_name_.compare(other.index_name_);
1658 }
1659
ObjectStoreDataKey()1660 ObjectStoreDataKey::ObjectStoreDataKey() {}
~ObjectStoreDataKey()1661 ObjectStoreDataKey::~ObjectStoreDataKey() {}
1662
Decode(StringPiece * slice,ObjectStoreDataKey * result)1663 bool ObjectStoreDataKey::Decode(StringPiece* slice,
1664 ObjectStoreDataKey* result) {
1665 KeyPrefix prefix;
1666 if (!KeyPrefix::Decode(slice, &prefix))
1667 return false;
1668 DCHECK(prefix.database_id_);
1669 DCHECK(prefix.object_store_id_);
1670 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1671 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1672 return false;
1673 return true;
1674 }
1675
Encode(int64 database_id,int64 object_store_id,const std::string encoded_user_key)1676 std::string ObjectStoreDataKey::Encode(int64 database_id,
1677 int64 object_store_id,
1678 const std::string encoded_user_key) {
1679 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1680 database_id, object_store_id, kSpecialIndexNumber));
1681 std::string ret = prefix.Encode();
1682 ret.append(encoded_user_key);
1683
1684 return ret;
1685 }
1686
Encode(int64 database_id,int64 object_store_id,const IndexedDBKey & user_key)1687 std::string ObjectStoreDataKey::Encode(int64 database_id,
1688 int64 object_store_id,
1689 const IndexedDBKey& user_key) {
1690 std::string encoded_key;
1691 EncodeIDBKey(user_key, &encoded_key);
1692 return Encode(database_id, object_store_id, encoded_key);
1693 }
1694
user_key() const1695 scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const {
1696 scoped_ptr<IndexedDBKey> key;
1697 StringPiece slice(encoded_user_key_);
1698 if (!DecodeIDBKey(&slice, &key)) {
1699 // TODO(jsbell): Return error.
1700 }
1701 return key.Pass();
1702 }
1703
1704 const int64 ObjectStoreDataKey::kSpecialIndexNumber = kObjectStoreDataIndexId;
1705
ExistsEntryKey()1706 ExistsEntryKey::ExistsEntryKey() {}
~ExistsEntryKey()1707 ExistsEntryKey::~ExistsEntryKey() {}
1708
Decode(StringPiece * slice,ExistsEntryKey * result)1709 bool ExistsEntryKey::Decode(StringPiece* slice, ExistsEntryKey* result) {
1710 KeyPrefix prefix;
1711 if (!KeyPrefix::Decode(slice, &prefix))
1712 return false;
1713 DCHECK(prefix.database_id_);
1714 DCHECK(prefix.object_store_id_);
1715 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1716 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1717 return false;
1718 return true;
1719 }
1720
Encode(int64 database_id,int64 object_store_id,const std::string & encoded_key)1721 std::string ExistsEntryKey::Encode(int64 database_id,
1722 int64 object_store_id,
1723 const std::string& encoded_key) {
1724 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1725 database_id, object_store_id, kSpecialIndexNumber));
1726 std::string ret = prefix.Encode();
1727 ret.append(encoded_key);
1728 return ret;
1729 }
1730
Encode(int64 database_id,int64 object_store_id,const IndexedDBKey & user_key)1731 std::string ExistsEntryKey::Encode(int64 database_id,
1732 int64 object_store_id,
1733 const IndexedDBKey& user_key) {
1734 std::string encoded_key;
1735 EncodeIDBKey(user_key, &encoded_key);
1736 return Encode(database_id, object_store_id, encoded_key);
1737 }
1738
user_key() const1739 scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const {
1740 scoped_ptr<IndexedDBKey> key;
1741 StringPiece slice(encoded_user_key_);
1742 if (!DecodeIDBKey(&slice, &key)) {
1743 // TODO(jsbell): Return error.
1744 }
1745 return key.Pass();
1746 }
1747
1748 const int64 ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId;
1749
IndexDataKey()1750 IndexDataKey::IndexDataKey()
1751 : database_id_(-1),
1752 object_store_id_(-1),
1753 index_id_(-1),
1754 sequence_number_(-1) {}
1755
~IndexDataKey()1756 IndexDataKey::~IndexDataKey() {}
1757
Decode(StringPiece * slice,IndexDataKey * result)1758 bool IndexDataKey::Decode(StringPiece* slice, IndexDataKey* result) {
1759 KeyPrefix prefix;
1760 if (!KeyPrefix::Decode(slice, &prefix))
1761 return false;
1762 DCHECK(prefix.database_id_);
1763 DCHECK(prefix.object_store_id_);
1764 DCHECK_GE(prefix.index_id_, kMinimumIndexId);
1765 result->database_id_ = prefix.database_id_;
1766 result->object_store_id_ = prefix.object_store_id_;
1767 result->index_id_ = prefix.index_id_;
1768 result->sequence_number_ = -1;
1769 result->encoded_primary_key_ = MinIDBKey();
1770
1771 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1772 return false;
1773
1774 // [optional] sequence number
1775 if (slice->empty())
1776 return true;
1777 if (!DecodeVarInt(slice, &result->sequence_number_))
1778 return false;
1779
1780 // [optional] primary key
1781 if (slice->empty())
1782 return true;
1783 if (!ExtractEncodedIDBKey(slice, &result->encoded_primary_key_))
1784 return false;
1785 return true;
1786 }
1787
Encode(int64 database_id,int64 object_store_id,int64 index_id,const std::string & encoded_user_key,const std::string & encoded_primary_key,int64 sequence_number)1788 std::string IndexDataKey::Encode(int64 database_id,
1789 int64 object_store_id,
1790 int64 index_id,
1791 const std::string& encoded_user_key,
1792 const std::string& encoded_primary_key,
1793 int64 sequence_number) {
1794 KeyPrefix prefix(database_id, object_store_id, index_id);
1795 std::string ret = prefix.Encode();
1796 ret.append(encoded_user_key);
1797 EncodeVarInt(sequence_number, &ret);
1798 ret.append(encoded_primary_key);
1799 return ret;
1800 }
1801
Encode(int64 database_id,int64 object_store_id,int64 index_id,const IndexedDBKey & user_key)1802 std::string IndexDataKey::Encode(int64 database_id,
1803 int64 object_store_id,
1804 int64 index_id,
1805 const IndexedDBKey& user_key) {
1806 std::string encoded_key;
1807 EncodeIDBKey(user_key, &encoded_key);
1808 return Encode(
1809 database_id, object_store_id, index_id, encoded_key, MinIDBKey(), 0);
1810 }
1811
Encode(int64 database_id,int64 object_store_id,int64 index_id,const IndexedDBKey & user_key,const IndexedDBKey & user_primary_key)1812 std::string IndexDataKey::Encode(int64 database_id,
1813 int64 object_store_id,
1814 int64 index_id,
1815 const IndexedDBKey& user_key,
1816 const IndexedDBKey& user_primary_key) {
1817 std::string encoded_key;
1818 EncodeIDBKey(user_key, &encoded_key);
1819 std::string encoded_primary_key;
1820 EncodeIDBKey(user_primary_key, &encoded_primary_key);
1821 return Encode(database_id,
1822 object_store_id,
1823 index_id,
1824 encoded_key,
1825 encoded_primary_key,
1826 0);
1827 }
1828
EncodeMinKey(int64 database_id,int64 object_store_id,int64 index_id)1829 std::string IndexDataKey::EncodeMinKey(int64 database_id,
1830 int64 object_store_id,
1831 int64 index_id) {
1832 return Encode(
1833 database_id, object_store_id, index_id, MinIDBKey(), MinIDBKey(), 0);
1834 }
1835
EncodeMaxKey(int64 database_id,int64 object_store_id,int64 index_id)1836 std::string IndexDataKey::EncodeMaxKey(int64 database_id,
1837 int64 object_store_id,
1838 int64 index_id) {
1839 return Encode(database_id,
1840 object_store_id,
1841 index_id,
1842 MaxIDBKey(),
1843 MaxIDBKey(),
1844 std::numeric_limits<int64>::max());
1845 }
1846
DatabaseId() const1847 int64 IndexDataKey::DatabaseId() const {
1848 DCHECK_GE(database_id_, 0);
1849 return database_id_;
1850 }
1851
ObjectStoreId() const1852 int64 IndexDataKey::ObjectStoreId() const {
1853 DCHECK_GE(object_store_id_, 0);
1854 return object_store_id_;
1855 }
1856
IndexId() const1857 int64 IndexDataKey::IndexId() const {
1858 DCHECK_GE(index_id_, 0);
1859 return index_id_;
1860 }
1861
user_key() const1862 scoped_ptr<IndexedDBKey> IndexDataKey::user_key() const {
1863 scoped_ptr<IndexedDBKey> key;
1864 StringPiece slice(encoded_user_key_);
1865 if (!DecodeIDBKey(&slice, &key)) {
1866 // TODO(jsbell): Return error.
1867 }
1868 return key.Pass();
1869 }
1870
primary_key() const1871 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const {
1872 scoped_ptr<IndexedDBKey> key;
1873 StringPiece slice(encoded_primary_key_);
1874 if (!DecodeIDBKey(&slice, &key)) {
1875 // TODO(jsbell): Return error.
1876 }
1877 return key.Pass();
1878 }
1879
1880 } // namespace content
1881