1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file. 43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h" 63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/bind.h" 83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/prefs/pref_change_registrar.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/chrome_notification_types.h" 113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/chromeos/login/screens/user_image_screen.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h" 136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" 143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/chromeos/login/wizard_controller.h" 153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/chromeos/profiles/profile_helper.h" 163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable.h" 173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/common/pref_names.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/user_manager/user.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/user_manager/user_image/default_user_images.h" 206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h" 213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/notification_registrar.h" 223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/notification_service.h" 233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace chromeos { 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace { 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// A dictionary containing info about user image. 283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kUserImageInfo[] = "user_image_info"; 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Path to value with image index. 303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kImageIndex[] = "image_index"; 313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IsIndexSupported(int index) { 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (index >= user_manager::kFirstDefaultImageIndex && 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index < user_manager::kDefaultImagesCount) || 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (index == user_manager::User::USER_IMAGE_PROFILE); 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} // anonymous namespace 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)UserImageSyncObserver::Observer::~Observer() {} 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UserImageSyncObserver::UserImageSyncObserver(const user_manager::User* user) 433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : user_(user), 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) prefs_(NULL), 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_synced_(false), 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) local_image_changed_(false) { 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_registrar_.reset(new content::NotificationRegistrar); 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_registrar_->Add(this, 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) content::NotificationService::AllSources()); 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (Profile* profile = ProfileHelper::Get()->GetProfileByUser(user)) { 523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) OnProfileGained(profile); 533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_registrar_->Add(this, 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, 563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) content::NotificationService::AllSources()); 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)UserImageSyncObserver::~UserImageSyncObserver() { 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!is_synced_ && prefs_) 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) prefs_->RemoveObserver(this); 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (pref_change_registrar_) 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pref_change_registrar_->RemoveAll(); 653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// static 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::RegisterProfilePrefs( 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_prefs::PrefRegistrySyncable* registry_) { 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) registry_->RegisterDictionaryPref( 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kUserImageInfo, 723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::AddObserver(Observer* observer) { 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) observer_list_.AddObserver(observer); 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::RemoveObserver(Observer* observer) { 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) observer_list_.RemoveObserver(observer); 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::OnProfileGained(Profile* profile) { 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) prefs_ = PrefServiceSyncable::FromProfile(profile); 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pref_change_registrar_.reset(new PrefChangeRegistrar); 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pref_change_registrar_->Init(prefs_); 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pref_change_registrar_->Add(kUserImageInfo, 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Bind(&UserImageSyncObserver::OnPreferenceChanged, 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Unretained(this))); 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_synced_ = prefs_->IsPrioritySyncing(); 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!is_synced_) { 923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) prefs_->AddObserver(this); 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) OnInitialSync(); 953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::OnInitialSync() { 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int synced_index; 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool local_image_updated = false; 1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!GetSyncedImageIndex(&synced_index) || local_image_changed_) { 1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) UpdateSyncedImageFromLocal(); 1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (IsIndexSupported(synced_index) && CanUpdateLocalImageNow()) { 1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) UpdateLocalImageFromSynced(); 1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) local_image_updated = true; 1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FOR_EACH_OBSERVER(UserImageSyncObserver::Observer, observer_list_, 1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) OnInitialSync(local_image_updated)); 1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::OnPreferenceChanged(const std::string& pref_name) { 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // OnPreferenceChanged can be called before OnIsSyncingChanged. 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!is_synced_) { 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_synced_ = true; 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) prefs_->RemoveObserver(this); 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) OnInitialSync(); 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (CanUpdateLocalImageNow()) { 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) UpdateLocalImageFromSynced(); 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::Observe( 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int type, 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const content::NotificationSource& source, 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const content::NotificationDetails& details) { 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (type == chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) { 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (Profile* profile = ProfileHelper::Get()->GetProfileByUser(user_)) { 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) notification_registrar_->Remove( 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this, 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) content::NotificationService::AllSources()); 1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnProfileGained(profile); 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (type == chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) { 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (is_synced_) 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) UpdateSyncedImageFromLocal(); 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) else 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) local_image_changed_ = true; 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NOTREACHED(); 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::OnIsSyncingChanged() { 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_synced_ = prefs_->IsPrioritySyncing(); 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (is_synced_) { 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) prefs_->RemoveObserver(this); 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) OnInitialSync(); 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::UpdateSyncedImageFromLocal() { 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int local_index = user_->image_index(); 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!IsIndexSupported(local_index)) { 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) local_index = user_manager::User::USER_IMAGE_INVALID; 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int synced_index; 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (GetSyncedImageIndex(&synced_index) && (synced_index == local_index)) 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DictionaryPrefUpdate update(prefs_, kUserImageInfo); 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = update.Get(); 1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dict->SetInteger(kImageIndex, local_index); 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Saved avatar index " << local_index << " to sync."; 1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserImageSyncObserver::UpdateLocalImageFromSynced() { 1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int synced_index; 1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetSyncedImageIndex(&synced_index); 1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int local_index = user_->image_index(); 1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((synced_index == local_index) || !IsIndexSupported(synced_index)) 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UserImageManager* image_manager = 1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ChromeUserManager::Get()->GetUserImageManager(user_->email()); 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (synced_index == user_manager::User::USER_IMAGE_PROFILE) { 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) image_manager->SaveUserImageFromProfileImage(); 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) image_manager->SaveUserDefaultImageIndex(synced_index); 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Loaded avatar index " << synced_index << " from sync."; 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool UserImageSyncObserver::GetSyncedImageIndex(int* index) { 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *index = user_manager::User::USER_IMAGE_INVALID; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* dict = prefs_->GetDictionary(kUserImageInfo); 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return dict && dict->GetInteger(kImageIndex, index); 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool UserImageSyncObserver::CanUpdateLocalImageNow() { 1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (WizardController* wizard_controller = 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) WizardController::default_controller()) { 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UserImageScreen* screen = UserImageScreen::Get(wizard_controller); 1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (wizard_controller->current_screen() == screen) { 1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (screen->user_selected_image()) 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} // namespace chromeos 2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 202