OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/chromeos/login/user_image_sync_observer.h" | |
6 | |
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" | |
24 | |
25 namespace chromeos { | |
26 namespace { | |
27 | |
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"; | |
32 | |
33 bool IsIndexSupported(int index) { | |
34 return (index >= kFirstDefaultImageIndex && index < kDefaultImagesCount) || | |
35 (index == User::kProfileImageIndex); | |
36 } | |
37 | |
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); | |
45 } | |
46 | |
47 } // anonymous namespace | |
48 | |
49 UserImageSyncObserver::Observer::~Observer() {} | |
50 | |
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()); | |
67 } | |
68 } | |
69 | |
70 UserImageSyncObserver::~UserImageSyncObserver() { | |
71 if (!is_synced_ && prefs_) | |
72 prefs_->RemoveObserver(this); | |
73 if (pref_change_registrar_) | |
74 pref_change_registrar_->RemoveAll(); | |
75 } | |
76 | |
77 // static | |
78 void UserImageSyncObserver::RegisterProfilePrefs( | |
79 user_prefs::PrefRegistrySyncable* registry_) { | |
80 registry_->RegisterDictionaryPref( | |
81 kUserImageInfo, | |
82 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); | |
83 } | |
84 | |
85 void UserImageSyncObserver::AddObserver(Observer* observer) { | |
86 observer_list_.AddObserver(observer); | |
87 } | |
88 | |
89 void UserImageSyncObserver::RemoveObserver(Observer* observer) { | |
90 observer_list_.RemoveObserver(observer); | |
91 } | |
92 | |
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(); | |
105 } | |
106 } | |
107 | |
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; | |
116 } | |
117 FOR_EACH_OBSERVER(UserImageSyncObserver::Observer, observer_list_, | |
118 OnInitialSync(local_image_updated)); | |
119 } | |
120 | |
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(); | |
129 } | |
130 } | |
131 | |
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(); | |
152 } | |
153 } | |
154 | |
155 void UserImageSyncObserver::OnIsSyncingChanged() { | |
156 is_synced_ = prefs_->IsPrioritySyncing(); | |
157 if (is_synced_) { | |
158 prefs_->RemoveObserver(this); | |
159 OnInitialSync(); | |
160 } | |
161 } | |
162 | |
163 void UserImageSyncObserver::UpdateSyncedImageFromLocal() { | |
164 int local_index = user_->image_index(); | |
165 if (!IsIndexSupported(local_index)) { | |
166 local_index = User::kInvalidImageIndex; | |
167 } | |
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."; | |
175 } | |
176 | |
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); | |
189 } | |
190 VLOG(1) << "Loaded avatar index " << synced_index << " from sync."; | |
191 } | |
192 | |
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); | |
197 } | |
198 | |
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; | |
206 } | |
207 } | |
208 return true; | |
209 } | |
210 | |
211 } // namespace chromeos | |
212 | |
OLD | NEW |