15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/contacts/contact_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/contacts/contact.pb.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/contacts/contact_manager_observer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/contacts/contact_store.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/contacts/google_contact_store.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace contacts {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Singleton instance.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContactManager* g_instance = NULL;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContactManager* ContactManager::GetInstance() {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(g_instance);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_instance;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContactManager::ContactManager()
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_observers_deleter_(&profile_observers_),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      contact_store_factory_(new GoogleContactStoreFactory),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      contact_stores_deleter_(&contact_stores_),
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!g_instance);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_instance = this;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContactManager::~ContactManager() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(g_instance, this);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_instance = NULL;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ContactStoreMap::const_iterator it = contact_stores_.begin();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != contact_stores_.end(); ++it) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->second->RemoveObserver(this);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::SetContactStoreForTesting(
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ContactStoreFactory> factory) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(contact_stores_.empty());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contact_store_factory_.swap(factory);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::Init() {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_PROFILE_CREATED,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_PROFILE_DESTROYED,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify about any already-existing profiles.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Profile*> profiles(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_browser_process->profile_manager()->GetLoadedProfiles());
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < profiles.size(); ++i)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HandleProfileCreated(profiles[i]);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::WeakPtr<ContactManagerInterface> ContactManager::GetWeakPtr() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return weak_ptr_factory_.GetWeakPtr();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::AddObserver(ContactManagerObserver* observer,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 Profile* profile) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(observer);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Observers* observers = GetObserversForProfile(profile, true);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers->AddObserver(observer);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::RemoveObserver(ContactManagerObserver* observer,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    Profile* profile) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(observer);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Observers* observers = GetObserversForProfile(profile, false);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observers)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers->RemoveObserver(observer);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<ContactPointers> ContactManager::GetAllContacts(Profile* profile) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ContactPointers> contacts(new ContactPointers);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContactStoreMap::const_iterator it = contact_stores_.find(profile);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != contact_stores_.end())
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->second->AppendContacts(contacts.get());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contacts.Pass();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Contact* ContactManager::GetContactById(Profile* profile,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const std::string& contact_id) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContactStoreMap::const_iterator it = contact_stores_.find(profile);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it != contact_stores_.end() ?
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it->second->GetContactById(contact_id) :
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         NULL;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::OnContactsUpdated(ContactStore* store) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ContactStoreMap::const_iterator it = contact_stores_.begin();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != contact_stores_.end(); ++it) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->second == store) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile* profile = it->first;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Observers* observers = GetObserversForProfile(profile, false);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (observers) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FOR_EACH_OBSERVER(ContactManagerObserver,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          *observers,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          OnContactsUpdated(profile));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Got update from unknown contact store " << store;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::Observe(int type,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationSource& source,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationDetails& details) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_PROFILE_CREATED:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleProfileCreated(content::Source<Profile>(source).ptr());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_PROFILE_DESTROYED: {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile* profile = content::Details<Profile>(details).ptr();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (profile)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        HandleProfileDestroyed(profile);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected notification " << type;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContactManager::Observers* ContactManager::GetObserversForProfile(
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool create) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileObserversMap::const_iterator it = profile_observers_.find(profile);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != profile_observers_.end())
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!create)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Observers* observers = new Observers;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_observers_[profile] = observers;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return observers;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::HandleProfileCreated(Profile* profile) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContactStoreMap::iterator it = contact_stores_.find(profile);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != contact_stores_.end())
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!contact_store_factory_->CanCreateContactStoreForProfile(profile))
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Adding profile " << profile->GetProfileName();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContactStore* store = contact_store_factory_->CreateContactStore(profile);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(store);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->AddObserver(this);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->Init();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(contact_stores_.count(profile), static_cast<size_t>(0));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contact_stores_[profile] = store;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ContactManager::HandleProfileDestroyed(Profile* profile) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContactStoreMap::iterator store_it = contact_stores_.find(profile);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (store_it != contact_stores_.end()) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    store_it->second->RemoveObserver(this);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete store_it->second;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contact_stores_.erase(store_it);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileObserversMap::iterator observer_it = profile_observers_.find(profile);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_it != profile_observers_.end()) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete observer_it->second;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_observers_.erase(observer_it);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace contacts
217