Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / user_image_sync_observer.cc
blobc699a6030554213869341573525a205f803e8b8d
1 // Copyright 2013 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/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/browser_process.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/chromeos/login/default_user_images.h"
13 #include "chrome/browser/chromeos/login/screens/user_image_screen.h"
14 #include "chrome/browser/chromeos/login/user.h"
15 #include "chrome/browser/chromeos/login/user_image_manager.h"
16 #include "chrome/browser/chromeos/login/wizard_controller.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/prefs/pref_service_syncable.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/common/pref_names.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 >= kFirstDefaultImageIndex && index < kDefaultImagesCount) ||
35 (index == User::kProfileImageIndex);
38 Profile* GetUserProfile() {
39 ProfileManager* profile_manager = g_browser_process->profile_manager();
40 if (!profile_manager || !profile_manager->IsLoggedIn())
41 return NULL;
42 base::FilePath profile_path = profile_manager->user_data_dir().Append(
43 profile_manager->GetInitialProfileDir());
44 return profile_manager->GetProfileByPath(profile_path);
47 } // anonymous namespace
49 UserImageSyncObserver::Observer::~Observer() {}
51 UserImageSyncObserver::UserImageSyncObserver(const User* user)
52 : user_(user),
53 prefs_(NULL),
54 is_synced_(false),
55 local_image_changed_(false) {
56 notification_registrar_.reset(new content::NotificationRegistrar);
57 notification_registrar_->Add(this,
58 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
59 content::NotificationService::AllSources());
60 Profile* profile = GetUserProfile();
61 if (profile) {
62 OnProfileGained(profile);
63 } else {
64 notification_registrar_->Add(this,
65 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
66 content::NotificationService::AllSources());
70 UserImageSyncObserver::~UserImageSyncObserver() {
71 if (!is_synced_ && prefs_)
72 prefs_->RemoveObserver(this);
73 if (pref_change_registrar_)
74 pref_change_registrar_->RemoveAll();
77 // static
78 void UserImageSyncObserver::RegisterProfilePrefs(
79 user_prefs::PrefRegistrySyncable* registry_) {
80 registry_->RegisterDictionaryPref(
81 kUserImageInfo,
82 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
85 void UserImageSyncObserver::AddObserver(Observer* observer) {
86 observer_list_.AddObserver(observer);
89 void UserImageSyncObserver::RemoveObserver(Observer* observer) {
90 observer_list_.RemoveObserver(observer);
93 void UserImageSyncObserver::OnProfileGained(Profile* profile) {
94 prefs_ = PrefServiceSyncable::FromProfile(profile);
95 pref_change_registrar_.reset(new PrefChangeRegistrar);
96 pref_change_registrar_->Init(prefs_);
97 pref_change_registrar_->Add(kUserImageInfo,
98 base::Bind(&UserImageSyncObserver::OnPreferenceChanged,
99 base::Unretained(this)));
100 is_synced_ = prefs_->IsPrioritySyncing();
101 if (!is_synced_) {
102 prefs_->AddObserver(this);
103 } else {
104 OnInitialSync();
108 void UserImageSyncObserver::OnInitialSync() {
109 int synced_index;
110 bool local_image_updated = false;
111 if (!GetSyncedImageIndex(&synced_index) || local_image_changed_) {
112 UpdateSyncedImageFromLocal();
113 } else if (IsIndexSupported(synced_index) && CanUpdateLocalImageNow()) {
114 UpdateLocalImageFromSynced();
115 local_image_updated = true;
117 FOR_EACH_OBSERVER(UserImageSyncObserver::Observer, observer_list_,
118 OnInitialSync(local_image_updated));
121 void UserImageSyncObserver::OnPreferenceChanged(const std::string& pref_name) {
122 // OnPreferenceChanged can be called before OnIsSyncingChanged.
123 if (!is_synced_) {
124 is_synced_ = true;
125 prefs_->RemoveObserver(this);
126 OnInitialSync();
127 } else if (CanUpdateLocalImageNow()) {
128 UpdateLocalImageFromSynced();
132 void UserImageSyncObserver::Observe(
133 int type,
134 const content::NotificationSource& source,
135 const content::NotificationDetails& details) {
136 if (type == chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) {
137 Profile* profile = content::Details<Profile>(details).ptr();
138 if (GetUserProfile() != profile)
139 return;
140 notification_registrar_->Remove(
141 this,
142 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
143 content::NotificationService::AllSources());
144 OnProfileGained(profile);
145 } else if (type == chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) {
146 if (is_synced_)
147 UpdateSyncedImageFromLocal();
148 else
149 local_image_changed_ = true;
150 } else {
151 NOTREACHED();
155 void UserImageSyncObserver::OnIsSyncingChanged() {
156 is_synced_ = prefs_->IsPrioritySyncing();
157 if (is_synced_) {
158 prefs_->RemoveObserver(this);
159 OnInitialSync();
163 void UserImageSyncObserver::UpdateSyncedImageFromLocal() {
164 int local_index = user_->image_index();
165 if (!IsIndexSupported(local_index)) {
166 local_index = User::kInvalidImageIndex;
168 int synced_index;
169 if (GetSyncedImageIndex(&synced_index) && (synced_index == local_index))
170 return;
171 DictionaryPrefUpdate update(prefs_, kUserImageInfo);
172 base::DictionaryValue* dict = update.Get();
173 dict->SetInteger(kImageIndex, local_index);
174 VLOG(1) << "Saved avatar index " << local_index << " to sync.";
177 void UserImageSyncObserver::UpdateLocalImageFromSynced() {
178 int synced_index;
179 GetSyncedImageIndex(&synced_index);
180 int local_index = user_->image_index();
181 if ((synced_index == local_index) || !IsIndexSupported(synced_index))
182 return;
183 UserImageManager* image_manager =
184 UserManager::Get()->GetUserImageManager(user_->email());
185 if (synced_index == User::kProfileImageIndex) {
186 image_manager->SaveUserImageFromProfileImage();
187 } else {
188 image_manager->SaveUserDefaultImageIndex(synced_index);
190 VLOG(1) << "Loaded avatar index " << synced_index << " from sync.";
193 bool UserImageSyncObserver::GetSyncedImageIndex(int* index) {
194 *index = User::kInvalidImageIndex;
195 const base::DictionaryValue* dict = prefs_->GetDictionary(kUserImageInfo);
196 return dict && dict->GetInteger(kImageIndex, index);
199 bool UserImageSyncObserver::CanUpdateLocalImageNow() {
200 if (WizardController* wizard_controller =
201 WizardController::default_controller()) {
202 UserImageScreen* screen = wizard_controller->GetUserImageScreen();
203 if (wizard_controller->current_screen() == screen) {
204 if (screen->user_selected_image())
205 return false;
208 return true;
211 } // namespace chromeos