| // 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/chrome_notification_types.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 "content/public/browser/browser_thread.h" |
| #include "content/public/browser/notification_service.h" |
| |
| using content::BrowserThread; |
| |
| namespace contacts { |
| |
| namespace { |
| |
| // Singleton instance. |
| ContactManager* g_instance = NULL; |
| |
| } // namespace |
| |
| // static |
| ContactManager* ContactManager::GetInstance() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK(g_instance); |
| return g_instance; |
| } |
| |
| ContactManager::ContactManager() |
| : profile_observers_deleter_(&profile_observers_), |
| contact_store_factory_(new GoogleContactStoreFactory), |
| contact_stores_deleter_(&contact_stores_), |
| weak_ptr_factory_(this) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK(!g_instance); |
| g_instance = this; |
| } |
| |
| ContactManager::~ContactManager() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK_EQ(g_instance, this); |
| weak_ptr_factory_.InvalidateWeakPtrs(); |
| g_instance = NULL; |
| for (ContactStoreMap::const_iterator it = contact_stores_.begin(); |
| it != contact_stores_.end(); ++it) { |
| it->second->RemoveObserver(this); |
| } |
| } |
| |
| void ContactManager::SetContactStoreForTesting( |
| 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]); |
| } |
| |
| base::WeakPtr<ContactManagerInterface> ContactManager::GetWeakPtr() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| 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::GetContactById(Profile* profile, |
| const std::string& contact_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK(profile); |
| ContactStoreMap::const_iterator it = contact_stores_.find(profile); |
| return it != contact_stores_.end() ? |
| it->second->GetContactById(contact_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(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); |
| 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()) { |
| store_it->second->RemoveObserver(this); |
| 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 |