1 // Copyright (c) 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 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_ 6 #define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_ 7 8 #include <map> 9 #include <set> 10 #include <string> 11 12 #include "base/basictypes.h" 13 #include "base/compiler_specific.h" 14 #include "base/memory/linked_ptr.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/time/time.h" 19 #include "base/timer/timer.h" 20 #include "base/values.h" 21 #include "chrome/browser/chromeos/login/user.h" 22 #include "chrome/browser/chromeos/login/user_image_loader.h" 23 #include "chrome/browser/chromeos/login/user_image_manager.h" 24 #include "chrome/browser/chromeos/policy/cloud_external_data_policy_observer.h" 25 #include "chrome/browser/profiles/profile_downloader_delegate.h" 26 #include "ui/gfx/image/image_skia.h" 27 28 class ProfileDownloader; 29 class UserImage; 30 31 namespace base { 32 class FilePath; 33 class SequencedTaskRunner; 34 } 35 36 namespace chromeos { 37 38 class CrosSettings; 39 class UserImageSyncObserver; 40 class UserManager; 41 42 class UserImageManagerImpl 43 : public UserImageManager, 44 public ProfileDownloaderDelegate, 45 public policy::CloudExternalDataPolicyObserver::Delegate { 46 public: 47 UserImageManagerImpl(CrosSettings* cros_settings, UserManager* user_manager); 48 49 // UserImageManager: 50 virtual ~UserImageManagerImpl(); 51 virtual void LoadUserImages(const UserList& users) OVERRIDE; 52 virtual void UserLoggedIn(const std::string& user_id, 53 bool user_is_new, 54 bool user_is_local) OVERRIDE; 55 virtual void SaveUserDefaultImageIndex(const std::string& user_id, 56 int default_image_index) OVERRIDE; 57 virtual void SaveUserImage(const std::string& user_id, 58 const UserImage& user_image) OVERRIDE; 59 virtual void SaveUserImageFromFile(const std::string& user_id, 60 const base::FilePath& path) OVERRIDE; 61 virtual void SaveUserImageFromProfileImage( 62 const std::string& user_id) OVERRIDE; 63 virtual void DeleteUserImage(const std::string& user_id) OVERRIDE; 64 virtual void DownloadProfileImage(const std::string& reason) OVERRIDE; 65 virtual const gfx::ImageSkia& DownloadedProfileImage() const OVERRIDE; 66 virtual UserImageSyncObserver* GetSyncObserver() const OVERRIDE; 67 virtual void Shutdown() OVERRIDE; 68 69 // policy::CloudExternalDataPolicyObserver::Delegate: 70 virtual void OnExternalDataSet(const std::string& policy, 71 const std::string& user_id) OVERRIDE; 72 virtual void OnExternalDataCleared(const std::string& policy, 73 const std::string& user_id) OVERRIDE; 74 virtual void OnExternalDataFetched(const std::string& policy, 75 const std::string& user_id, 76 scoped_ptr<std::string> data) OVERRIDE; 77 78 static void IgnoreProfileDataDownloadDelayForTesting(); 79 void StopPolicyObserverForTesting(); 80 81 private: 82 friend class UserImageManagerTest; 83 84 // Every image load or update is encapsulated by a Job. Whenever an image load 85 // or update is requested for a user, the Job currently running for that user 86 // (if any) is canceled. This ensures that at most one Job is running per user 87 // at any given time. There are two further guarantees: 88 // 89 // * Changes to User objects and local state are performed on the thread that 90 // |this| runs on. 91 // * File writes and deletions are performed via |background_task_runner_|. 92 // 93 // With the above, it is guaranteed that any changes made by a canceled Job 94 // cannot race against against changes made by the superseding Job. 95 class Job; 96 97 // ProfileDownloaderDelegate: 98 virtual bool NeedsProfilePicture() const OVERRIDE; 99 virtual int GetDesiredImageSideLength() const OVERRIDE; 100 virtual Profile* GetBrowserProfile() OVERRIDE; 101 virtual std::string GetCachedPictureURL() const OVERRIDE; 102 virtual void OnProfileDownloadSuccess(ProfileDownloader* downloader) OVERRIDE; 103 virtual void OnProfileDownloadFailure( 104 ProfileDownloader* downloader, 105 ProfileDownloaderDelegate::FailureReason reason) OVERRIDE; 106 107 // Returns true if the user image for |user_id| is managed by policy and the 108 // user is not allowed to change it. 109 bool IsUserImageManaged(const std::string& user_id) const; 110 111 // Randomly chooses one of the default images for the specified user, sends a 112 // LOGIN_USER_IMAGE_CHANGED notification and updates local state. 113 void SetInitialUserImage(const std::string& user_id); 114 115 // Initializes the |downloaded_profile_image_| for the currently logged-in 116 // user to a profile image that had been downloaded and saved before if such 117 // a saved image is available and no updated image has been downloaded yet. 118 void TryToInitDownloadedProfileImage(); 119 120 // Returns true if the profile image needs to be downloaded. This is the case 121 // when a GAIA user is logged in and at least one of the following applies: 122 // * The profile image has explicitly been requested by a call to 123 // DownloadProfileImage() and has not been successfully downloaded since. 124 // * The user's user image is the profile image. 125 bool NeedProfileImage() const; 126 127 // Downloads the profile data for the currently logged-in user. The user's 128 // full name and, if NeedProfileImage() is true, the profile image are 129 // downloaded. |reason| is an arbitrary string (used to report UMA histograms 130 // with download times). 131 void DownloadProfileData(const std::string& reason); 132 133 // Removes |user_id| from the dictionary |prefs_dict_root| in local state and 134 // deletes the image file that the dictionary referenced for that user. 135 void DeleteUserImageAndLocalStateEntry(const std::string& user_id, 136 const char* prefs_dict_root); 137 138 // Called when a Job updates the copy of the user image held in memory by 139 // |user|. Allows |this| to update |downloaded_profile_image_| and send a 140 // NOTIFICATION_LOGIN_USER_IMAGE_CHANGED notification. 141 void OnJobChangedUserImage(const User* user); 142 143 // Called when a Job for |user_id| finishes. If a migration was required for 144 // the user, the migration is now complete and the old image file for that 145 // user, if any, is deleted. 146 void OnJobDone(const std::string& user_id); 147 148 // Completes migration by removing |user_id| from the old prefs dictionary. 149 void UpdateLocalStateAfterMigration(const std::string& user_id); 150 151 // Create a sync observer if a user is logged in, the user's user image is 152 // allowed to be synced and no sync observer exists yet. 153 void TryToCreateImageSyncObserver(); 154 155 // The user manager. 156 UserManager* user_manager_; 157 158 // Loader for JPEG user images. 159 scoped_refptr<UserImageLoader> image_loader_; 160 161 // Unsafe loader instance for all user images formats. 162 scoped_refptr<UserImageLoader> unsafe_image_loader_; 163 164 // Whether the |profile_downloader_| is downloading the profile image for the 165 // currently logged-in user (and not just the full name). Only valid when a 166 // download is currently in progress. 167 bool downloading_profile_image_; 168 169 // Download reason given to DownloadProfileImage(), used for UMA histograms. 170 // Only valid when a download is currently in progress and 171 // |downloading_profile_image_| is true. 172 std::string profile_image_download_reason_; 173 174 // Time when the profile image download started. Only valid when a download is 175 // currently in progress and |downloading_profile_image_| is true. 176 base::TimeTicks profile_image_load_start_time_; 177 178 // Downloader for the current user's profile data. NULL when no download is 179 // currently in progress. 180 scoped_ptr<ProfileDownloader> profile_downloader_; 181 182 // The currently logged-in user's downloaded profile image, if successfully 183 // downloaded or initialized from a previously downloaded and saved image. 184 gfx::ImageSkia downloaded_profile_image_; 185 186 // Data URL corresponding to |downloaded_profile_image_|. Empty if no 187 // |downloaded_profile_image_| is currently available. 188 std::string downloaded_profile_image_data_url_; 189 190 // URL from which |downloaded_profile_image_| was downloaded. Empty if no 191 // |downloaded_profile_image_| is currently available. 192 GURL profile_image_url_; 193 194 // Whether a download of the currently logged-in user's profile image has been 195 // explicitly requested by a call to DownloadProfileImage() and has not been 196 // satisfied by a successful download yet. 197 bool profile_image_requested_; 198 199 // Timer used to start a profile data download shortly after login and to 200 // restart the download after network errors. 201 base::OneShotTimer<UserImageManagerImpl> profile_download_one_shot_timer_; 202 203 // Timer used to periodically start a profile data, ensuring the profile data 204 // stays up to date. 205 base::RepeatingTimer<UserImageManagerImpl> profile_download_periodic_timer_; 206 207 // Users whose user images need to be migrated from the old dictionary pref to 208 // the new dictionary pref, converting any non-default images to JPEG format. 209 std::set<std::string> users_to_migrate_; 210 211 // Sync observer for the currently logged-in user. 212 scoped_ptr<UserImageSyncObserver> user_image_sync_observer_; 213 214 // Observer for the policy that can be used to manage user images. 215 scoped_ptr<policy::CloudExternalDataPolicyObserver> policy_observer_; 216 217 // Background task runner on which Jobs perform file I/O and the image 218 // decoders run. 219 scoped_refptr<base::SequencedTaskRunner> background_task_runner_; 220 221 // The currently running jobs. 222 std::map<std::string, linked_ptr<Job> > jobs_; 223 224 // List of user_ids whose user image is managed by policy. 225 std::set<std::string> users_with_managed_images_; 226 227 base::WeakPtrFactory<UserImageManagerImpl> weak_factory_; 228 229 DISALLOW_COPY_AND_ASSIGN(UserImageManagerImpl); 230 }; 231 232 } // namespace chromeos 233 234 #endif // CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_ 235