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, 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 [DatabaseNameKey]
58 //
59 //
60 // Database metadata: [DatabaseMetaDataKey]
61 // ----------------------------------------
62 // The prefix is <database id, 0, 0> followed by a metadata type byte:
63 //
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
70 //
71 //
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.
76 //
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
85 //
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.
89 //
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.
97 //
98 //
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.
104 //
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
109 //
110 //
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.
116 //
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]
126 //
127 //
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.
132 //
133 // <database id, object store id, 1, user key>
134 // => "version", serialized script value
135 //
136 //
137 // "Exists" entry: [ExistsEntryKey]
138 // --------------------------------
139 // The prefix is followed by a type byte and the encoded IDB primary key.
140 //
141 // <database id, object store id, 2, user key> => "version"
142 //
143 //
144 // Blob entry table: [BlobEntryKey]
145 // --------------------------------
146 //
147 // The prefix is followed by a type byte and the encoded IDB primary key.
148 //
149 // <database id, object store id, 3, user key> => array of IndexedDBBlobInfo
150 //
151 //
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.
156 //
157 // <database id, object store id, index id, index key, sequence number,
158 // primary key> => "version", primary key [IndexDataKey]
159 //
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.
163
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;
178
179 namespace content {
180
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;
185
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;
193
194 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
195 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
196
197 static const unsigned char kObjectStoreDataIndexId = 1;
198 static const unsigned char kExistsEntryIndexId = 2;
199 static const unsigned char kBlobEntryIndexId = 3;
200
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;
210
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;
217
218 static const unsigned char kObjectMetaDataTypeMaximum = 255;
219 static const unsigned char kIndexMetaDataTypeMaximum = 255;
220
221 const unsigned char kMinimumIndexId = 30;
222
EncodeIntSafely(int64 nParam,int64 max,std::string * into)223 inline void EncodeIntSafely(int64 nParam, int64 max, std::string* into) {
224 DCHECK_LE(nParam, max);
225 return EncodeInt(nParam, into);
226 }
227
MaxIDBKey()228 std::string MaxIDBKey() {
229 std::string ret;
230 EncodeByte(kIndexedDBKeyNullTypeByte, &ret);
231 return ret;
232 }
233
MinIDBKey()234 std::string MinIDBKey() {
235 std::string ret;
236 EncodeByte(kIndexedDBKeyMinKeyTypeByte, &ret);
237 return ret;
238 }
239
EncodeByte(unsigned char value,std::string * into)240 void EncodeByte(unsigned char value, std::string* into) {
241 into->push_back(value);
242 }
243
EncodeBool(bool value,std::string * into)244 void EncodeBool(bool value, std::string* into) {
245 into->push_back(value ? 1 : 0);
246 }
247
EncodeInt(int64 value,std::string * into)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);
254
255 do {
256 unsigned char c = n;
257 into->push_back(c);
258 n >>= 8;
259 } while (n);
260 }
261
EncodeVarInt(int64 value,std::string * into)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);
268
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);
276 }
277
EncodeString(const base::string16 & value,std::string * into)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));
285
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++);
291 }
292
EncodeBinary(const std::string & value,std::string * into)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());
297 }
298
EncodeStringWithLength(const base::string16 & value,std::string * into)299 void EncodeStringWithLength(const base::string16& value, std::string* into) {
300 EncodeVarInt(value.length(), into);
301 EncodeString(value, into);
302 }
303
EncodeDouble(double value,std::string * 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));
308 }
309
EncodeIDBKey(const IndexedDBKey & value,std::string * into)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;
322 }
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;
350 }
351 }
352
EncodeIDBKeyPath(const IndexedDBKeyPath & value,std::string * into)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;
366 }
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);
373 }
374 break;
375 }
376 }
377 }
378
EncodeBlobJournal(const BlobJournalType & journal,std::string * into)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);
384 }
385 }
386
DecodeByte(StringPiece * slice,unsigned char * value)387 bool DecodeByte(StringPiece* slice, unsigned char* value) {
388 if (slice->empty())
389 return false;
390
391 *value = (*slice)[0];
392 slice->remove_prefix(1);
393 return true;
394 }
395
DecodeBool(StringPiece * slice,bool * value)396 bool DecodeBool(StringPiece* slice, bool* value) {
397 if (slice->empty())
398 return false;
399
400 *value = !!(*slice)[0];
401 slice->remove_prefix(1);
402 return true;
403 }
404
DecodeInt(StringPiece * slice,int64 * value)405 bool DecodeInt(StringPiece* slice, int64* value) {
406 if (slice->empty())
407 return false;
408
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;
416 }
417 *value = ret;
418 slice->remove_prefix(it - slice->begin());
419 return true;
420 }
421
DecodeVarInt(StringPiece * slice,int64 * value)422 bool DecodeVarInt(StringPiece* slice, int64* value) {
423 if (slice->empty())
424 return false;
425
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;
432
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;
440 }
441
DecodeString(StringPiece * slice,base::string16 * value)442 bool DecodeString(StringPiece* slice, base::string16* value) {
443 if (slice->empty()) {
444 value->clear();
445 return true;
446 }
447
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++));
457
458 *value = decoded;
459 slice->remove_prefix(length * sizeof(base::char16));
460 return true;
461 }
462
DecodeStringWithLength(StringPiece * slice,base::string16 * value)463 bool DecodeStringWithLength(StringPiece* slice, base::string16* 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 bytes = length * sizeof(base::char16);
471 if (slice->size() < bytes)
472 return false;
473
474 StringPiece subpiece(slice->begin(), bytes);
475 slice->remove_prefix(bytes);
476 if (!DecodeString(&subpiece, value))
477 return false;
478
479 return true;
480 }
481
DecodeBinary(StringPiece * slice,std::string * value)482 bool DecodeBinary(StringPiece* slice, std::string* value) {
483 if (slice->empty())
484 return false;
485
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;
492
493 value->assign(slice->begin(), size);
494 slice->remove_prefix(size);
495 return true;
496 }
497
DecodeIDBKey(StringPiece * slice,scoped_ptr<IndexedDBKey> * value)498 bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
499 if (slice->empty())
500 return false;
501
502 unsigned char type = (*slice)[0];
503 slice->remove_prefix(1);
504
505 switch (type) {
506 case kIndexedDBKeyNullTypeByte:
507 *value = make_scoped_ptr(new IndexedDBKey());
508 return true;
509
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);
520 }
521 *value = make_scoped_ptr(new IndexedDBKey(array));
522 return true;
523 }
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;
530 }
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;
537 }
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;
544 }
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;
551 }
552 }
553
554 NOTREACHED();
555 return false;
556 }
557
DecodeDouble(StringPiece * slice,double * value)558 bool DecodeDouble(StringPiece* slice, double* value) {
559 if (slice->size() < sizeof(*value))
560 return false;
561
562 memcpy(value, slice->begin(), sizeof(*value));
563 slice->remove_prefix(sizeof(*value));
564 return true;
565 }
566
DecodeIDBKeyPath(StringPiece * slice,IndexedDBKeyPath * value)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;
578 }
579
580 slice->remove_prefix(2);
581 DCHECK(!slice->empty());
582 WebIDBKeyPathType type = static_cast<WebIDBKeyPathType>((*slice)[0]);
583 slice->remove_prefix(1);
584
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;
597 }
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);
609 }
610 DCHECK(slice->empty());
611 *value = IndexedDBKeyPath(array);
612 return true;
613 }
614 }
615 NOTREACHED();
616 return false;
617 }
618
DecodeBlobJournal(StringPiece * slice,BlobJournalType * journal)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;
633 }
634 output.push_back(std::make_pair(database_id, blob_key));
635 }
636 journal->swap(output);
637 return true;
638 }
639
ConsumeEncodedIDBKey(StringPiece * slice)640 bool ConsumeEncodedIDBKey(StringPiece* slice) {
641 unsigned char type = (*slice)[0];
642 slice->remove_prefix(1);
643
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;
655 }
656 return true;
657 }
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;
666 }
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;
675 }
676 case kIndexedDBKeyDateTypeByte:
677 case kIndexedDBKeyNumberTypeByte:
678 if (slice->size() < sizeof(double))
679 return false;
680 slice->remove_prefix(sizeof(double));
681 return true;
682 }
683 NOTREACHED();
684 return false;
685 }
686
ExtractEncodedIDBKey(StringPiece * slice,std::string * result)687 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) {
688 const char* start = slice->begin();
689 if (!ConsumeEncodedIDBKey(slice))
690 return false;
691
692 if (result)
693 result->assign(start, slice->begin());
694 return true;
695 }
696
KeyTypeByteToKeyType(unsigned char type)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;
713 }
714
715 NOTREACHED();
716 return WebIDBKeyTypeInvalid;
717 }
718
CompareEncodedStringsWithLength(StringPiece * slice1,StringPiece * slice2,bool * ok)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;
726 }
727 DCHECK_GE(len1, 0);
728 DCHECK_GE(len2, 0);
729 if (len1 < 0 || len2 < 0) {
730 *ok = false;
731 return 0;
732 }
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;
739 }
740
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));
746
747 *ok = true;
748 // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
749 return string1.compare(string2);
750 }
751
CompareEncodedBinary(StringPiece * slice1,StringPiece * slice2,bool * ok)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;
759 }
760 DCHECK_GE(len1, 0);
761 DCHECK_GE(len2, 0);
762 if (len1 < 0 || len2 < 0) {
763 *ok = false;
764 return 0;
765 }
766 size_t size1 = len1;
767 size_t size2 = len2;
768
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;
774 }
775
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);
781
782 *ok = true;
783 // This is the same as a memcmp()
784 return binary1.compare(binary2);
785 }
786
CompareInts(int64 a,int64 b)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;
799 }
800
CompareSizes(size_t a,size_t b)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;
807 }
808
CompareTypes(WebIDBKeyType a,WebIDBKeyType b)809 static int CompareTypes(WebIDBKeyType a, WebIDBKeyType b) { return b - a; }
810
CompareEncodedIDBKeys(StringPiece * slice_a,StringPiece * slice_b,bool * ok)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);
821
822 if (int x = CompareTypes(KeyTypeByteToKeyType(type_a),
823 KeyTypeByteToKeyType(type_b)))
824 return x;
825
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;
837 }
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;
842 }
843 return length_a - length_b;
844 }
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;
855 }
856 if (d < e)
857 return -1;
858 if (d > e)
859 return 1;
860 return 0;
861 }
862 }
863
864 NOTREACHED();
865 return 0;
866 }
867
868 namespace {
869
870 template <typename KeyType>
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys,bool * ok)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;
877
878 StringPiece slice_a(a);
879 if (!KeyType::Decode(&slice_a, &key_a)) {
880 *ok = false;
881 return 0;
882 }
883 StringPiece slice_b(b);
884 if (!KeyType::Decode(&slice_b, &key_b)) {
885 *ok = false;
886 return 0;
887 }
888
889 *ok = true;
890 return key_a.Compare(key_b);
891 }
892
893 template <typename KeyType>
CompareSuffix(StringPiece * a,StringPiece * b,bool only_compare_index_keys,bool * ok)894 int CompareSuffix(StringPiece* a,
895 StringPiece* b,
896 bool only_compare_index_keys,
897 bool* ok) {
898 NOTREACHED();
899 return 0;
900 }
901
902 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)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);
910 }
911
912 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)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);
918 }
919
920 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)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);
926 }
927
928 template <>
CompareSuffix(StringPiece * slice_a,StringPiece * slice_b,bool only_compare_index_keys,bool * ok)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;
939
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;
947
948 if (slice_a->empty() || slice_b->empty())
949 return CompareSizes(slice_a->size(), slice_b->size());
950
951 // primary key [optional]
952 result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
953 if (!*ok || result)
954 return result;
955
956 return CompareInts(sequence_number_a, sequence_number_b);
957 }
958
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys,bool * ok)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;
974 }
975
976 *ok = true;
977 if (int x = prefix_a.Compare(prefix_b))
978 return x;
979
980 switch (prefix_a.type()) {
981 case KeyPrefix::GLOBAL_METADATA: {
982 DCHECK(!slice_a.empty());
983 DCHECK(!slice_b.empty());
984
985 unsigned char type_byte_a;
986 if (!DecodeByte(&slice_a, &type_byte_a)) {
987 *ok = false;
988 return 0;
989 }
990
991 unsigned char type_byte_b;
992 if (!DecodeByte(&slice_b, &type_byte_b)) {
993 *ok = false;
994 return 0;
995 }
996
997 if (int x = type_byte_a - type_byte_b)
998 return x;
999 if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte)
1000 return 0;
1001
1002 // Compare<> is used (which re-decodes the prefix) rather than an
1003 // specialized CompareSuffix<> because metadata is relatively uncommon
1004 // in the database.
1005
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);
1009 }
1010 if (type_byte_a == kDatabaseNameTypeByte) {
1011 return Compare<DatabaseNameKey>(
1012 a, b, /*only_compare_index_keys*/ false, ok);
1013 }
1014 break;
1015 }
1016
1017 case KeyPrefix::DATABASE_METADATA: {
1018 DCHECK(!slice_a.empty());
1019 DCHECK(!slice_b.empty());
1020
1021 unsigned char type_byte_a;
1022 if (!DecodeByte(&slice_a, &type_byte_a)) {
1023 *ok = false;
1024 return 0;
1025 }
1026
1027 unsigned char type_byte_b;
1028 if (!DecodeByte(&slice_b, &type_byte_b)) {
1029 *ok = false;
1030 return 0;
1031 }
1032
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;
1037
1038 // Compare<> is used (which re-decodes the prefix) rather than an
1039 // specialized CompareSuffix<> because metadata is relatively uncommon
1040 // in the database.
1041
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);
1046 }
1047 if (type_byte_a == kIndexMetaDataTypeByte) {
1048 return Compare<IndexMetaDataKey>(
1049 a, b, /*only_compare_index_keys*/ false, ok);
1050 }
1051 if (type_byte_a == kObjectStoreFreeListTypeByte) {
1052 return Compare<ObjectStoreFreeListKey>(
1053 a, b, only_compare_index_keys, ok);
1054 }
1055 if (type_byte_a == kIndexFreeListTypeByte) {
1056 return Compare<IndexFreeListKey>(
1057 a, b, /*only_compare_index_keys*/ false, ok);
1058 }
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);
1063 }
1064 if (type_byte_a == kIndexNamesKeyTypeByte) {
1065 return Compare<IndexNamesKey>(
1066 a, b, /*only_compare_index_keys*/ false, ok);
1067 }
1068 break;
1069 }
1070
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());
1075
1076 return CompareSuffix<ObjectStoreDataKey>(
1077 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1078 }
1079
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());
1084
1085 return CompareSuffix<ExistsEntryKey>(
1086 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1087 }
1088
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());
1093
1094 return CompareSuffix<BlobEntryKey>(
1095 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1096 }
1097
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());
1102
1103 return CompareSuffix<IndexDataKey>(
1104 &slice_a, &slice_b, only_compare_index_keys, ok);
1105 }
1106
1107 case KeyPrefix::INVALID_TYPE:
1108 break;
1109 }
1110
1111 NOTREACHED();
1112 *ok = false;
1113 return 0;
1114 }
1115
1116 } // namespace
1117
Compare(const StringPiece & a,const StringPiece & b,bool only_compare_index_keys)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;
1127 }
1128
KeyPrefix()1129 KeyPrefix::KeyPrefix()
1130 : database_id_(INVALID_TYPE),
1131 object_store_id_(INVALID_TYPE),
1132 index_id_(INVALID_TYPE) {}
1133
KeyPrefix(int64 database_id)1134 KeyPrefix::KeyPrefix(int64 database_id)
1135 : database_id_(database_id), object_store_id_(0), index_id_(0) {
1136 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1137 }
1138
KeyPrefix(int64 database_id,int64 object_store_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));
1145 }
1146
KeyPrefix(int64 database_id,int64 object_store_id,int64 index_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));
1154 }
1155
KeyPrefix(enum Type type,int64 database_id,int64 object_store_id,int64 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));
1166 }
1167
CreateWithSpecialIndex(int64 database_id,int64 object_store_id,int64 index_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);
1175 }
1176
IsValidDatabaseId(int64 database_id)1177 bool KeyPrefix::IsValidDatabaseId(int64 database_id) {
1178 return (database_id > 0) && (database_id < KeyPrefix::kMaxDatabaseId);
1179 }
1180
IsValidObjectStoreId(int64 object_store_id)1181 bool KeyPrefix::IsValidObjectStoreId(int64 object_store_id) {
1182 return (object_store_id > 0) &&
1183 (object_store_id < KeyPrefix::kMaxObjectStoreId);
1184 }
1185
IsValidIndexId(int64 index_id)1186 bool KeyPrefix::IsValidIndexId(int64 index_id) {
1187 return (index_id >= kMinimumIndexId) && (index_id < KeyPrefix::kMaxIndexId);
1188 }
1189
Decode(StringPiece * slice,KeyPrefix * result)1190 bool KeyPrefix::Decode(StringPiece* slice, KeyPrefix* result) {
1191 unsigned char first_byte;
1192 if (!DecodeByte(slice, &first_byte))
1193 return false;
1194
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;
1198
1199 if (database_id_bytes + object_store_id_bytes + index_id_bytes >
1200 slice->size())
1201 return false;
1202
1203 {
1204 StringPiece tmp(slice->begin(), database_id_bytes);
1205 if (!DecodeInt(&tmp, &result->database_id_))
1206 return false;
1207 }
1208 slice->remove_prefix(database_id_bytes);
1209 {
1210 StringPiece tmp(slice->begin(), object_store_id_bytes);
1211 if (!DecodeInt(&tmp, &result->object_store_id_))
1212 return false;
1213 }
1214 slice->remove_prefix(object_store_id_bytes);
1215 {
1216 StringPiece tmp(slice->begin(), index_id_bytes);
1217 if (!DecodeInt(&tmp, &result->index_id_))
1218 return false;
1219 }
1220 slice->remove_prefix(index_id_bytes);
1221 return true;
1222 }
1223
EncodeEmpty()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;
1228 }
1229
Encode() const1230 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_);
1235 }
1236
EncodeInternal(int64 database_id,int64 object_store_id,int64 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;
1243
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);
1247
1248 DCHECK(database_id_string.size() <= kMaxDatabaseIdSizeBytes);
1249 DCHECK(object_store_id_string.size() <= kMaxObjectStoreIdSizeBytes);
1250 DCHECK(index_id_string.size() <= kMaxIndexIdSizeBytes);
1251
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);
1267
1268 DCHECK_LE(ret.size(), kDefaultInlineBufferSize);
1269 return ret;
1270 }
1271
Compare(const KeyPrefix & other) const1272 int KeyPrefix::Compare(const KeyPrefix& other) const {
1273 DCHECK(database_id_ != kInvalidId);
1274 DCHECK(object_store_id_ != kInvalidId);
1275 DCHECK(index_id_ != kInvalidId);
1276
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;
1284 }
1285
type() const1286 KeyPrefix::Type KeyPrefix::type() const {
1287 DCHECK(database_id_ != kInvalidId);
1288 DCHECK(object_store_id_ != kInvalidId);
1289 DCHECK(index_id_ != kInvalidId);
1290
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;
1303
1304 NOTREACHED();
1305 return INVALID_TYPE;
1306 }
1307
Encode()1308 std::string SchemaVersionKey::Encode() {
1309 std::string ret = KeyPrefix::EncodeEmpty();
1310 ret.push_back(kSchemaVersionTypeByte);
1311 return ret;
1312 }
1313
Encode()1314 std::string MaxDatabaseIdKey::Encode() {
1315 std::string ret = KeyPrefix::EncodeEmpty();
1316 ret.push_back(kMaxDatabaseIdTypeByte);
1317 return ret;
1318 }
1319
Encode()1320 std::string DataVersionKey::Encode() {
1321 std::string ret = KeyPrefix::EncodeEmpty();
1322 ret.push_back(kDataVersionTypeByte);
1323 return ret;
1324 }
1325
Encode()1326 std::string BlobJournalKey::Encode() {
1327 std::string ret = KeyPrefix::EncodeEmpty();
1328 ret.push_back(kBlobJournalTypeByte);
1329 return ret;
1330 }
1331
Encode()1332 std::string LiveBlobJournalKey::Encode() {
1333 std::string ret = KeyPrefix::EncodeEmpty();
1334 ret.push_back(kLiveBlobJournalTypeByte);
1335 return ret;
1336 }
1337
DatabaseFreeListKey()1338 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {}
1339
Decode(StringPiece * slice,DatabaseFreeListKey * result)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;
1355 }
1356
Encode(int64 database_id)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;
1362 }
1363
EncodeMaxKey()1364 std::string DatabaseFreeListKey::EncodeMaxKey() {
1365 return Encode(std::numeric_limits<int64>::max());
1366 }
1367
DatabaseId() const1368 int64 DatabaseFreeListKey::DatabaseId() const {
1369 DCHECK_GE(database_id_, 0);
1370 return database_id_;
1371 }
1372
Compare(const DatabaseFreeListKey & other) const1373 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey& other) const {
1374 DCHECK_GE(database_id_, 0);
1375 return CompareInts(database_id_, other.database_id_);
1376 }
1377
Decode(StringPiece * slice,DatabaseNameKey * result)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;
1394 }
1395
Encode(const std::string & origin_identifier,const base::string16 & database_name)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;
1403 }
1404
EncodeMinKeyForOrigin(const std::string & origin_identifier)1405 std::string DatabaseNameKey::EncodeMinKeyForOrigin(
1406 const std::string& origin_identifier) {
1407 return Encode(origin_identifier, base::string16());
1408 }
1409
EncodeStopKeyForOrigin(const std::string & origin_identifier)1410 std::string DatabaseNameKey::EncodeStopKeyForOrigin(
1411 const std::string& origin_identifier) {
1412 // just after origin in collation order
1413 return EncodeMinKeyForOrigin(origin_identifier + '\x01');
1414 }
1415
Compare(const DatabaseNameKey & other)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_);
1420 }
1421
IsValidBlobKey(int64 blob_key)1422 bool DatabaseMetaDataKey::IsValidBlobKey(int64 blob_key) {
1423 return blob_key >= kBlobKeyGeneratorInitialNumber;
1424 }
1425
1426 const int64 DatabaseMetaDataKey::kAllBlobsKey = 1;
1427 const int64 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber = 2;
1428 const int64 DatabaseMetaDataKey::kInvalidBlobKey = -1;
1429
Encode(int64 database_id,MetaDataType meta_data_type)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;
1436 }
1437
ObjectStoreMetaDataKey()1438 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
1439 : object_store_id_(-1), meta_data_type_(-1) {}
1440
Decode(StringPiece * slice,ObjectStoreMetaDataKey * result)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;
1459 }
1460
Encode(int64 database_id,int64 object_store_id,unsigned char meta_data_type)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;
1470 }
1471
EncodeMaxKey(int64 database_id)1472 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id) {
1473 return Encode(database_id,
1474 std::numeric_limits<int64>::max(),
1475 kObjectMetaDataTypeMaximum);
1476 }
1477
EncodeMaxKey(int64 database_id,int64 object_store_id)1478 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id,
1479 int64 object_store_id) {
1480 return Encode(database_id, object_store_id, kObjectMetaDataTypeMaximum);
1481 }
1482
ObjectStoreId() const1483 int64 ObjectStoreMetaDataKey::ObjectStoreId() const {
1484 DCHECK_GE(object_store_id_, 0);
1485 return object_store_id_;
1486 }
MetaDataType() const1487 unsigned char ObjectStoreMetaDataKey::MetaDataType() const {
1488 return meta_data_type_;
1489 }
1490
Compare(const ObjectStoreMetaDataKey & other)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_;
1496 }
1497
IndexMetaDataKey()1498 IndexMetaDataKey::IndexMetaDataKey()
1499 : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {}
1500
Decode(StringPiece * slice,IndexMetaDataKey * result)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;
1519 }
1520
Encode(int64 database_id,int64 object_store_id,int64 index_id,unsigned char meta_data_type)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;
1532 }
1533
EncodeMaxKey(int64 database_id,int64 object_store_id)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);
1540 }
1541
EncodeMaxKey(int64 database_id,int64 object_store_id,int64 index_id)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);
1547 }
1548
Compare(const IndexMetaDataKey & other)1549 int IndexMetaDataKey::Compare(const IndexMetaDataKey& other) {
1550 DCHECK_GE(object_store_id_, 0);
1551 DCHECK_GE(index_id_, 0);
1552
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_;
1558 }
1559
IndexId() const1560 int64 IndexMetaDataKey::IndexId() const {
1561 DCHECK_GE(index_id_, 0);
1562 return index_id_;
1563 }
1564
ObjectStoreFreeListKey()1565 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {}
1566
Decode(StringPiece * slice,ObjectStoreFreeListKey * result)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;
1582 }
1583
Encode(int64 database_id,int64 object_store_id)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;
1591 }
1592
EncodeMaxKey(int64 database_id)1593 std::string ObjectStoreFreeListKey::EncodeMaxKey(int64 database_id) {
1594 return Encode(database_id, std::numeric_limits<int64>::max());
1595 }
1596
ObjectStoreId() const1597 int64 ObjectStoreFreeListKey::ObjectStoreId() const {
1598 DCHECK_GE(object_store_id_, 0);
1599 return object_store_id_;
1600 }
1601
Compare(const ObjectStoreFreeListKey & other)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_);
1608 }
1609
IndexFreeListKey()1610 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {}
1611
Decode(StringPiece * slice,IndexFreeListKey * result)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;
1628 }
1629
Encode(int64 database_id,int64 object_store_id,int64 index_id)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;
1639 }
1640
EncodeMaxKey(int64 database_id,int64 object_store_id)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());
1645 }
1646
Compare(const IndexFreeListKey & other)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_);
1653 }
1654
ObjectStoreId() const1655 int64 IndexFreeListKey::ObjectStoreId() const {
1656 DCHECK_GE(object_store_id_, 0);
1657 return object_store_id_;
1658 }
1659
IndexId() const1660 int64 IndexFreeListKey::IndexId() const {
1661 DCHECK_GE(index_id_, 0);
1662 return index_id_;
1663 }
1664
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?
Decode(StringPiece * slice,ObjectStoreNamesKey * result)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;
1683 }
1684
Encode(int64 database_id,const base::string16 & object_store_name)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;
1693 }
1694
Compare(const ObjectStoreNamesKey & other)1695 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey& other) {
1696 return object_store_name_.compare(other.object_store_name_);
1697 }
1698
IndexNamesKey()1699 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {}
1700
1701 // TODO(jsbell): We never use this to look up index ids, because a mapping
1702 // is kept at a higher level.
Decode(StringPiece * slice,IndexNamesKey * result)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;
1719 }
1720
Encode(int64 database_id,int64 object_store_id,const base::string16 & index_name)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;
1730 }
1731
Compare(const IndexNamesKey & other)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_);
1737 }
1738
ObjectStoreDataKey()1739 ObjectStoreDataKey::ObjectStoreDataKey() {}
~ObjectStoreDataKey()1740 ObjectStoreDataKey::~ObjectStoreDataKey() {}
1741
Decode(StringPiece * slice,ObjectStoreDataKey * result)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;
1753 }
1754
Encode(int64 database_id,int64 object_store_id,const std::string encoded_user_key)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);
1762
1763 return ret;
1764 }
1765
Encode(int64 database_id,int64 object_store_id,const IndexedDBKey & user_key)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);
1772 }
1773
user_key() const1774 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.
1779 }
1780 return key.Pass();
1781 }
1782
1783 const int64 ObjectStoreDataKey::kSpecialIndexNumber = kObjectStoreDataIndexId;
1784
ExistsEntryKey()1785 ExistsEntryKey::ExistsEntryKey() {}
~ExistsEntryKey()1786 ExistsEntryKey::~ExistsEntryKey() {}
1787
Decode(StringPiece * slice,ExistsEntryKey * result)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;
1798 }
1799
Encode(int64 database_id,int64 object_store_id,const std::string & encoded_key)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;
1808 }
1809
Encode(int64 database_id,int64 object_store_id,const IndexedDBKey & user_key)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);
1816 }
1817
user_key() const1818 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.
1823 }
1824 return key.Pass();
1825 }
1826
1827 const int64 ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId;
1828
Decode(StringPiece * slice,BlobEntryKey * result)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);
1836
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_;
1841
1842 return true;
1843 }
1844
FromObjectStoreDataKey(StringPiece * slice,BlobEntryKey * result)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);
1853
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;
1859 }
1860
ReencodeToObjectStoreDataKey(StringPiece * slice)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();
1866
1867 return ObjectStoreDataKey::Encode(
1868 key.database_id_, key.object_store_id_, key.encoded_user_key_);
1869 }
1870
EncodeMinKeyForObjectStore(int64 database_id,int64 object_store_id)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());
1875 }
1876
EncodeStopKeyForObjectStore(int64 database_id,int64 object_store_id)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();
1883 }
1884
Encode() const1885 std::string BlobEntryKey::Encode() const {
1886 DCHECK(!encoded_user_key_.empty());
1887 return Encode(database_id_, object_store_id_, encoded_user_key_);
1888 }
1889
Encode(int64 database_id,int64 object_store_id,const IndexedDBKey & 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);
1896 }
1897
Encode(int64 database_id,int64 object_store_id,const std::string & encoded_user_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;
1905 }
1906
1907 const int64 BlobEntryKey::kSpecialIndexNumber = kBlobEntryIndexId;
1908
IndexDataKey()1909 IndexDataKey::IndexDataKey()
1910 : database_id_(-1),
1911 object_store_id_(-1),
1912 index_id_(-1),
1913 sequence_number_(-1) {}
1914
~IndexDataKey()1915 IndexDataKey::~IndexDataKey() {}
1916
Decode(StringPiece * slice,IndexDataKey * result)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();
1929
1930 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1931 return false;
1932
1933 // [optional] sequence number
1934 if (slice->empty())
1935 return true;
1936 if (!DecodeVarInt(slice, &result->sequence_number_))
1937 return false;
1938
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;
1945 }
1946
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)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;
1959 }
1960
Encode(int64 database_id,int64 object_store_id,int64 index_id,const IndexedDBKey & user_key)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);
1969 }
1970
Encode(int64 database_id,int64 object_store_id,int64 index_id,const IndexedDBKey & user_key,const IndexedDBKey & user_primary_key)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,
1985 0);
1986 }
1987
EncodeMinKey(int64 database_id,int64 object_store_id,int64 index_id)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);
1993 }
1994
EncodeMaxKey(int64 database_id,int64 object_store_id,int64 index_id)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());
2004 }
2005
DatabaseId() const2006 int64 IndexDataKey::DatabaseId() const {
2007 DCHECK_GE(database_id_, 0);
2008 return database_id_;
2009 }
2010
ObjectStoreId() const2011 int64 IndexDataKey::ObjectStoreId() const {
2012 DCHECK_GE(object_store_id_, 0);
2013 return object_store_id_;
2014 }
2015
IndexId() const2016 int64 IndexDataKey::IndexId() const {
2017 DCHECK_GE(index_id_, 0);
2018 return index_id_;
2019 }
2020
user_key() const2021 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.
2026 }
2027 return key.Pass();
2028 }
2029
primary_key() const2030 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.
2035 }
2036 return key.Pass();
2037 }
2038
2039 } // namespace content
2040