| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/chromeos/contacts/google_contact_store.h" | 5 #include "chrome/browser/chromeos/contacts/google_contact_store.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 } | 74 } |
| 75 | 75 |
| 76 void GoogleContactStore::TestAPI::NotifyAboutNetworkStateChange(bool online) { | 76 void GoogleContactStore::TestAPI::NotifyAboutNetworkStateChange(bool online) { |
| 77 net::NetworkChangeNotifier::ConnectionType type = | 77 net::NetworkChangeNotifier::ConnectionType type = |
| 78 online ? | 78 online ? |
| 79 net::NetworkChangeNotifier::CONNECTION_UNKNOWN : | 79 net::NetworkChangeNotifier::CONNECTION_UNKNOWN : |
| 80 net::NetworkChangeNotifier::CONNECTION_NONE; | 80 net::NetworkChangeNotifier::CONNECTION_NONE; |
| 81 store_->OnConnectionTypeChanged(type); | 81 store_->OnConnectionTypeChanged(type); |
| 82 } | 82 } |
| 83 | 83 |
| 84 scoped_ptr<ContactPointers> GoogleContactStore::TestAPI::GetLoadedContacts() { |
| 85 scoped_ptr<ContactPointers> contacts(new ContactPointers); |
| 86 for (ContactMap::const_iterator it = store_->contacts_.begin(); |
| 87 it != store_->contacts_.end(); ++it) { |
| 88 contacts->push_back(it->second); |
| 89 } |
| 90 return contacts.Pass(); |
| 91 } |
| 92 |
| 84 GoogleContactStore::GoogleContactStore(Profile* profile) | 93 GoogleContactStore::GoogleContactStore(Profile* profile) |
| 85 : profile_(profile), | 94 : profile_(profile), |
| 86 db_(new ContactDatabase), | 95 db_(new ContactDatabase), |
| 87 update_delay_on_next_failure_( | 96 update_delay_on_next_failure_( |
| 88 base::TimeDelta::FromSeconds(kUpdateFailureInitialRetrySec)), | 97 base::TimeDelta::FromSeconds(kUpdateFailureInitialRetrySec)), |
| 89 is_online_(true), | 98 is_online_(true), |
| 90 should_update_when_online_(false), | 99 should_update_when_online_(false), |
| 91 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 100 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 93 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | 102 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 124 for (ContactMap::const_iterator it = contacts_.begin(); | 133 for (ContactMap::const_iterator it = contacts_.begin(); |
| 125 it != contacts_.end(); ++it) { | 134 it != contacts_.end(); ++it) { |
| 126 if (!it->second->deleted()) | 135 if (!it->second->deleted()) |
| 127 contacts_out->push_back(it->second); | 136 contacts_out->push_back(it->second); |
| 128 } | 137 } |
| 129 } | 138 } |
| 130 | 139 |
| 131 const Contact* GoogleContactStore::GetContactById( | 140 const Contact* GoogleContactStore::GetContactById( |
| 132 const std::string& contact_id) { | 141 const std::string& contact_id) { |
| 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 134 const Contact* contact = contacts_.Find(contact_id); | 143 return contacts_.Find(contact_id); |
| 135 return (contact && !contact->deleted()) ? contact : NULL; | |
| 136 } | 144 } |
| 137 | 145 |
| 138 void GoogleContactStore::AddObserver(ContactStoreObserver* observer) { | 146 void GoogleContactStore::AddObserver(ContactStoreObserver* observer) { |
| 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 140 DCHECK(observer); | 148 DCHECK(observer); |
| 141 observers_.AddObserver(observer); | 149 observers_.AddObserver(observer); |
| 142 } | 150 } |
| 143 | 151 |
| 144 void GoogleContactStore::RemoveObserver(ContactStoreObserver* observer) { | 152 void GoogleContactStore::RemoveObserver(ContactStoreObserver* observer) { |
| 145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 VLOG(1) << "Scheduling update of " << profile_->GetProfileName() | 241 VLOG(1) << "Scheduling update of " << profile_->GetProfileName() |
| 234 << " in " << delay.InSeconds() << " second(s)"; | 242 << " in " << delay.InSeconds() << " second(s)"; |
| 235 update_timer_.Start( | 243 update_timer_.Start( |
| 236 FROM_HERE, delay, this, &GoogleContactStore::UpdateContacts); | 244 FROM_HERE, delay, this, &GoogleContactStore::UpdateContacts); |
| 237 } | 245 } |
| 238 | 246 |
| 239 void GoogleContactStore::MergeContacts( | 247 void GoogleContactStore::MergeContacts( |
| 240 bool is_full_update, | 248 bool is_full_update, |
| 241 scoped_ptr<ScopedVector<Contact> > updated_contacts) { | 249 scoped_ptr<ScopedVector<Contact> > updated_contacts) { |
| 242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 243 if (is_full_update) | 251 |
| 252 if (is_full_update) { |
| 244 contacts_.Clear(); | 253 contacts_.Clear(); |
| 245 size_t num_updated_contacts = updated_contacts->size(); | 254 last_contact_update_time_ = base::Time(); |
| 246 contacts_.Merge(updated_contacts.Pass(), ContactMap::KEEP_DELETED_CONTACTS); | 255 } |
| 247 | 256 |
| 248 if (is_full_update || num_updated_contacts > 0) | 257 // Find the maximum update time from |updated_contacts| since contacts whose |
| 249 last_contact_update_time_ = contacts_.GetMaxUpdateTime(); | 258 // |deleted| flags are set won't be saved to |contacts_|. |
| 259 for (ScopedVector<Contact>::iterator it = updated_contacts->begin(); |
| 260 it != updated_contacts->end(); ++it) { |
| 261 last_contact_update_time_ = |
| 262 std::max(last_contact_update_time_, |
| 263 base::Time::FromInternalValue((*it)->update_time())); |
| 264 } |
| 250 VLOG(1) << "Last contact update time is " | 265 VLOG(1) << "Last contact update time is " |
| 251 << (last_contact_update_time_.is_null() ? | 266 << (last_contact_update_time_.is_null() ? |
| 252 std::string("null") : | 267 std::string("null") : |
| 253 gdata::util::FormatTimeAsString(last_contact_update_time_)); | 268 gdata::util::FormatTimeAsString(last_contact_update_time_)); |
| 269 |
| 270 contacts_.Merge(updated_contacts.Pass(), ContactMap::DROP_DELETED_CONTACTS); |
| 254 } | 271 } |
| 255 | 272 |
| 256 void GoogleContactStore::OnDownloadSuccess( | 273 void GoogleContactStore::OnDownloadSuccess( |
| 257 bool is_full_update, | 274 bool is_full_update, |
| 258 const base::Time& update_start_time, | 275 const base::Time& update_start_time, |
| 259 scoped_ptr<ScopedVector<Contact> > updated_contacts) { | 276 scoped_ptr<ScopedVector<Contact> > updated_contacts) { |
| 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 261 VLOG(1) << "Got " << updated_contacts->size() << " contact(s) for " | 278 VLOG(1) << "Got " << updated_contacts->size() << " contact(s) for " |
| 262 << profile_->GetProfileName(); | 279 << profile_->GetProfileName(); |
| 263 | 280 |
| 264 // Copy the pointers so we can update just these contacts in the database. | 281 // Copy the pointers so we can update just these contacts in the database. |
| 265 scoped_ptr<ContactPointers> contacts_to_save_to_db(new ContactPointers); | 282 scoped_ptr<ContactPointers> contacts_to_save_to_db(new ContactPointers); |
| 283 scoped_ptr<ContactDatabaseInterface::ContactIds> |
| 284 contact_ids_to_delete_from_db(new ContactDatabaseInterface::ContactIds); |
| 266 if (db_) { | 285 if (db_) { |
| 267 for (size_t i = 0; i < updated_contacts->size(); ++i) | 286 for (size_t i = 0; i < updated_contacts->size(); ++i) { |
| 268 contacts_to_save_to_db->push_back((*updated_contacts)[i]); | 287 Contact* contact = (*updated_contacts)[i]; |
| 288 if (contact->deleted()) |
| 289 contact_ids_to_delete_from_db->push_back(contact->contact_id()); |
| 290 else |
| 291 contacts_to_save_to_db->push_back(contact); |
| 292 } |
| 269 } | 293 } |
| 270 bool got_updates = !updated_contacts->empty(); | 294 bool got_updates = !updated_contacts->empty(); |
| 271 | 295 |
| 272 MergeContacts(is_full_update, updated_contacts.Pass()); | 296 MergeContacts(is_full_update, updated_contacts.Pass()); |
| 273 last_successful_update_start_time_ = update_start_time; | 297 last_successful_update_start_time_ = update_start_time; |
| 274 | 298 |
| 275 if (is_full_update || got_updates) { | 299 if (is_full_update || got_updates) { |
| 276 FOR_EACH_OBSERVER(ContactStoreObserver, | 300 FOR_EACH_OBSERVER(ContactStoreObserver, |
| 277 observers_, | 301 observers_, |
| 278 OnContactsUpdated(this)); | 302 OnContactsUpdated(this)); |
| 279 } | 303 } |
| 280 | 304 |
| 281 if (db_) { | 305 if (db_) { |
| 282 // Even if this was an incremental update and we didn't get any updated | 306 // Even if this was an incremental update and we didn't get any updated |
| 283 // contacts, we still want to write updated metadata containing | 307 // contacts, we still want to write updated metadata containing |
| 284 // |update_start_time|. | 308 // |update_start_time|. |
| 285 VLOG(1) << "Saving " << contacts_to_save_to_db->size() << " contact(s) to " | 309 VLOG(1) << "Saving " << contacts_to_save_to_db->size() << " contact(s) to " |
| 286 << "database as " << (is_full_update ? "full" : "incremental") | 310 << "database and deleting " << contact_ids_to_delete_from_db->size() |
| 287 << " update"; | 311 << " as " << (is_full_update ? "full" : "incremental") << " update"; |
| 312 |
| 288 scoped_ptr<UpdateMetadata> metadata(new UpdateMetadata); | 313 scoped_ptr<UpdateMetadata> metadata(new UpdateMetadata); |
| 289 metadata->set_last_update_start_time(update_start_time.ToInternalValue()); | 314 metadata->set_last_update_start_time(update_start_time.ToInternalValue()); |
| 315 metadata->set_last_contact_update_time( |
| 316 last_contact_update_time_.ToInternalValue()); |
| 317 |
| 290 db_->SaveContacts( | 318 db_->SaveContacts( |
| 291 contacts_to_save_to_db.Pass(), | 319 contacts_to_save_to_db.Pass(), |
| 320 contact_ids_to_delete_from_db.Pass(), |
| 292 metadata.Pass(), | 321 metadata.Pass(), |
| 293 is_full_update, | 322 is_full_update, |
| 294 base::Bind(&GoogleContactStore::OnDatabaseContactsSaved, | 323 base::Bind(&GoogleContactStore::OnDatabaseContactsSaved, |
| 295 weak_ptr_factory_.GetWeakPtr())); | 324 weak_ptr_factory_.GetWeakPtr())); |
| 296 | 325 |
| 297 // We'll schedule an update from OnDatabaseContactsSaved() after we're done | 326 // We'll schedule an update from OnDatabaseContactsSaved() after we're done |
| 298 // writing to the database -- we don't want to modify the contacts while | 327 // writing to the database -- we don't want to modify the contacts while |
| 299 // they're being used by the database. | 328 // they're being used by the database. |
| 300 } else { | 329 } else { |
| 301 ScheduleUpdate(true); | 330 ScheduleUpdate(true); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 328 void GoogleContactStore::OnDatabaseContactsLoaded( | 357 void GoogleContactStore::OnDatabaseContactsLoaded( |
| 329 bool success, | 358 bool success, |
| 330 scoped_ptr<ScopedVector<Contact> > contacts, | 359 scoped_ptr<ScopedVector<Contact> > contacts, |
| 331 scoped_ptr<UpdateMetadata> metadata) { | 360 scoped_ptr<UpdateMetadata> metadata) { |
| 332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 333 if (success) { | 362 if (success) { |
| 334 VLOG(1) << "Loaded " << contacts->size() << " contact(s) from database"; | 363 VLOG(1) << "Loaded " << contacts->size() << " contact(s) from database"; |
| 335 MergeContacts(true, contacts.Pass()); | 364 MergeContacts(true, contacts.Pass()); |
| 336 last_successful_update_start_time_ = | 365 last_successful_update_start_time_ = |
| 337 base::Time::FromInternalValue(metadata->last_update_start_time()); | 366 base::Time::FromInternalValue(metadata->last_update_start_time()); |
| 367 last_contact_update_time_ = std::max( |
| 368 last_contact_update_time_, |
| 369 base::Time::FromInternalValue(metadata->last_contact_update_time())); |
| 338 | 370 |
| 339 if (!contacts_.empty()) { | 371 if (!contacts_.empty()) { |
| 340 FOR_EACH_OBSERVER(ContactStoreObserver, | 372 FOR_EACH_OBSERVER(ContactStoreObserver, |
| 341 observers_, | 373 observers_, |
| 342 OnContactsUpdated(this)); | 374 OnContactsUpdated(this)); |
| 343 } | 375 } |
| 344 } else { | 376 } else { |
| 345 LOG(WARNING) << "Failed to load contacts from database"; | 377 LOG(WARNING) << "Failed to load contacts from database"; |
| 346 } | 378 } |
| 347 UpdateContacts(); | 379 UpdateContacts(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 370 return gdata::util::IsGDataAvailable(profile); | 402 return gdata::util::IsGDataAvailable(profile); |
| 371 } | 403 } |
| 372 | 404 |
| 373 ContactStore* GoogleContactStoreFactory::CreateContactStore(Profile* profile) { | 405 ContactStore* GoogleContactStoreFactory::CreateContactStore(Profile* profile) { |
| 374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 406 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 375 DCHECK(CanCreateContactStoreForProfile(profile)); | 407 DCHECK(CanCreateContactStoreForProfile(profile)); |
| 376 return new GoogleContactStore(profile); | 408 return new GoogleContactStore(profile); |
| 377 } | 409 } |
| 378 | 410 |
| 379 } // namespace contacts | 411 } // namespace contacts |
| OLD | NEW |