| Index: chrome/browser/chromeos/contacts/contact_database.cc
|
| diff --git a/chrome/browser/chromeos/contacts/contact_database.cc b/chrome/browser/chromeos/contacts/contact_database.cc
|
| index c5b4c62d80068d1c27e78c998d0a5acfa364ff34..f843fc579aab9b0221d088357457cac414d2dedb 100644
|
| --- a/chrome/browser/chromeos/contacts/contact_database.cc
|
| +++ b/chrome/browser/chromeos/contacts/contact_database.cc
|
| @@ -22,6 +22,13 @@ using content::BrowserThread;
|
|
|
| namespace contacts {
|
|
|
| +namespace {
|
| +
|
| +// LevelDB key used for storing UpdateMetadata messages.
|
| +const char kUpdateMetadataKey[] = "__chrome_update_metadata__";
|
| +
|
| +} // namespace
|
| +
|
| ContactDatabase::ContactDatabase() : weak_ptr_factory_(this) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
|
| @@ -54,6 +61,7 @@ void ContactDatabase::Init(const FilePath& database_dir,
|
| }
|
|
|
| void ContactDatabase::SaveContacts(scoped_ptr<ContactPointers> contacts,
|
| + scoped_ptr<UpdateMetadata> metadata,
|
| bool is_full_update,
|
| SaveCallback callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| @@ -63,6 +71,7 @@ void ContactDatabase::SaveContacts(scoped_ptr<ContactPointers> contacts,
|
| base::Bind(&ContactDatabase::SaveContactsFromTaskRunner,
|
| base::Unretained(this),
|
| base::Passed(contacts.Pass()),
|
| + base::Passed(metadata.Pass()),
|
| is_full_update,
|
| success),
|
| base::Bind(&ContactDatabase::RunSaveCallback,
|
| @@ -73,20 +82,28 @@ void ContactDatabase::SaveContacts(scoped_ptr<ContactPointers> contacts,
|
|
|
| void ContactDatabase::LoadContacts(LoadCallback callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| bool* success = new bool(false);
|
| scoped_ptr<ScopedVector<Contact> > contacts(new ScopedVector<Contact>);
|
| + scoped_ptr<UpdateMetadata> metadata(new UpdateMetadata);
|
| +
|
| + // Extract pointers before we calling Pass() so we can use them below.
|
| ScopedVector<Contact>* contacts_ptr = contacts.get();
|
| + UpdateMetadata* metadata_ptr = metadata.get();
|
| +
|
| task_runner_->PostTaskAndReply(
|
| FROM_HERE,
|
| base::Bind(&ContactDatabase::LoadContactsFromTaskRunner,
|
| base::Unretained(this),
|
| success,
|
| - contacts_ptr),
|
| + contacts_ptr,
|
| + metadata_ptr),
|
| base::Bind(&ContactDatabase::RunLoadCallback,
|
| weak_ptr_factory_.GetWeakPtr(),
|
| callback,
|
| base::Owned(success),
|
| - base::Passed(contacts.Pass())));
|
| + base::Passed(contacts.Pass()),
|
| + base::Passed(metadata.Pass())));
|
| }
|
|
|
| ContactDatabase::~ContactDatabase() {
|
| @@ -117,9 +134,10 @@ void ContactDatabase::RunSaveCallback(SaveCallback callback,
|
| void ContactDatabase::RunLoadCallback(
|
| LoadCallback callback,
|
| const bool* success,
|
| - scoped_ptr<ScopedVector<Contact> > contacts) {
|
| + scoped_ptr<ScopedVector<Contact> > contacts,
|
| + scoped_ptr<UpdateMetadata> metadata) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - callback.Run(*success, contacts.Pass());
|
| + callback.Run(*success, contacts.Pass(), metadata.Pass());
|
| }
|
|
|
| void ContactDatabase::InitFromTaskRunner(const FilePath& database_dir,
|
| @@ -161,6 +179,7 @@ void ContactDatabase::InitFromTaskRunner(const FilePath& database_dir,
|
|
|
| void ContactDatabase::SaveContactsFromTaskRunner(
|
| scoped_ptr<ContactPointers> contacts,
|
| + scoped_ptr<UpdateMetadata> metadata,
|
| bool is_full_update,
|
| bool* success) {
|
| DCHECK(IsRunByTaskRunner());
|
| @@ -178,7 +197,9 @@ void ContactDatabase::SaveContactsFromTaskRunner(
|
| scoped_ptr<leveldb::Iterator> db_iterator(db_->NewIterator(options));
|
| db_iterator->SeekToFirst();
|
| while (db_iterator->Valid()) {
|
| - keys_to_delete.insert(db_iterator->key().ToString());
|
| + std::string key = db_iterator->key().ToString();
|
| + if (key != kUpdateMetadataKey)
|
| + keys_to_delete.insert(key);
|
| db_iterator->Next();
|
| }
|
| }
|
| @@ -192,9 +213,15 @@ void ContactDatabase::SaveContactsFromTaskRunner(
|
| for (ContactPointers::const_iterator it = contacts->begin();
|
| it != contacts->end(); ++it) {
|
| const contacts::Contact& contact = **it;
|
| + if (contact.provider_id() == kUpdateMetadataKey) {
|
| + LOG(WARNING) << "Skipping contact with reserved ID "
|
| + << contact.provider_id();
|
| + continue;
|
| + }
|
| updates.Put(leveldb::Slice(contact.provider_id()),
|
| leveldb::Slice(contact.SerializeAsString()));
|
| - keys_to_delete.erase(contact.provider_id());
|
| + if (is_full_update)
|
| + keys_to_delete.erase(contact.provider_id());
|
| }
|
|
|
| for (std::set<std::string>::const_iterator it = keys_to_delete.begin();
|
| @@ -202,6 +229,9 @@ void ContactDatabase::SaveContactsFromTaskRunner(
|
| updates.Delete(leveldb::Slice(*it));
|
| }
|
|
|
| + updates.Put(leveldb::Slice(kUpdateMetadataKey),
|
| + leveldb::Slice(metadata->SerializeAsString()));
|
| +
|
| leveldb::WriteOptions options;
|
| options.sync = true;
|
| leveldb::Status status = db_->Write(options, &updates);
|
| @@ -213,26 +243,37 @@ void ContactDatabase::SaveContactsFromTaskRunner(
|
|
|
| void ContactDatabase::LoadContactsFromTaskRunner(
|
| bool* success,
|
| - ScopedVector<Contact>* contacts_out) {
|
| + ScopedVector<Contact>* contacts,
|
| + UpdateMetadata* metadata) {
|
| DCHECK(IsRunByTaskRunner());
|
| DCHECK(success);
|
| - DCHECK(contacts_out);
|
| + DCHECK(contacts);
|
| + DCHECK(metadata);
|
|
|
| *success = false;
|
| - contacts_out->clear();
|
| + contacts->clear();
|
| + metadata->Clear();
|
|
|
| leveldb::ReadOptions options;
|
| scoped_ptr<leveldb::Iterator> db_iterator(db_->NewIterator(options));
|
| db_iterator->SeekToFirst();
|
| while (db_iterator->Valid()) {
|
| - scoped_ptr<Contact> contact(new Contact);
|
| leveldb::Slice value_slice = db_iterator->value();
|
| - if (!contact->ParseFromArray(value_slice.data(), value_slice.size())) {
|
| - LOG(WARNING) << "Unable to parse contact "
|
| - << db_iterator->key().ToString();
|
| - return;
|
| +
|
| + if (db_iterator->key().ToString() == kUpdateMetadataKey) {
|
| + if (!metadata->ParseFromArray(value_slice.data(), value_slice.size())) {
|
| + LOG(WARNING) << "Unable to parse metadata";
|
| + return;
|
| + }
|
| + } else {
|
| + scoped_ptr<Contact> contact(new Contact);
|
| + if (!contact->ParseFromArray(value_slice.data(), value_slice.size())) {
|
| + LOG(WARNING) << "Unable to parse contact "
|
| + << db_iterator->key().ToString();
|
| + return;
|
| + }
|
| + contacts->push_back(contact.release());
|
| }
|
| - contacts_out->push_back(contact.release());
|
| db_iterator->Next();
|
| }
|
|
|
|
|