Home | History | Annotate | Download | only in contacts
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/contacts/contact_manager.h"
      6 
      7 #include "base/logging.h"
      8 #include "chrome/browser/browser_process.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/browser/chromeos/contacts/contact.pb.h"
     11 #include "chrome/browser/chromeos/contacts/contact_manager_observer.h"
     12 #include "chrome/browser/chromeos/contacts/contact_store.h"
     13 #include "chrome/browser/chromeos/contacts/google_contact_store.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/profiles/profile_manager.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "content/public/browser/notification_service.h"
     18 
     19 using content::BrowserThread;
     20 
     21 namespace contacts {
     22 
     23 namespace {
     24 
     25 // Singleton instance.
     26 ContactManager* g_instance = NULL;
     27 
     28 }  // namespace
     29 
     30 // static
     31 ContactManager* ContactManager::GetInstance() {
     32   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     33   DCHECK(g_instance);
     34   return g_instance;
     35 }
     36 
     37 ContactManager::ContactManager()
     38     : profile_observers_deleter_(&profile_observers_),
     39       contact_store_factory_(new GoogleContactStoreFactory),
     40       contact_stores_deleter_(&contact_stores_),
     41       weak_ptr_factory_(this) {
     42   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     43   DCHECK(!g_instance);
     44   g_instance = this;
     45 }
     46 
     47 ContactManager::~ContactManager() {
     48   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     49   DCHECK_EQ(g_instance, this);
     50   weak_ptr_factory_.InvalidateWeakPtrs();
     51   g_instance = NULL;
     52   for (ContactStoreMap::const_iterator it = contact_stores_.begin();
     53        it != contact_stores_.end(); ++it) {
     54     it->second->RemoveObserver(this);
     55   }
     56 }
     57 
     58 void ContactManager::SetContactStoreForTesting(
     59     scoped_ptr<ContactStoreFactory> factory) {
     60   DCHECK(contact_stores_.empty());
     61   contact_store_factory_.swap(factory);
     62 }
     63 
     64 void ContactManager::Init() {
     65   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     66   registrar_.Add(
     67       this,
     68       chrome::NOTIFICATION_PROFILE_CREATED,
     69       content::NotificationService::AllSources());
     70   registrar_.Add(
     71       this,
     72       chrome::NOTIFICATION_PROFILE_DESTROYED,
     73       content::NotificationService::AllSources());
     74 
     75   // Notify about any already-existing profiles.
     76   std::vector<Profile*> profiles(
     77       g_browser_process->profile_manager()->GetLoadedProfiles());
     78   for (size_t i = 0; i < profiles.size(); ++i)
     79     HandleProfileCreated(profiles[i]);
     80 }
     81 
     82 base::WeakPtr<ContactManagerInterface> ContactManager::GetWeakPtr() {
     83   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     84   return weak_ptr_factory_.GetWeakPtr();
     85 }
     86 
     87 void ContactManager::AddObserver(ContactManagerObserver* observer,
     88                                  Profile* profile) {
     89   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     90   DCHECK(observer);
     91   DCHECK(profile);
     92   Observers* observers = GetObserversForProfile(profile, true);
     93   observers->AddObserver(observer);
     94 }
     95 
     96 void ContactManager::RemoveObserver(ContactManagerObserver* observer,
     97                                     Profile* profile) {
     98   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     99   DCHECK(observer);
    100   DCHECK(profile);
    101   Observers* observers = GetObserversForProfile(profile, false);
    102   if (observers)
    103     observers->RemoveObserver(observer);
    104 }
    105 
    106 scoped_ptr<ContactPointers> ContactManager::GetAllContacts(Profile* profile) {
    107   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    108   DCHECK(profile);
    109   scoped_ptr<ContactPointers> contacts(new ContactPointers);
    110   ContactStoreMap::const_iterator it = contact_stores_.find(profile);
    111   if (it != contact_stores_.end())
    112     it->second->AppendContacts(contacts.get());
    113   return contacts.Pass();
    114 }
    115 
    116 const Contact* ContactManager::GetContactById(Profile* profile,
    117                                               const std::string& contact_id) {
    118   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    119   DCHECK(profile);
    120   ContactStoreMap::const_iterator it = contact_stores_.find(profile);
    121   return it != contact_stores_.end() ?
    122          it->second->GetContactById(contact_id) :
    123          NULL;
    124 }
    125 
    126 void ContactManager::OnContactsUpdated(ContactStore* store) {
    127   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    128   for (ContactStoreMap::const_iterator it = contact_stores_.begin();
    129        it != contact_stores_.end(); ++it) {
    130     if (it->second == store) {
    131       Profile* profile = it->first;
    132       Observers* observers = GetObserversForProfile(profile, false);
    133       if (observers) {
    134         FOR_EACH_OBSERVER(ContactManagerObserver,
    135                           *observers,
    136                           OnContactsUpdated(profile));
    137       }
    138       return;
    139     }
    140   }
    141   NOTREACHED() << "Got update from unknown contact store " << store;
    142 }
    143 
    144 void ContactManager::Observe(int type,
    145                              const content::NotificationSource& source,
    146                              const content::NotificationDetails& details) {
    147   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    148   switch (type) {
    149     case chrome::NOTIFICATION_PROFILE_CREATED:
    150       HandleProfileCreated(content::Source<Profile>(source).ptr());
    151       break;
    152     case chrome::NOTIFICATION_PROFILE_DESTROYED: {
    153       Profile* profile = content::Details<Profile>(details).ptr();
    154       if (profile)
    155         HandleProfileDestroyed(profile);
    156       break;
    157     }
    158     default:
    159       NOTREACHED() << "Unexpected notification " << type;
    160   }
    161 }
    162 
    163 ContactManager::Observers* ContactManager::GetObserversForProfile(
    164     Profile* profile,
    165     bool create) {
    166   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    167   ProfileObserversMap::const_iterator it = profile_observers_.find(profile);
    168   if (it != profile_observers_.end())
    169     return it->second;
    170   if (!create)
    171     return NULL;
    172 
    173   Observers* observers = new Observers;
    174   profile_observers_[profile] = observers;
    175   return observers;
    176 }
    177 
    178 void ContactManager::HandleProfileCreated(Profile* profile) {
    179   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    180   DCHECK(profile);
    181 
    182   ContactStoreMap::iterator it = contact_stores_.find(profile);
    183   if (it != contact_stores_.end())
    184     return;
    185 
    186   if (!contact_store_factory_->CanCreateContactStoreForProfile(profile))
    187     return;
    188 
    189   VLOG(1) << "Adding profile " << profile->GetProfileName();
    190   ContactStore* store = contact_store_factory_->CreateContactStore(profile);
    191   DCHECK(store);
    192   store->AddObserver(this);
    193   store->Init();
    194   DCHECK_EQ(contact_stores_.count(profile), static_cast<size_t>(0));
    195   contact_stores_[profile] = store;
    196 }
    197 
    198 void ContactManager::HandleProfileDestroyed(Profile* profile) {
    199   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    200   DCHECK(profile);
    201 
    202   ContactStoreMap::iterator store_it = contact_stores_.find(profile);
    203   if (store_it != contact_stores_.end()) {
    204     store_it->second->RemoveObserver(this);
    205     delete store_it->second;
    206     contact_stores_.erase(store_it);
    207   }
    208 
    209   ProfileObserversMap::iterator observer_it = profile_observers_.find(profile);
    210   if (observer_it != profile_observers_.end()) {
    211     delete observer_it->second;
    212     profile_observers_.erase(observer_it);
    213   }
    214 }
    215 
    216 }  // namespace contacts
    217