Chromium Code Reviews| Index: chrome/browser/chromeos/contacts/contact_manager.cc |
| diff --git a/chrome/browser/chromeos/contacts/contact_manager.cc b/chrome/browser/chromeos/contacts/contact_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7f21632c97dd5baa302fb5e9f086aee05e12d0af |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/contacts/contact_manager.cc |
| @@ -0,0 +1,201 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/chromeos/contacts/contact_manager.h" |
| + |
| +#include "base/logging.h" |
| +#include "chrome/browser/browser_process.h" |
| +#include "chrome/browser/chromeos/contacts/contact.pb.h" |
| +#include "chrome/browser/chromeos/contacts/contact_manager_observer.h" |
| +#include "chrome/browser/chromeos/contacts/contact_store.h" |
| +#include "chrome/browser/chromeos/contacts/google_contact_store.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/browser/profiles/profile_manager.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/notification_service.h" |
| + |
| +using content::BrowserThread; |
| + |
| +namespace contacts { |
| + |
| +ContactManager* ContactManager::instance_ = NULL; |
| + |
| +// static |
| +ContactManager* ContactManager::GetInstance() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(instance_); |
| + return instance_; |
| +} |
| + |
| +ContactManager::ContactManager() |
| + : profile_observers_deleter_(&profile_observers_), |
| + contact_store_factory_(new GoogleContactStoreFactory), |
| + contact_stores_deleter_(&contact_stores_) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(!instance_); |
| + instance_ = this; |
| +} |
| + |
| +ContactManager::~ContactManager() { |
| + // This should also be running on the UI thread but we can't check it; the |
| + // message loop is already getting torn down at this point. |
|
Daniel Erat
2012/08/03 22:12:07
I think that I can avoid this by just destroying t
|
| + DCHECK_EQ(instance_, this); |
| + instance_ = NULL; |
| +} |
| + |
| +void ContactManager::set_contact_store_factory_for_testing( |
| + scoped_ptr<ContactStoreFactory> factory) { |
| + DCHECK(contact_stores_.empty()); |
| + contact_store_factory_.swap(factory); |
| +} |
| + |
| +void ContactManager::Init() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + registrar_.Add( |
| + this, |
| + chrome::NOTIFICATION_PROFILE_CREATED, |
| + content::NotificationService::AllSources()); |
| + registrar_.Add( |
| + this, |
| + chrome::NOTIFICATION_PROFILE_DESTROYED, |
| + content::NotificationService::AllSources()); |
| + |
| + // Notify about any already-existing profiles. |
| + std::vector<Profile*> profiles( |
| + g_browser_process->profile_manager()->GetLoadedProfiles()); |
| + for (size_t i = 0; i < profiles.size(); ++i) |
| + HandleProfileCreated(profiles[i]); |
| +} |
| + |
| +void ContactManager::AddObserver(ContactManagerObserver* observer, |
| + Profile* profile) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(observer); |
| + DCHECK(profile); |
| + Observers* observers = GetObserversForProfile(profile, true); |
| + observers->AddObserver(observer); |
| +} |
| + |
| +void ContactManager::RemoveObserver(ContactManagerObserver* observer, |
| + Profile* profile) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(observer); |
| + DCHECK(profile); |
| + Observers* observers = GetObserversForProfile(profile, false); |
| + if (observers) |
| + observers->RemoveObserver(observer); |
| +} |
| + |
| +scoped_ptr<ContactPointers> ContactManager::GetAllContacts(Profile* profile) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(profile); |
| + scoped_ptr<ContactPointers> contacts(new ContactPointers); |
| + ContactStoreMap::const_iterator it = contact_stores_.find(profile); |
| + if (it != contact_stores_.end()) |
| + it->second->AppendContacts(contacts.get()); |
| + return contacts.Pass(); |
| +} |
| + |
| +const Contact* ContactManager::GetContactByProviderId( |
| + Profile* profile, |
| + const std::string& provider_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(profile); |
| + ContactStoreMap::const_iterator it = contact_stores_.find(profile); |
| + return it != contact_stores_.end() ? |
| + it->second->GetContactByProviderId(provider_id) : |
| + NULL; |
| +} |
| + |
| +void ContactManager::OnContactsUpdated(ContactStore* store) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + for (ContactStoreMap::const_iterator it = contact_stores_.begin(); |
| + it != contact_stores_.end(); ++it) { |
| + if (it->second == store) { |
| + Profile* profile = it->first; |
| + Observers* observers = GetObserversForProfile(profile, false); |
| + if (observers) { |
| + FOR_EACH_OBSERVER(ContactManagerObserver, |
| + *observers, |
| + OnContactsUpdated(this, profile)); |
| + } |
| + return; |
| + } |
| + } |
| + NOTREACHED() << "Got update from unknown contact store " << store; |
| +} |
| + |
| +void ContactManager::Observe(int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + switch (type) { |
| + case chrome::NOTIFICATION_PROFILE_CREATED: |
| + HandleProfileCreated(content::Source<Profile>(source).ptr()); |
| + break; |
| + case chrome::NOTIFICATION_PROFILE_DESTROYED: { |
| + Profile* profile = content::Details<Profile>(details).ptr(); |
| + if (profile) |
| + HandleProfileDestroyed(profile); |
| + break; |
| + } |
| + default: |
| + NOTREACHED() << "Unexpected notification " << type; |
| + } |
| +} |
| + |
| +ContactManager::Observers* ContactManager::GetObserversForProfile( |
| + Profile* profile, |
| + bool create) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + ProfileObserversMap::const_iterator it = profile_observers_.find(profile); |
| + if (it != profile_observers_.end()) |
| + return it->second; |
| + if (!create) |
| + return NULL; |
| + |
| + Observers* observers = new Observers; |
| + profile_observers_[profile] = observers; |
| + return observers; |
| +} |
| + |
| +void ContactManager::HandleProfileCreated(Profile* profile) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(profile); |
| + |
| + ContactStoreMap::iterator it = contact_stores_.find(profile); |
| + if (it != contact_stores_.end()) |
| + return; |
| + |
| + if (!contact_store_factory_->CanCreateContactStoreForProfile(profile)) |
| + return; |
| + |
| + VLOG(1) << "Adding profile " << profile->GetProfileName(); |
| + ContactStore* store = contact_store_factory_->CreateContactStore(profile); |
| + DCHECK(store); |
| + store->AddObserver(this); |
|
satorux1
2012/08/03 21:16:22
I don't see store->RemoveObserver(this); Usually t
Daniel Erat
2012/08/03 22:12:07
Heh, went back and forth on this. Updated.
|
| + store->Init(); |
| + DCHECK_EQ(contact_stores_.count(profile), static_cast<size_t>(0)); |
| + contact_stores_[profile] = store; |
| +} |
| + |
| +void ContactManager::HandleProfileDestroyed(Profile* profile) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(profile); |
| + |
| + ContactStoreMap::iterator store_it = contact_stores_.find(profile); |
| + if (store_it != contact_stores_.end()) { |
| + delete store_it->second; |
| + contact_stores_.erase(store_it); |
| + } |
| + |
| + ProfileObserversMap::iterator observer_it = profile_observers_.find(profile); |
| + if (observer_it != profile_observers_.end()) { |
| + delete observer_it->second; |
| + profile_observers_.erase(observer_it); |
| + } |
| +} |
| + |
| +} // namespace contacts |