summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/drive
diff options
context:
space:
mode:
authorhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-17 09:16:46 +0000
committerhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-17 09:16:46 +0000
commit74f678eddfd2c35556d6c4e448889c1d8460429e (patch)
tree56ad0bf1f7634dc1d9b7d3b7112243f2574da677 /chrome/browser/chromeos/drive
parentd40b5e91db2725e975149c7bf344b6eeeac062bb (diff)
downloadchromium_src-74f678eddfd2c35556d6c4e448889c1d8460429e.zip
chromium_src-74f678eddfd2c35556d6c4e448889c1d8460429e.tar.gz
chromium_src-74f678eddfd2c35556d6c4e448889c1d8460429e.tar.bz2
chromeos: Check validity of loaded data in DriveResourceMetadataStorageDB::Initialize
Broken data should be detected and cleared during initialization to avoid fatal bugs. BUG=232054 TEST=unit_tests Review URL: https://codereview.chromium.org/14167009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194550 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos/drive')
-rw-r--r--chrome/browser/chromeos/drive/drive_resource_metadata_storage.cc76
-rw-r--r--chrome/browser/chromeos/drive/drive_resource_metadata_storage.h3
-rw-r--r--chrome/browser/chromeos/drive/drive_resource_metadata_storage_unittest.cc63
3 files changed, 133 insertions, 9 deletions
diff --git a/chrome/browser/chromeos/drive/drive_resource_metadata_storage.cc b/chrome/browser/chromeos/drive/drive_resource_metadata_storage.cc
index 17bf4e9..7546b1c 100644
--- a/chrome/browser/chromeos/drive/drive_resource_metadata_storage.cc
+++ b/chrome/browser/chromeos/drive/drive_resource_metadata_storage.cc
@@ -201,12 +201,10 @@ bool DriveResourceMetadataStorageDB::Initialize() {
if (status.ok())
child_map_.reset(db);
- // Check the version of existing DB.
+ // Check the validity of existing DB.
if (resource_map_ && child_map_) {
- scoped_ptr<DriveResourceMetadataHeader> header = GetHeader();
- if (!header ||
- header->version() != kDBVersion) {
- LOG(ERROR) << "Reject incompatible DB.";
+ if (!CheckValidity()) {
+ LOG(ERROR) << "Reject invalid DB.";
resource_map_.reset();
child_map_.reset();
}
@@ -429,4 +427,72 @@ DriveResourceMetadataStorageDB::GetHeader() {
return header.Pass();
}
+bool DriveResourceMetadataStorageDB::CheckValidity() {
+ base::ThreadRestrictions::AssertIOAllowed();
+
+ // Perform read with checksums verification enalbed.
+ leveldb::ReadOptions options;
+ options.verify_checksums = true;
+
+ scoped_ptr<leveldb::Iterator> it(resource_map_->NewIterator(options));
+ it->SeekToFirst();
+
+ // Check the header.
+ DriveResourceMetadataHeader header;
+ if (!it->Valid() ||
+ it->key() != GetHeaderDBKey() || // Header entry must come first.
+ !header.ParseFromArray(it->value().data(), it->value().size()) ||
+ header.version() != kDBVersion) {
+ DLOG(ERROR) << "Invalid header detected. version = " << header.version();
+ return false;
+ }
+
+ // Check all entires.
+ size_t num_checked_child_map_entries = 0;
+ DriveEntryProto entry;
+ std::string child_resource_id;
+ for (it->Next(); it->Valid(); it->Next()) {
+ // Check if stored data is broken.
+ if (!entry.ParseFromArray(it->value().data(), it->value().size()) ||
+ entry.resource_id() != it->key()) {
+ DLOG(ERROR) << "Broken entry detected";
+ return false;
+ }
+
+ // Check if parent-child relationship is stored correctly.
+ if (!entry.parent_resource_id().empty()) {
+ leveldb::Status status = child_map_->Get(
+ options,
+ leveldb::Slice(GetChildMapKey(entry.parent_resource_id(),
+ entry.base_name())),
+ &child_resource_id);
+ if (!status.ok() || child_resource_id != entry.resource_id()) {
+ DLOG(ERROR) << "Child map is broken. status = " << status.ToString();
+ return false;
+ }
+ ++num_checked_child_map_entries;
+ }
+ }
+ if (!it->status().ok()) {
+ DLOG(ERROR) << "Error during checking resource map. status = "
+ << it->status().ToString();
+ return false;
+ }
+
+ // Check all child map entries are referenced from |resource_map_|.
+ size_t num_child_map_entries = 0;
+ it.reset(child_map_->NewIterator(options));
+ for (it->SeekToFirst(); it->Valid(); it->Next()) {
+ ++num_child_map_entries;
+ }
+ if (!it->status().ok() ||
+ num_child_map_entries != num_checked_child_map_entries) {
+ DLOG(ERROR) << "Error during checking child map. status = "
+ << it->status().ToString();
+ return false;
+ }
+
+ return true;
+}
+
} // namespace drive
diff --git a/chrome/browser/chromeos/drive/drive_resource_metadata_storage.h b/chrome/browser/chromeos/drive/drive_resource_metadata_storage.h
index fb78c4b..13da193 100644
--- a/chrome/browser/chromeos/drive/drive_resource_metadata_storage.h
+++ b/chrome/browser/chromeos/drive/drive_resource_metadata_storage.h
@@ -162,6 +162,9 @@ class DriveResourceMetadataStorageDB
// Gets header.
scoped_ptr<DriveResourceMetadataHeader> GetHeader();
+ // Checks validity of the data.
+ bool CheckValidity();
+
// Path to the directory where the data is stored.
base::FilePath directory_path_;
diff --git a/chrome/browser/chromeos/drive/drive_resource_metadata_storage_unittest.cc b/chrome/browser/chromeos/drive/drive_resource_metadata_storage_unittest.cc
index 10dfd8f..f9f7c62 100644
--- a/chrome/browser/chromeos/drive/drive_resource_metadata_storage_unittest.cc
+++ b/chrome/browser/chromeos/drive/drive_resource_metadata_storage_unittest.cc
@@ -44,6 +44,10 @@ class DriveResourceMetadataStorageTest : public testing::Test {
storage_->PutHeader(*header);
}
+ bool CheckValidity() {
+ return storage_->CheckValidity();
+ }
+
base::ScopedTempDir temp_dir_;
scoped_ptr<DriveResourceMetadataStorageDB> storage_;
};
@@ -199,23 +203,32 @@ TEST_F(DriveResourceMetadataStorageTest, OpenExistingDB) {
DriveEntryProto entry1;
entry1.set_resource_id(parent_id1);
+ DriveEntryProto entry2;
+ entry2.set_resource_id(child_id1);
+ entry2.set_parent_resource_id(parent_id1);
+ entry2.set_base_name(child_name1);
// Put some data.
storage_->PutEntry(entry1);
+ storage_->PutEntry(entry2);
storage_->PutChild(parent_id1, child_name1, child_id1);
- scoped_ptr<DriveEntryProto> result = storage_->GetEntry(parent_id1);
- ASSERT_TRUE(result);
- EXPECT_EQ(parent_id1, result->resource_id());
- EXPECT_EQ(child_id1, storage_->GetChild(parent_id1, child_name1));
// Close DB and reopen.
storage_.reset(new DriveResourceMetadataStorageDB(temp_dir_.path()));
ASSERT_TRUE(storage_->Initialize());
// Can read data.
+ scoped_ptr<DriveEntryProto> result;
result = storage_->GetEntry(parent_id1);
ASSERT_TRUE(result);
EXPECT_EQ(parent_id1, result->resource_id());
+
+ result = storage_->GetEntry(child_id1);
+ ASSERT_TRUE(result);
+ EXPECT_EQ(child_id1, result->resource_id());
+ EXPECT_EQ(parent_id1, result->parent_resource_id());
+ EXPECT_EQ(child_name1, result->base_name());
+
EXPECT_EQ(child_id1, storage_->GetChild(parent_id1, child_name1));
}
@@ -251,4 +264,46 @@ TEST_F(DriveResourceMetadataStorageTest, WrongPath) {
ASSERT_FALSE(storage_->Initialize());
}
+TEST_F(DriveResourceMetadataStorageTest, CheckValidity) {
+ const std::string key1 = "foo";
+ const std::string name1 = "hoge";
+ const std::string key2 = "bar";
+ const std::string name2 = "fuga";
+ const std::string key3 = "boo";
+ const std::string name3 = "piyo";
+
+ // Put entry with key1.
+ DriveEntryProto entry;
+ entry.set_resource_id(key1);
+ entry.set_base_name(name1);
+ storage_->PutEntry(entry);
+ EXPECT_TRUE(CheckValidity());
+
+ // Put entry with key2 under key1.
+ entry.set_resource_id(key2);
+ entry.set_parent_resource_id(key1);
+ entry.set_base_name(name2);
+ storage_->PutEntry(entry);
+ EXPECT_FALSE(CheckValidity()); // Missing parent-child relationship.
+
+ // Add missing parent-child relationship between key1 and key2.
+ storage_->PutChild(key1, name2, key2);
+ EXPECT_TRUE(CheckValidity());
+
+ // Add parent-child relationship between key1 and key3.
+ storage_->PutChild(key1, name3, key3);
+ EXPECT_FALSE(CheckValidity()); // key3 is not stored in the storage.
+
+ // Put entry with key3 under key1.
+ entry.set_resource_id(key3);
+ entry.set_parent_resource_id(key1);
+ entry.set_base_name(name3);
+ storage_->PutEntry(entry);
+ EXPECT_TRUE(CheckValidity());
+
+ // Parent-child relationship with wrong name.
+ storage_->PutChild(key1, name2, key3);
+ EXPECT_FALSE(CheckValidity());
+}
+
} // namespace drive