summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsbell@chromium.org <jsbell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-21 03:08:54 +0000
committerjsbell@chromium.org <jsbell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-21 03:08:54 +0000
commit28f4165b9b0eb6266245b47edf913539cc4ebb0a (patch)
tree3b5410256363471cf9d54b62f33ea0b8120ca7de
parent0eea36cb9143d199db648e37a38278c6d91ec731 (diff)
downloadchromium_src-28f4165b9b0eb6266245b47edf913539cc4ebb0a.zip
chromium_src-28f4165b9b0eb6266245b47edf913539cc4ebb0a.tar.gz
chromium_src-28f4165b9b0eb6266245b47edf913539cc4ebb0a.tar.bz2
IndexedDB: Support binary keys in Chromium back-end
Back-end support for binary values (Uint8Arrays) as IDB keys. This requires Blink public API changes before landing. (This is part 3 of a 4 part landing sequence.) BUG=297304 Review URL: https://codereview.chromium.org/23439009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236380 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/indexed_db/indexed_db_leveldb_coding.cc86
-rw-r--r--content/browser/indexed_db/indexed_db_leveldb_coding.h3
-rw-r--r--content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc69
-rw-r--r--content/child/indexed_db/indexed_db_key_builders.cc6
-rw-r--r--content/common/indexed_db/indexed_db_key.cc11
-rw-r--r--content/common/indexed_db/indexed_db_key.h3
-rw-r--r--content/common/indexed_db/indexed_db_param_traits.cc13
7 files changed, 190 insertions, 1 deletions
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index 46e5121..dd3964a 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -149,6 +149,7 @@
using base::StringPiece;
using blink::WebIDBKeyType;
using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
using blink::WebIDBKeyTypeDate;
using blink::WebIDBKeyTypeInvalid;
using blink::WebIDBKeyTypeMin;
@@ -173,6 +174,7 @@ static const unsigned char kIndexedDBKeyDateTypeByte = 2;
static const unsigned char kIndexedDBKeyNumberTypeByte = 3;
static const unsigned char kIndexedDBKeyArrayTypeByte = 4;
static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
+static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
@@ -269,6 +271,12 @@ void EncodeString(const string16& value, std::string* into) {
*dst++ = htons(*src++);
}
+void EncodeBinary(const std::string& value, std::string* into) {
+ EncodeVarInt(value.length(), into);
+ into->append(value.begin(), value.end());
+ DCHECK(into->size() >= value.size());
+}
+
void EncodeStringWithLength(const string16& value, std::string* into) {
EncodeVarInt(value.length(), into);
EncodeString(value, into);
@@ -301,6 +309,12 @@ void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
DCHECK_GT(into->size(), previous_size);
return;
}
+ case WebIDBKeyTypeBinary: {
+ EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
+ EncodeBinary(value.binary(), into);
+ DCHECK_GT(into->size(), previous_size);
+ return;
+ }
case WebIDBKeyTypeString: {
EncodeByte(kIndexedDBKeyStringTypeByte, into);
EncodeStringWithLength(value.string(), into);
@@ -446,6 +460,22 @@ bool DecodeStringWithLength(StringPiece* slice, string16* value) {
return true;
}
+bool DecodeBinary(StringPiece* slice, std::string* value) {
+ if (slice->empty())
+ return false;
+
+ int64 length = 0;
+ if (!DecodeVarInt(slice, &length) || length < 0)
+ return false;
+ size_t size = length;
+ if (slice->size() < size)
+ return false;
+
+ value->assign(slice->begin(), size);
+ slice->remove_prefix(size);
+ return true;
+}
+
bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
if (slice->empty())
return false;
@@ -472,6 +502,13 @@ bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
*value = make_scoped_ptr(new IndexedDBKey(array));
return true;
}
+ case kIndexedDBKeyBinaryTypeByte: {
+ std::string binary;
+ if (!DecodeBinary(slice, &binary))
+ return false;
+ *value = make_scoped_ptr(new IndexedDBKey(binary));
+ return true;
+ }
case kIndexedDBKeyStringTypeByte: {
string16 s;
if (!DecodeStringWithLength(slice, &s))
@@ -578,6 +615,15 @@ bool ConsumeEncodedIDBKey(StringPiece* slice) {
}
return true;
}
+ case kIndexedDBKeyBinaryTypeByte: {
+ int64 length = 0;
+ if (!DecodeVarInt(slice, &length) || length < 0)
+ return false;
+ if (slice->size() < static_cast<size_t>(length))
+ return false;
+ slice->remove_prefix(length);
+ return true;
+ }
case kIndexedDBKeyStringTypeByte: {
int64 length = 0;
if (!DecodeVarInt(slice, &length) || length < 0)
@@ -614,6 +660,8 @@ static WebIDBKeyType KeyTypeByteToKeyType(unsigned char type) {
return WebIDBKeyTypeInvalid;
case kIndexedDBKeyArrayTypeByte:
return WebIDBKeyTypeArray;
+ case kIndexedDBKeyBinaryTypeByte:
+ return WebIDBKeyTypeBinary;
case kIndexedDBKeyStringTypeByte:
return WebIDBKeyTypeString;
case kIndexedDBKeyDateTypeByte:
@@ -650,6 +698,7 @@ int CompareEncodedStringsWithLength(StringPiece* slice1,
return 0;
}
+ // Extract the string data, and advance the passed slices.
StringPiece string1(slice1->begin(), len1 * sizeof(char16));
StringPiece string2(slice2->begin(), len2 * sizeof(char16));
slice1->remove_prefix(len1 * sizeof(char16));
@@ -660,6 +709,41 @@ int CompareEncodedStringsWithLength(StringPiece* slice1,
return string1.compare(string2);
}
+int CompareEncodedBinary(StringPiece* slice1,
+ StringPiece* slice2,
+ bool* ok) {
+ int64 len1, len2;
+ if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
+ *ok = false;
+ return 0;
+ }
+ DCHECK_GE(len1, 0);
+ DCHECK_GE(len2, 0);
+ if (len1 < 0 || len2 < 0) {
+ *ok = false;
+ return 0;
+ }
+ size_t size1 = len1;
+ size_t size2 = len2;
+
+ DCHECK_GE(slice1->size(), size1);
+ DCHECK_GE(slice2->size(), size2);
+ if (slice1->size() < size1 || slice2->size() < size2) {
+ *ok = false;
+ return 0;
+ }
+
+ // Extract the binary data, and advance the passed slices.
+ StringPiece binary1(slice1->begin(), size1);
+ StringPiece binary2(slice2->begin(), size2);
+ slice1->remove_prefix(size1);
+ slice2->remove_prefix(size2);
+
+ *ok = true;
+ // This is the same as a memcmp()
+ return binary1.compare(binary2);
+}
+
static int CompareInts(int64 a, int64 b) {
#ifndef NDEBUG
// Exercised by unit tests in debug only.
@@ -718,6 +802,8 @@ int CompareEncodedIDBKeys(StringPiece* slice_a,
}
return length_a - length_b;
}
+ case kIndexedDBKeyBinaryTypeByte:
+ return CompareEncodedBinary(slice_a, slice_b, ok);
case kIndexedDBKeyStringTypeByte:
return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
case kIndexedDBKeyDateTypeByte:
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.h b/content/browser/indexed_db/indexed_db_leveldb_coding.h
index 4aca1b9..8d0c780 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -30,6 +30,7 @@ CONTENT_EXPORT void EncodeVarInt(int64 value, std::string* into);
CONTENT_EXPORT void EncodeString(const string16& value, std::string* into);
CONTENT_EXPORT void EncodeStringWithLength(const string16& value,
std::string* into);
+CONTENT_EXPORT void EncodeBinary(const std::string& value, std::string* into);
CONTENT_EXPORT void EncodeDouble(double value, std::string* into);
CONTENT_EXPORT void EncodeIDBKey(const IndexedDBKey& value, std::string* into);
CONTENT_EXPORT void EncodeIDBKeyPath(const IndexedDBKeyPath& value,
@@ -48,6 +49,8 @@ CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeString(base::StringPiece* slice,
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeStringWithLength(
base::StringPiece* slice,
string16* value);
+CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBinary(base::StringPiece* slice,
+ std::string* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeDouble(base::StringPiece* slice,
double* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKey(
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
index e5e4927..6d6ab0b 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
@@ -123,6 +123,8 @@ TEST(IndexedDBLevelDBCodingTest, MaxIDBKey) {
std::string min_key = MinIDBKey();
std::string array_key;
EncodeIDBKey(IndexedDBKey(IndexedDBKey::KeyArray()), &array_key);
+ std::string binary_key;
+ EncodeIDBKey(IndexedDBKey(std::string("\x00\x01\x02")), &binary_key);
std::string string_key;
EncodeIDBKey(IndexedDBKey(ASCIIToUTF16("Hello world")), &string_key);
std::string number_key;
@@ -132,6 +134,7 @@ TEST(IndexedDBLevelDBCodingTest, MaxIDBKey) {
EXPECT_GT(CompareKeys(max_key, min_key), 0);
EXPECT_GT(CompareKeys(max_key, array_key), 0);
+ EXPECT_GT(CompareKeys(max_key, binary_key), 0);
EXPECT_GT(CompareKeys(max_key, string_key), 0);
EXPECT_GT(CompareKeys(max_key, number_key), 0);
EXPECT_GT(CompareKeys(max_key, date_key), 0);
@@ -143,6 +146,8 @@ TEST(IndexedDBLevelDBCodingTest, MinIDBKey) {
std::string max_key = MaxIDBKey();
std::string array_key;
EncodeIDBKey(IndexedDBKey(IndexedDBKey::KeyArray()), &array_key);
+ std::string binary_key;
+ EncodeIDBKey(IndexedDBKey(std::string("\x00\x01\x02")), &binary_key);
std::string string_key;
EncodeIDBKey(IndexedDBKey(ASCIIToUTF16("Hello world")), &string_key);
std::string number_key;
@@ -152,6 +157,7 @@ TEST(IndexedDBLevelDBCodingTest, MinIDBKey) {
EXPECT_LT(CompareKeys(min_key, max_key), 0);
EXPECT_LT(CompareKeys(min_key, array_key), 0);
+ EXPECT_LT(CompareKeys(min_key, binary_key), 0);
EXPECT_LT(CompareKeys(min_key, string_key), 0);
EXPECT_LT(CompareKeys(min_key, number_key), 0);
EXPECT_LT(CompareKeys(min_key, date_key), 0);
@@ -473,6 +479,58 @@ TEST(IndexedDBLevelDBCodingTest, CompareEncodedStringsWithLength) {
}
}
+static std::string WrappedEncodeBinary(std::string value) {
+ std::string buffer;
+ EncodeBinary(value, &buffer);
+ return buffer;
+}
+
+TEST(IndexedDBLevelDBCodingTest, EncodeBinary) {
+ const unsigned char binary_data[] = {0x00, 0x01, 0xfe, 0xff};
+ EXPECT_EQ(
+ static_cast<size_t>(1),
+ WrappedEncodeBinary(std::string(binary_data, binary_data + 0)).size());
+ EXPECT_EQ(
+ static_cast<size_t>(2),
+ WrappedEncodeBinary(std::string(binary_data, binary_data + 1)).size());
+ EXPECT_EQ(
+ static_cast<size_t>(5),
+ WrappedEncodeBinary(std::string(binary_data, binary_data + 4)).size());
+}
+
+TEST(IndexedDBLevelDBCodingTest, DecodeBinary) {
+ const unsigned char binary_data[] = { 0x00, 0x01, 0xfe, 0xff };
+
+ std::vector<std::string> test_cases;
+ test_cases.push_back(std::string(binary_data, binary_data + 0));
+ test_cases.push_back(std::string(binary_data, binary_data + 1));
+ test_cases.push_back(std::string(binary_data, binary_data + 4));
+
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ std::string value = test_cases[i];
+ std::string v = WrappedEncodeBinary(value);
+ ASSERT_GT(v.size(), static_cast<size_t>(0));
+ StringPiece slice(v);
+ std::string result;
+ EXPECT_TRUE(DecodeBinary(&slice, &result));
+ EXPECT_EQ(value, result);
+ EXPECT_TRUE(slice.empty());
+
+ slice = StringPiece(&*v.begin(), v.size() - 1);
+ EXPECT_FALSE(DecodeBinary(&slice, &result));
+
+ slice = StringPiece(&*v.begin(), static_cast<size_t>(0));
+ EXPECT_FALSE(DecodeBinary(&slice, &result));
+
+ // Verify decoding at an offset, to detect unaligned memory access.
+ v.insert(v.begin(), static_cast<size_t>(1), static_cast<char>(0));
+ slice = StringPiece(&*v.begin() + 1, v.size() - 1);
+ EXPECT_TRUE(DecodeBinary(&slice, &result));
+ EXPECT_EQ(value, result);
+ EXPECT_TRUE(slice.empty());
+ }
+}
+
static std::string WrappedEncodeDouble(double value) {
std::string buffer;
EncodeDouble(value, &buffer);
@@ -524,12 +582,14 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeIDBKey) {
test_cases.push_back(IndexedDBKey(1234, WebIDBKeyTypeNumber));
test_cases.push_back(IndexedDBKey(7890, WebIDBKeyTypeDate));
test_cases.push_back(IndexedDBKey(ASCIIToUTF16("Hello World!")));
+ test_cases.push_back(IndexedDBKey(std::string("\x01\x02")));
test_cases.push_back(IndexedDBKey(IndexedDBKey::KeyArray()));
IndexedDBKey::KeyArray array;
array.push_back(IndexedDBKey(1234, WebIDBKeyTypeNumber));
array.push_back(IndexedDBKey(7890, WebIDBKeyTypeDate));
array.push_back(IndexedDBKey(ASCIIToUTF16("Hello World!")));
+ array.push_back(IndexedDBKey(std::string("\x01\x02")));
array.push_back(IndexedDBKey(IndexedDBKey::KeyArray()));
test_cases.push_back(IndexedDBKey(array));
@@ -685,6 +745,15 @@ TEST(IndexedDBLevelDBCodingTest, ExtractAndCompareIDBKeys) {
keys.push_back(IndexedDBKey(ASCIIToUTF16("baab")));
keys.push_back(IndexedDBKey(ASCIIToUTF16("c")));
+ keys.push_back(IndexedDBKey(std::string()));
+ keys.push_back(IndexedDBKey(std::string("\x01")));
+ keys.push_back(IndexedDBKey(std::string("\x01\x01")));
+ keys.push_back(IndexedDBKey(std::string("\x01\x02")));
+ keys.push_back(IndexedDBKey(std::string("\x02")));
+ keys.push_back(IndexedDBKey(std::string("\x02\x01")));
+ keys.push_back(IndexedDBKey(std::string("\x02\x02")));
+ keys.push_back(IndexedDBKey(std::string("\xff")));
+
keys.push_back(CreateArrayIDBKey());
keys.push_back(CreateArrayIDBKey(IndexedDBKey(0, WebIDBKeyTypeNumber)));
keys.push_back(CreateArrayIDBKey(IndexedDBKey(0, WebIDBKeyTypeNumber),
diff --git a/content/child/indexed_db/indexed_db_key_builders.cc b/content/child/indexed_db/indexed_db_key_builders.cc
index 162546c..a17065f 100644
--- a/content/child/indexed_db/indexed_db_key_builders.cc
+++ b/content/child/indexed_db/indexed_db_key_builders.cc
@@ -10,6 +10,7 @@
using blink::WebIDBKey;
using blink::WebIDBKeyRange;
using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
using blink::WebIDBKeyTypeDate;
using blink::WebIDBKeyTypeInvalid;
using blink::WebIDBKeyTypeMin;
@@ -44,6 +45,9 @@ IndexedDBKey IndexedDBKeyBuilder::Build(const blink::WebIDBKey& key) {
switch (key.keyType()) {
case WebIDBKeyTypeArray:
return IndexedDBKey(CopyKeyArray(key));
+ case WebIDBKeyTypeBinary:
+ return IndexedDBKey(
+ std::string(key.binary().data(), key.binary().size()));
case WebIDBKeyTypeString:
return IndexedDBKey(key.string());
case WebIDBKeyTypeDate:
@@ -72,6 +76,8 @@ WebIDBKey WebIDBKeyBuilder::Build(const IndexedDBKey& key) {
}
return WebIDBKey::createArray(web_array);
}
+ case WebIDBKeyTypeBinary:
+ return WebIDBKey::createBinary(key.binary());
case WebIDBKeyTypeString:
return WebIDBKey::createString(key.string());
case WebIDBKeyTypeDate:
diff --git a/content/common/indexed_db/indexed_db_key.cc b/content/common/indexed_db/indexed_db_key.cc
index 0ee2383..71ddd6a 100644
--- a/content/common/indexed_db/indexed_db_key.cc
+++ b/content/common/indexed_db/indexed_db_key.cc
@@ -12,6 +12,7 @@ namespace content {
using blink::WebIDBKey;
using blink::WebIDBKeyType;
using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
using blink::WebIDBKeyTypeDate;
using blink::WebIDBKeyTypeInvalid;
using blink::WebIDBKeyTypeMin;
@@ -69,6 +70,12 @@ IndexedDBKey::IndexedDBKey(const KeyArray& keys)
number_(0),
size_estimate_(kOverheadSize + CalculateArraySize(keys)) {}
+IndexedDBKey::IndexedDBKey(const std::string& key)
+ : type_(WebIDBKeyTypeBinary),
+ binary_(key),
+ size_estimate_(kOverheadSize +
+ (key.length() * sizeof(std::string::value_type))) {}
+
IndexedDBKey::IndexedDBKey(const string16& key)
: type_(WebIDBKeyTypeString),
string_(key),
@@ -94,8 +101,10 @@ int IndexedDBKey::Compare(const IndexedDBKey& other) const {
if (array_.size() > other.array_.size())
return 1;
return 0;
+ case WebIDBKeyTypeBinary:
+ return binary_.compare(other.binary_);
case WebIDBKeyTypeString:
- return -other.string_.compare(string_);
+ return string_.compare(other.string_);
case WebIDBKeyTypeDate:
return (date_ < other.date_) ? -1 : (date_ > other.date_) ? 1 : 0;
case WebIDBKeyTypeNumber:
diff --git a/content/common/indexed_db/indexed_db_key.h b/content/common/indexed_db/indexed_db_key.h
index 8cfc67f..b10eb1f 100644
--- a/content/common/indexed_db/indexed_db_key.h
+++ b/content/common/indexed_db/indexed_db_key.h
@@ -26,6 +26,7 @@ class CONTENT_EXPORT IndexedDBKey {
IndexedDBKey(); // Defaults to blink::WebIDBKeyTypeInvalid.
IndexedDBKey(blink::WebIDBKeyType); // must be Null or Invalid
explicit IndexedDBKey(const KeyArray& array);
+ explicit IndexedDBKey(const std::string& binary);
explicit IndexedDBKey(const string16& str);
IndexedDBKey(double number,
blink::WebIDBKeyType type); // must be date or number
@@ -39,6 +40,7 @@ class CONTENT_EXPORT IndexedDBKey {
blink::WebIDBKeyType type() const { return type_; }
const std::vector<IndexedDBKey>& array() const { return array_; }
+ const std::string& binary() const { return binary_; }
const string16& string() const { return string_; }
double date() const { return date_; }
double number() const { return number_; }
@@ -48,6 +50,7 @@ class CONTENT_EXPORT IndexedDBKey {
private:
blink::WebIDBKeyType type_;
std::vector<IndexedDBKey> array_;
+ std::string binary_;
string16 string_;
double date_;
double number_;
diff --git a/content/common/indexed_db/indexed_db_param_traits.cc b/content/common/indexed_db/indexed_db_param_traits.cc
index 10c572f..94b2053 100644
--- a/content/common/indexed_db/indexed_db_param_traits.cc
+++ b/content/common/indexed_db/indexed_db_param_traits.cc
@@ -20,6 +20,7 @@ using blink::WebIDBKeyPathTypeNull;
using blink::WebIDBKeyPathTypeString;
using blink::WebIDBKeyType;
using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
using blink::WebIDBKeyTypeDate;
using blink::WebIDBKeyTypeInvalid;
using blink::WebIDBKeyTypeMin;
@@ -35,6 +36,9 @@ void ParamTraits<IndexedDBKey>::Write(Message* m, const param_type& p) {
case WebIDBKeyTypeArray:
WriteParam(m, p.array());
return;
+ case WebIDBKeyTypeBinary:
+ WriteParam(m, p.binary());
+ return;
case WebIDBKeyTypeString:
WriteParam(m, p.string());
return;
@@ -70,6 +74,13 @@ bool ParamTraits<IndexedDBKey>::Read(const Message* m,
*r = IndexedDBKey(array);
return true;
}
+ case WebIDBKeyTypeBinary: {
+ std::string binary;
+ if (!ReadParam(m, iter, &binary))
+ return false;
+ *r = IndexedDBKey(binary);
+ return true;
+ }
case WebIDBKeyTypeString: {
string16 string;
if (!ReadParam(m, iter, &string))
@@ -111,6 +122,8 @@ void ParamTraits<IndexedDBKey>::Log(const param_type& p, std::string* l) {
l->append(", ");
}
l->append("], ");
+ LogParam(p.binary(), l);
+ l->append(", ");
LogParam(p.string(), l);
l->append(", ");
LogParam(p.date(), l);