Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / chromeos / login / users / avatar / user_image_sync_observer.cc
blobbf501d12330461c877619b417f5e1787587a4998
1 // Copyright 2014 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.
5 #include "chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h"
7 #include "base/bind.h"
8 #include "base/prefs/pref_change_registrar.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/chromeos/login/screens/user_image_screen.h"
12 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
13 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
14 #include "chrome/browser/chromeos/login/wizard_controller.h"
15 #include "chrome/browser/chromeos/profiles/profile_helper.h"
16 #include "chrome/browser/prefs/pref_service_syncable_util.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/syncable_prefs/pref_service_syncable.h"
19 #include "components/user_manager/user.h"
20 #include "components/user_manager/user_image/default_user_images.h"
21 #include "components/user_manager/user_manager.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "content/public/browser/notification_service.h"
25 namespace chromeos {
26 namespace {
28 // A dictionary containing info about user image.
29 const char kUserImageInfo[] = "user_image_info";
30 // Path to value with image index.
31 const char kImageIndex[] = "image_index";
33 bool IsIndexSupported(int index) {
34 return (index >= user_manager::kFirstDefaultImageIndex &&
35 index < user_manager::kDefaultImagesCount) ||
36 (index == user_manager::User::USER_IMAGE_PROFILE);
39 } // anonymous namespace
41 UserImageSyncObserver::Observer::~Observer() {}
43 UserImageSyncObserver::UserImageSyncObserver(const user_manager::User* user)
44 : user_(user),
45 prefs_(NULL),
46 is_synced_(false),
47 local_image_changed_(false) {
48 notification_registrar_.reset(new content::NotificationRegistrar);
49 notification_registrar_->Add(this,
50 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
51 content::NotificationService::AllSources());
52 if (Profile* profile = ProfileHelper::Get()->GetProfileByUser(user)) {
53 OnProfileGained(profile);
54 } else {
55 notification_registrar_->Add(this,
56 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
57 content::NotificationService::AllSources());
61 UserImageSyncObserver::~UserImageSyncObserver() {
62 if (!is_synced_ && prefs_)
63 prefs_->RemoveObserver(this);
64 if (pref_change_registrar_)
65 pref_change_registrar_->RemoveAll();
68 // static
69 void UserImageSyncObserver::RegisterProfilePrefs(
70 user_prefs::PrefRegistrySyncable* registry_) {
71 registry_->RegisterDictionaryPref(
72 kUserImageInfo,
73 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
76 void UserImageSyncObserver::AddObserver(Observer* observer) {
77 observer_list_.AddObserver(observer);
80 void UserImageSyncObserver::RemoveObserver(Observer* observer) {
81 observer_list_.RemoveObserver(observer);
84 void UserImageSyncObserver::OnProfileGained(Profile* profile) {
85 prefs_ = PrefServiceSyncableFromProfile(profile);
86 pref_change_registrar_.reset(new PrefChangeRegistrar);
87 pref_change_registrar_->Init(prefs_);
88 pref_change_registrar_->Add(kUserImageInfo,
89 base::Bind(&UserImageSyncObserver::OnPreferenceChanged,
90 base::Unretained(this)));
91 is_synced_ = prefs_->IsPrioritySyncing();
92 if (!is_synced_) {
93 prefs_->AddObserver(this);
94 } else {
95 OnInitialSync();
99 void UserImageSyncObserver::OnInitialSync() {
100 int synced_index;
101 bool local_image_updated = false;
102 if (!GetSyncedImageIndex(&synced_index) || local_image_changed_) {
103 UpdateSyncedImageFromLocal();
104 } else if (IsIndexSupported(synced_index) && CanUpdateLocalImageNow()) {
105 UpdateLocalImageFromSynced();
106 local_image_updated = true;
108 FOR_EACH_OBSERVER(UserImageSyncObserver::Observer, observer_list_,
109 OnInitialSync(local_image_updated));
112 void UserImageSyncObserver::OnPreferenceChanged(const std::string& pref_name) {
113 // OnPreferenceChanged can be called before OnIsSyncingChanged.
114 if (!is_synced_) {
115 is_synced_ = true;
116 prefs_->RemoveObserver(this);
117 OnInitialSync();
118 } else if (CanUpdateLocalImageNow()) {
119 UpdateLocalImageFromSynced();
123 void UserImageSyncObserver::Observe(
124 int type,
125 const content::NotificationSource& source,
126 const content::NotificationDetails& details) {
127 if (type == chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) {
128 if (Profile* profile = ProfileHelper::Get()->GetProfileByUser(user_)) {
129 notification_registrar_->Remove(
130 this,
131 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
132 content::NotificationService::AllSources());
133 OnProfileGained(profile);
135 } else if (type == chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) {
136 if (is_synced_)
137 UpdateSyncedImageFromLocal();
138 else
139 local_image_changed_ = true;
140 } else {
141 NOTREACHED();
145 void UserImageSyncObserver::OnIsSyncingChanged() {
146 is_synced_ = prefs_->IsPrioritySyncing();
147 if (is_synced_) {
148 prefs_->RemoveObserver(this);
149 OnInitialSync();
153 void UserImageSyncObserver::UpdateSyncedImageFromLocal() {
154 int local_index = user_->image_index();
155 if (!IsIndexSupported(local_index)) {
156 local_index = user_manager::User::USER_IMAGE_INVALID;
158 int synced_index;
159 if (GetSyncedImageIndex(&synced_index) && (synced_index == local_index))
160 return;
161 DictionaryPrefUpdate update(prefs_, kUserImageInfo);
162 base::DictionaryValue* dict = update.Get();
163 dict->SetInteger(kImageIndex, local_index);
164 VLOG(1) << "Saved avatar index " << local_index << " to sync.";
167 void UserImageSyncObserver::UpdateLocalImageFromSynced() {
168 int synced_index;
169 GetSyncedImageIndex(&synced_index);
170 int local_index = user_->image_index();
171 if ((synced_index == local_index) || !IsIndexSupported(synced_index))
172 return;
173 UserImageManager* image_manager =
174 ChromeUserManager::Get()->GetUserImageManager(user_->email());
175 if (synced_index == user_manager::User::USER_IMAGE_PROFILE) {
176 image_manager->SaveUserImageFromProfileImage();
177 } else {
178 image_manager->SaveUserDefaultImageIndex(synced_index);
180 VLOG(1) << "Loaded avatar index " << synced_index << " from sync.";
183 bool UserImageSyncObserver::GetSyncedImageIndex(int* index) {
184 *index = user_manager::User::USER_IMAGE_INVALID;
185 const base::DictionaryValue* dict = prefs_->GetDictionary(kUserImageInfo);
186 return dict && dict->GetInteger(kImageIndex, index);
189 bool UserImageSyncObserver::CanUpdateLocalImageNow() {
190 if (WizardController* wizard_controller =
191 WizardController::default_controller()) {
192 UserImageScreen* screen = UserImageScreen::Get(wizard_controller);
193 if (wizard_controller->current_screen() == screen) {
194 if (screen->user_selected_image())
195 return false;
198 return true;
201 } // namespace chromeos