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_WALLPAPER_MANAGER_H_ 6 #define CHROME_BROWSER_CHROMEOS_LOGIN_WALLPAPER_MANAGER_H_ 7 8 #include <string> 9 10 #include "ash/desktop_background/desktop_background_controller.h" 11 #include "base/files/file_path.h" 12 #include "base/memory/ref_counted_memory.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/observer_list.h" 16 #include "base/threading/sequenced_worker_pool.h" 17 #include "base/time/time.h" 18 #include "chrome/browser/chromeos/login/user.h" 19 #include "chrome/browser/chromeos/login/user_image.h" 20 #include "chrome/browser/chromeos/login/user_image_loader.h" 21 #include "chrome/browser/chromeos/settings/cros_settings.h" 22 #include "content/public/browser/notification_observer.h" 23 #include "content/public/browser/notification_registrar.h" 24 #include "third_party/icu/source/i18n/unicode/timezone.h" 25 #include "ui/gfx/image/image_skia.h" 26 27 class CommandLine; 28 class PrefRegistrySimple; 29 30 namespace base { 31 class SequencedTaskRunner; 32 } 33 34 namespace chromeos { 35 36 struct WallpaperInfo { 37 // Online wallpaper URL or file name of migrated wallpaper. 38 std::string file; 39 ash::WallpaperLayout layout; 40 User::WallpaperType type; 41 base::Time date; 42 bool operator==(const WallpaperInfo& other) { 43 return (file == other.file) && (layout == other.layout) && 44 (type == other.type); 45 } 46 }; 47 48 class WallpaperManagerBrowserTest; 49 class UserImage; 50 51 // Name of wallpaper sequence token. 52 extern const char kWallpaperSequenceTokenName[]; 53 54 // File path suffices of resized small or large wallpaper. 55 // TODO(bshe): Use the same sub folder system as custom wallpapers use. 56 // crbug.com/174928 57 extern const char kSmallWallpaperSuffix[]; 58 extern const char kLargeWallpaperSuffix[]; 59 60 // Directory names of custom wallpapers. 61 extern const char kSmallWallpaperSubDir[]; 62 extern const char kLargeWallpaperSubDir[]; 63 extern const char kOriginalWallpaperSubDir[]; 64 extern const char kThumbnailWallpaperSubDir[]; 65 66 // This class maintains wallpapers for users who have logged into this Chrome 67 // OS device. 68 class WallpaperManager: public content::NotificationObserver { 69 public: 70 // For testing. 71 class TestApi { 72 public: 73 explicit TestApi(WallpaperManager* wallpaper_manager); 74 virtual ~TestApi(); 75 76 base::FilePath current_wallpaper_path(); 77 78 private: 79 WallpaperManager* wallpaper_manager_; // not owned 80 81 DISALLOW_COPY_AND_ASSIGN(TestApi); 82 }; 83 84 class Observer { 85 public: 86 virtual ~Observer() {} 87 virtual void OnWallpaperAnimationFinished(const std::string& email) = 0; 88 }; 89 90 static WallpaperManager* Get(); 91 92 WallpaperManager(); 93 virtual ~WallpaperManager(); 94 95 void set_command_line_for_testing(CommandLine* command_line) { 96 command_line_for_testing_ = command_line; 97 } 98 99 // Indicates imminent shutdown, allowing the WallpaperManager to remove any 100 // observers it has registered. 101 void Shutdown(); 102 103 // Registers wallpaper manager preferences. 104 static void RegisterPrefs(PrefRegistrySimple* registry); 105 106 // Adds PowerManagerClient, TimeZoneSettings and CrosSettings observers. 107 void AddObservers(); 108 109 // Loads wallpaper asynchronously if the current wallpaper is not the 110 // wallpaper of logged in user. 111 void EnsureLoggedInUserWallpaperLoaded(); 112 113 // Clears ONLINE and CUSTOM wallpaper cache. 114 void ClearWallpaperCache(); 115 116 // Returns custom wallpaper path. Append |sub_dir|, |user_id_hash| and |file| 117 // to custom wallpaper directory. 118 base::FilePath GetCustomWallpaperPath(const char* sub_dir, 119 const std::string& user_id_hash, 120 const std::string& file); 121 122 // Gets encoded wallpaper from cache. Returns true if success. 123 bool GetWallpaperFromCache(const std::string& email, 124 gfx::ImageSkia* wallpaper); 125 126 // Returns filepath to save original custom wallpaper for the given user. 127 base::FilePath GetOriginalWallpaperPathForUser(const std::string& username); 128 129 // Gets wallpaper information of logged in user. 130 bool GetLoggedInUserWallpaperInfo(WallpaperInfo* info); 131 132 // Initializes wallpaper. If logged in, loads user's wallpaper. If not logged 133 // in, uses a solid color wallpaper. If logged in as a stub user, uses an 134 // empty wallpaper. 135 void InitializeWallpaper(); 136 137 // NotificationObserver overrides: 138 virtual void Observe(int type, 139 const content::NotificationSource& source, 140 const content::NotificationDetails& details) OVERRIDE; 141 142 // Removes all |email| related wallpaper info and saved wallpapers. 143 void RemoveUserWallpaperInfo(const std::string& email); 144 145 // Resizes |wallpaper| to a resolution which is nearest to |preferred_width| 146 // and |preferred_height| while maintaining aspect ratio. 147 bool ResizeWallpaper(const UserImage& wallpaper, 148 ash::WallpaperLayout layout, 149 int preferred_width, 150 int preferred_height, 151 scoped_refptr<base::RefCountedBytes>* output); 152 153 // Resizes |wallpaper| to a resolution which is nearest to |preferred_width| 154 // and |preferred_height| while maintaining aspect ratio. And saves the 155 // resized wallpaper to |path|. 156 void ResizeAndSaveWallpaper(const UserImage& wallpaper, 157 const base::FilePath& path, 158 ash::WallpaperLayout layout, 159 int preferred_width, 160 int preferred_height); 161 162 // Saves custom wallpaper to file, post task to generate thumbnail and updates 163 // local state preferences. 164 void SetCustomWallpaper(const std::string& username, 165 const std::string& user_id_hash, 166 const std::string& file, 167 ash::WallpaperLayout layout, 168 User::WallpaperType type, 169 const UserImage& wallpaper); 170 171 // Sets wallpaper to default wallpaper. 172 void SetDefaultWallpaper(); 173 174 // Sets one of the default wallpapers for the specified user and saves this 175 // settings in local state. 176 void SetInitialUserWallpaper(const std::string& username, bool is_persistent); 177 178 // Sets selected wallpaper information for |username| and saves it to Local 179 // State if |is_persistent| is true. 180 void SetUserWallpaperInfo(const std::string& username, 181 const WallpaperInfo& info, 182 bool is_persistent); 183 184 // Sets last selected user on user pod row. 185 void SetLastSelectedUser(const std::string& last_selected_user); 186 187 // Sets |email|'s wallpaper. 188 void SetUserWallpaper(const std::string& email); 189 190 // Sets wallpaper to |wallpaper|. 191 void SetWallpaperFromImageSkia(const gfx::ImageSkia& wallpaper, 192 ash::WallpaperLayout layout); 193 194 // Updates current wallpaper. It may switch the size of wallpaper based on the 195 // current display's resolution. 196 void UpdateWallpaper(); 197 198 // Adds given observer to the list. 199 void AddObserver(Observer* observer); 200 201 // Removes given observer from the list. 202 void RemoveObserver(Observer* observer); 203 204 private: 205 friend class TestApi; 206 friend class WallpaperManagerBrowserTest; 207 typedef std::map<std::string, gfx::ImageSkia> CustomWallpaperMap; 208 209 // The number of wallpapers have loaded. For test only. 210 int loaded_wallpapers() const { return loaded_wallpapers_; } 211 212 // Cache some (or all) logged in users' wallpapers to memory at login 213 // screen. It should not compete with first wallpaper loading when boot 214 // up/initialize login WebUI page. 215 // There are two ways the first wallpaper might be loaded: 216 // 1. Loaded on boot. Login WebUI waits for it. 217 // 2. When flag --disable-boot-animation is passed. Login WebUI is loaded 218 // right away and in 500ms after. Wallpaper started to load. 219 // For case 2, should_cache_wallpaper_ is used to indicate if we need to 220 // cache wallpapers on wallpaper animation finished. The cache operation 221 // should be only executed once. 222 void CacheUsersWallpapers(); 223 224 // Caches |email|'s wallpaper to memory. 225 void CacheUserWallpaper(const std::string& email); 226 227 // Clears all obsolete wallpaper prefs from old version wallpaper pickers. 228 void ClearObsoleteWallpaperPrefs(); 229 230 // Deletes everything else except |path| in the same directory. 231 void DeleteAllExcept(const base::FilePath& path); 232 233 // Deletes a list of wallpaper files in |file_list|. 234 void DeleteWallpaperInList(const std::vector<base::FilePath>& file_list); 235 236 // Deletes all |email| related custom wallpapers and directories. 237 void DeleteUserWallpapers(const std::string& email, 238 const std::string& path_to_file); 239 240 // Creates all new custom wallpaper directories for |user_id_hash| if not 241 // exist. 242 void EnsureCustomWallpaperDirectories(const std::string& user_id_hash); 243 244 // Gets the CommandLine representing the current process's command line. 245 CommandLine* GetComandLine(); 246 247 // Initialize wallpaper of registered device after device policy is trusted. 248 // Note that before device is enrolled, it proceeds with untrusted setting. 249 void InitializeRegisteredDeviceWallpaper(); 250 251 // Loads |email|'s wallpaper. When |update_wallpaper| is true, sets wallpaper 252 // to the loaded wallpaper. 253 void LoadWallpaper(const std::string& email, 254 const WallpaperInfo& info, 255 bool update_wallpaper); 256 257 // Moves custom wallpapers from |email| directory to |user_id_hash| 258 // directory. 259 void MoveCustomWallpapersOnWorker(const std::string& email, 260 const std::string& user_id_hash); 261 262 // Called when the original custom wallpaper is moved to the new place. 263 // Updates the corresponding user wallpaper info. 264 void MoveCustomWallpapersSuccess(const std::string& email, 265 const std::string& user_id_hash); 266 267 // Moves custom wallpaper to a new place. Email address was used as directory 268 // name in the old system, this is not safe. New directory system uses 269 // user_id_hash instead of email. This must be called after user_id_hash is 270 // ready. 271 void MoveLoggedInUserCustomWallpaper(); 272 273 // Gets |email|'s custom wallpaper at |wallpaper_path|. Falls back on original 274 // custom wallpaper. When |update_wallpaper| is true, sets wallpaper to the 275 // loaded wallpaper. Must run on wallpaper sequenced worker thread. 276 void GetCustomWallpaperInternal(const std::string& email, 277 const WallpaperInfo& info, 278 const base::FilePath& wallpaper_path, 279 bool update_wallpaper); 280 281 // Gets wallpaper information of |email| from Local State or memory. Returns 282 // false if wallpaper information is not found. 283 bool GetUserWallpaperInfo(const std::string& email, WallpaperInfo* info); 284 285 // Sets wallpaper to the decoded wallpaper if |update_wallpaper| is true. 286 // Otherwise, cache wallpaper to memory if not logged in. 287 void OnWallpaperDecoded(const std::string& email, 288 ash::WallpaperLayout layout, 289 bool update_wallpaper, 290 const UserImage& wallpaper); 291 292 // Generates thumbnail of custom wallpaper on wallpaper sequenced worker 293 // thread. If |persistent| is true, saves original custom image and resized 294 // images to disk. 295 void ProcessCustomWallpaper(const std::string& user_id_hash, 296 bool persistent, 297 const WallpaperInfo& info, 298 scoped_ptr<gfx::ImageSkia> image, 299 const UserImage::RawImage& raw_image); 300 301 // Record data for User Metrics Analysis. 302 void RecordUma(User::WallpaperType type, int index); 303 304 // Saves original custom wallpaper to |path| (absolute path) on filesystem 305 // and starts resizing operation of the custom wallpaper if necessary. 306 void SaveCustomWallpaper(const std::string& user_id_hash, 307 const base::FilePath& path, 308 ash::WallpaperLayout layout, 309 const UserImage& wallpaper); 310 311 // Saves wallpaper image raw |data| to |path| (absolute path) in file system. 312 void SaveWallpaperInternal(const base::FilePath& path, const char* data, 313 int size); 314 315 // Starts to load wallpaper at |wallpaper_path|. If |wallpaper_path| is the 316 // same as |current_wallpaper_path_|, do nothing. Must be called on UI thread. 317 void StartLoad(const std::string& email, 318 const WallpaperInfo& info, 319 bool update_wallpaper, 320 const base::FilePath& wallpaper_path); 321 322 // Notify all registed observers. 323 void NotifyAnimationFinished(); 324 325 // The number of loaded wallpapers. 326 int loaded_wallpapers_; 327 328 // Sequence token associated with wallpaper operations. 329 base::SequencedWorkerPool::SequenceToken sequence_token_; 330 331 // Wallpaper sequenced task runner. 332 scoped_refptr<base::SequencedTaskRunner> task_runner_; 333 334 // The file path of current loaded/loading custom/online wallpaper. 335 base::FilePath current_wallpaper_path_; 336 337 // Loads user wallpaper from its file. 338 scoped_refptr<UserImageLoader> wallpaper_loader_; 339 340 // Logged-in user wallpaper information. 341 WallpaperInfo current_user_wallpaper_info_; 342 343 // If non-NULL, used in place of the real command line. 344 CommandLine* command_line_for_testing_; 345 346 // Caches wallpapers of users. Accessed only on UI thread. 347 CustomWallpaperMap wallpaper_cache_; 348 349 // The last selected user on user pod row. 350 std::string last_selected_user_; 351 352 bool should_cache_wallpaper_; 353 354 scoped_ptr<CrosSettings::ObserverSubscription> 355 show_user_name_on_signin_subscription_; 356 357 base::WeakPtrFactory<WallpaperManager> weak_factory_; 358 359 content::NotificationRegistrar registrar_; 360 361 ObserverList<Observer> observers_; 362 363 DISALLOW_COPY_AND_ASSIGN(WallpaperManager); 364 }; 365 366 } // namespace chromeos 367 368 #endif // CHROME_BROWSER_CHROMEOS_LOGIN_WALLPAPER_MANAGER_H_ 369