OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" | 5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
6 | 6 |
7 #include <iterator> | 7 #include <iterator> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/strings/string16.h" | 11 #include "base/strings/string16.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "base/sys_byteorder.h" | 13 #include "base/sys_byteorder.h" |
14 #include "content/common/indexed_db/indexed_db_key.h" | 14 #include "content/common/indexed_db/indexed_db_key.h" |
15 #include "content/common/indexed_db/indexed_db_key_path.h" | 15 #include "content/common/indexed_db/indexed_db_key_path.h" |
16 #include "third_party/WebKit/public/platform/WebIDBKeyPath.h" | |
17 | 16 |
18 // LevelDB stores key/value pairs. Keys and values are strings of bytes, | 17 // LevelDB stores key/value pairs. Keys and values are strings of bytes, |
19 // normally of type std::string. | 18 // normally of type std::string. |
20 // | 19 // |
21 // The keys in the backing store are variable-length tuples with different types | 20 // The keys in the backing store are variable-length tuples with different types |
22 // of fields. Each key in the backing store starts with a ternary prefix: | 21 // of fields. Each key in the backing store starts with a ternary prefix: |
23 // (database id, object store id, index id). For each, 0 is reserved for | 22 // (database id, object store id, index id). For each, 0 is reserved for |
24 // meta-data. | 23 // meta-data. |
25 // The prefix makes sure that data for a specific database, object store, and | 24 // The prefix makes sure that data for a specific database, object store, and |
26 // index are grouped together. The locality is important for performance: common | 25 // index are grouped together. The locality is important for performance: common |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 // stale | 142 // stale |
144 // index data. Whenever new object store data is inserted, it gets a new | 143 // index data. Whenever new object store data is inserted, it gets a new |
145 // "version" number, and new index data is written with this number. When | 144 // "version" number, and new index data is written with this number. When |
146 // the index is used for look-ups, entries are validated against the | 145 // the index is used for look-ups, entries are validated against the |
147 // "exists" entries, and records with old "version" numbers are deleted | 146 // "exists" entries, and records with old "version" numbers are deleted |
148 // when they are encountered in get_primary_key_via_index, | 147 // when they are encountered in get_primary_key_via_index, |
149 // IndexCursorImpl::load_current_row, and | 148 // IndexCursorImpl::load_current_row, and |
150 // IndexKeyCursorImpl::load_current_row). | 149 // IndexKeyCursorImpl::load_current_row). |
151 | 150 |
152 using base::StringPiece; | 151 using base::StringPiece; |
153 using WebKit::WebIDBKey; | 152 using WebKit::WebIDBKeyType; |
| 153 using WebKit::WebIDBKeyTypeArray; |
| 154 using WebKit::WebIDBKeyTypeDate; |
| 155 using WebKit::WebIDBKeyTypeInvalid; |
| 156 using WebKit::WebIDBKeyTypeMin; |
| 157 using WebKit::WebIDBKeyTypeNull; |
| 158 using WebKit::WebIDBKeyTypeNumber; |
| 159 using WebKit::WebIDBKeyTypeString; |
154 using WebKit::WebIDBKeyPath; | 160 using WebKit::WebIDBKeyPath; |
| 161 using WebKit::WebIDBKeyPathType; |
| 162 using WebKit::WebIDBKeyPathTypeArray; |
| 163 using WebKit::WebIDBKeyPathTypeNull; |
| 164 using WebKit::WebIDBKeyPathTypeString; |
155 | 165 |
156 namespace content { | 166 namespace content { |
157 | 167 |
158 // As most of the IndexedDBKeys and encoded values are short, we | 168 // As most of the IndexedDBKeys and encoded values are short, we |
159 // initialize some Vectors with a default inline buffer size to reduce | 169 // initialize some Vectors with a default inline buffer size to reduce |
160 // the memory re-allocations when the Vectors are appended. | 170 // the memory re-allocations when the Vectors are appended. |
161 static const size_t kDefaultInlineBufferSize = 32; | 171 static const size_t kDefaultInlineBufferSize = 32; |
162 | 172 |
163 static const unsigned char kIndexedDBKeyNullTypeByte = 0; | 173 static const unsigned char kIndexedDBKeyNullTypeByte = 0; |
164 static const unsigned char kIndexedDBKeyStringTypeByte = 1; | 174 static const unsigned char kIndexedDBKeyStringTypeByte = 1; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 void EncodeDouble(double value, std::string* into) { | 280 void EncodeDouble(double value, std::string* into) { |
271 // This always has host endianness. | 281 // This always has host endianness. |
272 const char* p = reinterpret_cast<char*>(&value); | 282 const char* p = reinterpret_cast<char*>(&value); |
273 into->insert(into->end(), p, p + sizeof(value)); | 283 into->insert(into->end(), p, p + sizeof(value)); |
274 } | 284 } |
275 | 285 |
276 void EncodeIDBKey(const IndexedDBKey& value, std::string* into) { | 286 void EncodeIDBKey(const IndexedDBKey& value, std::string* into) { |
277 size_t previous_size = into->size(); | 287 size_t previous_size = into->size(); |
278 DCHECK(value.IsValid()); | 288 DCHECK(value.IsValid()); |
279 switch (value.type()) { | 289 switch (value.type()) { |
280 case WebIDBKey::NullType: | 290 case WebIDBKeyTypeNull: |
281 case WebIDBKey::InvalidType: | 291 case WebIDBKeyTypeInvalid: |
282 case WebIDBKey::MinType: { | 292 case WebIDBKeyTypeMin: { |
283 NOTREACHED(); | 293 NOTREACHED(); |
284 EncodeByte(kIndexedDBKeyNullTypeByte, into); | 294 EncodeByte(kIndexedDBKeyNullTypeByte, into); |
285 return; | 295 return; |
286 } | 296 } |
287 case WebIDBKey::ArrayType: { | 297 case WebIDBKeyTypeArray: { |
288 EncodeByte(kIndexedDBKeyArrayTypeByte, into); | 298 EncodeByte(kIndexedDBKeyArrayTypeByte, into); |
289 size_t length = value.array().size(); | 299 size_t length = value.array().size(); |
290 EncodeVarInt(length, into); | 300 EncodeVarInt(length, into); |
291 for (size_t i = 0; i < length; ++i) | 301 for (size_t i = 0; i < length; ++i) |
292 EncodeIDBKey(value.array()[i], into); | 302 EncodeIDBKey(value.array()[i], into); |
293 DCHECK_GT(into->size(), previous_size); | 303 DCHECK_GT(into->size(), previous_size); |
294 return; | 304 return; |
295 } | 305 } |
296 case WebIDBKey::StringType: { | 306 case WebIDBKeyTypeString: { |
297 EncodeByte(kIndexedDBKeyStringTypeByte, into); | 307 EncodeByte(kIndexedDBKeyStringTypeByte, into); |
298 EncodeStringWithLength(value.string(), into); | 308 EncodeStringWithLength(value.string(), into); |
299 DCHECK_GT(into->size(), previous_size); | 309 DCHECK_GT(into->size(), previous_size); |
300 return; | 310 return; |
301 } | 311 } |
302 case WebIDBKey::DateType: { | 312 case WebIDBKeyTypeDate: { |
303 EncodeByte(kIndexedDBKeyDateTypeByte, into); | 313 EncodeByte(kIndexedDBKeyDateTypeByte, into); |
304 EncodeDouble(value.date(), into); | 314 EncodeDouble(value.date(), into); |
305 DCHECK_EQ(static_cast<size_t>(9), | 315 DCHECK_EQ(static_cast<size_t>(9), |
306 static_cast<size_t>(into->size() - previous_size)); | 316 static_cast<size_t>(into->size() - previous_size)); |
307 return; | 317 return; |
308 } | 318 } |
309 case WebIDBKey::NumberType: { | 319 case WebIDBKeyTypeNumber: { |
310 EncodeByte(kIndexedDBKeyNumberTypeByte, into); | 320 EncodeByte(kIndexedDBKeyNumberTypeByte, into); |
311 EncodeDouble(value.number(), into); | 321 EncodeDouble(value.number(), into); |
312 DCHECK_EQ(static_cast<size_t>(9), | 322 DCHECK_EQ(static_cast<size_t>(9), |
313 static_cast<size_t>(into->size() - previous_size)); | 323 static_cast<size_t>(into->size() - previous_size)); |
314 return; | 324 return; |
315 } | 325 } |
316 } | 326 } |
317 | 327 |
318 NOTREACHED(); | 328 NOTREACHED(); |
319 } | 329 } |
320 | 330 |
321 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) { | 331 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) { |
322 // May be typed, or may be a raw string. An invalid leading | 332 // May be typed, or may be a raw string. An invalid leading |
323 // byte is used to identify typed coding. New records are | 333 // byte is used to identify typed coding. New records are |
324 // always written as typed. | 334 // always written as typed. |
325 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into); | 335 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into); |
326 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into); | 336 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into); |
327 EncodeByte(static_cast<char>(value.type()), into); | 337 EncodeByte(static_cast<char>(value.type()), into); |
328 switch (value.type()) { | 338 switch (value.type()) { |
329 case WebIDBKeyPath::NullType: | 339 case WebIDBKeyPathTypeNull: |
330 break; | 340 break; |
331 case WebIDBKeyPath::StringType: { | 341 case WebIDBKeyPathTypeString: { |
332 EncodeStringWithLength(value.string(), into); | 342 EncodeStringWithLength(value.string(), into); |
333 break; | 343 break; |
334 } | 344 } |
335 case WebIDBKeyPath::ArrayType: { | 345 case WebIDBKeyPathTypeArray: { |
336 const std::vector<string16>& array = value.array(); | 346 const std::vector<string16>& array = value.array(); |
337 size_t count = array.size(); | 347 size_t count = array.size(); |
338 EncodeVarInt(count, into); | 348 EncodeVarInt(count, into); |
339 for (size_t i = 0; i < count; ++i) { | 349 for (size_t i = 0; i < count; ++i) { |
340 EncodeStringWithLength(array[i], into); | 350 EncodeStringWithLength(array[i], into); |
341 } | 351 } |
342 break; | 352 break; |
343 } | 353 } |
344 } | 354 } |
345 } | 355 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 string16 s; | 478 string16 s; |
469 if (!DecodeStringWithLength(slice, &s)) | 479 if (!DecodeStringWithLength(slice, &s)) |
470 return false; | 480 return false; |
471 *value = make_scoped_ptr(new IndexedDBKey(s)); | 481 *value = make_scoped_ptr(new IndexedDBKey(s)); |
472 return true; | 482 return true; |
473 } | 483 } |
474 case kIndexedDBKeyDateTypeByte: { | 484 case kIndexedDBKeyDateTypeByte: { |
475 double d; | 485 double d; |
476 if (!DecodeDouble(slice, &d)) | 486 if (!DecodeDouble(slice, &d)) |
477 return false; | 487 return false; |
478 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::DateType)); | 488 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeDate)); |
479 return true; | 489 return true; |
480 } | 490 } |
481 case kIndexedDBKeyNumberTypeByte: { | 491 case kIndexedDBKeyNumberTypeByte: { |
482 double d; | 492 double d; |
483 if (!DecodeDouble(slice, &d)) | 493 if (!DecodeDouble(slice, &d)) |
484 return false; | 494 return false; |
485 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::NumberType)); | 495 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeNumber)); |
486 return true; | 496 return true; |
487 } | 497 } |
488 } | 498 } |
489 | 499 |
490 NOTREACHED(); | 500 NOTREACHED(); |
491 return false; | 501 return false; |
492 } | 502 } |
493 | 503 |
494 bool DecodeDouble(StringPiece* slice, double* value) { | 504 bool DecodeDouble(StringPiece* slice, double* value) { |
495 if (slice->size() < sizeof(*value)) | 505 if (slice->size() < sizeof(*value)) |
(...skipping 12 matching lines...) Expand all Loading... |
508 (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) { | 518 (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) { |
509 string16 s; | 519 string16 s; |
510 if (!DecodeString(slice, &s)) | 520 if (!DecodeString(slice, &s)) |
511 return false; | 521 return false; |
512 *value = IndexedDBKeyPath(s); | 522 *value = IndexedDBKeyPath(s); |
513 return true; | 523 return true; |
514 } | 524 } |
515 | 525 |
516 slice->remove_prefix(2); | 526 slice->remove_prefix(2); |
517 DCHECK(!slice->empty()); | 527 DCHECK(!slice->empty()); |
518 WebIDBKeyPath::Type type = static_cast<WebIDBKeyPath::Type>((*slice)[0]); | 528 WebIDBKeyPathType type = static_cast<WebIDBKeyPathType>((*slice)[0]); |
519 slice->remove_prefix(1); | 529 slice->remove_prefix(1); |
520 | 530 |
521 switch (type) { | 531 switch (type) { |
522 case WebIDBKeyPath::NullType: | 532 case WebIDBKeyPathTypeNull: |
523 DCHECK(slice->empty()); | 533 DCHECK(slice->empty()); |
524 *value = IndexedDBKeyPath(); | 534 *value = IndexedDBKeyPath(); |
525 return true; | 535 return true; |
526 case WebIDBKeyPath::StringType: { | 536 case WebIDBKeyPathTypeString: { |
527 string16 string; | 537 string16 string; |
528 if (!DecodeStringWithLength(slice, &string)) | 538 if (!DecodeStringWithLength(slice, &string)) |
529 return false; | 539 return false; |
530 DCHECK(slice->empty()); | 540 DCHECK(slice->empty()); |
531 *value = IndexedDBKeyPath(string); | 541 *value = IndexedDBKeyPath(string); |
532 return true; | 542 return true; |
533 } | 543 } |
534 case WebIDBKeyPath::ArrayType: { | 544 case WebIDBKeyPathTypeArray: { |
535 std::vector<string16> array; | 545 std::vector<string16> array; |
536 int64 count; | 546 int64 count; |
537 if (!DecodeVarInt(slice, &count)) | 547 if (!DecodeVarInt(slice, &count)) |
538 return false; | 548 return false; |
539 DCHECK_GE(count, 0); | 549 DCHECK_GE(count, 0); |
540 while (count--) { | 550 while (count--) { |
541 string16 string; | 551 string16 string; |
542 if (!DecodeStringWithLength(slice, &string)) | 552 if (!DecodeStringWithLength(slice, &string)) |
543 return false; | 553 return false; |
544 array.push_back(string); | 554 array.push_back(string); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) { | 603 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) { |
594 const char* start = slice->begin(); | 604 const char* start = slice->begin(); |
595 if (!ExtractEncodedIDBKey(slice)) | 605 if (!ExtractEncodedIDBKey(slice)) |
596 return 0; | 606 return 0; |
597 | 607 |
598 if (result) | 608 if (result) |
599 result->assign(start, slice->begin()); | 609 result->assign(start, slice->begin()); |
600 return true; | 610 return true; |
601 } | 611 } |
602 | 612 |
603 static WebIDBKey::Type KeyTypeByteToKeyType(unsigned char type) { | 613 static WebIDBKeyType KeyTypeByteToKeyType(unsigned char type) { |
604 switch (type) { | 614 switch (type) { |
605 case kIndexedDBKeyNullTypeByte: | 615 case kIndexedDBKeyNullTypeByte: |
606 return WebIDBKey::InvalidType; | 616 return WebIDBKeyTypeInvalid; |
607 case kIndexedDBKeyArrayTypeByte: | 617 case kIndexedDBKeyArrayTypeByte: |
608 return WebIDBKey::ArrayType; | 618 return WebIDBKeyTypeArray; |
609 case kIndexedDBKeyStringTypeByte: | 619 case kIndexedDBKeyStringTypeByte: |
610 return WebIDBKey::StringType; | 620 return WebIDBKeyTypeString; |
611 case kIndexedDBKeyDateTypeByte: | 621 case kIndexedDBKeyDateTypeByte: |
612 return WebIDBKey::DateType; | 622 return WebIDBKeyTypeDate; |
613 case kIndexedDBKeyNumberTypeByte: | 623 case kIndexedDBKeyNumberTypeByte: |
614 return WebIDBKey::NumberType; | 624 return WebIDBKeyTypeNumber; |
615 case kIndexedDBKeyMinKeyTypeByte: | 625 case kIndexedDBKeyMinKeyTypeByte: |
616 return WebIDBKey::MinType; | 626 return WebIDBKeyTypeMin; |
617 } | 627 } |
618 | 628 |
619 NOTREACHED(); | 629 NOTREACHED(); |
620 return WebIDBKey::InvalidType; | 630 return WebIDBKeyTypeInvalid; |
621 } | 631 } |
622 | 632 |
623 int CompareEncodedStringsWithLength(StringPiece* slice1, | 633 int CompareEncodedStringsWithLength(StringPiece* slice1, |
624 StringPiece* slice2, | 634 StringPiece* slice2, |
625 bool* ok) { | 635 bool* ok) { |
626 int64 len1, len2; | 636 int64 len1, len2; |
627 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) { | 637 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) { |
628 *ok = false; | 638 *ok = false; |
629 return 0; | 639 return 0; |
630 } | 640 } |
(...skipping 28 matching lines...) Expand all Loading... |
659 DCHECK_GE(b, 0); | 669 DCHECK_GE(b, 0); |
660 #endif | 670 #endif |
661 int64 diff = a - b; | 671 int64 diff = a - b; |
662 if (diff < 0) | 672 if (diff < 0) |
663 return -1; | 673 return -1; |
664 if (diff > 0) | 674 if (diff > 0) |
665 return 1; | 675 return 1; |
666 return 0; | 676 return 0; |
667 } | 677 } |
668 | 678 |
669 static int CompareTypes(WebIDBKey::Type a, WebIDBKey::Type b) { return b - a; } | 679 static int CompareTypes(WebIDBKeyType a, WebIDBKeyType b) { return b - a; } |
670 | 680 |
671 int CompareEncodedIDBKeys(StringPiece* slice_a, | 681 int CompareEncodedIDBKeys(StringPiece* slice_a, |
672 StringPiece* slice_b, | 682 StringPiece* slice_b, |
673 bool* ok) { | 683 bool* ok) { |
674 *ok = true; | 684 *ok = true; |
675 unsigned char type_a = (*slice_a)[0]; | 685 unsigned char type_a = (*slice_a)[0]; |
676 unsigned char type_b = (*slice_b)[0]; | 686 unsigned char type_b = (*slice_b)[0]; |
677 slice_a->remove_prefix(1); | 687 slice_a->remove_prefix(1); |
678 slice_b->remove_prefix(1); | 688 slice_b->remove_prefix(1); |
679 | 689 |
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1885 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const { | 1895 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const { |
1886 scoped_ptr<IndexedDBKey> key; | 1896 scoped_ptr<IndexedDBKey> key; |
1887 StringPiece slice(encoded_primary_key_); | 1897 StringPiece slice(encoded_primary_key_); |
1888 if (!DecodeIDBKey(&slice, &key)) { | 1898 if (!DecodeIDBKey(&slice, &key)) { |
1889 // TODO(jsbell): Return error. | 1899 // TODO(jsbell): Return error. |
1890 } | 1900 } |
1891 return key.Pass(); | 1901 return key.Pass(); |
1892 } | 1902 } |
1893 | 1903 |
1894 } // namespace content | 1904 } // namespace content |
OLD | NEW |