- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / contacts / contact_manager.cc
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