// 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