// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_WALLPAPER_WALLPAPER_MANAGER_BASE_H_ #define COMPONENTS_WALLPAPER_WALLPAPER_MANAGER_BASE_H_ #include #include #include #include #include #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/thread_task_runner_handle.h" #include "base/threading/sequenced_worker_pool.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "components/signin/core/account_id/account_id.h" #include "components/user_manager/user.h" #include "components/user_manager/user_image/user_image.h" #include "components/wallpaper/wallpaper_export.h" #include "components/wallpaper/wallpaper_layout.h" #include "ui/gfx/image/image_skia.h" class PrefRegistrySimple; namespace base { class CommandLine; class SequencedTaskRunner; } namespace user_manager { class User; class UserImage; } namespace wallpaper { // This object is passed between several threads while wallpaper is being // loaded. It will notify callback when last reference to it is removed // (thus indicating that the last load action has finished). class WALLPAPER_EXPORT MovableOnDestroyCallback { public: explicit MovableOnDestroyCallback(const base::Closure& callback); ~MovableOnDestroyCallback(); private: base::Closure callback_; }; typedef scoped_ptr MovableOnDestroyCallbackHolder; struct WALLPAPER_EXPORT WallpaperInfo { WallpaperInfo(); WallpaperInfo(const std::string& in_location, WallpaperLayout in_layout, user_manager::User::WallpaperType in_type, const base::Time& in_date); ~WallpaperInfo(); // Either file name of migrated wallpaper including first directory level // (corresponding to user id hash) or online wallpaper URL. std::string location; WallpaperLayout layout; user_manager::User::WallpaperType type; base::Time date; bool operator==(const WallpaperInfo& other) { return (location == other.location) && (layout == other.layout) && (type == other.type); } }; class WallpaperManagerBrowserTest; // Name of wallpaper sequence token. WALLPAPER_EXPORT extern const char kWallpaperSequenceTokenName[]; // File path suffices of resized small or large wallpaper. // TODO(bshe): Use the same sub folder system as custom wallpapers use. // crbug.com/174928 WALLPAPER_EXPORT extern const char kSmallWallpaperSuffix[]; WALLPAPER_EXPORT extern const char kLargeWallpaperSuffix[]; // Directory names of custom wallpapers. WALLPAPER_EXPORT extern const char kSmallWallpaperSubDir[]; WALLPAPER_EXPORT extern const char kLargeWallpaperSubDir[]; WALLPAPER_EXPORT extern const char kOriginalWallpaperSubDir[]; WALLPAPER_EXPORT extern const char kThumbnailWallpaperSubDir[]; // The width and height of small/large resolution wallpaper. When screen size is // smaller than |kSmallWallpaperMaxWidth| and |kSmallWallpaperMaxHeight|, the // small resolution wallpaper should be used. Otherwise, use the large // resolution wallpaper. WALLPAPER_EXPORT extern const int kSmallWallpaperMaxWidth; WALLPAPER_EXPORT extern const int kSmallWallpaperMaxHeight; WALLPAPER_EXPORT extern const int kLargeWallpaperMaxWidth; WALLPAPER_EXPORT extern const int kLargeWallpaperMaxHeight; // The width and height of wallpaper thumbnails. WALLPAPER_EXPORT extern const int kWallpaperThumbnailWidth; WALLPAPER_EXPORT extern const int kWallpaperThumbnailHeight; // A dictionary that maps usernames to wallpaper properties. WALLPAPER_EXPORT extern const char kUsersWallpaperInfo[]; // A dictionary pref that maps usernames to file paths to their wallpapers. // Deprecated. Will remove this const char after done migration. WALLPAPER_EXPORT extern const char kUserWallpapers[]; // A dictionary pref that maps usernames to wallpaper properties. WALLPAPER_EXPORT extern const char kUserWallpapersProperties[]; // This singleton class maintains wallpapers for users. class WALLPAPER_EXPORT WallpaperManagerBase { public: enum WallpaperResolution { WALLPAPER_RESOLUTION_LARGE, WALLPAPER_RESOLUTION_SMALL }; class CustomizedWallpaperRescaledFiles { public: CustomizedWallpaperRescaledFiles(const base::FilePath& path_downloaded, const base::FilePath& path_rescaled_small, const base::FilePath& path_rescaled_large); bool AllSizesExist() const; // Closure will hold unretained pointer to this object. So caller must // make sure that the closure will be destoyed before this object. // Closure must be called on BlockingPool. base::Closure CreateCheckerClosure(); const base::FilePath& path_downloaded() const; const base::FilePath& path_rescaled_small() const; const base::FilePath& path_rescaled_large() const; bool downloaded_exists() const; bool rescaled_small_exists() const; bool rescaled_large_exists() const; private: // Must be called on BlockingPool. void CheckCustomizedWallpaperFilesExist(); const base::FilePath path_downloaded_; const base::FilePath path_rescaled_small_; const base::FilePath path_rescaled_large_; bool downloaded_exists_; bool rescaled_small_exists_; bool rescaled_large_exists_; DISALLOW_COPY_AND_ASSIGN(CustomizedWallpaperRescaledFiles); }; // For testing. class TestApi { public: explicit TestApi(WallpaperManagerBase* wallpaper_manager); virtual ~TestApi(); bool GetWallpaperFromCache(const AccountId& account_id, gfx::ImageSkia* image); bool GetPathFromCache(const AccountId& account_id, base::FilePath* path); void SetWallpaperCache(const AccountId& account_id, const base::FilePath& path, const gfx::ImageSkia& image); void ClearDisposableWallpaperCache(); private: WallpaperManagerBase* wallpaper_manager_; // not owned DISALLOW_COPY_AND_ASSIGN(TestApi); }; class Observer { public: virtual ~Observer() {} virtual void OnWallpaperAnimationFinished(const AccountId& account_id) = 0; virtual void OnUpdateWallpaperForTesting() {} virtual void OnPendingListEmptyForTesting() {} }; // set path IDs for used directories static void SetPathIds(int dir_user_data_enum, int dir_chromeos_wallpapers_enum, int dir_chromeos_custom_wallpapers_enum); // Returns custom wallpaper directory by appending corresponding |sub_dir|. static base::FilePath GetCustomWallpaperDir(const char* sub_dir); // Registers wallpaper manager preferences. static void RegisterPrefs(PrefRegistrySimple* registry); // Resizes |image| to a resolution which is nearest to |preferred_width| and // |preferred_height| while respecting the |layout| choice. |output_skia| is // optional (may be NULL). Returns true on success. static bool ResizeImage(const gfx::ImageSkia& image, WallpaperLayout layout, int preferred_width, int preferred_height, scoped_refptr* output, gfx::ImageSkia* output_skia); // Resizes |image| to a resolution which is nearest to |preferred_width| and // |preferred_height| while respecting the |layout| choice and saves the // resized wallpaper to |path|. |output_skia| is optional (may be // NULL). Returns true on success. static bool ResizeAndSaveWallpaper(const gfx::ImageSkia& image, const base::FilePath& path, WallpaperLayout layout, int preferred_width, int preferred_height, gfx::ImageSkia* output_skia); // Returns custom wallpaper path. Append |sub_dir|, |user_id_hash| and |file| // to custom wallpaper directory. static base::FilePath GetCustomWallpaperPath(const char* sub_dir, const std::string& user_id_hash, const std::string& file); WallpaperManagerBase(); virtual ~WallpaperManagerBase(); // Returns the appropriate wallpaper resolution for all root windows. virtual WallpaperResolution GetAppropriateResolution() = 0; virtual void SetCommandLineForTesting(base::CommandLine* command_line); // Adds PowerManagerClient, TimeZoneSettings and CrosSettings observers. virtual void AddObservers() = 0; // Loads wallpaper asynchronously if the current wallpaper is not the // wallpaper of logged in user. virtual void EnsureLoggedInUserWallpaperLoaded(); // Gets wallpaper information of logged in user. virtual bool GetLoggedInUserWallpaperInfo(WallpaperInfo* info); // Initializes wallpaper. If logged in, loads user's wallpaper. If not logged // in, uses a solid color wallpaper. If logged in as a stub user, uses an // empty wallpaper. virtual void InitializeWallpaper() = 0; // Removes all |account_id| related wallpaper info and saved wallpapers. virtual void RemoveUserWallpaperInfo(const AccountId& account_id) = 0; // Saves custom wallpaper to file, post task to generate thumbnail and updates // local state preferences. If |update_wallpaper| is false, don't change // wallpaper but only update cache. virtual void SetCustomWallpaper(const AccountId& account_id, const std::string& user_id_hash, const std::string& file, WallpaperLayout layout, user_manager::User::WallpaperType type, const gfx::ImageSkia& image, bool update_wallpaper) = 0; // Use given files as new default wallpaper. // Reloads current wallpaper, if old default was loaded. // Current value of default_wallpaper_image_ is destroyed. // Sets default_wallpaper_image_ either to |small_wallpaper_image| or // |large_wallpaper_image| depending on GetAppropriateResolution(). virtual void SetDefaultWallpaperPath( const base::FilePath& customized_default_wallpaper_file_small, scoped_ptr small_wallpaper_image, const base::FilePath& customized_default_wallpaper_file_large, scoped_ptr large_wallpaper_image) = 0; // Sets wallpaper to default wallpaper (asynchronously with zero delay). virtual void SetDefaultWallpaperNow(const AccountId& account_id) = 0; // Sets wallpaper to default wallpaper (asynchronously with default delay). virtual void SetDefaultWallpaperDelayed(const AccountId& account_id) = 0; // Sets selected wallpaper information for |account_id| and saves it to Local // State if |is_persistent| is true. virtual void SetUserWallpaperInfo(const AccountId& account_id, const WallpaperInfo& info, bool is_persistent) = 0; // Sets |account_id|'s wallpaper (asynchronously with zero delay). virtual void SetUserWallpaperNow(const AccountId& account_id); // Sets |account_id|'s wallpaper (asynchronously with default delay). virtual void SetUserWallpaperDelayed(const AccountId& account_id); // Sets wallpaper to |image| (asynchronously with zero delay). If // |update_wallpaper| is false, skip change wallpaper but only update cache. virtual void SetWallpaperFromImageSkia(const AccountId& account_id, const gfx::ImageSkia& image, WallpaperLayout layout, bool update_wallpaper) = 0; // Updates current wallpaper. It may switch the size of wallpaper based on the // current display's resolution. (asynchronously with zero delay) virtual void UpdateWallpaper(bool clear_cache); // Adds given observer to the list. virtual void AddObserver(Observer* observer); // Removes given observer from the list. virtual void RemoveObserver(Observer* observer); // Returns whether a wallpaper policy is enforced for |account_id|. virtual bool IsPolicyControlled(const AccountId& account_id) const; // Called when a wallpaper policy has been set for |account_id|. Blocks user // from changing the wallpaper. virtual void OnPolicySet(const std::string& policy, const AccountId& account_id); // Called when the wallpaper policy has been cleared for |account_id|. virtual void OnPolicyCleared(const std::string& policy, const AccountId& account_id); // Called when the policy-set wallpaper has been fetched. Initiates decoding // of the JPEG |data| with a callback to SetPolicyControlledWallpaper(). virtual void OnPolicyFetched(const std::string& policy, const AccountId& account_id, scoped_ptr data) = 0; // This is called from CustomizationDocument. // |resized_directory| is the directory where resized versions are stored and // must be writable. virtual void SetCustomizedDefaultWallpaper( const GURL& wallpaper_url, const base::FilePath& downloaded_file, const base::FilePath& resized_directory); // Returns queue size. virtual size_t GetPendingListSizeForTesting() const = 0; protected: friend class TestApi; friend class WallpaperManagerBrowserTest; friend class WallpaperManagerBrowserTestDefaultWallpaper; friend class WallpaperManagerPolicyTest; // The |CustomWallpaperElement| contains |first| the path of the image which // is currently being loaded and or in progress of being loaded and |second| // the image itself. typedef std::pair CustomWallpaperElement; typedef std::map CustomWallpaperMap; // Saves original custom wallpaper to |path| (absolute path) on filesystem // and starts resizing operation of the custom wallpaper if necessary. static void SaveCustomWallpaper(const std::string& user_id_hash, const base::FilePath& path, WallpaperLayout layout, scoped_ptr image); // Moves custom wallpapers from user email directory to |user_id_hash| // directory. static void MoveCustomWallpapersOnWorker( const AccountId& account_id, const std::string& user_id_hash, const scoped_refptr& reply_task_runner, base::WeakPtr weak_ptr); // Gets |account_id|'s custom wallpaper at |wallpaper_path|. Falls back on // original custom wallpaper. When |update_wallpaper| is true, sets wallpaper // to the loaded wallpaper. Must run on wallpaper sequenced worker thread. static void GetCustomWallpaperInternal( const AccountId& account_id, const WallpaperInfo& info, const base::FilePath& wallpaper_path, bool update_wallpaper, const scoped_refptr& reply_task_runner, MovableOnDestroyCallbackHolder on_finish, base::WeakPtr weak_ptr); // Resize and save customized default wallpaper. static void ResizeCustomizedDefaultWallpaper( scoped_ptr image, const user_manager::UserImage::RawImage& raw_image, const CustomizedWallpaperRescaledFiles* rescaled_files, bool* success, gfx::ImageSkia* small_wallpaper_image, gfx::ImageSkia* large_wallpaper_image); // Initialize wallpaper for the specified user to default and saves this // settings in local state. virtual void InitInitialUserWallpaper(const AccountId& account_id, bool is_persistent); // Gets encoded wallpaper from cache. Returns true if success. virtual bool GetWallpaperFromCache(const AccountId& account_id, gfx::ImageSkia* image); // Gets path of encoded wallpaper from cache. Returns true if success. virtual bool GetPathFromCache(const AccountId& account_id, base::FilePath* path); // The number of wallpapers have loaded. For test only. virtual int loaded_wallpapers_for_test() const; // Cache some (or all) logged in users' wallpapers to memory at login // screen. It should not compete with first wallpaper loading when boot // up/initialize login WebUI page. // There are two ways the first wallpaper might be loaded: // 1. Loaded on boot. Login WebUI waits for it. // 2. When flag --disable-boot-animation is passed. Login WebUI is loaded // right away and in 500ms after. Wallpaper started to load. // For case 2, should_cache_wallpaper_ is used to indicate if we need to // cache wallpapers on wallpaper animation finished. The cache operation // should be only executed once. virtual void CacheUsersWallpapers(); // Caches |account_id|'s wallpaper to memory. virtual void CacheUserWallpaper(const AccountId& account_id); // Clears disposable ONLINE and CUSTOM wallpaper cache. At multi profile // world, logged in users' wallpaper cache is not disposable. virtual void ClearDisposableWallpaperCache(); // Deletes all |account_id| related custom wallpapers and directories. virtual void DeleteUserWallpapers(const AccountId& account_id, const std::string& path_to_file); // Gets the CommandLine representing the current process's command line. virtual base::CommandLine* GetCommandLine(); // Initialize wallpaper of registered device after device policy is trusted. // Note that before device is enrolled, it proceeds with untrusted setting. virtual void InitializeRegisteredDeviceWallpaper() = 0; // Loads |account_id|'s wallpaper. When |update_wallpaper| is true, sets // wallpaper to the loaded wallpaper. virtual void LoadWallpaper(const AccountId& account_id, const WallpaperInfo& info, bool update_wallpaper, MovableOnDestroyCallbackHolder on_finish); // Called when the original custom wallpaper is moved to the new place. // Updates the corresponding user wallpaper info. virtual void MoveCustomWallpapersSuccess(const AccountId& account_id, const std::string& user_id_hash); // Moves custom wallpaper to a new place. Email address was used as directory // name in the old system, this is not safe. New directory system uses // user_id_hash instead of account_id. This must be called after user_id_hash // is // ready. virtual void MoveLoggedInUserCustomWallpaper(); // Gets wallpaper information of |account_id| from Local State or memory. // Returns // false if wallpaper information is not found. virtual bool GetUserWallpaperInfo(const AccountId& account_id, WallpaperInfo* info) const = 0; // Sets wallpaper to the decoded wallpaper if |update_wallpaper| is true. // Otherwise, cache wallpaper to memory if not logged in. (Takes a UserImage // because that's the callback interface provided by UserImageLoader.) virtual void OnWallpaperDecoded( const AccountId& account_id, WallpaperLayout layout, bool update_wallpaper, MovableOnDestroyCallbackHolder on_finish, const user_manager::UserImage& user_image) = 0; // Creates new PendingWallpaper request (or updates currently pending). virtual void ScheduleSetUserWallpaper(const AccountId& account_id, bool delayed) = 0; // Sets wallpaper to default. virtual void DoSetDefaultWallpaper( const AccountId& account_id, MovableOnDestroyCallbackHolder on_finish) = 0; // Starts to load wallpaper at |wallpaper_path|. If |wallpaper_path| is // already loaded for that user, do nothing. Must be called on UI thread. virtual void StartLoad(const AccountId& account_id, const WallpaperInfo& info, bool update_wallpaper, const base::FilePath& wallpaper_path, MovableOnDestroyCallbackHolder on_finish) = 0; // After completed load operation, update average load time. virtual void SaveLastLoadTime(const base::TimeDelta elapsed); // Notify all registered observers. virtual void NotifyAnimationFinished(); // Calculate delay for next wallpaper load. // It is usually average wallpaper load time. // If last wallpaper load happened long ago, timeout should be reduced by // the time passed after last wallpaper load. So usual user experience results // in zero delay. virtual base::TimeDelta GetWallpaperLoadDelay() const; // This is called after we check that supplied default wallpaper files exist. virtual void SetCustomizedDefaultWallpaperAfterCheck( const GURL& wallpaper_url, const base::FilePath& downloaded_file, scoped_ptr rescaled_files) = 0; // Starts rescaling of customized wallpaper. virtual void OnCustomizedDefaultWallpaperDecoded( const GURL& wallpaper_url, scoped_ptr rescaled_files, const user_manager::UserImage& user_image); // Check the result of ResizeCustomizedDefaultWallpaper and finally // apply Customized Default Wallpaper. virtual void OnCustomizedDefaultWallpaperResized( const GURL& wallpaper_url, scoped_ptr rescaled_files, scoped_ptr success, scoped_ptr small_wallpaper_image, scoped_ptr large_wallpaper_image) = 0; // Init |*default_*_wallpaper_file_| from given command line and // clear |default_wallpaper_image_|. virtual void SetDefaultWallpaperPathsFromCommandLine( base::CommandLine* command_line) = 0; // Sets wallpaper to decoded default. virtual void OnDefaultWallpaperDecoded( const base::FilePath& path, const WallpaperLayout layout, scoped_ptr* result, MovableOnDestroyCallbackHolder on_finish, const user_manager::UserImage& user_image) = 0; // Start decoding given default wallpaper. virtual void StartLoadAndSetDefaultWallpaper( const base::FilePath& path, const WallpaperLayout layout, MovableOnDestroyCallbackHolder on_finish, scoped_ptr* result_out) = 0; // Returns wallpaper subdirectory name for current resolution. virtual const char* GetCustomWallpaperSubdirForCurrentResolution(); // Init default_wallpaper_image_ with 1x1 image of default color. virtual void CreateSolidDefaultWallpaper(); // The number of loaded wallpapers. int loaded_wallpapers_for_test_; base::ThreadChecker thread_checker_; // Sequence token associated with wallpaper operations. base::SequencedWorkerPool::SequenceToken sequence_token_; // Wallpaper sequenced task runner. scoped_refptr task_runner_; // Logged-in user wallpaper information. WallpaperInfo current_user_wallpaper_info_; // If non-NULL, used in place of the real command line. base::CommandLine* command_line_for_testing_; // Caches wallpapers of users. Accessed only on UI thread. CustomWallpaperMap wallpaper_cache_; // The last selected user on user pod row. AccountId last_selected_user_ = EmptyAccountId(); bool should_cache_wallpaper_; base::ObserverList observers_; // These members are for the scheduler: // When last load attempt finished. base::Time last_load_finished_at_; // last N wallpaper loads times. std::deque last_load_times_; base::FilePath default_small_wallpaper_file_; base::FilePath default_large_wallpaper_file_; base::FilePath guest_small_wallpaper_file_; base::FilePath guest_large_wallpaper_file_; base::FilePath child_small_wallpaper_file_; base::FilePath child_large_wallpaper_file_; // Current decoded default image is stored in cache. scoped_ptr default_wallpaper_image_; base::WeakPtrFactory weak_factory_; private: DISALLOW_COPY_AND_ASSIGN(WallpaperManagerBase); }; } // namespace wallpaper #endif // COMPONENTS_WALLPAPER_WALLPAPER_MANAGER_BASE_H_