#ifndef ASH_WALLPAPER_WALLPAPER_CONTROLLER_IMPL_H_
#define ASH_WALLPAPER_WALLPAPER_CONTROLLER_IMPL_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "ash/ash_export.h"
#include "ash/display/window_tree_host_manager.h"
#include "ash/public/cpp/image_downloader.h"
#include "ash/public/cpp/image_util.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/public/cpp/tablet_mode_observer.h"
#include "ash/public/cpp/wallpaper/google_photos_wallpaper_params.h"
#include "ash/public/cpp/wallpaper/online_wallpaper_params.h"
#include "ash/public/cpp/wallpaper/wallpaper_controller.h"
#include "ash/public/cpp/wallpaper/wallpaper_info.h"
#include "ash/public/cpp/wallpaper/wallpaper_types.h"
#include "ash/shell_observer.h"
#include "ash/system/scheduled_feature/scheduled_feature.h"
#include "ash/wallpaper/online_wallpaper_variant_info_fetcher.h"
#include "ash/wallpaper/wallpaper_utils/wallpaper_calculated_colors.h"
#include "ash/webui/personalization_app/mojom/personalization_app.mojom-forward.h"
#include "ash/wm/overview/overview_observer.h"
#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/timer/wall_clock_timer.h"
#include "components/account_id/account_id.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/user_manager/user_type.h"
#include "ui/compositor/compositor_lock.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_observer.h"
namespace base {
class SequencedTaskRunner;
}
namespace color_utils {
struct ColorProfile;
}
namespace ash {
class WallpaperColorCalculator;
class WallpaperDriveFsDelegate;
class WallpaperImageDownloader;
class WallpaperMetricsManager;
class WallpaperPrefManager;
class WallpaperResizer;
class WallpaperWindowStateManager;
using CustomWallpaperElement = std::pair<base::FilePath, gfx::ImageSkia>;
using CustomWallpaperMap = std::map<AccountId, CustomWallpaperElement>;
class ASH_EXPORT WallpaperControllerImpl
: public WallpaperController,
public WindowTreeHostManager::Observer,
public ShellObserver,
public SessionObserver,
public TabletModeObserver,
public OverviewObserver,
public ui::CompositorLockClient,
public ui::NativeThemeObserver,
public ScheduledFeature::CheckpointObserver {
public:
static const char kSmallWallpaperSubDir[];
static const char kLargeWallpaperSubDir[];
static const char kOriginalWallpaperSubDir[];
static std::unique_ptr<WallpaperControllerImpl> Create(
PrefService* local_state);
static void SetWallpaperPrefManagerForTesting(
std::unique_ptr<WallpaperPrefManager> pref_manager);
static void SetWallpaperImageDownloaderForTesting(
std::unique_ptr<WallpaperImageDownloader> image_downloader);
explicit WallpaperControllerImpl(
std::unique_ptr<WallpaperPrefManager> pref_manager,
std::unique_ptr<OnlineWallpaperVariantInfoFetcher> fetcher,
std::unique_ptr<WallpaperImageDownloader> image_downloader);
WallpaperControllerImpl(const WallpaperControllerImpl&) = delete;
WallpaperControllerImpl& operator=(const WallpaperControllerImpl&) = delete;
~WallpaperControllerImpl() override;
static base::FilePath GetCustomWallpaperPath(
const std::string& sub_dir,
const std::string& wallpaper_files_id,
const std::string& file_name);
static base::FilePath GetCustomWallpaperDir(const std::string& sub_dir);
SkColor GetProminentColor(color_utils::ColorProfile color_profile) const;
SkColor GetKMeanColor() const;
const absl::optional<WallpaperCalculatedColors>& calculated_colors() const {
return calculated_colors_;
}
gfx::ImageSkia GetWallpaper() const;
WallpaperLayout GetWallpaperLayout() const;
WallpaperType GetWallpaperType() const;
base::TimeDelta animation_duration() const { return animation_duration_; }
bool ShouldShowInitialAnimation();
bool CanOpenWallpaperPicker();
bool HasShownAnyWallpaper() const;
void MaybeClosePreviewWallpaper();
void ShowWallpaperImage(const gfx::ImageSkia& image,
WallpaperInfo info,
bool preview_mode,
bool is_override);
void UpdateWallpaperBlurForLockState(bool blur);
void RestoreWallpaperBlurForLockState(float blur);
bool ShouldApplyShield() const;
bool IsBlurAllowedForLockState() const;
bool is_wallpaper_set() const { return !!current_wallpaper_.get(); }
bool SetUserWallpaperInfo(const AccountId& account_id,
const WallpaperInfo& info);
bool SetUserWallpaperInfo(const AccountId& account_id,
bool is_ephemeral,
const WallpaperInfo& info);
bool GetWallpaperFromCache(const AccountId& account_id,
gfx::ImageSkia* image);
bool GetPathFromCache(const AccountId& account_id, base::FilePath* path);
void AddFirstWallpaperAnimationEndCallback(base::OnceClosure callback,
aura::Window* window);
void StartDecodeFromPath(const AccountId& account_id,
const user_manager::UserType user_type,
const WallpaperInfo& info,
bool show_wallpaper,
const base::FilePath& wallpaper_path);
bool ShouldCalculateColors() const;
void SetClient(WallpaperControllerClient* client) override;
WallpaperDragDropDelegate* GetDragDropDelegate() override;
void SetDragDropDelegate(
std::unique_ptr<WallpaperDragDropDelegate> delegate) override;
void SetDriveFsDelegate(
std::unique_ptr<WallpaperDriveFsDelegate> drivefs_delegate) override;
void Init(const base::FilePath& user_data,
const base::FilePath& wallpapers,
const base::FilePath& custom_wallpapers,
const base::FilePath& device_policy_wallpaper) override;
bool CanSetUserWallpaper(const AccountId& account_id) const override;
void SetCustomWallpaper(const AccountId& account_id,
const base::FilePath& file_path,
WallpaperLayout layout,
bool preview_mode,
SetWallpaperCallback callback) override;
void SetDecodedCustomWallpaper(const AccountId& account_id,
const std::string& file_name,
WallpaperLayout layout,
bool preview_mode,
SetWallpaperCallback callback,
const std::string& file_path,
const gfx::ImageSkia& image) override;
void SetOnlineWallpaper(const OnlineWallpaperParams& params,
SetWallpaperCallback callback) override;
void SetGooglePhotosWallpaper(const GooglePhotosWallpaperParams& params,
SetWallpaperCallback callback) override;
void SetGooglePhotosDailyRefreshAlbumId(const AccountId& account_id,
const std::string& album_id) override;
std::string GetGooglePhotosDailyRefreshAlbumId(
const AccountId& account_id) const override;
bool SetDailyGooglePhotosWallpaperIdCache(
const AccountId& account_id,
const DailyGooglePhotosIdCache& ids) override;
bool GetDailyGooglePhotosWallpaperIdCache(
const AccountId& account_id,
DailyGooglePhotosIdCache& ids_out) const override;
void SetDefaultWallpaper(const AccountId& account_id,
bool show_wallpaper,
SetWallpaperCallback callback) override;
base::FilePath GetDefaultWallpaperPath(
user_manager::UserType user_type) override;
void SetCustomizedDefaultWallpaperPaths(
const base::FilePath& customized_default_small_path,
const base::FilePath& customized_default_large_path) override;
void SetPolicyWallpaper(const AccountId& account_id,
user_manager::UserType user_type,
const std::string& data) override;
void SetDevicePolicyWallpaperPath(
const base::FilePath& device_policy_wallpaper_path) override;
bool SetThirdPartyWallpaper(const AccountId& account_id,
const std::string& file_name,
WallpaperLayout layout,
const gfx::ImageSkia& image) override;
void ConfirmPreviewWallpaper() override;
void CancelPreviewWallpaper() override;
void UpdateCurrentWallpaperLayout(const AccountId& account_id,
WallpaperLayout layout) override;
void ShowUserWallpaper(const AccountId& account_id) override;
void ShowUserWallpaper(const AccountId& account_id,
const user_manager::UserType user_type) override;
void ShowSigninWallpaper() override;
void ShowOneShotWallpaper(const gfx::ImageSkia& image) override;
void ShowOverrideWallpaper(const base::FilePath& image_path,
bool always_on_top) override;
void RemoveOverrideWallpaper() override;
void RemoveUserWallpaper(const AccountId& account_id,
base::OnceClosure on_removed) override;
void RemovePolicyWallpaper(const AccountId& account_id) override;
void SetAnimationDuration(base::TimeDelta animation_duration) override;
void OpenWallpaperPickerIfAllowed() override;
void MinimizeInactiveWindows(const std::string& user_id_hash) override;
void RestoreMinimizedWindows(const std::string& user_id_hash) override;
void AddObserver(WallpaperControllerObserver* observer) override;
void RemoveObserver(WallpaperControllerObserver* observer) override;
gfx::ImageSkia GetWallpaperImage() override;
scoped_refptr<base::RefCountedMemory> GetPreviewImage() override;
bool IsWallpaperBlurredForLockState() const override;
bool IsActiveUserWallpaperControlledByPolicy() override;
bool IsWallpaperControlledByPolicy(
const AccountId& account_id) const override;
absl::optional<WallpaperInfo> GetActiveUserWallpaperInfo() const override;
bool ShouldShowWallpaperSetting() override;
void SetDailyRefreshCollectionId(const AccountId& account_id,
const std::string& collection_id) override;
std::string GetDailyRefreshCollectionId(
const AccountId& account_id) const override;
void UpdateDailyRefreshWallpaper(
RefreshWallpaperCallback callback = base::DoNothing()) override;
void SyncLocalAndRemotePrefs(const AccountId& account_id) override;
void OnDisplayConfigurationChanged() override;
void OnRootWindowAdded(aura::Window* root_window) override;
void OnShellInitialized() override;
void OnShellDestroying() override;
void OnSessionStateChanged(session_manager::SessionState state) override;
void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
void OnActiveUserSessionChanged(const AccountId& account_id) override;
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
void OnCheckpointChanged(const ScheduledFeature* src,
const ScheduleCheckpoint new_checkpoint) override;
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
void OnOverviewModeWillStart() override;
void OnOverviewModeStarting() override;
void OnOverviewModeEnded() override;
void CompositorLockTimedOut() override;
void ShowDefaultWallpaperForTesting();
void CreateEmptyWallpaperForTesting();
void set_wallpaper_reload_no_delay_for_test() {
wallpaper_reload_delay_ = base::Milliseconds(0);
}
void ReloadWallpaperForTesting(bool clear_cache);
void ClearPrefChangeObserverForTesting();
void set_bypass_decode_for_testing() { bypass_decode_for_testing_ = true; }
void set_allow_blur_or_shield_for_testing() {
allow_blur_or_shield_for_testing_ = true;
}
void UpdateDailyRefreshWallpaperForTesting();
base::WallClockTimer& GetUpdateWallpaperTimerForTesting();
WallpaperDriveFsDelegate* drivefs_delegate_for_testing() {
return drivefs_delegate_.get();
}
private:
FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest, BasicReparenting);
FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest,
WallpaperMovementDuringUnlock);
friend class WallpaperControllerTest;
friend class WallpaperControllerTestApi;
friend class KeyboardBacklightColorControllerTest;
enum WallpaperMode { WALLPAPER_NONE, WALLPAPER_IMAGE };
struct CachedDefaultWallpaper {
gfx::ImageSkia image;
base::FilePath file_path;
};
void OnWallpaperResized();
bool GetUserWallpaperInfo(const AccountId& account_id,
WallpaperInfo* info) const;
void UpdateWallpaperForRootWindow(aura::Window* root_window,
bool lock_state_changed,
bool new_root);
void UpdateWallpaperForAllRootWindows(bool lock_state_changed);
bool ReparentWallpaper(int container);
int GetWallpaperContainerId(bool locked);
void RemoveUserWallpaperImpl(const AccountId& account_id,
base::OnceClosure on_removed);
void RemoveUserWallpaperImplWithFilesId(
const AccountId& account_id,
base::OnceClosure on_removed,
const std::string& wallpaper_files_id);
void SetDefaultWallpaperImpl(user_manager::UserType user_type,
bool show_wallpaper,
SetWallpaperCallback callback);
bool WallpaperIsAlreadyLoaded(const gfx::ImageSkia& image,
bool compare_layouts,
WallpaperLayout layout) const;
void ReadAndDecodeWallpaper(image_util::DecodeImageCallback callback,
const base::FilePath& file_path);
bool SetDefaultWallpaperInfo(const AccountId& account_id,
const base::Time& date);
void SetOnlineWallpaperFromPath(SetWallpaperCallback callback,
const OnlineWallpaperParams& params,
const base::FilePath& file_path);
void SetOnlineWallpaperFromVariantPaths(
SetWallpaperCallback callback,
const OnlineWallpaperParams& params,
const base::flat_map<std::string, base::FilePath>& url_to_file_path_map);
void OnWallpaperVariantsFetched(WallpaperType type,
bool start_daily_refresh_timer,
SetWallpaperCallback callback,
absl::optional<OnlineWallpaperParams> params);
void OnOnlineWallpaperDecoded(const OnlineWallpaperParams& params,
bool save_file,
SetWallpaperCallback callback,
const gfx::ImageSkia& image);
void OnGooglePhotosPhotoFetched(
GooglePhotosWallpaperParams params,
SetWallpaperCallback callback,
ash::personalization_app::mojom::GooglePhotosPhotoPtr photo,
bool success);
void OnDailyGooglePhotosPhotoFetched(
const AccountId& account_id,
const std::string& album_id,
RefreshWallpaperCallback callback,
ash::personalization_app::mojom::GooglePhotosPhotoPtr photo,
bool success);
void OnDailyGooglePhotosWallpaperDownloaded(
const AccountId& account_id,
const std::string& photo_id,
const std::string& album_id,
absl::optional<std::string> dedup_key,
RefreshWallpaperCallback callback,
const gfx::ImageSkia& image);
void GetGooglePhotosWallpaperFromCacheOrDownload(
const GooglePhotosWallpaperParams& params,
ash::personalization_app::mojom::GooglePhotosPhotoPtr photo,
SetWallpaperCallback callback,
const base::FilePath& cached_path,
bool cached_path_exists);
void OnGooglePhotosWallpaperDecoded(const WallpaperInfo& info,
const AccountId& account_id,
const base::FilePath& path,
SetWallpaperCallback callback,
const gfx::ImageSkia& image);
void OnGooglePhotosAuthenticationTokenFetched(
ash::personalization_app::mojom::GooglePhotosPhotoPtr photo,
const AccountId& account_id,
ImageDownloader::DownloadCallback callback,
const absl::optional<std::string>& access_token);
void OnGooglePhotosWallpaperDownloaded(
const GooglePhotosWallpaperParams& params,
SetWallpaperCallback callback,
const gfx::ImageSkia& image);
void SetGooglePhotosWallpaperAndUpdateCache(const AccountId& account_id,
const WallpaperInfo& info,
const gfx::ImageSkia& image,
bool show_wallpaper);
void SetOnlineWallpaperImpl(const OnlineWallpaperParams& params,
const gfx::ImageSkia& image,
bool show_wallpaper);
void SetWallpaperFromInfo(const AccountId& account_id,
const WallpaperInfo& info,
bool show_wallpaper);
void OnDefaultWallpaperDecoded(const base::FilePath& path,
WallpaperLayout layout,
bool show_wallpaper,
SetWallpaperCallback callback,
const gfx::ImageSkia& image);
void SaveAndSetWallpaper(const AccountId& account_id,
bool is_ephemeral,
const std::string& file_name,
const std::string& file_path,
WallpaperType type,
WallpaperLayout layout,
bool show_wallpaper,
const gfx::ImageSkia& image);
void SaveAndSetWallpaperWithCompletion(
const AccountId& account_id,
bool is_ephemeral,
const std::string& file_name,
const std::string& file_path,
WallpaperType type,
WallpaperLayout layout,
bool show_wallpaper,
const gfx::ImageSkia& image,
base::OnceCallback<void(const base::FilePath&)> image_saved_callback);
void SaveAndSetWallpaperWithCompletionFilesId(
const AccountId& account_id,
bool is_ephemeral,
const std::string& file_name,
const std::string& file_path,
WallpaperType type,
WallpaperLayout layout,
bool show_wallpaper,
const gfx::ImageSkia& image,
base::OnceCallback<void(const base::FilePath&)> image_saved_callback,
const std::string& wallpaper_files_id);
void OnWallpaperDecoded(const AccountId& account_id,
const base::FilePath& path,
const WallpaperInfo& info,
bool show_wallpaper,
const gfx::ImageSkia& image);
void ReloadWallpaper(bool clear_cache);
void SetCalculatedColors(const WallpaperCalculatedColors& calculated_colors);
void ResetCalculatedColors();
void CalculateWallpaperColors();
void OnColorCalculationComplete(const WallpaperInfo& info,
const WallpaperCalculatedColors& colors);
void OnOverrideWallpaperDecoded(const WallpaperInfo& info,
const gfx::ImageSkia& image);
bool IsDevicePolicyWallpaper() const;
bool IsOneShotWallpaper() const;
bool ShouldSetDevicePolicyWallpaper() const;
void SetDevicePolicyWallpaper();
void OnDevicePolicyWallpaperDecoded(const gfx::ImageSkia& image);
void GetInternalDisplayCompositorLock();
void RepaintWallpaper();
void HandleWallpaperInfoSyncedIn(const AccountId& account_id,
const WallpaperInfo& info);
void OnAttemptSetOnlineWallpaper(const OnlineWallpaperParams& params,
SetWallpaperCallback callback,
bool success);
void OnOnlineWallpaperVariantDownloaded(const OnlineWallpaperParams& params,
base::RepeatingClosure on_done,
size_t current_index,
const gfx::ImageSkia& image);
void OnAllOnlineWallpaperVariantsDownloaded(
const OnlineWallpaperParams& params,
SetWallpaperCallback callback);
bool IsDailyRefreshEnabled() const;
bool IsDailyGooglePhotosWallpaperSelected();
bool IsGooglePhotosWallpaperSet() const;
void StartDailyRefreshTimer();
void StartGooglePhotosStalenessTimer();
void OnFetchDailyWallpaperFailed();
void StartUpdateWallpaperTimer(base::TimeDelta delay);
base::TimeDelta GetTimeToNextDailyRefreshUpdate() const;
void OnUpdateWallpaperTimerExpired();
void CheckGooglePhotosStaleness(const AccountId& account_id,
const WallpaperInfo& info);
void HandleGooglePhotosStalenessCheck(
const AccountId& account_id,
ash::personalization_app::mojom::GooglePhotosPhotoPtr photo,
bool success);
void SaveWallpaperToDriveFsAndSyncInfo(const AccountId& account_id,
const base::FilePath& origin_path);
void WallpaperSavedToDriveFS(const AccountId& account_id, bool success);
void HandleCustomWallpaperInfoSyncedIn(const AccountId& account_id,
const WallpaperInfo& info);
void OnDriveFsWallpaperChange(const AccountId& account_id, bool success);
void OnGetDriveFsWallpaperModificationTime(
const AccountId& account_id,
const WallpaperInfo& wallpaper_info,
base::Time modification_time);
PrefService* GetUserPrefServiceSyncable(const AccountId& account_id) const;
void HandleDailyWallpaperInfoSyncedIn(const AccountId& account_id,
const WallpaperInfo& info);
void HandleGooglePhotosWallpaperInfoSyncedIn(const AccountId& account_id,
const WallpaperInfo& info);
void HandleSettingOnlineWallpaperFromWallpaperInfo(
const AccountId& account_id,
const WallpaperInfo& info);
void CleanUpBeforeSettingUserWallpaperInfo(const AccountId& account_id,
const WallpaperInfo& info);
bool locked_ = false;
WallpaperMode wallpaper_mode_ = WALLPAPER_NONE;
raw_ptr<WallpaperControllerClient, ExperimentalAsh>
wallpaper_controller_client_ = nullptr;
base::ObserverList<WallpaperControllerObserver>::Unchecked observers_;
std::unique_ptr<WallpaperMetricsManager> wallpaper_metrics_manager_;
std::unique_ptr<WallpaperResizer> current_wallpaper_;
std::unique_ptr<WallpaperPrefManager> pref_manager_;
std::unique_ptr<WallpaperDragDropDelegate> drag_drop_delegate_;
std::unique_ptr<WallpaperDriveFsDelegate> drivefs_delegate_;
std::unique_ptr<WallpaperColorCalculator> color_calculator_;
std::unique_ptr<WallpaperWindowStateManager> window_state_manager_;
std::unique_ptr<OnlineWallpaperVariantInfoFetcher> variant_info_fetcher_;
absl::optional<WallpaperCalculatedColors> calculated_colors_;
const std::vector<color_utils::ColorProfile> color_profiles_;
AccountId current_user_;
CustomWallpaperMap wallpaper_cache_map_;
CachedDefaultWallpaper cached_default_wallpaper_;
base::FilePath customized_default_small_path_;
base::FilePath customized_default_large_path_;
gfx::Size current_max_display_size_;
base::OneShotTimer timer_;
base::TimeDelta wallpaper_reload_delay_;
bool is_wallpaper_blurred_for_lock_state_ = false;
base::TimeDelta animation_duration_;
base::FilePath device_policy_wallpaper_path_;
bool is_first_wallpaper_ = false;
bool is_always_on_top_wallpaper_ = false;
bool is_override_wallpaper_ = false;
const std::unique_ptr<WallpaperImageDownloader> wallpaper_image_downloader_;
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
ScopedSessionObserver scoped_session_observer_{this};
base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>
theme_observation_{this};
std::unique_ptr<ui::CompositorLock> compositor_lock_;
std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
base::OnceClosure confirm_preview_wallpaper_callback_;
base::RepeatingClosure reload_preview_wallpaper_callback_;
base::RepeatingClosure reload_override_wallpaper_callback_;
gfx::ImageSkia online_wallpaper_variant_to_use_;
size_t num_variants_downloaded_ = 0;
bool bypass_decode_for_testing_ = false;
int wallpaper_count_for_testing_ = 0;
bool allow_blur_or_shield_for_testing_ = false;
std::vector<base::FilePath> decode_requests_for_testing_;
base::WallClockTimer update_wallpaper_timer_;
base::WeakPtrFactory<WallpaperControllerImpl> weak_factory_{this};
base::WeakPtrFactory<WallpaperControllerImpl> set_wallpaper_weak_factory_{
this};
};
}
#endif