// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <array>
#include <cstdlib>
#include <string>
#include <vector>
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/constants/ash_switches.h"
#include "ash/public/cpp/personalization_app/time_of_day_test_utils.h"
#include "ash/public/cpp/schedule_enums.h"
#include "ash/public/cpp/session/session_controller.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/test/in_process_data_decoder.h"
#include "ash/public/cpp/test/shell_test_api.h"
#include "ash/public/cpp/wallpaper/online_wallpaper_params.h"
#include "ash/public/cpp/wallpaper/online_wallpaper_variant.h"
#include "ash/public/cpp/wallpaper/sea_pen_image.h"
#include "ash/public/cpp/wallpaper/wallpaper_controller_client.h"
#include "ash/public/cpp/wallpaper/wallpaper_controller_observer.h"
#include "ash/public/cpp/wallpaper/wallpaper_info.h"
#include "ash/public/cpp/wallpaper/wallpaper_types.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/session/test_session_controller_client.h"
#include "ash/shell.h"
#include "ash/style/dark_light_mode_controller_impl.h"
#include "ash/system/geolocation/geolocation_controller.h"
#include "ash/system/geolocation/geolocation_controller_test_util.h"
#include "ash/system/geolocation/test_geolocation_url_loader_factory.h"
#include "ash/system/time/calendar_unittest_utils.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/ash_test_util.h"
#include "ash/wallpaper/sea_pen_wallpaper_manager.h"
#include "ash/wallpaper/test_sea_pen_wallpaper_manager_session_delegate.h"
#include "ash/wallpaper/test_wallpaper_controller_client.h"
#include "ash/wallpaper/test_wallpaper_drivefs_delegate.h"
#include "ash/wallpaper/test_wallpaper_image_downloader.h"
#include "ash/wallpaper/views/wallpaper_view.h"
#include "ash/wallpaper/views/wallpaper_widget_controller.h"
#include "ash/wallpaper/wallpaper_blur_manager.h"
#include "ash/wallpaper/wallpaper_constants.h"
#include "ash/wallpaper/wallpaper_controller_impl.h"
#include "ash/wallpaper/wallpaper_daily_refresh_scheduler.h"
#include "ash/wallpaper/wallpaper_metrics_manager.h"
#include "ash/wallpaper/wallpaper_pref_manager.h"
#include "ash/wallpaper/wallpaper_time_of_day_scheduler.h"
#include "ash/wallpaper/wallpaper_utils/sea_pen_metadata_utils.h"
#include "ash/wallpaper/wallpaper_utils/wallpaper_file_utils.h"
#include "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h"
#include "ash/webui/common/mojom/sea_pen.mojom-forward.h"
#include "ash/webui/personalization_app/proto/backdrop_wallpaper.pb.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/window_cycle/window_cycle_controller.h"
#include "ash/wm/window_state.h"
#include "base/command_line.h"
#include "base/containers/flat_map.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_writer.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/metrics_hashes.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/task/current_thread.h"
#include "base/task/task_observer.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/repeating_test_future.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/test/values_test_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/time/time_override.h"
#include "base/version.h"
#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
#include "chromeos/constants/chromeos_features.h"
#include "components/account_id/account_id.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/user_manager/user_names.h"
#include "components/user_manager/user_type.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/data_decoder/public/mojom/image_decoder.mojom-shared.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/compositor/test/layer_animator_test_controller.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/color_analysis.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/views/view_tracker.h"
#include "ui/views/widget/widget.h"
using session_manager::SessionState;
namespace ash {
namespace {
// Containers IDs used for tests.
constexpr int kWallpaperId = kShellWindowId_WallpaperContainer;
constexpr int kLockScreenWallpaperId =
kShellWindowId_LockScreenWallpaperContainer;
constexpr int kAlwaysOnTopWallpaperId =
kShellWindowId_AlwaysOnTopWallpaperContainer;
constexpr char kDefaultSmallWallpaperName[] = "small.jpg";
constexpr char kDefaultLargeWallpaperName[] = "large.jpg";
constexpr char kGuestSmallWallpaperName[] = "guest_small.jpg";
constexpr char kGuestLargeWallpaperName[] = "guest_large.jpg";
constexpr char kChildSmallWallpaperName[] = "child_small.jpg";
constexpr char kChildLargeWallpaperName[] = "child_large.jpg";
constexpr char kCustomizationSmallWallpaperName[] = "small_customization.jpeg";
constexpr char kCustomizationLargeWallpaperName[] = "large_customization.jpeg";
// Colors used to distinguish between wallpapers with large and small
// resolution.
constexpr SkColor kLargeCustomWallpaperColor = SK_ColorDKGRAY;
constexpr SkColor kSmallCustomWallpaperColor = SK_ColorLTGRAY;
// A color that can be passed to |CreateImage|. Specifically chosen to not
// conflict with any of the custom wallpaper colors.
constexpr SkColor kWallpaperColor = SK_ColorMAGENTA;
std::string GetDummyFileId(const AccountId& account_id) {
return account_id.GetUserEmail() + "-hash";
}
std::string GetDummyFileName(const AccountId& account_id) {
return account_id.GetUserEmail() + "-file";
}
constexpr char kUser1[] = "[email protected]";
const AccountId kAccountId1 = AccountId::FromUserEmailGaiaId(kUser1, kUser1);
const std::string kWallpaperFilesId1 = GetDummyFileId(kAccountId1);
const std::string kFileName1 = GetDummyFileName(kAccountId1);
constexpr char kUser2[] = "[email protected]";
const AccountId kAccountId2 = AccountId::FromUserEmailGaiaId(kUser2, kUser2);
const std::string kWallpaperFilesId2 = GetDummyFileId(kAccountId2);
const std::string kFileName2 = GetDummyFileName(kAccountId2);
constexpr char kChildEmail[] = "[email protected]";
constexpr char kDummyUrl[] = "https://best_wallpaper/1";
constexpr char kDummyUrl2[] = "https://best_wallpaper/2";
constexpr char kDummyUrl3[] = "https://best_wallpaper/3";
constexpr char kDummyUrl4[] = "https://best_wallpaper/4";
const uint64_t kAssetId = 1;
const uint64_t kAssetId2 = 2;
const uint64_t kAssetId3 = 3;
const uint64_t kAssetId4 = 4;
const uint64_t kUnitId = 1;
const uint64_t kUnitId2 = 2;
const std::string kFakeGooglePhotosAlbumId = "fake_album";
const std::string kFakeGooglePhotosPhotoId = "fake_photo";
// For checking that the wallpaper changes at approximately the correct time
// when the "auto" schedule is enabled. The sunrise/set times specified in
// `WallpaperControllerAutoScheduleTest` are just approximate and do not occur
// exactly on the hour specified.
MATCHER_P(WallpaperChangeTimeNear, hours_elapsed_since_test_start, "") {
static constexpr base::TimeDelta kTolerance = base::Minutes(5);
base::TimeDelta expected_duration_since_test_start =
base::Hours(hours_elapsed_since_test_start);
return expected_duration_since_test_start - kTolerance <= arg &&
arg <= expected_duration_since_test_start + kTolerance;
}
// Creates an image of size |size|.
gfx::ImageSkia CreateImage(int width, int height, SkColor color) {
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height);
bitmap.eraseColor(color);
gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
return image;
}
// Returns number of child windows in a shell window container.
int ChildCountForContainer(int container_id) {
aura::Window* root = Shell::Get()->GetPrimaryRootWindow();
aura::Window* container = root->GetChildById(container_id);
return static_cast<int>(container->children().size());
}
// Steps a layer animation until it is completed. Animations must be enabled.
void RunAnimationForLayer(ui::Layer* layer) {
// Animations must be enabled for stepping to work.
ASSERT_NE(ui::ScopedAnimationDurationScaleMode::duration_multiplier(),
ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
ui::LayerAnimatorTestController controller(layer->GetAnimator());
// Multiple steps are required to complete complex animations.
// TODO(vollick): This should not be necessary. crbug.com/154017
while (controller.animator()->is_animating()) {
controller.StartThreadedAnimationsIfNeeded();
base::TimeTicks step_time = controller.animator()->last_step_time();
layer->GetAnimator()->Step(step_time + base::Milliseconds(1000));
}
}
// Writes a JPEG image of the specified size and color to |path|. Returns true
// on success.
bool WriteJPEGFile(const base::FilePath& path,
int width,
int height,
SkColor color) {
base::ScopedAllowBlockingForTesting allow_blocking;
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height);
bitmap.eraseColor(color);
std::vector<unsigned char> output;
if (!gfx::JPEGCodec::Encode(bitmap, 80 /*quality*/, &output)) {
LOG(ERROR) << "Unable to encode " << width << "x" << height << " bitmap";
return false;
}
if (!base::WriteFile(path, output)) {
LOG(ERROR) << "Writing to " << path.value() << " failed.";
return false;
}
return true;
}
// Returns custom wallpaper path. Creates the directory if it doesn't exist.
base::FilePath GetCustomWallpaperPath(const char* sub_dir,
const std::string& wallpaper_files_id,
const std::string& file_name) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath wallpaper_path =
WallpaperControllerImpl::GetCustomWallpaperPath(
sub_dir, wallpaper_files_id, file_name);
if (!base::DirectoryExists(wallpaper_path.DirName()))
base::CreateDirectory(wallpaper_path.DirName());
return wallpaper_path;
}
void WaitUntilCustomWallpapersDeleted(const AccountId& account_id) {
const std::string wallpaper_file_id = GetDummyFileId(account_id);
base::FilePath small_wallpaper_dir =
WallpaperControllerImpl::GetCustomWallpaperDir(kSmallWallpaperSubDir)
.Append(wallpaper_file_id);
base::FilePath large_wallpaper_dir =
WallpaperControllerImpl::GetCustomWallpaperDir(kLargeWallpaperSubDir)
.Append(wallpaper_file_id);
base::FilePath original_wallpaper_dir =
WallpaperControllerImpl::GetCustomWallpaperDir(kOriginalWallpaperSubDir)
.Append(wallpaper_file_id);
while (base::PathExists(small_wallpaper_dir) ||
base::PathExists(large_wallpaper_dir) ||
base::PathExists(original_wallpaper_dir)) {
}
}
// Monitors if any task is processed by the message loop.
class TaskObserver : public base::TaskObserver {
public:
TaskObserver() : processed_(false) {}
TaskObserver(const TaskObserver&) = delete;
TaskObserver& operator=(const TaskObserver&) = delete;
~TaskObserver() override = default;
// TaskObserver:
void WillProcessTask(const base::PendingTask& /* pending_task */,
bool /* was_blocked_or_low_priority */) override {}
void DidProcessTask(const base::PendingTask& pending_task) override {
processed_ = true;
}
// Returns true if any task was processed.
bool processed() const { return processed_; }
private:
bool processed_;
};
// See content::RunAllTasksUntilIdle().
void RunAllTasksUntilIdle() {
while (true) {
TaskObserver task_observer;
base::CurrentThread::Get()->AddTaskObserver(&task_observer);
// May spin message loop.
base::ThreadPoolInstance::Get()->FlushForTesting();
base::RunLoop().RunUntilIdle();
base::CurrentThread::Get()->RemoveTaskObserver(&task_observer);
if (!task_observer.processed())
break;
}
}
PrefService* GetProfilePrefService(const AccountId& account_id) {
return Shell::Get()->session_controller()->GetUserPrefServiceForUser(
account_id);
}
WallpaperInfo InfoWithType(WallpaperType type) {
WallpaperInfo info(std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, type,
base::Time::Now());
if (IsOnlineWallpaper(type)) {
// Daily and Online types require asset id and collection id.
info.unit_id = 1234;
info.collection_id = "placeholder collection";
info.location = "https://example.com/example.jpeg";
}
if (type == WallpaperType::kOnceGooglePhotos)
info.dedup_key = "dedup_key";
return info;
}
base::Time DayBeforeYesterdayish() {
base::TimeDelta today_delta =
base::Time::Now().LocalMidnight().ToDeltaSinceWindowsEpoch();
base::TimeDelta yesterday_delta = today_delta - base::Days(2);
return base::Time::FromDeltaSinceWindowsEpoch(yesterday_delta);
}
// A test implementation of the WallpaperControllerObserver interface.
class TestWallpaperControllerObserver : public WallpaperControllerObserver {
public:
explicit TestWallpaperControllerObserver(WallpaperController* controller)
: controller_(controller) {
controller_->AddObserver(this);
}
TestWallpaperControllerObserver(const TestWallpaperControllerObserver&) =
delete;
TestWallpaperControllerObserver& operator=(
const TestWallpaperControllerObserver&) = delete;
~TestWallpaperControllerObserver() override {
controller_->RemoveObserver(this);
}
void SetOnResizeCallback(base::RepeatingClosure callback) {
resize_callback_ = callback;
}
void SetOnColorsCalculatedCallback(base::RepeatingClosure callback) {
colors_calculated_callback_ = callback;
}
// WallpaperControllerObserver
void OnWallpaperChanged() override { ++wallpaper_changed_count_; }
void OnWallpaperResized() override {
if (resize_callback_) {
resize_callback_.Run();
}
}
void OnWallpaperColorsChanged() override {
++colors_changed_count_;
if (colors_calculated_callback_) {
colors_calculated_callback_.Run();
}
}
void OnWallpaperBlurChanged() override { ++blur_changed_count_; }
void OnFirstWallpaperShown() override { ++first_shown_count_; }
void OnWallpaperPreviewStarted() override {
DCHECK(!is_in_wallpaper_preview_);
is_in_wallpaper_preview_ = true;
}
void OnWallpaperPreviewEnded() override {
DCHECK(is_in_wallpaper_preview_);
is_in_wallpaper_preview_ = false;
}
void OnDailyRefreshCheckpointChanged() override {
++daily_refresh_checkpoint_count_;
}
int colors_changed_count() const { return colors_changed_count_; }
int blur_changed_count() const { return blur_changed_count_; }
int first_shown_count() const { return first_shown_count_; }
int wallpaper_changed_count() const { return wallpaper_changed_count_; }
int daily_refresh_checkpoint_count() const {
return daily_refresh_checkpoint_count_;
}
bool is_in_wallpaper_preview() const { return is_in_wallpaper_preview_; }
void ClearDailyRefreshCheckpointCount() {
daily_refresh_checkpoint_count_ = 0;
}
private:
raw_ptr<WallpaperController> controller_;
base::RepeatingClosure resize_callback_;
base::RepeatingClosure colors_calculated_callback_;
int colors_changed_count_ = 0;
int blur_changed_count_ = 0;
int first_shown_count_ = 0;
int wallpaper_changed_count_ = 0;
int daily_refresh_checkpoint_count_ = 0;
bool is_in_wallpaper_preview_ = false;
};
// Runs until the next time the wallpaper changes.
class WallpaperChangedBarrier : public WallpaperControllerObserver {
public:
WallpaperChangedBarrier(WallpaperController* controller,
base::test::TaskEnvironment* task_environment)
: task_environment_(task_environment) {
CHECK(task_environment_);
controller_observation_.Observe(controller);
}
WallpaperChangedBarrier(const WallpaperChangedBarrier&) = delete;
WallpaperChangedBarrier& operator=(const WallpaperChangedBarrier&) = delete;
~WallpaperChangedBarrier() override = default;
// WallpaperControllerObserver:
void OnWallpaperChanged() override { wallpaper_changed_ = true; }
bool RunUntilNextWallpaperChange() {
wallpaper_changed_ = false;
while (!wallpaper_changed_) {
RunAllTasksUntilIdle();
base::TimeDelta delay_until_next_task =
task_environment_->NextMainThreadPendingTaskDelay();
if (delay_until_next_task == base::TimeDelta::Max()) {
// Technically, a delayed task on a different thread than "main" could
// trigger a wallpaper change but that is currently not the case.
return false;
}
task_environment_->FastForwardBy(delay_until_next_task);
}
return true;
}
private:
base::ScopedObservation<WallpaperController, WallpaperControllerObserver>
controller_observation_{this};
const raw_ptr<base::test::TaskEnvironment> task_environment_;
bool wallpaper_changed_ = false;
};
// Returns the image in `backdrop_image_data` whose `image_url` matches `url`,
// or nullptr if no match is found.
const backdrop::Image* GetImageMatchingUrl(
const GURL& url,
const std::vector<backdrop::Image>& backdrop_image_data) {
for (const backdrop::Image& image : backdrop_image_data) {
if (image.image_url() == url.spec()) {
return ℑ
}
}
return nullptr;
}
// Returns the time of day wallpapers in order of light, morning, late
// afternoon, and dark.
std::vector<backdrop::Image> TimeOfDayImageSet() {
const std::vector<backdrop::Image_ImageType> image_types = {
backdrop::Image::IMAGE_TYPE_LIGHT_MODE,
backdrop::Image::IMAGE_TYPE_MORNING_MODE,
backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE,
backdrop::Image::IMAGE_TYPE_DARK_MODE};
std::vector<backdrop::Image> images;
for (size_t i = 0; i < image_types.size(); ++i) {
const uint64_t asset_id = i + 99;
const std::string url =
base::StringPrintf("https://preferred_wallpaper/images/%zu", asset_id);
backdrop::Image image;
image.set_asset_id(asset_id);
image.set_unit_id(wallpaper_constants::kDefaultTimeOfDayWallpaperUnitId);
image.set_image_type(image_types[i]);
image.set_image_url(url);
images.push_back(image);
}
return images;
}
// Returns a collection of images with randomized asset ids.
std::vector<backdrop::Image> ImageSet() {
const size_t image_size = 10;
const auto base_asset_id = rand() % 100;
std::vector<backdrop::Image> images;
for (size_t i = 0; i < image_size; ++i) {
const uint64_t asset_id = i + base_asset_id;
const std::string url =
base::StringPrintf("https://preferred_wallpaper/images/%zu", asset_id);
backdrop::Image image;
image.set_asset_id(asset_id);
image.set_unit_id(asset_id);
image.set_image_type(backdrop::Image::IMAGE_TYPE_UNKNOWN);
image.set_image_url(url);
images.push_back(image);
}
return images;
}
} // namespace
class WallpaperControllerTestBase : public AshTestBase {
public:
WallpaperControllerTestBase()
: AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
WallpaperControllerTestBase(const WallpaperControllerTestBase&) = delete;
WallpaperControllerTestBase& operator=(const WallpaperControllerTestBase&) =
delete;
void SetUp() override {
auto pref_manager = WallpaperPrefManager::Create(local_state());
pref_manager_ = pref_manager.get();
// Override the pref manager and image downloader that will be used to
// construct the WallpaperController.
WallpaperControllerImpl::SetWallpaperPrefManagerForTesting(
std::move(pref_manager));
WallpaperControllerImpl::SetWallpaperImageDownloaderForTesting(
std::make_unique<TestWallpaperImageDownloader>());
AshTestBase::SetUp();
SeaPenWallpaperManager::GetInstance()->SetSessionDelegateForTesting(
std::make_unique<TestSeaPenWallpaperManagerSessionDelegate>());
TestSessionControllerClient* const client = GetSessionControllerClient();
client->ProvidePrefServiceForUser(kAccountId1);
client->ProvidePrefServiceForUser(kAccountId2);
client->ProvidePrefServiceForUser(
AccountId::FromUserEmail(user_manager::kGuestUserName));
client->ProvidePrefServiceForUser(kChildAccountId);
controller_ = Shell::Get()->wallpaper_controller();
controller_->set_wallpaper_reload_no_delay_for_test();
ASSERT_TRUE(user_data_dir_.CreateUniqueTempDir());
ASSERT_TRUE(online_wallpaper_dir_.CreateUniqueTempDir());
ASSERT_TRUE(custom_wallpaper_dir_.CreateUniqueTempDir());
base::FilePath policy_wallpaper;
controller_->Init(user_data_dir_.GetPath(), online_wallpaper_dir_.GetPath(),
custom_wallpaper_dir_.GetPath(), policy_wallpaper);
client_.ResetCounts();
controller_->SetClient(&client_);
std::unique_ptr<TestWallpaperDriveFsDelegate> drivefs_delegate =
std::make_unique<TestWallpaperDriveFsDelegate>();
drivefs_delegate_ = drivefs_delegate.get();
controller_->SetDriveFsDelegate(std::move(drivefs_delegate));
client_.set_fake_files_id_for_account_id(kAccountId1, kWallpaperFilesId1);
client_.set_fake_files_id_for_account_id(kAccountId2, kWallpaperFilesId2);
CreateDefaultWallpapers();
}
void TearDown() override {
AshTestBase::TearDown();
}
WallpaperView* wallpaper_view() {
return Shell::Get()
->GetPrimaryRootWindowController()
->wallpaper_widget_controller()
->wallpaper_view();
}
protected:
// Helper function that tests the wallpaper is always fitted to the native
// display resolution when the layout is WALLPAPER_LAYOUT_CENTER.
void WallpaperFitToNativeResolution(WallpaperView* view,
float device_scale_factor,
int image_width,
int image_height,
SkColor color) {
gfx::Size size = view->bounds().size();
gfx::Canvas canvas(size, device_scale_factor, true);
view->OnPaint(&canvas);
SkBitmap bitmap = canvas.GetBitmap();
int bitmap_width = bitmap.width();
int bitmap_height = bitmap.height();
for (int i = 0; i < bitmap_width; i++) {
for (int j = 0; j < bitmap_height; j++) {
if (i >= (bitmap_width - image_width) / 2 &&
i < (bitmap_width + image_width) / 2 &&
j >= (bitmap_height - image_height) / 2 &&
j < (bitmap_height + image_height) / 2) {
EXPECT_EQ(color, bitmap.getColor(i, j));
} else {
EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(i, j));
}
}
}
}
// Runs AnimatingWallpaperWidgetController's animation to completion.
void RunDesktopControllerAnimation() {
WallpaperWidgetController* controller =
Shell::Get()
->GetPrimaryRootWindowController()
->wallpaper_widget_controller();
ASSERT_TRUE(controller);
ui::LayerTreeOwner* owner = controller->old_layer_tree_owner_for_testing();
if (!owner)
return;
ASSERT_NO_FATAL_FAILURE(RunAnimationForLayer(owner->root()));
}
// Convenience function to ensure ShouldCalculateColors() returns true.
void EnableShelfColoring() {
const gfx::ImageSkia kImage = CreateImage(10, 10, kWallpaperColor);
controller_->ShowWallpaperImage(
kImage, CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH),
/*preview_mode=*/false, /*is_override=*/false);
SetSessionState(SessionState::ACTIVE);
EXPECT_TRUE(ShouldCalculateColors());
}
// Convenience function to set the SessionState.
void SetSessionState(SessionState session_state) {
GetSessionControllerClient()->SetSessionState(session_state);
}
// Helper function to create a |WallpaperInfo| struct with dummy values
// given the desired layout.
WallpaperInfo CreateWallpaperInfo(WallpaperLayout layout) {
return WallpaperInfo(std::string(), layout, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
}
// Saves wallpaper images in the appropriate location for |account_id| and
// returns the relative path of the file.
base::FilePath PrecacheWallpapers(const AccountId& account_id) {
std::string wallpaper_files_id = GetDummyFileId(account_id);
std::string file_name = GetDummyFileName(account_id);
base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
kSmallWallpaperSubDir, wallpaper_files_id, file_name);
base::FilePath large_wallpaper_path = GetCustomWallpaperPath(
kLargeWallpaperSubDir, wallpaper_files_id, file_name);
// Saves the small/large resolution wallpapers to small/large custom
// wallpaper paths.
CHECK(WriteJPEGFile(small_wallpaper_path, kSmallWallpaperMaxWidth,
kSmallWallpaperMaxHeight, kSmallCustomWallpaperColor));
CHECK(WriteJPEGFile(large_wallpaper_path, kLargeWallpaperMaxWidth,
kLargeWallpaperMaxHeight, kLargeCustomWallpaperColor));
return base::FilePath(wallpaper_files_id).Append(file_name);
}
// Saves images with different resolution to corresponding paths and saves
// wallpaper info to local state, so that subsequent calls of |ShowWallpaper|
// can retrieve the images and info.
void CreateAndSaveWallpapers(const AccountId& account_id) {
base::FilePath relative_path = PrecacheWallpapers(account_id);
// Saves wallpaper info to local state for user.
WallpaperInfo info = {
relative_path.value(), WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight()};
ASSERT_TRUE(pref_manager_->SetUserWallpaperInfo(account_id, info));
}
// Initializes default wallpaper paths "*default_*file" and writes JPEG
// wallpaper images to them. Called during SetUp() to mimic production
// behavior, which expects default wallpapers to always exist.
void CreateDefaultWallpapers() {
base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(default_wallpaper_dir_.CreateUniqueTempDir());
const base::FilePath default_wallpaper_path =
default_wallpaper_dir_.GetPath();
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
const base::FilePath small_file =
default_wallpaper_path.Append(kDefaultSmallWallpaperName);
command_line->AppendSwitchASCII(switches::kDefaultWallpaperSmall,
small_file.value());
const base::FilePath large_file =
default_wallpaper_path.Append(kDefaultLargeWallpaperName);
command_line->AppendSwitchASCII(switches::kDefaultWallpaperLarge,
large_file.value());
const base::FilePath guest_small_file =
default_wallpaper_path.Append(kGuestSmallWallpaperName);
command_line->AppendSwitchASCII(switches::kGuestWallpaperSmall,
guest_small_file.value());
const base::FilePath guest_large_file =
default_wallpaper_path.Append(kGuestLargeWallpaperName);
command_line->AppendSwitchASCII(switches::kGuestWallpaperLarge,
guest_large_file.value());
const base::FilePath child_small_file =
default_wallpaper_path.Append(kChildSmallWallpaperName);
command_line->AppendSwitchASCII(switches::kChildWallpaperSmall,
child_small_file.value());
const base::FilePath child_large_file =
default_wallpaper_path.Append(kChildLargeWallpaperName);
command_line->AppendSwitchASCII(switches::kChildWallpaperLarge,
child_large_file.value());
const int kWallpaperSize = 2;
ASSERT_TRUE(WriteJPEGFile(small_file, kWallpaperSize, kWallpaperSize,
kWallpaperColor));
ASSERT_TRUE(WriteJPEGFile(large_file, kWallpaperSize, kWallpaperSize,
kWallpaperColor));
ASSERT_TRUE(WriteJPEGFile(guest_small_file, kWallpaperSize, kWallpaperSize,
kWallpaperColor));
ASSERT_TRUE(WriteJPEGFile(guest_large_file, kWallpaperSize, kWallpaperSize,
kWallpaperColor));
ASSERT_TRUE(WriteJPEGFile(child_small_file, kWallpaperSize, kWallpaperSize,
kWallpaperColor));
ASSERT_TRUE(WriteJPEGFile(child_large_file, kWallpaperSize, kWallpaperSize,
kWallpaperColor));
}
// Returns the paths of a small and large jpeg for use with customized default
// wallpapers.
[[nodiscard]] std::pair<const base::FilePath, const base::FilePath>
CreateCustomizationWallpapers() {
base::ScopedAllowBlockingForTesting allow_blocking;
CHECK(customization_wallpaper_dir_.CreateUniqueTempDir());
base::FilePath root = customization_wallpaper_dir_.GetPath();
const base::FilePath small_file =
root.Append(kCustomizationSmallWallpaperName);
const base::FilePath large_file =
root.Append(kCustomizationLargeWallpaperName);
CHECK(WriteJPEGFile(small_file, 800, 800, SK_ColorGREEN));
CHECK(WriteJPEGFile(large_file, 2000, 2000, SK_ColorBLUE));
return {small_file, large_file};
}
// A helper to test the behavior of setting online wallpaper after the image
// is decoded. This is needed because image decoding is not supported in unit
// tests.
void SetOnlineWallpaperFromImage(
const AccountId& account_id,
uint64_t asset_id,
const gfx::ImageSkia& image,
const std::string& url,
const std::string& collection_id,
WallpaperLayout layout,
bool preview_mode,
bool from_user,
uint64_t unit_id,
WallpaperController::SetWallpaperCallback callback) {
const OnlineWallpaperVariant variant(asset_id, GURL(url),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
const OnlineWallpaperParams params = {
account_id, collection_id, layout,
preview_mode, from_user, /*daily_refresh_enabled=*/false,
unit_id, {variant}};
controller_->OnOnlineWallpaperDecoded(account_id, preview_mode,
WallpaperInfo(params, variant),
std::move(callback), image);
}
// Returns color of the current wallpaper. Note: this function assumes the
// wallpaper has a solid color.
SkColor GetWallpaperColor() {
const gfx::ImageSkiaRep& representation =
controller_->GetWallpaper().GetRepresentation(1.0f);
return representation.GetBitmap().getColor(0, 0);
}
// Wrapper for private ShouldCalculateColors().
bool ShouldCalculateColors() { return controller_->ShouldCalculateColors(); }
// Wrapper for private IsDevicePolicyWallpaper().
bool IsDevicePolicyWallpaper() {
return controller_->IsDevicePolicyWallpaper();
}
int GetWallpaperCount() { return controller_->wallpaper_count_for_testing_; }
const std::vector<base::FilePath>& GetDecodeFilePaths() {
return controller_->decode_requests_for_testing_;
}
// Returns the `WallpaperInfo` associated with the current
// `WallpaperResizer`. Usually, this is the same as
// `GetActiveUserWallpaperInfo()` except when the user is not logged in.
const WallpaperInfo GetCurrentWallpaperInfo() {
WallpaperResizer* wallpaper = controller_->current_wallpaper_.get();
if (!wallpaper)
return WallpaperInfo();
return wallpaper->wallpaper_info();
}
void ClearWallpaperCount() { controller_->wallpaper_count_for_testing_ = 0; }
void ClearDecodeFilePaths() {
controller_->decode_requests_for_testing_.clear();
}
void ClearWallpaper() { controller_->current_wallpaper_.reset(); }
const base::HistogramTester& histogram_tester() const {
return histogram_tester_;
}
void CacheOnlineWallpaper(std::string path) {
// Set an Online Wallpaper from Data, so syncing in doesn't need to download
// an Online Wallpaper.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->SetOnlineWallpaper(
OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(path), backdrop::Image::IMAGE_TYPE_UNKNOWN}}),
base::DoNothing());
RunAllTasksUntilIdle();
// Change the on-screen wallpaper to a different one. (Otherwise the
// subsequent calls will be no-op since we intentionally prevent reloading
// the same wallpaper.)
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"",
CreateImage(640, 480, kWallpaperColor));
RunAllTasksUntilIdle();
}
void SetSeaPenWallpaper(const AccountId& account_id,
SkColor color,
uint32_t id,
bool preview_mode,
gfx::ImageSkia* image) {
TestWallpaperControllerObserver observer(controller_);
std::string jpg_bytes = CreateEncodedImageForTesting(
{1, 1}, color, data_decoder::mojom::ImageCodec::kDefault, image);
ASSERT_TRUE(!jpg_bytes.empty());
base::test::TestFuture<bool> save_sea_pen_image_future;
auto* sea_pen_wallpaper_manager = SeaPenWallpaperManager::GetInstance();
sea_pen_wallpaper_manager->SaveSeaPenImage(
account_id, {std::move(jpg_bytes), id},
personalization_app::mojom::SeaPenQuery::NewTextQuery("search_query"),
save_sea_pen_image_future.GetCallback());
ASSERT_TRUE(save_sea_pen_image_future.Get());
base::test::TestFuture<bool> set_wallpaper_future;
controller_->SetSeaPenWallpaper(account_id, id, preview_mode,
set_wallpaper_future.GetCallback());
EXPECT_TRUE(set_wallpaper_future.Take());
EXPECT_EQ(1, observer.wallpaper_changed_count());
histogram_tester().ExpectUniqueSample("Ash.Wallpaper.SeaPen.Result2",
SetWallpaperResult::kSuccess, 1);
}
TestWallpaperImageDownloader* test_wallpaper_image_downloader() {
return static_cast<TestWallpaperImageDownloader*>(
controller_->wallpaper_image_downloader_for_testing());
}
void WaitForWallpaperCount(int count) {
base::RunLoop run_loop;
base::RepeatingTimer repeating_timer;
repeating_timer.Start(FROM_HERE, base::Milliseconds(10),
base::BindLambdaForTesting([&]() {
if (GetWallpaperCount() >= count) {
repeating_timer.Stop();
run_loop.Quit();
}
}));
run_loop.Run();
}
// Returns the last modified time of a file. Returns the old last modified
// time if the process fails.
base::Time GetLastModifiedTime(const base::FilePath& path) {
base::File::Info info;
base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (file.GetInfo(&info)) {
return info.last_modified;
}
return base::Time();
}
raw_ptr<WallpaperControllerImpl, DanglingUntriaged> controller_;
raw_ptr<WallpaperPrefManager, DanglingUntriaged> pref_manager_ =
nullptr; // owned by controller
base::ScopedTempDir user_data_dir_;
base::ScopedTempDir online_wallpaper_dir_;
base::ScopedTempDir custom_wallpaper_dir_;
base::ScopedTempDir default_wallpaper_dir_;
base::ScopedTempDir customization_wallpaper_dir_;
base::HistogramTester histogram_tester_;
TestWallpaperControllerClient client_;
raw_ptr<TestWallpaperDriveFsDelegate, DanglingUntriaged> drivefs_delegate_;
const AccountId kChildAccountId =
AccountId::FromUserEmailGaiaId(kChildEmail, kChildEmail);
private:
InProcessDataDecoder decoder_;
base::Time mock_clock_origin_;
};
// All possible feature combinations that can occur in the real world.
enum class TimeOfDayFeatureCombination { kDisabled, kTimeOfDay };
class WallpaperControllerTest
: public WallpaperControllerTestBase,
public testing::WithParamInterface<TimeOfDayFeatureCombination> {
public:
WallpaperControllerTest() {
std::vector<base::test::FeatureRef> enabled_features;
std::vector<base::test::FeatureRef> disabled_features;
switch (GetParam()) {
case TimeOfDayFeatureCombination::kDisabled:
disabled_features = personalization_app::GetTimeOfDayDisabledFeatures();
break;
case TimeOfDayFeatureCombination::kTimeOfDay:
enabled_features = personalization_app::GetTimeOfDayEnabledFeatures();
break;
}
enabled_features.push_back(features::kSeaPen);
enabled_features.push_back(features::kFeatureManagementSeaPen);
enabled_features.push_back(features::kSeaPenDemoMode);
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
WallpaperControllerTest(const WallpaperControllerTest&) = delete;
WallpaperControllerTest& operator=(const WallpaperControllerTest&) = delete;
~WallpaperControllerTest() override = default;
bool IsTimeOfDayEnabled() const {
switch (GetParam()) {
case TimeOfDayFeatureCombination::kDisabled:
return false;
case TimeOfDayFeatureCombination::kTimeOfDay:
return true;
}
}
// Populate meaningful test suffixes instead of /0, /1, etc.
struct PrintToStringParamName {
std::string operator()(
const testing::TestParamInfo<ParamType>& info) const {
switch (info.param) {
case TimeOfDayFeatureCombination::kDisabled:
return "TimeOfDayOff";
case TimeOfDayFeatureCombination::kTimeOfDay:
return "TimeOfDayOn";
}
}
};
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// For tests that use the "auto" D/L mode setting and need a definitive
// geoposition/date with known sunrise/sunset times.
class WallpaperControllerAutoScheduleTest : public WallpaperControllerTest,
public ScheduledFeature::Clock {
protected:
// San Jose. Sunrise is approximately 7:00 AM, and sunset is approximately
// 7:00 PM PDT on `kTestDateMidnight`. Test starts at `kTestDateMidnight`
// by default.
static constexpr SimpleGeoposition kSanJoseGeoposition = {37.335480,
-121.893028};
static constexpr char kTestDateMidnight[] = "26 Sep 2023 00:00:00 PDT";
static constexpr char kPDTTimezone[] = "America/Los_Angeles";
WallpaperControllerAutoScheduleTest()
: task_environment_(task_environment()), timezone_pdt_(kPDTTimezone) {}
void SetUp() override {
ASSERT_TRUE(timezone_pdt_.is_success());
WallpaperControllerTest::SetUp();
task_environment_start_time_ = task_environment()->GetMockClock()->Now();
SetSimulatedStartTime(GetTestDateMidnight());
// Set fixed geoposition for testing.
scoped_refptr<TestGeolocationUrlLoaderFactory>
geolocation_url_loader_factory =
base::MakeRefCounted<TestGeolocationUrlLoaderFactory>();
geolocation_url_loader_factory->SetValidPosition(
kSanJoseGeoposition.latitude, kSanJoseGeoposition.longitude, Now());
SimpleGeolocationProvider::GetInstance()
->SetSharedUrlLoaderFactoryForTesting(
std::move(geolocation_url_loader_factory));
GeopositionResponsesWaiter waiter(Shell::Get()->geolocation_controller());
waiter.Wait();
}
// base::Clock:
base::Time Now() const override {
base::TimeDelta test_time_elapsed =
task_environment_->GetMockClock()->Now() - task_environment_start_time_;
return simulated_start_time_ + test_time_elapsed;
}
// base::TickClock:
base::TimeTicks NowTicks() const override {
return task_environment_->NowTicks();
}
base::Time GetTestDateMidnight() {
base::Time time;
CHECK(base::Time::FromString(kTestDateMidnight, &time));
return time;
}
void SetSimulatedStartTime(base::Time simulated_start_time) {
// Turn "auto" schedule off first to kill any internal timers within these
// objects before passing them a new clock.
WallpaperTimeOfDayScheduler& time_of_day_scheduler =
*Shell::Get()
->wallpaper_controller()
->time_of_day_scheduler_for_testing();
Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false);
time_of_day_scheduler.SetScheduleType(ScheduleType::kNone);
simulated_start_time_ = simulated_start_time;
Shell::Get()->geolocation_controller()->SetClockForTesting(this);
Shell::Get()->dark_light_mode_controller()->SetClockForTesting(this);
time_of_day_scheduler.SetClockForTesting(this);
Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(true);
time_of_day_scheduler.SetScheduleType(ScheduleType::kSunsetToSunrise);
}
const raw_ptr<base::test::TaskEnvironment> task_environment_;
const calendar_test_utils::ScopedLibcTimeZone timezone_pdt_;
base::Time simulated_start_time_;
base::Time task_environment_start_time_;
};
INSTANTIATE_TEST_SUITE_P(
// Empty to simplify gtest output
,
WallpaperControllerTest,
::testing::Values(TimeOfDayFeatureCombination::kDisabled,
TimeOfDayFeatureCombination::kTimeOfDay),
WallpaperControllerTest::PrintToStringParamName());
INSTANTIATE_TEST_SUITE_P(
// Empty to simplify gtest output
,
WallpaperControllerAutoScheduleTest,
::testing::Values(TimeOfDayFeatureCombination::kDisabled,
TimeOfDayFeatureCombination::kTimeOfDay),
WallpaperControllerTest::PrintToStringParamName());
TEST_P(WallpaperControllerTest, Client) {
base::FilePath empty_path;
controller_->Init(empty_path, empty_path, empty_path, empty_path);
EXPECT_EQ(0u, client_.open_count());
controller_->OpenWallpaperPickerIfAllowed();
EXPECT_EQ(1u, client_.open_count());
}
TEST_P(WallpaperControllerTest, BasicReparenting) {
WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller();
controller->CreateEmptyWallpaperForTesting();
// Wallpaper view/window exists in the wallpaper container and nothing is in
// the lock screen wallpaper container.
EXPECT_EQ(1, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(0, ChildCountForContainer(kLockScreenWallpaperId));
controller->OnSessionStateChanged(session_manager::SessionState::LOCKED);
// One window is moved from desktop to lock container.
EXPECT_EQ(0, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(1, ChildCountForContainer(kLockScreenWallpaperId));
controller->OnSessionStateChanged(session_manager::SessionState::ACTIVE);
// One window is moved from lock to desktop container.
EXPECT_EQ(1, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(0, ChildCountForContainer(kLockScreenWallpaperId));
}
TEST_P(WallpaperControllerTest, SwitchWallpapersWhenNewWallpaperAnimationEnds) {
// We cannot short-circuit animations for this test.
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
// Create the wallpaper and its view.
WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller();
controller->CreateEmptyWallpaperForTesting();
// The new wallpaper is ready to animate.
WallpaperWidgetController* widget_controller =
Shell::Get()
->GetPrimaryRootWindowController()
->wallpaper_widget_controller();
EXPECT_TRUE(widget_controller->IsAnimating());
// Force the animation to play to completion.
RunDesktopControllerAnimation();
EXPECT_FALSE(widget_controller->IsAnimating());
}
// Test for crbug.com/149043 "Unlock screen, no launcher appears". Ensure we
// move all wallpaper views if there are more than one.
TEST_P(WallpaperControllerTest, WallpaperMovementDuringUnlock) {
// We cannot short-circuit animations for this test.
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
// Reset wallpaper state, see ControllerOwnership above.
WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller();
controller->CreateEmptyWallpaperForTesting();
// Run wallpaper show animation to completion.
RunDesktopControllerAnimation();
// User locks the screen, which moves the wallpaper forward.
controller->OnSessionStateChanged(session_manager::SessionState::LOCKED);
// Suspend/resume cycle causes wallpaper to refresh, loading a new wallpaper
// that will animate in on top of the old one.
controller->CreateEmptyWallpaperForTesting();
const bool forest_enabled = features::IsForestFeatureEnabled();
// In this state we have a wallpaper views stored in
// LockScreenWallpaperContainer.
WallpaperWidgetController* widget_controller =
Shell::Get()
->GetPrimaryRootWindowController()
->wallpaper_widget_controller();
EXPECT_TRUE(widget_controller->IsAnimating());
EXPECT_EQ(0, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(1, ChildCountForContainer(kLockScreenWallpaperId));
if (forest_enabled) {
// There must be four layers: shield, underlay, original and old layers.
ASSERT_EQ(4u, wallpaper_view()->layer()->parent()->children().size());
} else {
// There must be three layers: shield, original and old layers.
ASSERT_EQ(3u, wallpaper_view()->layer()->parent()->children().size());
}
// Before the wallpaper's animation completes, user unlocks the screen, which
// moves the wallpaper to the back.
controller->OnSessionStateChanged(session_manager::SessionState::ACTIVE);
// Ensure that widget has moved.
EXPECT_EQ(1, ChildCountForContainer(kWallpaperId));
// The shield layer is gone during an active session.
if (forest_enabled) {
ASSERT_EQ(3u, wallpaper_view()->layer()->parent()->children().size());
} else {
ASSERT_EQ(2u, wallpaper_view()->layer()->parent()->children().size());
}
EXPECT_EQ(0, ChildCountForContainer(kLockScreenWallpaperId));
// Finish the new wallpaper animation.
RunDesktopControllerAnimation();
EXPECT_EQ(1, ChildCountForContainer(kWallpaperId));
if (forest_enabled) {
// Now there is one wallpaper and two layers: underlay and original.
ASSERT_EQ(2u, wallpaper_view()->layer()->parent()->children().size());
} else {
// Now there is one wallpaper and the original layer.
ASSERT_EQ(1u, wallpaper_view()->layer()->parent()->children().size());
}
EXPECT_EQ(0, ChildCountForContainer(kLockScreenWallpaperId));
}
// Test for crbug.com/156542. Animating wallpaper should immediately finish
// animation and replace current wallpaper before next animation starts.
TEST_P(WallpaperControllerTest, ChangeWallpaperQuick) {
// We cannot short-circuit animations for this test.
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
// Reset wallpaper state, see ControllerOwnership above.
WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller();
controller->CreateEmptyWallpaperForTesting();
// Run wallpaper show animation to completion.
RunDesktopControllerAnimation();
// Change to a new wallpaper.
controller->CreateEmptyWallpaperForTesting();
WallpaperWidgetController* widget_controller =
Shell::Get()
->GetPrimaryRootWindowController()
->wallpaper_widget_controller();
EXPECT_TRUE(widget_controller->IsAnimating());
// Change to another wallpaper before animation finished.
controller->CreateEmptyWallpaperForTesting();
// Run wallpaper show animation to completion.
RunDesktopControllerAnimation();
EXPECT_FALSE(widget_controller->IsAnimating());
}
TEST_P(WallpaperControllerTest, ResizeCustomWallpaper) {
UpdateDisplay("320x200");
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
// Set the image as custom wallpaper, wait for the resize to finish, and check
// that the resized image is the expected size.
controller_->ShowWallpaperImage(
image, CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH),
/*preview_mode=*/false, /*is_override=*/false);
EXPECT_TRUE(gfx::test::AreImagesEqual(gfx::Image(controller_->GetWallpaper()),
gfx::Image(image)));
RunAllTasksUntilIdle();
gfx::ImageSkia resized_image = controller_->GetWallpaper();
EXPECT_FALSE(gfx::test::AreImagesEqual(
gfx::Image(controller_->GetWallpaper()), gfx::Image(image)));
EXPECT_EQ(gfx::Size(320, 200).ToString(), resized_image.size().ToString());
// Load the original wallpaper again and check that we're still using the
// previously-resized image instead of doing another resize
// (http://crbug.com/321402).
controller_->ShowWallpaperImage(
image, CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH),
/*preview_mode=*/false, /*is_override=*/false);
RunAllTasksUntilIdle();
EXPECT_TRUE(resized_image.BackedBySameObjectAs(controller_->GetWallpaper()));
}
// Test that the wallpaper is always fitted to the native display resolution
// when the layout is WALLPAPER_LAYOUT_CENTER to prevent blurry images.
TEST_P(WallpaperControllerTest, DontScaleWallpaperWithCenterLayout) {
// We cannot short-circuit animations for this test.
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
const gfx::Size high_resolution(3600, 2400);
const gfx::Size low_resolution(360, 240);
const float high_dsf = 2.0f;
const float low_dsf = 1.0f;
gfx::ImageSkia image_high_res = CreateImage(
high_resolution.width(), high_resolution.height(), kWallpaperColor);
gfx::ImageSkia image_low_res = CreateImage(
low_resolution.width(), low_resolution.height(), kWallpaperColor);
UpdateDisplay("1200x600*2");
{
SCOPED_TRACE(base::StringPrintf("1200x600*2 high resolution"));
controller_->ShowWallpaperImage(
image_high_res, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
WallpaperFitToNativeResolution(wallpaper_view(), high_dsf,
high_resolution.width(),
high_resolution.height(), kWallpaperColor);
}
{
SCOPED_TRACE(base::StringPrintf("1200x600*2 low resolution"));
controller_->ShowWallpaperImage(
image_low_res, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
WallpaperFitToNativeResolution(wallpaper_view(), high_dsf,
low_resolution.width(),
low_resolution.height(), kWallpaperColor);
}
UpdateDisplay("1200x600");
{
SCOPED_TRACE(base::StringPrintf("1200x600 high resolution"));
controller_->ShowWallpaperImage(
image_high_res, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
WallpaperFitToNativeResolution(wallpaper_view(), low_dsf,
high_resolution.width(),
high_resolution.height(), kWallpaperColor);
}
{
SCOPED_TRACE(base::StringPrintf("1200x600 low resolution"));
controller_->ShowWallpaperImage(
image_low_res, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
WallpaperFitToNativeResolution(wallpaper_view(), low_dsf,
low_resolution.width(),
low_resolution.height(), kWallpaperColor);
}
UpdateDisplay("1200x600/[email protected]"); // 1.5 ui scale
{
SCOPED_TRACE(base::StringPrintf("1200x600/[email protected] high resolution"));
controller_->ShowWallpaperImage(
image_high_res, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
WallpaperFitToNativeResolution(wallpaper_view(), low_dsf,
high_resolution.width(),
high_resolution.height(), kWallpaperColor);
}
{
SCOPED_TRACE(base::StringPrintf("1200x600/[email protected] low resolution"));
controller_->ShowWallpaperImage(
image_low_res, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
WallpaperFitToNativeResolution(wallpaper_view(), low_dsf,
low_resolution.width(),
low_resolution.height(), kWallpaperColor);
}
}
TEST_P(WallpaperControllerTest, ShouldCalculateColorsBasedOnImage) {
EnableShelfColoring();
EXPECT_TRUE(ShouldCalculateColors());
controller_->CreateEmptyWallpaperForTesting();
EXPECT_FALSE(ShouldCalculateColors());
}
TEST_P(WallpaperControllerTest, ShouldCalculateColorsBasedOnSessionState) {
EnableShelfColoring();
LoginScreen::Get()->GetModel()->NotifyOobeDialogState(
OobeDialogState::HIDDEN);
SetSessionState(SessionState::UNKNOWN);
EXPECT_FALSE(ShouldCalculateColors());
SetSessionState(SessionState::OOBE);
EXPECT_TRUE(ShouldCalculateColors());
SetSessionState(SessionState::LOGIN_PRIMARY);
EXPECT_FALSE(ShouldCalculateColors());
SetSessionState(SessionState::LOGGED_IN_NOT_ACTIVE);
EXPECT_FALSE(ShouldCalculateColors());
SetSessionState(SessionState::ACTIVE);
EXPECT_TRUE(ShouldCalculateColors());
SetSessionState(SessionState::LOCKED);
EXPECT_FALSE(ShouldCalculateColors());
SetSessionState(SessionState::LOGIN_SECONDARY);
EXPECT_FALSE(ShouldCalculateColors());
}
TEST_P(WallpaperControllerTest, ShouldCalculateColorsBasedOnLoginDisplayState) {
EnableShelfColoring();
SetSessionState(SessionState::LOGIN_PRIMARY);
// Cover login screen
LoginScreen::Get()->GetModel()->NotifyOobeDialogState(
OobeDialogState::HIDDEN);
EXPECT_FALSE(ShouldCalculateColors());
// Cover OOBE enterprise enrollment flow
LoginScreen::Get()->GetModel()->NotifyOobeDialogState(
OobeDialogState::GAIA_SIGNIN);
EXPECT_TRUE(ShouldCalculateColors());
}
TEST_P(WallpaperControllerTest, ColorsCalculatedForMostRecentWallpaper) {
TestWallpaperControllerObserver observer(controller_);
// Total size of image must be greater than 100 pixels to trigger the async
// codepath (and any potential cancellation).
const int dimension = 20;
// Activate so we calculate colors.
SetSessionState(SessionState::ACTIVE);
base::RunLoop run_loop;
observer.SetOnResizeCallback(run_loop.QuitClosure());
// Sets the wallpaper to magenta.
const gfx::ImageSkia old_image =
CreateImage(dimension, dimension, kWallpaperColor);
WallpaperInfo old_info = CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH);
old_info.location = "old";
controller_->ShowWallpaperImage(old_image, old_info,
/*preview_mode=*/false,
/*is_override=*/false);
// Run the controller until resize completes for the first wallpaper and
// color calculation starts.
run_loop.Run();
observer.SetOnResizeCallback(base::NullCallback());
base::RunLoop colors_loop;
observer.SetOnColorsCalculatedCallback(colors_loop.QuitClosure());
// Immediately switch the wallpaper color to blue.
const gfx::ImageSkia image = CreateImage(dimension, dimension, SK_ColorBLUE);
WallpaperInfo info = CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH);
// Set location to somethind different than in `old_info`.
info.location = "new";
controller_->ShowWallpaperImage(image, info,
/*preview_mode=*/false,
/*is_override=*/false);
// Run until we get a notification of colors changed.
colors_loop.Run();
// There should only be one color change event if we interrupted the first
// attempt.
EXPECT_EQ(observer.colors_changed_count(), 1);
EXPECT_EQ(controller_->calculated_colors()->k_mean_color, SK_ColorBLUE);
EXPECT_FALSE(pref_manager_->GetCachedKMeanColor("old"));
EXPECT_TRUE(pref_manager_->GetCachedKMeanColor("new"));
base::RunLoop load_preview_image_loop;
controller_->LoadPreviewImage(base::BindLambdaForTesting(
[quit = load_preview_image_loop.QuitClosure()](
scoped_refptr<base::RefCountedMemory> image_bytes) {
EXPECT_TRUE(image_bytes);
std::move(quit).Run();
}));
load_preview_image_loop.Run();
}
TEST_P(WallpaperControllerTest, SaveCelebiColor) {
TestWallpaperControllerObserver observer(controller_);
const char location[] = "test_wallpaper_here";
// Set the wallpaper with a valid location.
WallpaperInfo wallpaper_info = CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH);
wallpaper_info.location = location;
const gfx::ImageSkia kImage = CreateImage(10, 10, kWallpaperColor);
controller_->ShowWallpaperImage(kImage, wallpaper_info,
/*preview_mode=*/false,
/*is_override=*/false);
SetSessionState(SessionState::ACTIVE);
// Wait for color computation to complete.
base::RunLoop colors_loop;
observer.SetOnColorsCalculatedCallback(colors_loop.QuitClosure());
colors_loop.Run();
EXPECT_EQ(kWallpaperColor, pref_manager_->GetCelebiColor(location));
}
TEST_P(WallpaperControllerTest,
GetCachedWallpaperColorForUser_WithCelebiColor) {
// Cache some wallpapers and store that in the local prefs. Otherwise, we
// can't cache colors.
base::FilePath relative_path = PrecacheWallpapers(kAccountId1);
WallpaperInfo info = InfoWithType(WallpaperType::kCustomized);
info.location = relative_path.value();
ASSERT_TRUE(pref_manager_->SetLocalWallpaperInfo(kAccountId1, info));
// Store colors in local prefs simulating cache behavior.
pref_manager_->CacheCelebiColor(relative_path.value(), kWallpaperColor);
// Reset to login screen.
GetSessionControllerClient()->RequestSignOut();
// User's wallpaper colors are accessible from login screen.
EXPECT_EQ(kWallpaperColor, controller_->GetCachedWallpaperColorForUser(
kAccountId1, /* use_k_means= */ false));
}
TEST_P(WallpaperControllerTest,
GetCachedWallpaperColorForUser_WithKMeansColor) {
// Cache some wallpapers and store that in the local prefs. Otherwise, we
// can't cache colors.
base::FilePath relative_path = PrecacheWallpapers(kAccountId1);
WallpaperInfo info = InfoWithType(WallpaperType::kCustomized);
info.location = relative_path.value();
ASSERT_TRUE(pref_manager_->SetLocalWallpaperInfo(kAccountId1, info));
// Store colors in local prefs simulating cache behavior.
pref_manager_->CacheKMeanColor(relative_path.value(), kWallpaperColor);
// Reset to login screen.
GetSessionControllerClient()->RequestSignOut();
// User's wallpaper colors are accessible from login screen.
EXPECT_EQ(kWallpaperColor, controller_->GetCachedWallpaperColorForUser(
kAccountId1, /* use_k_means= */ true));
}
TEST_P(WallpaperControllerTest, EnableShelfColoringNotifiesObservers) {
TestWallpaperControllerObserver observer(controller_);
EXPECT_EQ(0, observer.colors_changed_count());
// Enable shelf coloring will set a customized wallpaper image and change
// session state to ACTIVE, which will trigger wallpaper colors calculation.
EnableShelfColoring();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, observer.colors_changed_count());
}
TEST_P(WallpaperControllerTest,
OnWallpaperColorsChangedAlwaysCalledOnFirstUpdate) {
TestWallpaperControllerObserver observer(controller_);
controller_->ShowUserWallpaper(kAccountId1, user_manager::UserType::kRegular);
task_environment()->RunUntilIdle();
// Even though the wallpaper color is invalid, observers should still be
// notified for the first update.
EXPECT_EQ(observer.colors_changed_count(), 1);
controller_->ShowUserWallpaper(kAccountId2, user_manager::UserType::kRegular);
task_environment()->RunUntilIdle();
// Observers should not be notified after the first update if the colors do
// not change.
EXPECT_EQ(observer.colors_changed_count(), 1);
}
TEST_P(WallpaperControllerTest,
UpdatePrimaryUserWallpaperWhileSecondUserActive) {
WallpaperInfo wallpaper_info;
SimulateUserLogin(kAccountId1);
// Set an online wallpaper with image data. Verify that the wallpaper is set
// successfully.
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
controller_->SetOnlineWallpaper(params, base::DoNothing());
RunAllTasksUntilIdle();
// Verify that the user wallpaper info is updated.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info(params, params.variants.front());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
// Log in |kUser2|, and set another online wallpaper for |kUser1|. Verify that
// the on-screen wallpaper doesn't change since |kUser1| is not active, but
// wallpaper info is updated properly.
SimulateUserLogin(kAccountId2);
ClearWallpaperCount();
const OnlineWallpaperParams& new_params = OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId2,
/*variants=*/
{{kAssetId2, GURL(kDummyUrl2), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
controller_->SetOnlineWallpaper(new_params, base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info_2(new_params,
new_params.variants.front());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info_2));
}
TEST_P(WallpaperControllerTest, SetOnlineWallpaper) {
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
SimulateUserLogin(kAccountId1);
// Verify that calling |SetOnlineWallpaper| will download the image data if it
// does not exist. Verify that the wallpaper is set successfully.
auto run_loop = std::make_unique<base::RunLoop>();
ClearWallpaperCount();
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId, layout,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting([&run_loop](bool success) {
EXPECT_TRUE(success);
run_loop->Quit();
}));
run_loop->Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
// Verify that the user wallpaper info is updated.
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info(params, params.variants.front());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
// Verify that wallpaper & collection metrics are logged.
histogram_tester().ExpectBucketCount("Ash.Wallpaper.Image", kUnitId, 1);
histogram_tester().ExpectBucketCount(
"Ash.Wallpaper.Collection",
static_cast<int>(base::PersistentHash(
TestWallpaperControllerClient::kDummyCollectionId)),
1);
histogram_tester().ExpectBucketCount("Ash.Wallpaper.Type",
WallpaperType::kOnline, 1);
// Verify that the wallpaper with |url| is available offline, and the returned
// file name should not contain the small wallpaper suffix.
//
// The ThreadPool must be flushed to ensure that the online wallpaper is saved
// to disc before checking the test expectation below. Ideally, we'd wait for
// an explicit event, but the production code does not need this and it's not
// worthwhile to add something to the API just for tests.
RunAllTasksUntilIdle();
EXPECT_TRUE(base::PathExists(online_wallpaper_dir_.GetPath().Append(
GURL(kDummyUrl).ExtractFileName())));
}
TEST_P(WallpaperControllerTest,
SetOnlineWallpaper_FiresResizedSignalWhenSettingTheSameWallpaper) {
TestWallpaperControllerObserver observer(controller_);
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
SimulateUserLogin(kAccountId1);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId, layout,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
{
// Verify that calling |SetOnlineWallpaper| will download the image data if
// it does not exist. Verify that the wallpaper is set successfully.
base::RunLoop run_loop;
ClearWallpaperCount();
base::RunLoop resized_loop;
observer.SetOnResizeCallback(resized_loop.QuitClosure());
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting(
[quit = run_loop.QuitClosure()](bool success) {
EXPECT_TRUE(success);
std::move(quit).Run();
}));
run_loop.Run();
resized_loop.Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
}
{
// Verifies setting the same wallpaper still results in `OnWallpaperResized`
// being fired.
base::RunLoop run_loop;
base::RunLoop resized_loop;
observer.SetOnResizeCallback(resized_loop.QuitClosure());
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting(
[quit = run_loop.QuitClosure()](bool success) {
EXPECT_TRUE(success);
std::move(quit).Run();
}));
run_loop.Run();
resized_loop.Run();
}
}
TEST_P(WallpaperControllerTest, SetTimeOfDayWallpaper) {
if (!IsTimeOfDayEnabled()) {
return;
}
auto images = TimeOfDayImageSet();
client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
images);
SimulateUserLogin(kAccountId1);
// Verify that calling |SetTimeOfDayWallpaper| will download the image
// data if it does not exist. Verify that the wallpaper is set successfully.
base::RunLoop run_loop;
ClearWallpaperCount();
controller_->SetTimeOfDayWallpaper(
kAccountId1,
base::BindLambdaForTesting([quit = run_loop.QuitClosure()](bool success) {
EXPECT_TRUE(success);
std::move(quit).Run();
}));
run_loop.Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
// Verify that the user wallpaper info is updated.
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_EQ(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
wallpaper_info.collection_id);
EXPECT_EQ(WallpaperType::kOnline, wallpaper_info.type);
// Verify that the any of the wallpaper variant is available offline, and the
// returned file name should not contain the small wallpaper suffix.
//
// The ThreadPool must be flushed to ensure that the online wallpaper is saved
// to disc before checking the test expectation below. Ideally, we'd wait for
// an explicit event, but the production code does not need this and it's not
// worthwhile to add something to the API just for tests.
RunAllTasksUntilIdle();
EXPECT_TRUE(base::PathExists(online_wallpaper_dir_.GetPath().Append(
GURL(images[1].image_url()).ExtractFileName())));
}
TEST_P(WallpaperControllerTest,
ActiveUserPrefServiceChanged_SetTimeOfDayWallpaper) {
if (!IsTimeOfDayEnabled()) {
return;
}
auto images = TimeOfDayImageSet();
client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
images);
WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
SetSessionState(SessionState::OOBE);
// Log in and trigger `OnActiveUserPrefServiceChange`.
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(WallpaperType::kOnline, actual_info.type);
EXPECT_EQ(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
actual_info.collection_id);
histogram_tester().ExpectTotalCount("Ash.Wallpaper.IsSetToTimeOfDayAfterOobe",
1);
}
TEST_P(WallpaperControllerTest,
TimeOfDayWallpaper_ReplacedByUserWallpaper_DuringOobe) {
if (!IsTimeOfDayEnabled()) {
return;
}
auto images = TimeOfDayImageSet();
client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
images);
WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
SetSessionState(SessionState::OOBE);
// Log in and trigger `OnActiveUserPrefServiceChange`.
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(WallpaperType::kOnline, actual_info.type);
EXPECT_EQ(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
actual_info.collection_id);
// Keep OOBE state.
SetSessionState(SessionState::OOBE);
OnlineWallpaperVariant variant(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo synced_info = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId, {variant}),
variant);
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
RunAllTasksUntilIdle();
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(TestWallpaperControllerClient::kDummyCollectionId,
actual_info.collection_id);
EXPECT_TRUE(base::PathExists(online_wallpaper_dir_.GetPath().Append(
GURL(kDummyUrl).ExtractFileName())));
}
TEST_P(WallpaperControllerTest,
ActiveUserPrefServiceChanged_OOBEForSecondUser_SetTimeOfDayWallpaper) {
if (!IsTimeOfDayEnabled()) {
return;
}
auto images = TimeOfDayImageSet();
client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
images);
WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
SetSessionState(SessionState::LOGIN_PRIMARY);
LoginScreen::Get()->GetModel()->NotifyOobeDialogState(
OobeDialogState::GAIA_SIGNIN);
// Log in and trigger `OnActiveUserPrefServiceChange`.
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(WallpaperType::kOnline, actual_info.type);
EXPECT_EQ(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
actual_info.collection_id);
histogram_tester().ExpectTotalCount("Ash.Wallpaper.IsSetToTimeOfDayAfterOobe",
1);
}
TEST_P(
WallpaperControllerTest,
ActiveUserPrefServiceChanged_OOBEForSecondUser_SetPolicyWallpaper_TimeOfDayEnabled) {
if (!IsTimeOfDayEnabled()) {
return;
}
auto images = TimeOfDayImageSet();
client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
images);
WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
SetSessionState(SessionState::LOGIN_PRIMARY);
LoginScreen::Get()->GetModel()->NotifyOobeDialogState(
OobeDialogState::GAIA_SIGNIN);
// Log in and trigger `OnActiveUserPrefServiceChange`.
SimulateUserLogin(kAccountId1);
controller_->SetPolicyWallpaper(
kAccountId1, user_manager::UserType::kRegular,
CreateEncodedImageForTesting(gfx::Size(10, 10)));
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
WallpaperInfo policy_wallpaper_info(base::FilePath(kWallpaperFilesId1)
.Append("policy-controlled.jpeg")
.value(),
WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kPolicy,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(actual_info.MatchesSelection(policy_wallpaper_info));
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
}
TEST_P(WallpaperControllerTest,
ActiveUserPrefServiceChanged_NonOOBE_SetTimeOfDayWallpaper) {
if (!IsTimeOfDayEnabled()) {
return;
}
auto images = TimeOfDayImageSet();
client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
images);
WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
// Log in and trigger `OnActiveUserPrefServiceChange`.
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_TRUE(local_info.MatchesAsset(actual_info));
histogram_tester().ExpectTotalCount("Ash.Wallpaper.IsSetToTimeOfDayAfterOobe",
0);
}
TEST_P(WallpaperControllerTest, SetAndRemovePolicyWallpaper) {
// Simulate the login screen.
ClearLogin();
// The user starts with no wallpaper info and is not controlled by policy.
WallpaperInfo wallpaper_info;
EXPECT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_FALSE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
// A default wallpaper is shown for the user.
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
ASSERT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
// Set a policy wallpaper. Verify that the user becomes policy controlled and
// the wallpaper info is updated.
ClearWallpaperCount();
controller_->SetPolicyWallpaper(
kAccountId1, user_manager::UserType::kRegular,
CreateEncodedImageForTesting(gfx::Size(10, 10)));
RunAllTasksUntilIdle();
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo policy_wallpaper_info(base::FilePath(kWallpaperFilesId1)
.Append("policy-controlled.jpeg")
.value(),
WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kPolicy,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(policy_wallpaper_info));
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
// Verify the wallpaper is not updated since the user hasn't logged in.
EXPECT_EQ(0, GetWallpaperCount());
// Log in the user. Verify the policy wallpaper is now being shown.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
EXPECT_EQ(1, GetWallpaperCount());
ASSERT_EQ(controller_->GetWallpaperType(), WallpaperType::kPolicy);
// Clear the wallpaper and log out the user. Verify the policy wallpaper is
// shown in the login screen.
ClearWallpaper();
ClearLogin();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kPolicy);
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
// Remove the policy wallpaper. Verify the wallpaper info is reset to default
// and the user is no longer policy controlled.
ClearWallpaperCount();
controller_->RemovePolicyWallpaper(kAccountId1);
WaitUntilCustomWallpapersDeleted(kAccountId1);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(default_wallpaper_info));
EXPECT_FALSE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
// Verify the wallpaper is not updated since the user hasn't logged in (to
// avoid abrupt wallpaper change in login screen).
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kPolicy);
// Log in the user. Verify the default wallpaper is now being shown.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
}
// Simulates the scenario where the wallpaper are not yet resized and only the
// original size image is available.
TEST_P(WallpaperControllerTest, ShowUserWallpaper_OriginalFallback) {
// Simulate the login screen.
ClearLogin();
// Set a wallpaper.
CreateAndSaveWallpapers(kAccountId1);
RunAllTasksUntilIdle();
// Verify the wallpaper was set.
WallpaperInfo wallpaper_info;
ASSERT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
ASSERT_EQ(WallpaperType::kCustomized, wallpaper_info.type);
ASSERT_EQ("[email protected]/[email protected]", wallpaper_info.location);
// Move the wallpaper file to the original folder.
base::FilePath saved_wallpaper = custom_wallpaper_dir_.GetPath().Append(
"small/[email protected]/[email protected]");
ASSERT_TRUE(base::PathExists(saved_wallpaper));
base::CreateDirectory(
WallpaperControllerImpl::GetCustomWallpaperDir("original")
.Append("[email protected]"));
ASSERT_TRUE(base::PathExists(
WallpaperControllerImpl::GetCustomWallpaperDir("original")));
ASSERT_TRUE(
base::Move(saved_wallpaper,
WallpaperControllerImpl::GetCustomWallpaperDir("original")
.Append(wallpaper_info.location)));
ASSERT_FALSE(base::PathExists(saved_wallpaper));
ClearDecodeFilePaths();
// Show wallpaper
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
// Verify the wallpaper was found in the original folder.
EXPECT_FALSE(GetDecodeFilePaths().empty());
EXPECT_THAT(
GetDecodeFilePaths().back().value(),
testing::EndsWith("original/[email protected]/[email protected]"));
}
// Simulates a missing wallpaper due (possibly) an outdated preference. In this
// situation, we fallback to the default.
TEST_P(WallpaperControllerTest, ShowUserWallpaper_MissingFile) {
// Simulate the login screen.
ClearLogin();
// Set a wallpaper.
CreateAndSaveWallpapers(kAccountId1);
RunAllTasksUntilIdle();
// Verify the wallpaper was set.
WallpaperInfo wallpaper_info;
ASSERT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
ASSERT_EQ(WallpaperType::kCustomized, wallpaper_info.type);
ASSERT_EQ("[email protected]/[email protected]", wallpaper_info.location);
// Delete wallpaper file.
controller_->RemoveUserWallpaper(kAccountId1, base::DoNothing());
WaitUntilCustomWallpapersDeleted(kAccountId1);
ClearDecodeFilePaths();
// Show wallpaper
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
// Verify the default wallpaper was used because the stored wallpaper was
// missing.
EXPECT_FALSE(GetDecodeFilePaths().empty());
EXPECT_THAT(GetDecodeFilePaths().back().value(),
testing::EndsWith(kDefaultSmallWallpaperName));
}
TEST_P(WallpaperControllerTest, RemovePolicyWallpaperNoOp) {
auto verify_custom_wallpaper_info = [&]() {
EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(),
WALLPAPER_LAYOUT_CENTER, WallpaperType::kCustomized,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
};
// Set a custom wallpaper. Verify the user is not policy controlled and the
// wallpaper info is correct.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"",
CreateImage(640, 480, kWallpaperColor));
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_FALSE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
verify_custom_wallpaper_info();
// Verify RemovePolicyWallpaper() is a no-op when the user doesn't have a
// policy wallpaper.
controller_->RemovePolicyWallpaper(kAccountId1);
RunAllTasksUntilIdle();
verify_custom_wallpaper_info();
}
TEST_P(WallpaperControllerTest, SetThirdPartyWallpaper) {
SimulateUserLogin(kAccountId1);
// Verify the user starts with no wallpaper info.
WallpaperInfo wallpaper_info;
EXPECT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia third_party_wallpaper = CreateImage(640, 480, kWallpaperColor);
// Set a third-party wallpaper for |kUser1|.
EXPECT_TRUE(controller_->SetThirdPartyWallpaper(
kAccountId1, kFileName1, layout, third_party_wallpaper));
RunAllTasksUntilIdle();
// Verify the wallpaper is shown.
EXPECT_EQ(1, GetWallpaperCount());
// Verify the user wallpaper info is updated.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
}
TEST_P(WallpaperControllerTest, SetThirdPartyWallpaper_NonactiveUser) {
// Active user is |kUser2|, but set another third-party wallpaper for
// |kUser1|; the operation should not be allowed, because |kUser1| is not the
// active user.
SimulateUserLogin(kAccountId2);
WallpaperInfo wallpaper_info;
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia third_party_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_FALSE(controller_->SetThirdPartyWallpaper(
kAccountId1, kFileName2, layout, third_party_wallpaper));
// Verify the wallpaper is not shown.
EXPECT_EQ(0, GetWallpaperCount());
// Verify the wallpaper info for |kUser1| is updated, because setting
// wallpaper is still allowed for non-active users.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info_2(
base::FilePath(kWallpaperFilesId1).Append(kFileName2).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info_2));
}
TEST_P(WallpaperControllerTest, SetThirdPartyWallpaper_PolicyWallpaper) {
SimulateUserLogin(kAccountId2);
WallpaperInfo wallpaper_info;
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia third_party_wallpaper = CreateImage(640, 480, kWallpaperColor);
// Set a policy wallpaper for |kUser2|. Verify that |kUser2| becomes policy
// controlled.
controller_->SetPolicyWallpaper(
kAccountId2, user_manager::UserType::kRegular,
CreateEncodedImageForTesting(gfx::Size(10, 10)));
RunAllTasksUntilIdle();
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId2));
EXPECT_TRUE(controller_->IsActiveUserWallpaperControlledByPolicy());
// Setting a third-party wallpaper for |kUser2| should not be allowed, because
// third-party wallpapers cannot be set for policy controlled users.
ClearWallpaperCount();
EXPECT_FALSE(controller_->SetThirdPartyWallpaper(
kAccountId2, kFileName1, layout, third_party_wallpaper));
// Verify the wallpaper is not shown.
EXPECT_EQ(0, GetWallpaperCount());
// Verify |kUser2| is still policy controlled and has the policy wallpaper
// info.
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId2));
EXPECT_TRUE(controller_->IsActiveUserWallpaperControlledByPolicy());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId2, &wallpaper_info));
WallpaperInfo policy_wallpaper_info(base::FilePath(kWallpaperFilesId2)
.Append("policy-controlled.jpeg")
.value(),
WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kPolicy,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(policy_wallpaper_info));
}
TEST_P(WallpaperControllerTest, SetSeaPenWallpaper) {
SimulateUserLogin(kAccountId1);
WallpaperInfo wallpaper_info;
ASSERT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
gfx::ImageSkia expected_image;
SetSeaPenWallpaper(kAccountId1, SK_ColorGREEN, /*id=*/777u,
/*preview_mode=*/false, &expected_image);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_EQ(WallpaperType::kSeaPen, wallpaper_info.type);
EXPECT_EQ("777", wallpaper_info.location);
EXPECT_TRUE(wallpaper_info.user_file_path.empty());
// Use `AreBitmapsClose` because jpg encoding/decoding can alter the color
// channels +- 1.
EXPECT_TRUE(gfx::test::AreBitmapsClose(
*expected_image.bitmap(), *controller_->GetWallpaperImage().bitmap(),
/*max_deviation=*/1));
base::FileEnumerator file_enumerator(online_wallpaper_dir_.GetPath(),
/*recursive=*/true,
base::FileEnumerator::FileType::FILES);
std::vector<base::FilePath> wallpaper_files;
for (auto path = file_enumerator.Next(); !path.empty();
path = file_enumerator.Next()) {
wallpaper_files.push_back(path);
}
// One SeaPen image file saved to global wallpaper directory for account.
EXPECT_EQ(std::vector<base::FilePath>(
{base::FilePath(online_wallpaper_dir_.GetPath())
.Append(wallpaper_constants::kSeaPenWallpaperDirName)
.Append(kAccountId1.GetAccountIdKey())
.Append("777")
.AddExtension(".jpg")}),
wallpaper_files);
}
TEST_P(WallpaperControllerTest,
SeaPenWallpaperRemovedAfterSettingAnotherWallpaperType) {
const auto global_sea_pen_dir =
online_wallpaper_dir_.GetPath().Append("sea_pen").Append(
kAccountId1.GetAccountIdKey());
SimulateUserLogin(kAccountId1);
WallpaperInfo wallpaper_info;
ASSERT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
{
// Sets a sea pen wallpaper.
gfx::ImageSkia expected_image;
SetSeaPenWallpaper(kAccountId1, SK_ColorGREEN, /*id=*/848u,
/*preview_mode=*/false, &expected_image);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_EQ(WallpaperType::kSeaPen, wallpaper_info.type);
EXPECT_EQ("848", wallpaper_info.location);
EXPECT_TRUE(wallpaper_info.user_file_path.empty());
// Expects the sea pen wallpaper is saved to the global SeaPen directory.
ASSERT_TRUE(
base::PathExists(global_sea_pen_dir.Append(wallpaper_info.location)
.ReplaceExtension(".jpg")));
}
{
// Sets an online wallpaper.
base::RunLoop run_loop;
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting(
[quit = run_loop.QuitClosure()](bool success) {
EXPECT_TRUE(success);
std::move(quit).Run();
}));
run_loop.Run();
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
}
// Waits for clean up tasks to finish.
RunAllTasksUntilIdle();
// Expects the sea pen wallpaper is removed from the global SeaPen directory.
ASSERT_FALSE(
base::PathExists(global_sea_pen_dir.Append(wallpaper_info.location)
.ReplaceExtension(".jpg")));
}
TEST_P(WallpaperControllerTest, ShowSeaPenWallpaperOnLogin) {
SimulateUserLogin(kAccountId1);
WallpaperInfo wallpaper_info;
ASSERT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
gfx::ImageSkia expected_image;
SetSeaPenWallpaper(kAccountId1, SK_ColorBLUE, 888u, /*preview_mode=*/false,
&expected_image);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_EQ(WallpaperType::kSeaPen, wallpaper_info.type);
EXPECT_EQ("888", wallpaper_info.location);
EXPECT_TRUE(wallpaper_info.user_file_path.empty());
// Simulates device reboot.
controller_->ReloadWallpaperForTesting(/*clear_cache=*/true);
ClearWallpaper();
ClearLogin();
SimulateUserLogin(kAccountId1);
const AccountId active_account_id =
Shell::Get()->session_controller()->GetActiveAccountId();
controller_->ShowUserWallpaper(active_account_id);
RunAllTasksUntilIdle();
WallpaperInfo new_wallpaper_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(active_account_id,
&new_wallpaper_info));
EXPECT_EQ(WallpaperType::kSeaPen, new_wallpaper_info.type);
EXPECT_TRUE(wallpaper_info.MatchesAsset(new_wallpaper_info));
// Use `AreBitmapsClose` because jpg encoding/decoding can alter the color
// channels +- 1.
EXPECT_TRUE(gfx::test::AreBitmapsClose(
*expected_image.bitmap(), *controller_->GetWallpaperImage().bitmap(),
/*max_deviation=*/1));
}
TEST_P(WallpaperControllerTest, LoadsSeaPenWallpaperWithInvalidUserFilePath) {
// info.user_file_path should be ignored, but older versions may have invalid
// strings in it. Write an older WallpaperInfo to prefs.
ASSERT_TRUE(pref_manager_->SetUserWallpaperInfo(
kAccountId1, WallpaperInfo("1", WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kSeaPen, base::Time::Now(),
"invalid_user_file_path.jpg")));
gfx::ImageSkia created_image;
{
// Write a corresponding jpg to disk in the correct place.
std::string jpg_bytes = CreateEncodedImageForTesting(
{1, 1}, SK_ColorBLUE, data_decoder::mojom::ImageCodec::kDefault,
&created_image);
ASSERT_FALSE(jpg_bytes.empty());
base::test::TestFuture<bool> save_sea_pen_image_future;
SeaPenWallpaperManager::GetInstance()->SaveSeaPenImage(
kAccountId1, {std::move(jpg_bytes), 1u},
personalization_app::mojom::SeaPenQuery::NewTextQuery("search_query"),
save_sea_pen_image_future.GetCallback());
ASSERT_TRUE(save_sea_pen_image_future.Get());
}
{
// Log in.
SimulateUserLogin(kAccountId1);
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
}
EXPECT_TRUE(gfx::test::AreBitmapsClose(
*created_image.bitmap(), *controller_->GetWallpaperImage().bitmap(),
/*max_deviation=*/1));
}
// TODO(crbug.com/41484478): Flaky on linux-chromeos-rel.
TEST_P(WallpaperControllerTest, DISABLED_SetSeaPenWallpaperFromFile) {
SimulateUserLogin(kAccountId1);
TestWallpaperControllerObserver observer(controller_);
WallpaperInfo wallpaper_info;
ASSERT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
gfx::ImageSkia expected_image;
std::string jpg_bytes = CreateEncodedImageForTesting(
{1, 1}, SK_ColorGREEN, data_decoder::mojom::ImageCodec::kDefault,
&expected_image);
ASSERT_TRUE(!jpg_bytes.empty());
base::ScopedTempDir scoped_temp_dir;
ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
base::FilePath file_path = scoped_temp_dir.GetPath().Append("111.jpg");
ASSERT_TRUE(base::WriteFile(file_path, jpg_bytes));
// Updates the last modified time for the file.
ASSERT_TRUE(base::TouchFile(file_path, base::Time::Now() - base::Minutes(5),
base::Time::Now() - base::Minutes(5)));
base::Time old_last_modified_time = GetLastModifiedTime(file_path);
base::test::TestFuture<bool> set_wallpaper_future;
controller_->SetSeaPenWallpaper(kAccountId1, 111u, /*preview_mode=*/false,
set_wallpaper_future.GetCallback());
EXPECT_TRUE(set_wallpaper_future.Take());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_EQ(WallpaperType::kSeaPen, wallpaper_info.type);
EXPECT_EQ(1, observer.wallpaper_changed_count());
histogram_tester().ExpectUniqueSample("Ash.Wallpaper.SeaPen.Result2",
SetWallpaperResult::kSuccess, 1);
// Use `AreBitmapsClose` because jpg encoding/decoding can alter the color
// channels +- 1.
EXPECT_TRUE(gfx::test::AreBitmapsClose(
*expected_image.bitmap(), *controller_->GetWallpaperImage().bitmap(),
/*max_deviation=*/1));
// Last Modified Time should be updated to current time.
EXPECT_TRUE(GetLastModifiedTime(file_path) > old_last_modified_time);
}
TEST_P(WallpaperControllerTest, CancelSetSeaPenWallpaperInTabletMode) {
SimulateUserLogin(kAccountId1);
WallpaperInfo wallpaper_info;
ASSERT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
gfx::ImageSkia expected_image;
TestWallpaperControllerObserver observer(controller_);
SetSeaPenWallpaper(kAccountId1, SK_ColorBLUE, /*id=*/777u,
/*preview_mode=*/true, &expected_image);
RunAllTasksUntilIdle();
EXPECT_TRUE(observer.is_in_wallpaper_preview());
controller_->CancelPreviewWallpaper();
EXPECT_FALSE(observer.is_in_wallpaper_preview());
ASSERT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
}
TEST_P(WallpaperControllerTest, ConfirmSetSeaPenWallpaperInTabletMode) {
SimulateUserLogin(kAccountId1);
WallpaperInfo wallpaper_info;
ASSERT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
gfx::ImageSkia expected_image;
TestWallpaperControllerObserver observer(controller_);
SetSeaPenWallpaper(kAccountId1, SK_ColorGREEN, /*id=*/777u,
/*preview_mode=*/true, &expected_image);
RunAllTasksUntilIdle();
EXPECT_TRUE(observer.is_in_wallpaper_preview());
controller_->ConfirmPreviewWallpaper();
EXPECT_FALSE(observer.is_in_wallpaper_preview());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_EQ(WallpaperType::kSeaPen, wallpaper_info.type);
EXPECT_EQ("777", wallpaper_info.location);
EXPECT_TRUE(wallpaper_info.user_file_path.empty());
// Use `AreBitmapsClose` because jpg encoding/decoding can alter the color
// channels +- 1.
EXPECT_TRUE(gfx::test::AreBitmapsClose(
*expected_image.bitmap(), *controller_->GetWallpaperImage().bitmap(),
/*max_deviation=*/1));
base::FileEnumerator file_enumerator(online_wallpaper_dir_.GetPath(),
/*recursive=*/true,
base::FileEnumerator::FileType::FILES);
std::vector<base::FilePath> wallpaper_files;
for (auto path = file_enumerator.Next(); !path.empty();
path = file_enumerator.Next()) {
wallpaper_files.push_back(path);
}
// One SeaPen image file saved to global wallpaper directory for account.
EXPECT_EQ(std::vector<base::FilePath>(
{base::FilePath(online_wallpaper_dir_.GetPath())
.Append(wallpaper_constants::kSeaPenWallpaperDirName)
.Append(kAccountId1.GetAccountIdKey())
.Append("777")
.AddExtension(".jpg")}),
wallpaper_files);
}
TEST_P(WallpaperControllerTest, SeaPenMigrateFiles) {
constexpr std::array<uint32_t, 2> kImageIds = {888, 999};
const auto global_sea_pen_dir =
online_wallpaper_dir_.GetPath()
.Append(wallpaper_constants::kSeaPenWallpaperDirName)
.Append(kAccountId1.GetAccountIdKey());
ASSERT_TRUE(base::CreateDirectory(global_sea_pen_dir));
{
// Write files to the global SeaPen directory.
for (const auto id : kImageIds) {
ResizeAndSaveWallpaper(
gfx::test::CreateImageSkia(2),
global_sea_pen_dir.Append(base::NumberToString(id))
.AddExtension(".jpg"),
WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, {2, 2},
QueryDictToXmpString(SeaPenQueryToDict(
personalization_app::mojom::SeaPenQuery::NewTextQuery(
"testing query"))));
}
// Set the first one as the user's wallpaper info.
ASSERT_TRUE(pref_manager_->SetUserWallpaperInfo(
kAccountId1, WallpaperInfo(base::NumberToString(kImageIds.front()),
WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kSeaPen, base::Time::Now())));
}
{
// SeaPenWallpaperManager sees no files since they are not yet migrated.
base::test::TestFuture<const std::vector<uint32_t>&> get_image_ids_future;
SeaPenWallpaperManager::GetInstance()->GetImageIds(
kAccountId1, get_image_ids_future.GetCallback());
ASSERT_TRUE(get_image_ids_future.Get().empty());
}
ASSERT_TRUE(
SeaPenWallpaperManager::GetInstance()->ShouldMigrate(kAccountId1));
PrefChangeRegistrar pref_change_registrar;
auto* pref_service = SeaPenWallpaperManager::GetInstance()
->session_delegate_for_testing()
->GetPrefService(kAccountId1);
pref_change_registrar.Init(pref_service);
base::test::RepeatingTestFuture<const std::string&> pref_changed_future;
pref_change_registrar.Add(prefs::kWallpaperSeaPenMigrationStatus,
pref_changed_future.GetCallback());
SimulateUserLogin(kAccountId1);
{
// Writes kCrashed first.
ASSERT_EQ(prefs::kWallpaperSeaPenMigrationStatus,
pref_changed_future.Take());
EXPECT_FALSE(
SeaPenWallpaperManager::GetInstance()->ShouldMigrate(kAccountId1));
EXPECT_EQ(
SeaPenWallpaperManager::MigrationStatus::kCrashed,
static_cast<SeaPenWallpaperManager::MigrationStatus>(
pref_service->GetInteger(prefs::kWallpaperSeaPenMigrationStatus)));
// Performs migration and then writes kSuccess.
ASSERT_EQ(prefs::kWallpaperSeaPenMigrationStatus,
pref_changed_future.Take());
EXPECT_FALSE(
SeaPenWallpaperManager::GetInstance()->ShouldMigrate(kAccountId1));
EXPECT_EQ(
SeaPenWallpaperManager::MigrationStatus::kSuccess,
static_cast<SeaPenWallpaperManager::MigrationStatus>(
pref_service->GetInteger(prefs::kWallpaperSeaPenMigrationStatus)));
}
{
// SeaPenWallpaperManager sees files since they have been migrated;
base::test::TestFuture<const std::vector<uint32_t>&> get_image_ids_future;
SeaPenWallpaperManager::GetInstance()->GetImageIds(
kAccountId1, get_image_ids_future.GetCallback());
EXPECT_THAT(get_image_ids_future.Get(),
testing::UnorderedElementsAreArray(kImageIds));
}
RunAllTasksUntilIdle();
{
// The active wallpaper is copied back to the global directory.
EXPECT_TRUE(base::PathExists(
global_sea_pen_dir.Append(base::NumberToString(kImageIds.front()))
.AddExtension(".jpg")));
// The inactive file is not copied back.
EXPECT_FALSE(base::PathExists(
global_sea_pen_dir.Append(base::NumberToString(kImageIds.back()))
.AddExtension(".jpg")));
}
}
TEST_P(WallpaperControllerTest, SetSeaPenWallpaperForPublicAccount) {
ClearLogin();
const AccountId account_id = AccountId::FromUserEmail("public_session");
SimulateUserLogin(account_id, user_manager::UserType::kPublicAccount);
gfx::ImageSkia expected_image;
SetSeaPenWallpaper(account_id, SK_ColorBLUE, 12345u, /*preview_mode=*/false,
&expected_image);
WallpaperInfo wallpaper_info;
ASSERT_TRUE(pref_manager_->GetUserWallpaperInfo(account_id, &wallpaper_info));
EXPECT_EQ(WallpaperType::kSeaPen, wallpaper_info.type);
EXPECT_EQ("12345", wallpaper_info.location);
// Use `AreBitmapsClose` because jpg encoding/decoding can alter the color
// channels +- 1.
EXPECT_TRUE(gfx::test::AreBitmapsClose(
*expected_image.bitmap(), *controller_->GetWallpaperImage().bitmap(),
/*max_deviation=*/1));
base::FileEnumerator file_enumerator(online_wallpaper_dir_.GetPath(),
/*recursive=*/true,
base::FileEnumerator::FileType::FILES);
std::vector<base::FilePath> wallpaper_files;
for (auto path = file_enumerator.Next(); !path.empty();
path = file_enumerator.Next()) {
wallpaper_files.push_back(path);
}
// No wallpaper files saved to global wallpaper directory for public account.
EXPECT_TRUE(wallpaper_files.empty());
}
TEST_P(WallpaperControllerTest, SetDefaultWallpaperForRegularAccount) {
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
SimulateUserLogin(kAccountId1);
// Called to make sure `WallpaperControllerImpl::current_user_` is properly
// set.
controller_->ShowUserWallpaper(kAccountId1);
// First, simulate setting a user custom wallpaper.
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"", image);
RunAllTasksUntilIdle();
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_NE(wallpaper_info.type, default_wallpaper_info.type);
// Verify |SetDefaultWallpaper| removes the previously set custom wallpaper
// info, and the large default wallpaper is set successfully with the correct
// file path.
UpdateDisplay("1600x1200");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
controller_->SetDefaultWallpaper(kAccountId1, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kDefaultLargeWallpaperName),
GetDecodeFilePaths()[0]);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
// The user wallpaper info has been reset to the default value.
EXPECT_TRUE(wallpaper_info.MatchesSelection(default_wallpaper_info));
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"", image);
RunAllTasksUntilIdle();
// Verify |SetDefaultWallpaper| removes the previously set custom wallpaper
// info, and the small default wallpaper is set successfully with the correct
// file path.
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
controller_->SetDefaultWallpaper(kAccountId1, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kDefaultSmallWallpaperName),
GetDecodeFilePaths()[0]);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
// The user wallpaper info has been reset to the default value.
EXPECT_TRUE(wallpaper_info.MatchesSelection(default_wallpaper_info));
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"", image);
RunAllTasksUntilIdle();
// Verify that when screen is rotated, |SetDefaultWallpaper| removes the
// previously set custom wallpaper info, and the small default wallpaper is
// set successfully from the cache.
UpdateDisplay("800x600/r");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
controller_->SetDefaultWallpaper(kAccountId1, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(0u, GetDecodeFilePaths().size());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
// The user wallpaper info has been reset to the default value.
EXPECT_TRUE(wallpaper_info.MatchesSelection(default_wallpaper_info));
}
TEST_P(WallpaperControllerTest, SetDefaultWallpaperForChildAccount) {
SimulateUserLogin(kChildAccountId, user_manager::UserType::kChild);
// Verify the large child wallpaper is set successfully with the correct file
// path.
UpdateDisplay("1600x1200");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
controller_->SetDefaultWallpaper(kChildAccountId, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kChildLargeWallpaperName),
GetDecodeFilePaths()[0]);
// Verify the small child wallpaper is set successfully with the correct file
// path.
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
controller_->SetDefaultWallpaper(kChildAccountId, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kChildSmallWallpaperName),
GetDecodeFilePaths()[0]);
}
// Verify that the |ShowWallpaperImage| will be called with the default image
// for the guest session only even if there's a policy that has been set for
// another user which invokes |SetPolicyWallpaper|.
TEST_P(WallpaperControllerTest,
SetDefaultWallpaperForGuestSessionUnaffectedByWallpaperPolicy) {
// Simulate the login screen.
ClearLogin();
ClearWallpaperCount();
// First, simulate settings for a guest user which will show the default
// wallpaper image by invoking |ShowWallpaperImage|.
SimulateGuestLogin();
UpdateDisplay("1600x1200");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
const AccountId guest_id =
AccountId::FromUserEmail(user_manager::kGuestUserName);
SimulateUserLogin(guest_id, user_manager::UserType::kGuest);
controller_->SetDefaultWallpaper(guest_id, /*show_wallpaper=*/true,
base::DoNothing());
RunAllTasksUntilIdle();
WallpaperInfo wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
// Verify that the current displayed wallpaper is the default one inside the
// guest session.
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(guest_id, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(default_wallpaper_info));
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kGuestLargeWallpaperName),
GetDecodeFilePaths()[0]);
// Second, set a user policy for which is being set for another
// user and verifying that the policy has been applied successfully.
WallpaperInfo policy_wallpaper_info;
controller_->SetPolicyWallpaper(
kAccountId1, user_manager::UserType::kRegular,
CreateEncodedImageForTesting(gfx::Size(10, 10)));
RunAllTasksUntilIdle();
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &policy_wallpaper_info));
WallpaperInfo expected_policy_wallpaper_info(
base::FilePath(kWallpaperFilesId1)
.Append("policy-controlled.jpeg")
.value(),
WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kPolicy,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
policy_wallpaper_info.MatchesSelection(expected_policy_wallpaper_info));
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
// Finally, verifying that the guest session hasn't been affected by the new
// policy and |ShowWallpaperImage| hasn't been invoked another time.
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(guest_id, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(default_wallpaper_info));
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kGuestLargeWallpaperName),
GetDecodeFilePaths()[0]);
}
TEST_P(WallpaperControllerTest, SetDefaultWallpaperForGuestSessionAndPreview) {
const AccountId guest_id =
AccountId::FromUserEmail(user_manager::kGuestUserName);
controller_->ShowUserWallpaper(guest_id);
SimulateUserLogin(guest_id, user_manager::UserType::kGuest);
WallpaperInfo wallpaper_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(guest_id, &wallpaper_info));
EXPECT_EQ(wallpaper_info.type, WallpaperType::kDefault);
}
TEST_P(WallpaperControllerTest, SetDefaultWallpaperForGuestSession) {
// First, simulate setting a custom wallpaper for a regular user.
SimulateUserLogin(kAccountId1);
CreateAndSaveWallpapers(kAccountId1);
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_NE(wallpaper_info.type, default_wallpaper_info.type);
const AccountId guest_id =
AccountId::FromUserEmail(user_manager::kGuestUserName);
SimulateUserLogin(guest_id, user_manager::UserType::kGuest);
// Verify that during a guest session, |SetDefaultWallpaper| removes the user
// custom wallpaper info, but a guest specific wallpaper should be set,
// instead of the regular default wallpaper.
UpdateDisplay("1600x1200");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
controller_->SetDefaultWallpaper(guest_id, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(guest_id, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(default_wallpaper_info));
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kGuestLargeWallpaperName),
GetDecodeFilePaths()[0]);
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
ClearWallpaperCount();
ClearDecodeFilePaths();
controller_->SetDefaultWallpaper(guest_id, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kGuestSmallWallpaperName),
GetDecodeFilePaths()[0]);
}
TEST_P(WallpaperControllerTest, SetDefaultWallpaperCallbackTiming) {
SimulateUserLogin(kAccountId1);
// First, simulate setting a user custom wallpaper.
CreateAndSaveWallpapers(kAccountId1);
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_NE(wallpaper_info.type, WallpaperType::kDefault);
TestWallpaperControllerObserver observer(controller_);
// Set default wallpaper and wait for success callback.
base::RunLoop loop;
controller_->SetDefaultWallpaper(
kAccountId1, /*show_wallpaper=*/true,
base::BindLambdaForTesting([&loop, &observer](bool success) {
ASSERT_TRUE(success);
// Success callback should run before wallpaper observer is notified of
// change.
ASSERT_EQ(0, observer.wallpaper_changed_count());
loop.Quit();
}));
loop.Run();
// Wallpaper observer should have been notified of wallpaper change.
EXPECT_EQ(1, observer.wallpaper_changed_count());
}
TEST_P(WallpaperControllerTest, IgnoreWallpaperRequestInKioskMode) {
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
SimulateUserLogin("kiosk", user_manager::UserType::kKioskApp);
// Verify that |SetDecodedCustomWallpaper| doesn't set wallpaper in kiosk
// mode, and |kAccountId1|'s wallpaper info is not updated.
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"", image);
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
WallpaperInfo wallpaper_info;
EXPECT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
// Verify that |SetOnlineWallpaper| doesn't set wallpaper in kiosk
// mode, and |kAccountId1|'s wallpaper info is not updated.
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
ClearWallpaperCount();
controller_->SetOnlineWallpaper(
OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}}),
base::BindLambdaForTesting([&run_loop](bool success) {
EXPECT_FALSE(success);
run_loop->Quit();
}));
run_loop->Run();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
// Verify that |SetDefaultWallpaper| doesn't set wallpaper in kiosk mode, and
// |kAccountId1|'s wallpaper info is not updated.
ClearWallpaperCount();
controller_->SetDefaultWallpaper(kAccountId1, true /*show_wallpaper=*/,
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_FALSE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
}
TEST_P(WallpaperControllerTest, IgnoreWallpaperRequestWhenPolicyIsEnforced) {
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
SimulateUserLogin(kAccountId1);
// Set a policy wallpaper for the user. Verify the user is policy controlled.
controller_->SetPolicyWallpaper(
kAccountId1, user_manager::UserType::kRegular,
CreateEncodedImageForTesting(gfx::Size(10, 10)));
RunAllTasksUntilIdle();
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
WallpaperInfo wallpaper_info;
WallpaperInfo policy_wallpaper_info(base::FilePath(kWallpaperFilesId1)
.Append("policy-controlled.jpeg")
.value(),
WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kPolicy,
base::Time::Now().LocalMidnight());
{
// Verify that |SetDecodedCustomWallpaper| doesn't set wallpaper when policy
// is enforced, and the user wallpaper info is not updated.
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"", image);
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(policy_wallpaper_info));
}
{
// Verify that |SetCustomWallpaper| with callback doesn't set wallpaper when
// policy is enforced, and the user wallpaper info is not updated.
base::RunLoop run_loop;
ClearWallpaperCount();
controller_->SetCustomWallpaper(
kAccountId1, base::FilePath(kFileName1), WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false,
base::BindLambdaForTesting(
[quit = run_loop.QuitClosure()](bool success) {
EXPECT_FALSE(success);
std::move(quit).Run();
}));
run_loop.Run();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(policy_wallpaper_info));
}
{
// Verify that |SetOnlineWallpaper| doesn't set wallpaper when
// policy is enforced, and the user wallpaper info is not updated.
base::RunLoop run_loop;
ClearWallpaperCount();
controller_->SetOnlineWallpaper(
OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}}),
base::BindLambdaForTesting(
[quit = run_loop.QuitClosure()](bool success) {
EXPECT_FALSE(success);
std::move(quit).Run();
}));
run_loop.Run();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(policy_wallpaper_info));
}
{
// Verify that |SetOnlineWallpaper| doesn't set wallpaper when policy is
// enforced, and the user wallpaper info is not updated.
base::RunLoop run_loop;
ClearWallpaperCount();
controller_->SetOnlineWallpaper(
OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}}),
base::BindLambdaForTesting(
[quit = run_loop.QuitClosure()](bool success) {
EXPECT_FALSE(success);
std::move(quit).Run();
}));
run_loop.Run();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(policy_wallpaper_info));
}
{
// Verify that |SetDefaultWallpaper| doesn't set wallpaper when policy is
// enforced, and the user wallpaper info is not updated.
base::RunLoop run_loop;
ClearWallpaperCount();
controller_->SetDefaultWallpaper(
kAccountId1, true /*show_wallpaper=*/,
base::BindLambdaForTesting(
[quit = run_loop.QuitClosure()](bool success) {
EXPECT_FALSE(success);
std::move(quit).Run();
}));
run_loop.Run();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(policy_wallpaper_info));
}
}
TEST_P(WallpaperControllerTest, VerifyWallpaperCache) {
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
SimulateUserLogin(kAccountId1);
// |kUser1| doesn't have wallpaper cache in the beginning.
gfx::ImageSkia cached_wallpaper;
EXPECT_FALSE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
base::FilePath path;
EXPECT_FALSE(controller_->GetPathFromCache(kAccountId1, &path));
// Verify |SetOnlineWallpaper| updates wallpaper cache for |user1|.
controller_->SetOnlineWallpaper(
OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}}),
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_TRUE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
EXPECT_TRUE(controller_->GetPathFromCache(kAccountId1, &path));
// After |kUser2| is logged in, |user1|'s wallpaper cache should still be kept
// (crbug.com/339576). Note the active user is still |user1|.
TestSessionControllerClient* session = GetSessionControllerClient();
session->AddUserSession(kUser2);
EXPECT_TRUE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
EXPECT_TRUE(controller_->GetPathFromCache(kAccountId1, &path));
// Verify |SetDefaultWallpaper| clears wallpaper cache.
controller_->SetDefaultWallpaper(kAccountId1, true /*show_wallpaper=*/,
base::DoNothing());
EXPECT_FALSE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
EXPECT_FALSE(controller_->GetPathFromCache(kAccountId1, &path));
// Verify |SetDecodedCustomWallpaper| updates wallpaper cache for |user1|.
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"", image);
RunAllTasksUntilIdle();
EXPECT_TRUE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
EXPECT_TRUE(controller_->GetPathFromCache(kAccountId1, &path));
// Verify |RemoveUserWallpaper| clears wallpaper cache.
controller_->RemoveUserWallpaper(kAccountId1, base::DoNothing());
EXPECT_FALSE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
EXPECT_FALSE(controller_->GetPathFromCache(kAccountId1, &path));
}
// Tests that the appropriate wallpaper (large vs. small) is shown depending
// on the desktop resolution.
TEST_P(WallpaperControllerTest, ShowCustomWallpaperWithCorrectResolution) {
const base::FilePath small_custom_wallpaper_path = GetCustomWallpaperPath(
kSmallWallpaperSubDir, kWallpaperFilesId1, kFileName1);
const base::FilePath large_custom_wallpaper_path = GetCustomWallpaperPath(
kLargeWallpaperSubDir, kWallpaperFilesId1, kFileName1);
CreateAndSaveWallpapers(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
// Display is initialized to 800x600. The small resolution custom wallpaper is
// expected.
EXPECT_EQ(1, GetWallpaperCount());
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(small_custom_wallpaper_path, GetDecodeFilePaths()[0]);
// Hook up another 800x600 display. This shouldn't trigger a reload.
ClearWallpaperCount();
ClearDecodeFilePaths();
UpdateDisplay("800x600,800x600");
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(0u, GetDecodeFilePaths().size());
// Detach the secondary display.
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
// Hook up a 2000x2000 display. The large resolution custom wallpaper should
// be loaded.
ClearWallpaperCount();
ClearDecodeFilePaths();
UpdateDisplay("800x600,3000x2000");
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(large_custom_wallpaper_path, GetDecodeFilePaths()[0]);
// Detach the secondary display.
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
// Hook up the 3000x2000 display again. Test for crbug/165788.
ClearWallpaperCount();
ClearDecodeFilePaths();
UpdateDisplay("800x600,3000x2000");
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(large_custom_wallpaper_path, GetDecodeFilePaths()[0]);
}
// After the display is rotated, the sign in wallpaper should be kept. Test for
// crbug.com/794725.
TEST_P(WallpaperControllerTest, SigninWallpaperIsKeptAfterRotation) {
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
controller_->ShowSigninWallpaper();
RunAllTasksUntilIdle();
// Display is initialized to 800x600. The small resolution default wallpaper
// is expected.
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(1u, GetDecodeFilePaths().size());
EXPECT_EQ(default_wallpaper_dir_.GetPath().Append(kDefaultSmallWallpaperName),
GetDecodeFilePaths()[0]);
ClearWallpaperCount();
ClearDecodeFilePaths();
// After rotating the display, the small resolution default wallpaper should
// still be set from cache, instead of a custom wallpaper.
UpdateDisplay("800x600/r");
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ASSERT_EQ(0u, GetDecodeFilePaths().size());
}
// Display size change should trigger wallpaper reload.
TEST_P(WallpaperControllerTest, ReloadWallpaper) {
CreateAndSaveWallpapers(kAccountId1);
// Show a user wallpaper.
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
// Rotating the display should trigger a wallpaper reload.
ClearWallpaperCount();
UpdateDisplay("800x600/r");
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
// Calling |ShowUserWallpaper| again with the same account id and display
// size should not trigger wallpaper reload (crbug.com/158383).
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
// Start wallpaper preview.
SimulateUserLogin(kAccountId1);
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/true, base::DoNothing(), /*file_path=*/"",
CreateImage(640, 480, kWallpaperColor));
ClearWallpaperCount();
UpdateDisplay("800x600");
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
ClearWallpaperCount();
controller_->CancelPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
// Show an override wallpaper.
const base::FilePath image_path =
base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kGuestWallpaperLarge);
ClearWallpaperCount();
controller_->ShowOverrideWallpaper(image_path, /*always_on_top=*/true);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
// Rotating the display should trigger a wallpaper reload.
ClearWallpaperCount();
UpdateDisplay("800x600/r");
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
}
TEST_P(WallpaperControllerTest, UpdateCurrentWallpaperLayout) {
gfx::ImageSkia image = CreateImage(640, 480, kSmallCustomWallpaperColor);
WallpaperLayout layout = WALLPAPER_LAYOUT_STRETCH;
WallpaperLayout new_layout = WALLPAPER_LAYOUT_CENTER;
SimulateUserLogin(kAccountId1);
// Set a custom wallpaper for the user. Verify that it's set successfully
// and the wallpaper info is updated.
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/false,
base::DoNothing(),
/*file_path=*/"", image);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperLayout(), layout);
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_custom_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_custom_wallpaper_info));
// Now change to a different layout. Verify that the layout is updated for
// both the current wallpaper and the saved wallpaper info.
ClearWallpaperCount();
controller_->UpdateCurrentWallpaperLayout(kAccountId1, new_layout);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperLayout(), new_layout);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
expected_custom_wallpaper_info.layout = new_layout;
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_custom_wallpaper_info));
{
// Now set a Google Photos wallpaper. Verify that it's set successfully and
// the wallpaper info is updated.
ClearWallpaperCount();
controller_->SetGooglePhotosWallpaper(
GooglePhotosWallpaperParams(kAccountId1, "id",
/*daily_refresh_enabled=*/false, layout,
/*preview_mode=*/false, "dedup_key"),
base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(),
WallpaperType::kOnceGooglePhotos);
EXPECT_EQ(controller_->GetWallpaperLayout(), layout);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(
WallpaperInfo(GooglePhotosWallpaperParams(
kAccountId1, "id", /*daily_refresh_enabled=*/false, layout,
/*preview_mode=*/false, "dedup_key"))));
// Now change to a different layout. Verify that the layout is updated for
// both the current wallpaper and the saved wallpaper info.
ClearWallpaperCount();
controller_->UpdateCurrentWallpaperLayout(kAccountId1, new_layout);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperLayout(), new_layout);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(
WallpaperInfo(GooglePhotosWallpaperParams(
kAccountId1, "id", /*daily_refresh_enabled=*/false, new_layout,
/*preview_mode=*/false, "dedup_key"))));
}
// Now set an online wallpaper. Verify that it's set successfully and the
// wallpaper info is updated.
image = CreateImage(640, 480, kWallpaperColor);
ClearWallpaperCount();
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), layout,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
controller_->SetOnlineWallpaper(params, base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
EXPECT_EQ(controller_->GetWallpaperLayout(), layout);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_online_wallpaper_info(params, params.variants.front());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_online_wallpaper_info));
// Now change the layout of the online wallpaper. Verify that it's a no-op.
ClearWallpaperCount();
controller_->UpdateCurrentWallpaperLayout(kAccountId1, new_layout);
RunAllTasksUntilIdle();
// The wallpaper is not updated.
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperLayout(), layout);
// The saved wallpaper info is not updated.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_online_wallpaper_info));
}
// Tests that if a user who has a custom wallpaper is removed from the device,
// only the directory that contains the user's custom wallpapers gets removed.
// The other user's custom wallpaper is not affected.
TEST_P(WallpaperControllerTest, RemoveUserWithCustomWallpaper) {
SimulateUserLogin(kAccountId1);
base::FilePath small_wallpaper_path_1 = GetCustomWallpaperPath(
kSmallWallpaperSubDir, kWallpaperFilesId1, kFileName1);
// Set a custom wallpaper for |kUser1| and verify the wallpaper exists.
CreateAndSaveWallpapers(kAccountId1);
EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
// Now login another user and set a custom wallpaper for the user.
SimulateUserLogin(kAccountId2);
base::FilePath small_wallpaper_path_2 = GetCustomWallpaperPath(
kSmallWallpaperSubDir, kWallpaperFilesId2, GetDummyFileName(kAccountId2));
CreateAndSaveWallpapers(kAccountId2);
EXPECT_TRUE(base::PathExists(small_wallpaper_path_2));
// Simulate the removal of |kUser2|.
controller_->RemoveUserWallpaper(kAccountId2, base::DoNothing());
// Wait until all files under the user's custom wallpaper directory are
// removed.
WaitUntilCustomWallpapersDeleted(kAccountId2);
EXPECT_FALSE(base::PathExists(small_wallpaper_path_2));
// Verify that the other user's wallpaper is not affected.
EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
}
// Tests that if a user who has a default wallpaper is removed from the device,
// the other user's custom wallpaper is not affected.
TEST_P(WallpaperControllerTest, RemoveUserWithDefaultWallpaper) {
SimulateUserLogin(kAccountId1);
base::FilePath small_wallpaper_path_1 = GetCustomWallpaperPath(
kSmallWallpaperSubDir, kWallpaperFilesId1, kFileName1);
// Set a custom wallpaper for |kUser1| and verify the wallpaper exists.
CreateAndSaveWallpapers(kAccountId1);
EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
// Now login another user and set a default wallpaper for the user.
SimulateUserLogin(kAccountId2);
controller_->SetDefaultWallpaper(kAccountId2, true /*show_wallpaper=*/,
base::DoNothing());
// Simulate the removal of |kUser2|.
controller_->RemoveUserWallpaper(kAccountId2,
/*on_removed=*/base::DoNothing());
// Verify that the other user's wallpaper is not affected.
EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
}
// Tests that when a user who has a default wallpaper is removed from the
// device, the `on_remove` callback is called.
TEST_P(WallpaperControllerTest, RemoveUserWallpaperOnRemoveCallbackCalled) {
SimulateUserLogin(kAccountId1);
controller_->SetDefaultWallpaper(kAccountId1, /*show_wallpaper=*/true,
/*callback=*/base::DoNothing());
base::test::TestFuture<void> remove_was_called;
// Simulate the removal of |kUser1|.
controller_->RemoveUserWallpaper(kAccountId1,
remove_was_called.GetCallback());
// Assert that the `on_remove` callback is called
ASSERT_TRUE(remove_was_called.Wait());
}
TEST_P(WallpaperControllerTest, IsActiveUserWallpaperControlledByPolicy) {
// Simulate the login screen. Verify that it returns false since there's no
// active user.
ClearLogin();
EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
SimulateUserLogin(kAccountId1);
EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
// Set a policy wallpaper for the active user. Verify that the active user
// becomes policy controlled.
controller_->SetPolicyWallpaper(
kAccountId1, user_manager::UserType::kRegular,
CreateEncodedImageForTesting(gfx::Size(10, 10)));
RunAllTasksUntilIdle();
EXPECT_TRUE(controller_->IsActiveUserWallpaperControlledByPolicy());
// Switch the active user. Verify the active user is not policy controlled.
SimulateUserLogin(kAccountId2);
EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
// Logs out. Verify that it returns false since there's no active user.
ClearLogin();
EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
}
TEST_P(WallpaperControllerTest,
IsManagedGuestSessionWallpaperControlledByPolicy) {
// Simulate the login screen. Verify that it returns false since there's no
// active user.
ClearLogin();
EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
// Set a policy wallpaper for the managed guest session. Verify that the
// managed guest session becomes policy controlled.
controller_->SetPolicyWallpaper(
kAccountId1, user_manager::UserType::kPublicAccount,
CreateEncodedImageForTesting(gfx::Size(10, 10)));
SimulateUserLogin(kAccountId1, user_manager::UserType::kPublicAccount);
RunAllTasksUntilIdle();
EXPECT_TRUE(controller_->IsWallpaperControlledByPolicy(kAccountId1));
// Verify the wallpaper policy is applied after logging in.
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
EXPECT_EQ(1, GetWallpaperCount());
ASSERT_EQ(controller_->GetWallpaperType(), WallpaperType::kPolicy);
// Switch the active user. Verify the active user is not policy controlled.
SimulateUserLogin(kAccountId2);
EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
// Logs out. Verify that it returns false since there's no active user.
ClearLogin();
EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
}
TEST_P(WallpaperControllerTest, WallpaperBlur) {
TestWallpaperControllerObserver observer(controller_);
ASSERT_TRUE(controller_->blur_manager()->IsBlurAllowedForLockState(
controller_->GetWallpaperType()));
ASSERT_FALSE(controller_->IsWallpaperBlurredForLockState());
SetSessionState(SessionState::ACTIVE);
EXPECT_FALSE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(0, observer.blur_changed_count());
SetSessionState(SessionState::LOCKED);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(1, observer.blur_changed_count());
SetSessionState(SessionState::LOGGED_IN_NOT_ACTIVE);
EXPECT_FALSE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(2, observer.blur_changed_count());
SetSessionState(SessionState::LOGIN_SECONDARY);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(3, observer.blur_changed_count());
// Blur state does not change below.
SetSessionState(SessionState::LOGIN_PRIMARY);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(3, observer.blur_changed_count());
SetSessionState(SessionState::OOBE);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(3, observer.blur_changed_count());
SetSessionState(SessionState::UNKNOWN);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(3, observer.blur_changed_count());
}
TEST_P(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) {
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
gfx::ImageSkia image = CreateImage(600, 400, kWallpaperColor);
controller_->ShowWallpaperImage(
image, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
TestWallpaperControllerObserver observer(controller_);
ASSERT_TRUE(controller_->blur_manager()->IsBlurAllowedForLockState(
controller_->GetWallpaperType()));
ASSERT_FALSE(controller_->IsWallpaperBlurredForLockState());
const bool forest_enabled = features::IsForestFeatureEnabled();
if (forest_enabled) {
// There are three layers: underlay, original and old layers.
ASSERT_EQ(3u, wallpaper_view()->layer()->parent()->children().size());
EXPECT_EQ(ui::LAYER_SOLID_COLOR,
wallpaper_view()->layer()->parent()->children()[0]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[1]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[2]->type());
} else {
ASSERT_EQ(2u, wallpaper_view()->layer()->parent()->children().size());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[0]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[1]->type());
}
// Simulate lock and unlock sequence.
controller_->UpdateWallpaperBlurForLockState(true);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(1, observer.blur_changed_count());
SetSessionState(SessionState::LOCKED);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
if (forest_enabled) {
// There are four layers: shield, underlay, original and old layers.
ASSERT_EQ(4u, wallpaper_view()->layer()->parent()->children().size());
EXPECT_EQ(ui::LAYER_SOLID_COLOR,
wallpaper_view()->layer()->parent()->children()[0]->type());
EXPECT_EQ(ui::LAYER_SOLID_COLOR,
wallpaper_view()->layer()->parent()->children()[1]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[2]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[3]->type());
} else {
ASSERT_EQ(3u, wallpaper_view()->layer()->parent()->children().size());
EXPECT_EQ(ui::LAYER_SOLID_COLOR,
wallpaper_view()->layer()->parent()->children()[0]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[1]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[2]->type());
}
// Change of state to ACTIVE triggers post lock animation and
// UpdateWallpaperBlur(false)
SetSessionState(SessionState::ACTIVE);
EXPECT_FALSE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(2, observer.blur_changed_count());
if (forest_enabled) {
// There are three layers: underlay, original and old layers.
ASSERT_EQ(3u, wallpaper_view()->layer()->parent()->children().size());
EXPECT_EQ(ui::LAYER_SOLID_COLOR,
wallpaper_view()->layer()->parent()->children()[0]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[1]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[2]->type());
} else {
ASSERT_EQ(2u, wallpaper_view()->layer()->parent()->children().size());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[0]->type());
EXPECT_EQ(ui::LAYER_TEXTURED,
wallpaper_view()->layer()->parent()->children()[1]->type());
}
}
TEST_P(WallpaperControllerTest, LockDuringOverview) {
gfx::ImageSkia image = CreateImage(600, 400, kWallpaperColor);
controller_->ShowWallpaperImage(
image, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
/*preview_mode=*/false, /*is_override=*/false);
TestWallpaperControllerObserver observer(controller_);
EnterOverview();
EXPECT_FALSE(controller_->IsWallpaperBlurredForLockState());
EXPECT_EQ(0, observer.blur_changed_count());
// Simulate lock and unlock sequence.
SetSessionState(SessionState::LOCKED);
EXPECT_TRUE(controller_->IsWallpaperBlurredForLockState());
// Get wallpaper_view directly because it's not animating.
auto* wallpaper_view = Shell::Get()
->GetPrimaryRootWindowController()
->wallpaper_widget_controller()
->wallpaper_view();
// Make sure that wallpaper still have blur.
ASSERT_EQ(30, wallpaper_view->blur_sigma());
}
TEST_P(WallpaperControllerTest, DontLeakShieldView) {
SetSessionState(SessionState::LOCKED);
views::View* shield_view = wallpaper_view()->shield_view_for_testing();
ASSERT_TRUE(shield_view);
views::ViewTracker view_tracker(shield_view);
SetSessionState(SessionState::ACTIVE);
EXPECT_EQ(nullptr, wallpaper_view()->shield_view_for_testing());
EXPECT_EQ(nullptr, view_tracker.view());
}
TEST_P(WallpaperControllerTest, OnlyShowDevicePolicyWallpaperOnLoginScreen) {
// Make sure the device policy path exists so decoding succeeds.
ASSERT_TRUE(WriteJPEGFile(user_data_dir_.GetPath().Append(
base::FilePath(kDefaultSmallWallpaperName)),
/*width=*/2, /*height=*/2, kWallpaperColor));
// Verify the device policy wallpaper is shown on login screen.
SetSessionState(SessionState::LOGIN_PRIMARY);
controller_->SetDevicePolicyWallpaperPath(user_data_dir_.GetPath().Append(
base::FilePath(kDefaultSmallWallpaperName)));
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_TRUE(IsDevicePolicyWallpaper());
// Verify the device policy wallpaper shouldn't be blurred.
ASSERT_FALSE(controller_->blur_manager()->IsBlurAllowedForLockState(
controller_->GetWallpaperType()));
ASSERT_FALSE(controller_->IsWallpaperBlurredForLockState());
// Verify the device policy wallpaper is replaced when session state is no
// longer LOGIN_PRIMARY.
SetSessionState(SessionState::LOGGED_IN_NOT_ACTIVE);
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
EXPECT_FALSE(IsDevicePolicyWallpaper());
// Verify the device policy wallpaper never shows up again when session
// state changes.
SetSessionState(SessionState::ACTIVE);
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
EXPECT_FALSE(IsDevicePolicyWallpaper());
SetSessionState(SessionState::LOCKED);
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
EXPECT_FALSE(IsDevicePolicyWallpaper());
SetSessionState(SessionState::LOGIN_SECONDARY);
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
EXPECT_FALSE(IsDevicePolicyWallpaper());
}
TEST_P(WallpaperControllerTest, ShouldShowInitialAnimationAfterBoot) {
CreateAndSaveWallpapers(kChildAccountId);
// Simulate the login screen after system boot.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kFirstExecAfterBoot);
base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager);
ClearLogin();
// Show the first wallpaper. Verify that the slower animation should be used.
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_TRUE(controller_->ShouldShowInitialAnimation());
EXPECT_EQ(1, GetWallpaperCount());
// Show the second wallpaper. Verify that the slower animation should not be
// used. (Use a different user type to ensure a different wallpaper is shown,
// otherwise requests of loading the same wallpaper are ignored.)
ClearWallpaperCount();
controller_->ShowUserWallpaper(kChildAccountId);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->ShouldShowInitialAnimation());
EXPECT_EQ(1, GetWallpaperCount());
// Log in the user and show the wallpaper. Verify that the slower animation
// should not be used.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->ShouldShowInitialAnimation());
EXPECT_EQ(1, GetWallpaperCount());
}
TEST_P(WallpaperControllerTest, ShouldNotShowInitialAnimationAfterSignOut) {
// Simulate the login screen after user sign-out. Verify that the slower
// animation should never be used.
base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager);
CreateAndSaveWallpapers(kAccountId1);
ClearLogin();
// Show the first wallpaper.
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->ShouldShowInitialAnimation());
EXPECT_EQ(1, GetWallpaperCount());
// Show the second wallpaper.
ClearWallpaperCount();
controller_->ShowUserWallpaper(kChildAccountId);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->ShouldShowInitialAnimation());
EXPECT_EQ(1, GetWallpaperCount());
// Log in the user and show the wallpaper.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->ShouldShowInitialAnimation());
EXPECT_EQ(1, GetWallpaperCount());
}
TEST_P(WallpaperControllerTest, ClosePreviewWallpaperOnOverviewStart) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
// Set a custom wallpaper for the user and enable preview. Verify that the
// wallpaper is changed to the expected color.
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
ClearWallpaperCount();
TestWallpaperControllerObserver observer(controller_);
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/true,
base::DoNothing(),
/*file_path=*/"", custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_TRUE(observer.is_in_wallpaper_preview());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Now enter overview mode. Verify the wallpaper changes back to the default,
// the user wallpaper info remains unchanged, and enters overview mode
// properly.
ClearWallpaperCount();
EnterOverview();
RunAllTasksUntilIdle();
EXPECT_FALSE(observer.is_in_wallpaper_preview());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
EXPECT_TRUE(OverviewController::Get()->InOverviewSession());
}
TEST_P(WallpaperControllerTest, ClosePreviewWallpaperOnWindowCycleStart) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
TestWallpaperControllerObserver observer(controller_);
// Set a custom wallpaper for the user and enable preview. Verify that the
// wallpaper is changed to the expected color.
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/true,
base::DoNothing(),
/*file_path=*/"", custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_TRUE(observer.is_in_wallpaper_preview());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Now start window cycle. Verify the wallpaper changes back to the default,
// the user wallpaper info remains unchanged, and enters window cycle.
ClearWallpaperCount();
Shell::Get()->window_cycle_controller()->HandleCycleWindow(
WindowCycleController::WindowCyclingDirection::kForward);
RunAllTasksUntilIdle();
EXPECT_FALSE(observer.is_in_wallpaper_preview());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
EXPECT_TRUE(Shell::Get()->window_cycle_controller()->IsCycling());
}
TEST_P(WallpaperControllerTest,
ClosePreviewWallpaperOnActiveUserSessionChanged) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
TestWallpaperControllerObserver observer(controller_);
// Set a custom wallpaper for the user and enable preview. Verify that the
// wallpaper is changed to the expected color.
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/true,
base::DoNothing(),
/*file_path=*/"", custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_TRUE(observer.is_in_wallpaper_preview());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Now switch to another user. Verify the wallpaper changes back to the
// default and the user wallpaper remains unchanged.
ClearWallpaperCount();
SimulateUserLogin(kAccountId2);
controller_->ShowUserWallpaper(kAccountId2);
RunAllTasksUntilIdle();
EXPECT_FALSE(observer.is_in_wallpaper_preview());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId2, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
}
TEST_P(WallpaperControllerTest, ConfirmPreviewWallpaper) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
// Set a custom wallpaper for the user and enable preview. Verify that the
// wallpaper is changed to the expected color.
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/true,
base::DoNothing(),
/*file_path=*/"", custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Preview.Show", 1);
// Now confirm the preview wallpaper, verify that there's no wallpaper change
// because the wallpaper is already shown.
ClearWallpaperCount();
controller_->ConfirmPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info is now updated to the custom wallpaper
// info.
WallpaperInfo custom_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(custom_wallpaper_info));
// Set an empty online wallpaper for the user, verify it fails.
ClearWallpaperCount();
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
SetOnlineWallpaperFromImage(
kAccountId1, kAssetId, gfx::ImageSkia(), kDummyUrl,
TestWallpaperControllerClient::kDummyCollectionId, layout,
/*preview_mode=*/true, /*from_user=*/true, kUnitId,
base::BindLambdaForTesting([&run_loop](bool success) {
EXPECT_FALSE(success);
run_loop->Quit();
}));
run_loop->Run();
EXPECT_EQ(0, GetWallpaperCount());
// Now set a valid online wallpaper for the user and enable preview. Verify
// that the wallpaper is changed to the expected color.
const SkColor online_wallpaper_color = SK_ColorCYAN;
gfx::ImageSkia online_wallpaper =
CreateImage(640, 480, online_wallpaper_color);
EXPECT_NE(online_wallpaper_color, GetWallpaperColor());
TestWallpaperControllerObserver observer(controller_);
run_loop = std::make_unique<base::RunLoop>();
observer.SetOnResizeCallback(run_loop->QuitClosure());
SetOnlineWallpaperFromImage(
kAccountId1, kAssetId, online_wallpaper, kDummyUrl,
TestWallpaperControllerClient::kDummyCollectionId, layout,
/*preview_mode=*/true, /*from_user=*/true, kUnitId,
base::BindLambdaForTesting([](bool success) { EXPECT_TRUE(success); }));
run_loop->Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(online_wallpaper_color, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(custom_wallpaper_info));
// Now confirm the preview wallpaper, verify that there's no wallpaper change
// because the wallpaper is already shown.
ClearWallpaperCount();
controller_->ConfirmPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(online_wallpaper_color, GetWallpaperColor());
// Verify that the user wallpaper info is now updated to the online wallpaper
// info.
OnlineWallpaperVariant variant(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo online_wallpaper_info(
OnlineWallpaperParams(kAccountId1,
TestWallpaperControllerClient::kDummyCollectionId,
layout,
/*preview_mode=*/false,
/*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/{variant}),
variant);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(online_wallpaper_info));
}
TEST_P(WallpaperControllerTest, CancelPreviewWallpaper) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
// Set a custom wallpaper for the user and enable preview. Verify that the
// wallpaper is changed to the expected color.
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/true,
base::DoNothing(),
/*file_path=*/"", custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Now cancel the preview. Verify the wallpaper changes back to the default
// and the user wallpaper info remains unchanged.
ClearWallpaperCount();
controller_->CancelPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Now set an online wallpaper for the user and enable preview. Verify that
// the wallpaper is changed to the expected color.
const SkColor online_wallpaper_color = SK_ColorCYAN;
gfx::ImageSkia online_wallpaper =
CreateImage(640, 480, online_wallpaper_color);
EXPECT_NE(online_wallpaper_color, GetWallpaperColor());
ClearWallpaperCount();
SetOnlineWallpaperFromImage(
kAccountId1, kAssetId, online_wallpaper, kDummyUrl,
TestWallpaperControllerClient::kDummyCollectionId, layout,
/*preview_mode=*/true, /*from_user=*/true, kUnitId, base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(online_wallpaper_color, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Now cancel the preview. Verify the wallpaper changes back to the default
// and the user wallpaper info remains unchanged.
ClearWallpaperCount();
controller_->CancelPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_NE(online_wallpaper_color, GetWallpaperColor());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
}
TEST_P(WallpaperControllerTest, WallpaperSyncedDuringPreview) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
// Set a custom wallpaper for the user and enable preview. Verify that the
// wallpaper is changed to the expected color.
const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/true,
base::DoNothing(),
/*file_path=*/"", custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Now set another custom wallpaper for the user and disable preview (this
// happens if a custom wallpaper set on another device is being synced).
// Verify there's no wallpaper change since preview mode shouldn't be
// interrupted.
const SkColor synced_custom_wallpaper_color = SK_ColorBLUE;
gfx::ImageSkia synced_custom_wallpaper =
CreateImage(640, 480, synced_custom_wallpaper_color);
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName2, layout,
/*preview_mode=*/false, base::DoNothing(),
/*file_path=*/"", synced_custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// However, the user wallpaper info should already be updated to the new info.
WallpaperInfo synced_custom_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName2).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(synced_custom_wallpaper_info));
// Now cancel the preview. Verify the synced custom wallpaper is shown instead
// of the initial default wallpaper, and the user wallpaper info is still
// correct.
ClearWallpaperCount();
controller_->CancelPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(synced_custom_wallpaper_color, GetWallpaperColor());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(synced_custom_wallpaper_info));
// Repeat the above steps for online wallpapers: set a online wallpaper for
// the user and enable preview. Verify that the wallpaper is changed to the
// expected color.
gfx::ImageSkia online_wallpaper = CreateImage(640, 480, kWallpaperColor);
EXPECT_NE(kWallpaperColor, GetWallpaperColor());
ClearWallpaperCount();
SetOnlineWallpaperFromImage(
kAccountId1, kAssetId, online_wallpaper, kDummyUrl,
TestWallpaperControllerClient::kDummyCollectionId, layout,
/*preview_mode=*/true, /*from_user=*/true, kUnitId, base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(synced_custom_wallpaper_info));
// Now set another online wallpaper for the user and disable preview. Verify
// there's no wallpaper change since preview mode shouldn't be interrupted.
const SkColor synced_online_wallpaper_color = SK_ColorCYAN;
gfx::ImageSkia synced_online_wallpaper =
CreateImage(640, 480, synced_online_wallpaper_color);
ClearWallpaperCount();
SetOnlineWallpaperFromImage(
kAccountId1, kAssetId, synced_online_wallpaper, kDummyUrl2,
TestWallpaperControllerClient::kDummyCollectionId, layout,
/*preview_mode=*/false,
/*from_user=*/true, kUnitId, base::DoNothing());
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// However, the user wallpaper info should already be updated to the new info.
OnlineWallpaperVariant variant(kAssetId, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo synced_online_wallpaper_info = WallpaperInfo(
OnlineWallpaperParams(kAccountId1,
TestWallpaperControllerClient::kDummyCollectionId,
layout,
/*preview_mode=*/false,
/*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/{variant}),
variant);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(synced_online_wallpaper_info));
// Now cancel the preview. Verify the synced online wallpaper is shown instead
// of the previous custom wallpaper, and the user wallpaper info is still
// correct.
ClearWallpaperCount();
controller_->CancelPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(synced_online_wallpaper_color, GetWallpaperColor());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(synced_online_wallpaper_info));
}
TEST_P(WallpaperControllerTest, AddFirstWallpaperAnimationEndCallback) {
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
std::unique_ptr<aura::Window> test_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
base::RunLoop test_loop;
controller_->AddFirstWallpaperAnimationEndCallback(test_loop.QuitClosure(),
test_window.get());
// The callback is not run because the first wallpaper hasn't been set.
task_environment()->RunUntilIdle();
EXPECT_FALSE(test_loop.AnyQuitCalled());
// Set the first wallpaper.
controller_->ShowDefaultWallpaperForTesting();
controller_->AddFirstWallpaperAnimationEndCallback(test_loop.QuitClosure(),
test_window.get());
task_environment()->RunUntilIdle();
// Neither callback is run because the animation of the first wallpaper
// hasn't finished yet.
EXPECT_FALSE(test_loop.AnyQuitCalled());
// Force the animation to complete. The two callbacks are both run.
RunDesktopControllerAnimation();
test_loop.Run();
EXPECT_TRUE(test_loop.AnyQuitCalled());
// The callback added after the first wallpaper animation is run right away.
bool is_third_callback_run = false;
controller_->AddFirstWallpaperAnimationEndCallback(
base::BindLambdaForTesting(
[&is_third_callback_run]() { is_third_callback_run = true; }),
test_window.get());
EXPECT_TRUE(is_third_callback_run);
}
TEST_P(WallpaperControllerTest, ShowOneShotWallpaper) {
gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
SimulateUserLogin(kAccountId1);
// First, set a custom wallpaper for |kUser1|. Verify the wallpaper is shown
// successfully and the user wallpaper info is updated.
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/false,
base::DoNothing(),
/*file_path=*/"", custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
const WallpaperInfo expected_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
// Show a one-shot wallpaper. Verify it is shown successfully.
ClearWallpaperCount();
constexpr SkColor kOneShotWallpaperColor = SK_ColorWHITE;
gfx::ImageSkia one_shot_wallpaper =
CreateImage(640, 480, kOneShotWallpaperColor);
controller_->ShowOneShotWallpaper(one_shot_wallpaper);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kOneShotWallpaperColor, GetWallpaperColor());
EXPECT_EQ(WallpaperType::kOneShot, controller_->GetWallpaperType());
EXPECT_FALSE(controller_->blur_manager()->IsBlurAllowedForLockState(
controller_->GetWallpaperType()));
EXPECT_FALSE(controller_->ShouldApplyShield());
// Verify that we can reload wallpaer without losing it.
// This is important for screen rotation.
controller_->ReloadWallpaperForTesting(/*clear_cache=*/false);
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount()); // Reload increments count.
EXPECT_EQ(kOneShotWallpaperColor, GetWallpaperColor());
EXPECT_EQ(WallpaperType::kOneShot, controller_->GetWallpaperType());
EXPECT_FALSE(controller_->blur_manager()->IsBlurAllowedForLockState(
controller_->GetWallpaperType()));
EXPECT_FALSE(controller_->ShouldApplyShield());
// Verify the user wallpaper info is unaffected, and the one-shot wallpaper
// can be replaced by the user wallpaper.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
}
TEST_P(WallpaperControllerTest, OnFirstWallpaperShown) {
TestWallpaperControllerObserver observer(controller_);
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(0, observer.first_shown_count());
// Show the first wallpaper, verify the observer is notified.
controller_->ShowWallpaperImage(CreateImage(640, 480, SK_ColorBLUE),
CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH),
/*preview_mode=*/false,
/*is_override=*/false);
RunAllTasksUntilIdle();
EXPECT_EQ(SK_ColorBLUE, GetWallpaperColor());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(1, observer.first_shown_count());
// Show the second wallpaper, verify the observer is not notified.
controller_->ShowWallpaperImage(CreateImage(640, 480, SK_ColorCYAN),
CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH),
/*preview_mode=*/false,
/*is_override=*/false);
RunAllTasksUntilIdle();
EXPECT_EQ(SK_ColorCYAN, GetWallpaperColor());
EXPECT_EQ(2, GetWallpaperCount());
EXPECT_EQ(1, observer.first_shown_count());
}
// Although ephemeral users' custom wallpapers are not saved to disk, they
// should be kept within the user session. Test for https://crbug.com/825237.
TEST_P(WallpaperControllerTest, ShowWallpaperForEphemeralUser) {
// Clear the local pref so we can make sure nothing writes to it.
local_state()->ClearPref(prefs::kUserWallpaperInfo);
// Add an ephemeral user session and simulate login, like SimulateUserLogin.
UserSession session;
session.session_id = 0;
session.user_info.account_id = kAccountId1;
session.user_info.is_ephemeral = true;
Shell::Get()->session_controller()->UpdateUserSession(std::move(session));
TestSessionControllerClient* const client = GetSessionControllerClient();
client->SwitchActiveUser(kAccountId1);
client->SetSessionState(SessionState::ACTIVE);
// The user doesn't have wallpaper cache in the beginning.
gfx::ImageSkia cached_wallpaper;
EXPECT_FALSE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
base::FilePath path;
EXPECT_FALSE(controller_->GetPathFromCache(kAccountId1, &path));
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER,
/*preview_mode=*/false, base::DoNothing(), /*file_path=*/"",
CreateImage(640, 480, kWallpaperColor));
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
// Assert that we do not use local state for an ephemeral user.
auto* dict = local_state()->GetUserPrefValue(prefs::kUserWallpaperInfo);
ASSERT_FALSE(dict) << *dict;
// The custom wallpaper is cached.
EXPECT_TRUE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
EXPECT_EQ(
kWallpaperColor,
cached_wallpaper.GetRepresentation(1.0f).GetBitmap().getColor(0, 0));
EXPECT_TRUE(controller_->GetPathFromCache(kAccountId1, &path));
// Calling |ShowUserWallpaper| will continue showing the custom wallpaper
// instead of reverting to the default.
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
}
// Base class for `WallpaperControllerTest` parameterized by device properties
// which OOBE wallpaper flow should be used
class WallpaperControllerOobeWallpaperTest
: public WallpaperControllerTestBase,
public testing::WithParamInterface</*BootAnimation*/ bool> {
public:
WallpaperControllerOobeWallpaperTest() {
const bool boot_animation = GetParam();
scoped_feature_list_.InitWithFeatureStates({
{features::kFeatureManagementOobeSimon, boot_animation},
});
}
~WallpaperControllerOobeWallpaperTest() override = default;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
INSTANTIATE_TEST_SUITE_P(All,
WallpaperControllerOobeWallpaperTest,
/*BootAnimation*/ testing::Bool());
TEST_P(WallpaperControllerOobeWallpaperTest, ShowOobeWallpaper) {
controller_->ShowDefaultWallpaperForTesting();
RunAllTasksUntilIdle();
// Verify the OOBE wallpaper is shown during OOBE.
SetSessionState(SessionState::OOBE);
controller_->ReloadWallpaperForTesting(/*clear_cache=*/false);
RunAllTasksUntilIdle();
EXPECT_TRUE(controller_->IsOobeWallpaper());
controller_->ShowSigninWallpaper();
RunAllTasksUntilIdle();
EXPECT_TRUE(controller_->IsOobeWallpaper());
// Verify the OOBE wallpaper is replaced when session state is no
// longer OOBE.
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->IsOobeWallpaper());
// Verify the OOBE wallpaper never shows up again when session
// state changes.
SetSessionState(SessionState::LOGGED_IN_NOT_ACTIVE);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->IsOobeWallpaper());
SetSessionState(SessionState::ACTIVE);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->IsOobeWallpaper());
SetSessionState(SessionState::LOCKED);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->IsOobeWallpaper());
SetSessionState(SessionState::LOGIN_SECONDARY);
RunAllTasksUntilIdle();
EXPECT_FALSE(controller_->IsOobeWallpaper());
}
// Base class for `WallpaperControllerTest` parameterized by whether override
// wallpapers should be shown on top of everything except for the power off
// animation.
class WallpaperControllerOverrideWallpaperTest
: public WallpaperControllerTestBase,
public testing::WithParamInterface</*always_on_top=*/bool> {
public:
// Returns whether override wallpapers should be shown on top of everything
// except for the power off animation given test parameterization.
bool always_on_top() const { return GetParam(); }
};
INSTANTIATE_TEST_SUITE_P(All,
WallpaperControllerOverrideWallpaperTest,
/*always_on_top=*/testing::Bool());
TEST_P(WallpaperControllerOverrideWallpaperTest, OverrideWallpaper) {
// Show a default wallpaper.
EXPECT_EQ(0, GetWallpaperCount());
controller_->ShowSigninWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_EQ(1, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(0, ChildCountForContainer(kAlwaysOnTopWallpaperId));
// Show an override wallpaper.
const base::FilePath image_path =
base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kGuestWallpaperLarge);
controller_->ShowOverrideWallpaper(image_path, always_on_top());
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOneShot);
EXPECT_EQ(always_on_top() ? 0 : 1, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(always_on_top() ? 1 : 0,
ChildCountForContainer(kAlwaysOnTopWallpaperId));
// Subsequent wallpaper requests are ignored when the current wallpaper is
// overridden.
controller_->ShowSigninWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOneShot);
EXPECT_EQ(always_on_top() ? 0 : 1, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(always_on_top() ? 1 : 0,
ChildCountForContainer(kAlwaysOnTopWallpaperId));
// The wallpaper reverts to the default after the override wallpaper is
// removed.
controller_->RemoveOverrideWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(3, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_EQ(1, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(0, ChildCountForContainer(kAlwaysOnTopWallpaperId));
// Calling |RemoveOverrideWallpaper()| is a no-op when the current wallpaper
// is not overridden.
controller_->RemoveOverrideWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(3, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_EQ(1, ChildCountForContainer(kWallpaperId));
EXPECT_EQ(0, ChildCountForContainer(kAlwaysOnTopWallpaperId));
}
namespace {
class WallpaperControllerPrefTest : public AshTestBase {
public:
WallpaperControllerPrefTest() {
scoped_feature_list_.InitWithFeatures(
personalization_app::GetTimeOfDayEnabledFeatures(), {});
base::Value::Dict property;
property.Set("rotation", static_cast<int>(display::Display::ROTATE_90));
property.Set("width", 800);
property.Set("height", 600);
ScopedDictPrefUpdate update(local_state(), prefs::kDisplayProperties);
update->Set("2200000000", std::move(property));
}
~WallpaperControllerPrefTest() override = default;
void SetUp() override { AshTestBase::SetUp(); }
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
} // namespace
// Make sure that the display and the wallpaper view are rotated correctly at
// startup.
TEST_F(WallpaperControllerPrefTest, InitWithPrefs) {
auto* wallpaper_view = Shell::GetPrimaryRootWindowController()
->wallpaper_widget_controller()
->wallpaper_view();
auto* root_window =
wallpaper_view->GetWidget()->GetNativeWindow()->GetRootWindow();
EXPECT_EQ(gfx::Size(600, 800), display::Screen::GetScreen()
->GetDisplayNearestWindow(root_window)
.size());
EXPECT_EQ(root_window->bounds().size(), wallpaper_view->bounds().size());
}
TEST_P(WallpaperControllerTest, NoAnimationForNewRootWindowWhenLocked) {
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
SetSessionState(SessionState::LOCKED);
UpdateDisplay("800x600, 800x600");
auto* secondary_root_window_controller =
Shell::Get()->GetAllRootWindowControllers()[1];
EXPECT_FALSE(secondary_root_window_controller->wallpaper_widget_controller()
->IsAnimating());
EXPECT_FALSE(secondary_root_window_controller->wallpaper_widget_controller()
->GetWidget()
->GetLayer()
->GetAnimator()
->is_animating());
}
TEST_P(WallpaperControllerTest, SetCustomWallpaper) {
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
SimulateUserLogin(kAccountId1);
// Set a custom wallpaper for |kUser1|. Verify the wallpaper is set
// successfully and wallpaper info is updated.
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/false,
base::DoNothing(),
/*file_path=*/"", image);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kCustomized);
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
// Now set another custom wallpaper for |kUser1|. Verify that the on-screen
// wallpaper doesn't change since |kUser1| is not active, but wallpaper info
// is updated properly.
SimulateUserLogin(kAccountId2);
const SkColor custom_wallpaper_color = SK_ColorCYAN;
image = CreateImage(640, 480, custom_wallpaper_color);
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/false,
base::DoNothing(),
/*file_path=*/"", image);
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
// Verify the updated wallpaper is shown after |kUser1| becomes active again.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(custom_wallpaper_color, GetWallpaperColor());
}
TEST_P(WallpaperControllerTest, OldOnlineInfoSynced_Discarded) {
// Create a dictionary that looks like the preference from crrev.com/a040384.
// DO NOT CHANGE as there are preferences like this in production.
base::Value::Dict wallpaper_info_dict;
wallpaper_info_dict.Set(
WallpaperInfo::kNewWallpaperDateNodeName,
base::NumberToString(
base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds()));
wallpaper_info_dict.Set(WallpaperInfo::kNewWallpaperLocationNodeName,
"location");
wallpaper_info_dict.Set(WallpaperInfo::kNewWallpaperUserFilePathNodeName,
"user_file_path");
wallpaper_info_dict.Set(WallpaperInfo::kNewWallpaperLayoutNodeName,
WallpaperLayout::WALLPAPER_LAYOUT_CENTER);
wallpaper_info_dict.Set(WallpaperInfo::kNewWallpaperTypeNodeName,
static_cast<int>(WallpaperType::kOnline));
{
ScopedDictPrefUpdate wallpaper_update(GetProfilePrefService(kAccountId1),
prefs::kSyncableWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(),
std::move(wallpaper_info_dict));
}
SimulateUserLogin(kAccountId1);
task_environment()->RunUntilIdle();
// Unmigrated synced wallpaper info are discarded.
WallpaperInfo actual;
EXPECT_FALSE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual));
}
TEST_P(WallpaperControllerTest, MigrateWallpaperInfo_Online) {
WallpaperInfo expected_info = InfoWithType(WallpaperType::kOnline);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, expected_info);
SimulateUserLogin(kAccountId1);
WallpaperInfo info;
ASSERT_TRUE(pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &info));
EXPECT_TRUE(info.MatchesSelection(expected_info));
}
TEST_P(WallpaperControllerTest, MigrateWallpaperInfoCustomized) {
WallpaperInfo expected_info = InfoWithType(WallpaperType::kCustomized);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, expected_info);
SimulateUserLogin(kAccountId1);
WallpaperInfo info;
ASSERT_TRUE(pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &info));
EXPECT_TRUE(info.MatchesSelection(expected_info));
}
TEST_P(WallpaperControllerTest, MigrateWallpaperInfoDaily) {
OnlineWallpaperVariant variant(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo expected_info = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER, /*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId, {variant}),
variant);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, expected_info);
SimulateUserLogin(kAccountId1);
WallpaperInfo info;
ASSERT_TRUE(pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &info));
EXPECT_TRUE(info.MatchesSelection(expected_info));
}
TEST_P(WallpaperControllerTest,
MigrateWallpaperInfoDoesntHappenWhenSyncedInfoAlreadyExists) {
OnlineWallpaperVariant local_variant(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo local_info = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER, /*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId, {local_variant}),
local_variant);
OnlineWallpaperVariant synced_variant(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo synced_info = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER, /*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId, {synced_variant}),
synced_variant);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
SimulateUserLogin(kAccountId1);
WallpaperInfo info;
ASSERT_TRUE(pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &info));
// Synced info should be the same if local is the same age.
EXPECT_TRUE(synced_info.MatchesSelection(info));
}
TEST_P(WallpaperControllerTest,
ActiveUserPrefServiceChangedSyncedInfoHandledLocally) {
CacheOnlineWallpaper(kDummyUrl);
WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
synced_info.unit_id = kUnitId;
synced_info.collection_id = TestWallpaperControllerClient::kDummyCollectionId;
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
local_info.date = DayBeforeYesterdayish();
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
client_.ResetCounts();
controller_->OnActiveUserPrefServiceChanged(
GetProfilePrefService(kAccountId1));
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(WallpaperType::kOnline, actual_info.type);
}
TEST_P(WallpaperControllerTest, ActiveUserPrefServiceChanged_SyncDisabled) {
CacheOnlineWallpaper(kDummyUrl);
WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
synced_info.unit_id = kUnitId;
synced_info.collection_id = TestWallpaperControllerClient::kDummyCollectionId;
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault);
local_info.date = DayBeforeYesterdayish();
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
client_.ResetCounts();
client_.set_wallpaper_sync_enabled(false);
controller_->OnActiveUserPrefServiceChanged(
GetProfilePrefService(kAccountId1));
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(WallpaperType::kDefault, actual_info.type);
}
TEST_P(WallpaperControllerTest, HandleWallpaperInfoSyncedLocalIsPolicy) {
CacheOnlineWallpaper(kDummyUrl);
pref_manager_->SetLocalWallpaperInfo(kAccountId1,
InfoWithType(WallpaperType::kPolicy));
SimulateUserLogin(kAccountId1);
WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_NE(WallpaperType::kOnline, actual_info.type);
}
TEST_P(WallpaperControllerTest,
HandleWallpaperInfoSyncedLocalIsCustomizedAndOlder) {
CacheOnlineWallpaper(kDummyUrl);
WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
local_info.date = DayBeforeYesterdayish();
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
SimulateUserLogin(kAccountId1);
WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
synced_info.unit_id = kUnitId;
synced_info.collection_id = TestWallpaperControllerClient::kDummyCollectionId;
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(WallpaperType::kOnline, actual_info.type);
}
TEST_P(WallpaperControllerTest,
HandleWallpaperInfoSyncedLocalIsCustomizedAndNewer) {
CacheOnlineWallpaper(kDummyUrl);
pref_manager_->SetLocalWallpaperInfo(
kAccountId1, InfoWithType(WallpaperType::kCustomized));
WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, DayBeforeYesterdayish()};
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
SimulateUserLogin(kAccountId1);
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_EQ(WallpaperType::kCustomized, actual_info.type);
}
TEST_P(WallpaperControllerTest, HandleWallpaperInfoSyncedOnline) {
CacheOnlineWallpaper(kDummyUrl);
// Attempt to set an online wallpaper without providing the image data. Verify
// it succeeds this time because |SetOnlineWallpaper| has saved the file.
ClearWallpaperCount();
OnlineWallpaperVariant variant(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo info = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER, /*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId, {variant}),
variant);
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, info);
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
}
TEST_P(WallpaperControllerTest, HandleWallpaperInfoSyncedInactiveUser) {
CacheOnlineWallpaper(kDummyUrl);
// Make kAccountId1 the inactive user.
SimulateUserLogin(kAccountId2);
// Attempt to set an online wallpaper without providing the image data. Verify
// it succeeds this time because |SetOnlineWallpaper| has saved the file.
ClearWallpaperCount();
pref_manager_->SetSyncedWallpaperInfo(kAccountId1,
InfoWithType(WallpaperType::kOnline));
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
EXPECT_NE(controller_->GetWallpaperType(), WallpaperType::kOnline);
}
TEST_P(WallpaperControllerTest, UpdateDailyRefreshWallpaper) {
std::string expected{"fun_collection"};
SimulateUserLogin(kAccountId1);
WallpaperInfo info = {std::string(), WALLPAPER_LAYOUT_CENTER,
WallpaperType::kDaily, DayBeforeYesterdayish()};
info.unit_id = kUnitId;
info.collection_id = expected;
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
controller_->UpdateDailyRefreshWallpaper();
EXPECT_EQ(expected, client_.get_fetch_daily_refresh_wallpaper_param());
}
TEST_P(WallpaperControllerTest, UpdateDailyRefreshWallpaperCalledOnLogin) {
SimulateUserLogin(kAccountId1);
OnlineWallpaperVariant variant(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo info = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED, /*preview_mode=*/false,
/*from_user=*/false,
/*daily_refresh_enabled=*/true, kUnitId, {variant}),
variant);
info.date = DayBeforeYesterdayish();
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
ClearLogin();
SimulateUserLogin(kAccountId1);
// Info is set as over a day old so we expect one task to run in under an hour
// (due to fuzzing) then it will idle.
task_environment()->FastForwardBy(base::Hours(1));
// Make sure all the tasks such as syncing, setting wallpaper complete.
RunAllTasksUntilIdle();
EXPECT_EQ(TestWallpaperControllerClient::kDummyCollectionId,
client_.get_fetch_daily_refresh_wallpaper_param());
}
TEST_P(WallpaperControllerTest, UpdateDailyRefreshWallpaper_NotEnabled) {
SimulateUserLogin(kAccountId1);
WallpaperInfo info = {std::string(), WALLPAPER_LAYOUT_CENTER,
WallpaperType::kOnline, DayBeforeYesterdayish()};
info.collection_id = "fun_collection";
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
controller_->UpdateDailyRefreshWallpaper();
EXPECT_EQ(std::string(), client_.get_fetch_daily_refresh_wallpaper_param());
}
TEST_P(WallpaperControllerTest, UpdateDailyRefreshWallpaper_NoCollectionId) {
SimulateUserLogin(kAccountId1);
pref_manager_->SetUserWallpaperInfo(
kAccountId1,
WallpaperInfo(std::string(), WALLPAPER_LAYOUT_CENTER,
WallpaperType::kDaily, DayBeforeYesterdayish()));
controller_->UpdateDailyRefreshWallpaper();
EXPECT_EQ(std::string(), client_.get_fetch_daily_refresh_wallpaper_param());
}
TEST_P(WallpaperControllerTest, MigrateCustomWallpaper) {
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
SimulateUserLogin(kAccountId1);
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/false,
base::DoNothing(),
/*file_path=*/"", image);
RunAllTasksUntilIdle();
ClearLogin();
SimulateUserLogin(kAccountId1);
EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
}
TEST_P(WallpaperControllerTest, OnGoogleDriveMounted) {
WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
SimulateUserLogin(kAccountId1);
controller_->SyncLocalAndRemotePrefs(kAccountId1);
EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
}
TEST_P(WallpaperControllerTest, OnGoogleDriveMounted_WallpaperIsntCustom) {
WallpaperInfo local_info = InfoWithType(WallpaperType::kOnline);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
controller_->SyncLocalAndRemotePrefs(kAccountId1);
EXPECT_TRUE(drivefs_delegate_->get_save_wallpaper_account_id().empty());
}
TEST_P(WallpaperControllerTest, OnGoogleDriveMounted_AlreadySynced) {
WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
SimulateUserLogin(kAccountId1);
gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
controller_->SetDecodedCustomWallpaper(kAccountId1, kFileName1, layout,
/*preview_mode=*/false,
base::DoNothing(),
/*file_path=*/"", image);
RunAllTasksUntilIdle();
drivefs_delegate_->Reset();
// Should not reupload image if it has already been synced.
controller_->SyncLocalAndRemotePrefs(kAccountId1);
EXPECT_FALSE(drivefs_delegate_->get_save_wallpaper_account_id().is_valid());
}
TEST_P(WallpaperControllerTest, OnGoogleDriveMounted_OldLocalInfo) {
WallpaperInfo local_info = WallpaperInfo(
"a_url", WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kCustomized,
DayBeforeYesterdayish(), "/test/a_url");
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
WallpaperInfo synced_info = WallpaperInfo(
"b_url", WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kCustomized,
base::Time::Now().LocalMidnight(), "/test/b_url");
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
SimulateUserLogin(kAccountId1);
controller_->SyncLocalAndRemotePrefs(kAccountId1);
EXPECT_FALSE(drivefs_delegate_->get_save_wallpaper_account_id().is_valid());
}
TEST_P(WallpaperControllerTest, OnGoogleDriveMounted_NewLocalInfo) {
WallpaperInfo local_info = WallpaperInfo(
"a_url", WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kCustomized,
base::Time::Now().LocalMidnight(), "/test/a_url");
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
WallpaperInfo synced_info = WallpaperInfo(
"b_url", WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kCustomized,
DayBeforeYesterdayish(), "/test/b_url");
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
SimulateUserLogin(kAccountId1);
controller_->SyncLocalAndRemotePrefs(kAccountId1);
EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
}
TEST_P(WallpaperControllerTest, SetDailyRefreshCollectionId_Empty) {
std::string collection_id = "fun_collection";
WallpaperInfo info = {std::string(), WALLPAPER_LAYOUT_CENTER,
WallpaperType::kDaily, DayBeforeYesterdayish()};
info.collection_id = collection_id;
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
controller_->SetDailyRefreshCollectionId(kAccountId1, std::string());
WallpaperInfo expected = {std::string(), WALLPAPER_LAYOUT_CENTER,
WallpaperType::kOnline, DayBeforeYesterdayish()};
expected.collection_id = collection_id;
WallpaperInfo actual;
pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual);
// Type should be `WallpaperType::kOnline` now, and collection_id should be
// `WallpaperType::EMPTY`.
EXPECT_TRUE(actual.MatchesSelection(expected));
EXPECT_EQ(std::string(),
controller_->GetDailyRefreshCollectionId(kAccountId1));
}
// WallpaperType should not change with an empty collection id if the previous
// WallpaperType isn't |WallpaperType::kDaily|.
TEST_P(WallpaperControllerTest,
SetDailyRefreshCollectionId_Empty_NotTypeDaily) {
pref_manager_->SetUserWallpaperInfo(
kAccountId1,
WallpaperInfo(std::string(), WALLPAPER_LAYOUT_CENTER,
WallpaperType::kCustomized, DayBeforeYesterdayish()));
controller_->SetDailyRefreshCollectionId(kAccountId1, std::string());
WallpaperInfo expected =
WallpaperInfo(std::string(), WALLPAPER_LAYOUT_CENTER,
WallpaperType::kCustomized, DayBeforeYesterdayish());
WallpaperInfo actual;
pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual);
EXPECT_TRUE(actual.MatchesSelection(expected));
EXPECT_EQ(std::string(),
controller_->GetDailyRefreshCollectionId(kAccountId1));
}
TEST_P(WallpaperControllerTest, UpdateWallpaperOnScheduleCheckpointChanged) {
for (const bool is_guest : {false, true}) {
if (is_guest) {
SimulateGuestLogin();
} else {
SimulateUserLogin(kAccountId1);
}
const AccountId active_account_id =
Shell::Get()->session_controller()->GetActiveAccountId();
// Enable dark mode by default.
Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false);
Shell::Get()->dark_light_mode_controller()->SetDarkModeEnabledForTest(true);
auto run_loop = std::make_unique<base::RunLoop>();
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
active_account_id, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
// Use dark mode wallpaper initially.
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting([&run_loop](bool success) {
EXPECT_TRUE(success);
run_loop->Quit();
}));
run_loop->Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
WallpaperInfo actual;
ASSERT_TRUE(
pref_manager_->GetUserWallpaperInfo(active_account_id, &actual));
EXPECT_EQ(actual.location, kDummyUrl);
base::Time original_timestamp = actual.date;
task_environment()->FastForwardBy(base::Hours(1));
// Switch to light mode and simulate schedule checkpoint change to reflect
// light mode.
EXPECT_TRUE(
Shell::Get()->dark_light_mode_controller()->IsDarkModeEnabled());
Shell::Get()->dark_light_mode_controller()->ToggleColorMode();
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
ASSERT_TRUE(
pref_manager_->GetUserWallpaperInfo(active_account_id, &actual));
EXPECT_EQ(actual.location, kDummyUrl2);
// The wallpaper in pref should still match what was originally selected.
// However, the |date| should not be affected by the dark -> light change.
EXPECT_TRUE(
actual.MatchesSelection(WallpaperInfo(params, variants.back())));
EXPECT_EQ(actual.date, original_timestamp);
}
}
TEST_P(WallpaperControllerAutoScheduleTest, UpdateWallpaperOnAutoColorMode) {
base::expected<base::Time, GeolocationController::SunRiseSetError>
sunrise_time = Shell::Get()->geolocation_controller()->GetSunriseTime();
base::expected<base::Time, GeolocationController::SunRiseSetError>
sunset_time = Shell::Get()->geolocation_controller()->GetSunsetTime();
ASSERT_TRUE(sunrise_time.has_value());
ASSERT_TRUE(sunset_time.has_value());
SetSimulatedStartTime(sunrise_time.value());
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/true, kUnitId, variants);
base::test::TestFuture<bool> future;
controller_->SetOnlineWallpaper(params, future.GetCallback());
ASSERT_TRUE(future.Get());
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDaily);
WallpaperInfo actual;
ASSERT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual));
EXPECT_EQ(actual.location, kDummyUrl2);
base::Time original_timestamp = actual.date;
// Forward time to trigger checkpoints.
ASSERT_GT(sunset_time.value(), Now());
task_environment()->FastForwardBy(sunset_time.value() - Now());
RunAllTasksUntilIdle();
WallpaperInfo expected = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED, /*preview_mode=*/false,
/*from_user=*/true,
/*daily_refresh_enabled=*/true, kUnitId, variants),
variants.back());
ASSERT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual));
EXPECT_EQ(actual.location, kDummyUrl);
// The wallpaper in pref should still match what was originally selected.
// However, the |date| should not be affected by the dark -> light change.
EXPECT_TRUE(actual.MatchesSelection(expected));
EXPECT_EQ(actual.date, original_timestamp);
}
TEST_P(WallpaperControllerAutoScheduleTest,
UpdateTimeOfDayWallpaperWithAutoColorModeOff) {
static constexpr gfx::Size kTestImageSize = gfx::Size(100, 100);
static constexpr SkColor kSunriseImageColor = SK_ColorRED;
static constexpr SkColor kMorningImageColor = SK_ColorGREEN;
static constexpr SkColor kLateAfternoonImageColor = SK_ColorBLUE;
static constexpr SkColor kSunsetImageColor = SK_ColorYELLOW;
if (!IsTimeOfDayEnabled()) {
return;
}
const auto backdrop_image_data = TimeOfDayImageSet();
client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
backdrop_image_data);
const base::flat_map<backdrop::Image_ImageType, gfx::ImageSkia> test_images =
{{backdrop::Image::IMAGE_TYPE_LIGHT_MODE,
CreateSolidColorTestImage(kTestImageSize, kSunriseImageColor)},
{backdrop::Image::IMAGE_TYPE_MORNING_MODE,
CreateSolidColorTestImage(kTestImageSize, kMorningImageColor)},
{backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE,
CreateSolidColorTestImage(kTestImageSize, kLateAfternoonImageColor)},
{backdrop::Image::IMAGE_TYPE_DARK_MODE,
CreateSolidColorTestImage(kTestImageSize, kSunsetImageColor)}};
test_wallpaper_image_downloader()->set_image_generator(
base::BindLambdaForTesting([backdrop_image_data,
test_images](const GURL& url) {
const backdrop::Image* match_found =
GetImageMatchingUrl(url, backdrop_image_data);
return match_found
? test_images.at(match_found->image_type())
: CreateSolidColorTestImage(kTestImageSize, SK_ColorBLACK);
}));
SimulateUserLogin(kAccountId1);
Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false);
OnlineWallpaperParams params(
kAccountId1, wallpaper_constants::kTimeOfDayWallpaperCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false,
wallpaper_constants::kDefaultTimeOfDayWallpaperUnitId, /*variants=*/{});
for (const backdrop::Image& backdrop_image : backdrop_image_data) {
params.variants.emplace_back(backdrop_image.asset_id(),
GURL(backdrop_image.image_url()),
backdrop_image.image_type());
}
const auto wallpaper_has_color = [this](SkColor color) {
return gfx::test::AreImagesClose(
gfx::Image(controller_->GetWallpaper()),
gfx::Image(CreateSolidColorTestImage(controller_->GetWallpaper().size(),
color)),
/*max_deviation=*/1);
};
// Midnight
base::test::TestFuture<bool> future;
controller_->SetOnlineWallpaper(params, future.GetCallback());
ASSERT_TRUE(future.Get());
EXPECT_TRUE(wallpaper_has_color(kSunsetImageColor));
WallpaperChangedBarrier barrier(controller_, task_environment());
// Sunrise. 7 AM.
ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(7));
EXPECT_TRUE(wallpaper_has_color(kSunriseImageColor));
// Morning. 11 AM.
ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(11));
EXPECT_TRUE(wallpaper_has_color(kMorningImageColor));
// Sunrise. 5 PM.
ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(17));
EXPECT_TRUE(wallpaper_has_color(kLateAfternoonImageColor));
// Sunrise. 7 PM.
ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(19));
EXPECT_TRUE(wallpaper_has_color(kSunsetImageColor));
}
TEST_P(WallpaperControllerTest,
UpdateWallpaperOnScheduleCheckpointChanged_WithReplacedAsset) {
SimulateUserLogin(kAccountId1);
// Enable dark mode by default.
Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false);
Shell::Get()->dark_light_mode_controller()->SetDarkModeEnabledForTest(true);
auto run_loop = std::make_unique<base::RunLoop>();
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
// Use dark mode wallpaper initially.
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting([&run_loop](bool success) {
EXPECT_TRUE(success);
run_loop->Quit();
}));
run_loop->Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
// Simulate a wallpaper changes from the server by changing one of the
// variant's url.
WallpaperInfo local_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &local_info));
std::vector<OnlineWallpaperVariant> updated_variants;
const std::string updated_light_url = "https://light/new_light_url.jpg";
updated_variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
updated_variants.emplace_back(kAssetId2, GURL(updated_light_url),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
local_info.variants = updated_variants;
EXPECT_TRUE(pref_manager_->SetUserWallpaperInfo(kAccountId1, local_info));
// Switch to light mode and simulate schedule checkpoint change to reflect
// light mode.
EXPECT_TRUE(Shell::Get()->dark_light_mode_controller()->IsDarkModeEnabled());
Shell::Get()->dark_light_mode_controller()->ToggleColorMode();
RunAllTasksUntilIdle();
EXPECT_EQ(2, GetWallpaperCount());
WallpaperInfo expected = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED, /*preview_mode=*/false,
/*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, updated_variants),
updated_variants.back());
WallpaperInfo actual;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual));
EXPECT_TRUE(actual.MatchesAsset(expected));
// Verifies the new asset is downloaded and saved to disk.
EXPECT_TRUE(base::PathExists(online_wallpaper_dir_.GetPath().Append(
GURL(updated_light_url).ExtractFileName())));
}
TEST_P(WallpaperControllerTest,
DoesNotCrashOnScheduleCheckpointChangedWhenDownloadFails) {
SimulateUserLogin(kAccountId1);
// Enable dark mode by default.
Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false);
Shell::Get()->dark_light_mode_controller()->SetDarkModeEnabledForTest(true);
auto run_loop = std::make_unique<base::RunLoop>();
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
// Use dark mode wallpaper initially.
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting([&run_loop](bool success) {
EXPECT_TRUE(success);
run_loop->Quit();
}));
run_loop->Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
ClearWallpaperCount();
// Simulate a wallpaper changes from the server by changing one of the
// variant's url.
WallpaperInfo local_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &local_info));
std::vector<OnlineWallpaperVariant> updated_variants;
const std::string updated_light_url = "https://light/new_light_url.jpg";
updated_variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
updated_variants.emplace_back(kAssetId2, GURL(updated_light_url),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
local_info.variants = updated_variants;
EXPECT_TRUE(pref_manager_->SetUserWallpaperInfo(kAccountId1, local_info));
// Simulate a failure in image downloading.
test_wallpaper_image_downloader()->set_image_generator(
base::BindLambdaForTesting([](const GURL&) { return gfx::ImageSkia(); }));
// Switch to light mode and simulate schedule checkpoint change to reflect
// light mode.
EXPECT_TRUE(Shell::Get()->dark_light_mode_controller()->IsDarkModeEnabled());
Shell::Get()->dark_light_mode_controller()->ToggleColorMode();
RunAllTasksUntilIdle();
EXPECT_EQ(0, GetWallpaperCount());
WallpaperInfo expected = WallpaperInfo(params, updated_variants.front());
WallpaperInfo actual;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual));
EXPECT_EQ(actual.asset_id, expected.asset_id);
EXPECT_EQ(actual.location, expected.location);
// Assets aren't matched due to updated variant asset.
EXPECT_FALSE(actual.MatchesAsset(expected));
}
TEST_P(WallpaperControllerTest,
DoesNotUpdateWallpaperOnColorModeChangedWithNoVariants) {
SimulateUserLogin(kAccountId1);
auto run_loop = std::make_unique<base::RunLoop>();
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId,
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting([&run_loop](bool success) {
EXPECT_TRUE(success);
run_loop->Quit();
}));
run_loop->Run();
EXPECT_EQ(1, GetWallpaperCount());
// Toggles color mode a couple times. Wallpaper count shouldn't change.
Shell::Get()->dark_light_mode_controller()->ToggleColorMode();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
Shell::Get()->dark_light_mode_controller()->ToggleColorMode();
RunAllTasksUntilIdle();
EXPECT_EQ(1, GetWallpaperCount());
}
TEST_P(WallpaperControllerTest,
UpdateWallpaperInfoWithOnlineWallpaperVariants) {
SimulateUserLogin(kAccountId1);
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
pref_manager_->SetUserWallpaperInfo(kAccountId1,
WallpaperInfo(params, variants.front()));
WallpaperInfo expected = WallpaperInfo(params, variants.front());
WallpaperInfo actual;
pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual);
EXPECT_TRUE(actual.MatchesSelection(expected));
}
TEST_P(WallpaperControllerTest, SetOnlineWallpaperWithoutInternet) {
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
SimulateUserLogin(kAccountId1);
// Set an online wallpaper with image data. Verify that the wallpaper is set
// successfully.
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
ClearWallpaperCount();
controller_->SetOnlineWallpaper(params, base::DoNothing());
RunAllTasksUntilIdle();
ASSERT_EQ(1, GetWallpaperCount());
ASSERT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
// Change the on-screen wallpaper to a different one. (Otherwise the
// subsequent calls will be no-op since we intentionally prevent reloading the
// same wallpaper.)
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, base::DoNothing(),
/*file_path=*/"", CreateImage(640, 480, kWallpaperColor));
RunAllTasksUntilIdle();
ASSERT_EQ(1, GetWallpaperCount());
ASSERT_EQ(controller_->GetWallpaperType(), WallpaperType::kCustomized);
// Attempt to set the same online wallpaper without internet. Verify it
// still succeeds because the previous call to |SetOnlineWallpaper()| has
// saved the file.
test_wallpaper_image_downloader()->set_image_generator(
base::BindLambdaForTesting([](const GURL&) { return gfx::ImageSkia(); }));
ClearWallpaperCount();
base::RunLoop run_loop;
controller_->SetOnlineWallpaper(
params, base::BindLambdaForTesting([&run_loop](bool file_exists) {
EXPECT_TRUE(file_exists);
run_loop.Quit();
}));
run_loop.Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
}
TEST_P(WallpaperControllerTest,
HandleWallpaperInfoSyncedForDarkLightWallpapers_NotSynced) {
SimulateUserLogin(kAccountId1);
CacheOnlineWallpaper(kDummyUrl);
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
// Force local info to not have a unit_id.
WallpaperInfo local_info = WallpaperInfo(params, variants.front());
local_info.unit_id = std::nullopt;
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
// synced info tracks dark variant.
const WallpaperInfo& synced_info = WallpaperInfo(params, variants.back());
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_TRUE(actual_info.MatchesSelection(synced_info));
// Verify the wallpaper is set.
EXPECT_EQ(1, GetWallpaperCount());
}
TEST_P(WallpaperControllerTest,
HandleWallpaperInfoSyncedForDarkLightWallpapers_AlreadySynced) {
SimulateUserLogin(kAccountId1);
CacheOnlineWallpaper(kDummyUrl);
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
// local info tracks light variant.
const WallpaperInfo& local_info = WallpaperInfo(params, variants.front());
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
// synced info tracks dark variant.
const WallpaperInfo& synced_info = WallpaperInfo(params, variants.back());
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_TRUE(local_info.MatchesSelection(synced_info));
EXPECT_TRUE(local_info.MatchesSelection(actual_info));
// Verify the wallpaper is not set again.
EXPECT_EQ(0, GetWallpaperCount());
}
TEST_P(WallpaperControllerTest, WallpaperCustomization_Used) {
// Reset to login screen.
GetSessionControllerClient()->RequestSignOut();
// Emulate login screen behavior.
controller_->ShowSigninWallpaper();
// Let the task queue run so that we run `ShowWallpaperImage()`.
task_environment()->RunUntilIdle();
std::pair<const base::FilePath, const base::FilePath> paths =
CreateCustomizationWallpapers();
ASSERT_FALSE(paths.first.empty());
ASSERT_FALSE(paths.second.empty());
controller_->SetCustomizedDefaultWallpaperPaths(paths.first, paths.second);
task_environment()->RunUntilIdle();
// Verify that the customized wallpaper is in use.
EXPECT_THAT(GetCurrentWallpaperInfo().location,
testing::EndsWith(kCustomizationSmallWallpaperName));
}
TEST_P(WallpaperControllerTest, WallpaperCustomization_UnusedForNonDefault) {
SimulateUserLogin(kAccountId1);
// Set wallpaper to something a user may have chose.
controller_->SetOnlineWallpaper(
OnlineWallpaperParams(
kAccountId1,
/*collection_id=*/std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/false,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}}),
base::DoNothing());
// Let the task queue run so that we run `ShowWallpaperImage()`.
task_environment()->RunUntilIdle();
// Simulate wallpaper customization retrieval completing after login.
std::pair<const base::FilePath, const base::FilePath> paths =
CreateCustomizationWallpapers();
ASSERT_FALSE(paths.first.empty());
ASSERT_FALSE(paths.second.empty());
controller_->SetCustomizedDefaultWallpaperPaths(paths.first, paths.second);
task_environment()->RunUntilIdle();
// Verify that we still use the online wallpaper. i.e. did not switch to
// default.
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
}
TEST_P(WallpaperControllerTest, TimeOfDayWallpapers_NotSyncedIn) {
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
variants.emplace_back(kAssetId3, GURL(kDummyUrl3),
backdrop::Image::IMAGE_TYPE_MORNING_MODE);
variants.emplace_back(kAssetId4, GURL(kDummyUrl4),
backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
WallpaperInfo local_info = WallpaperInfo(params, variants.front());
local_info.unit_id = kUnitId;
local_info.date = DayBeforeYesterdayish();
pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
// synced info tracks a different wallpaper.
WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info));
EXPECT_TRUE(actual_info.MatchesSelection(local_info));
// Verify that no new wallpaper is set.
EXPECT_EQ(0, GetWallpaperCount());
}
TEST_P(WallpaperControllerTest, TimeOfDayWallpapers_NotSyncedOut) {
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
// synced info tracks a different wallpaper.
WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
synced_info.date = DayBeforeYesterdayish();
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
std::vector<OnlineWallpaperVariant> variants;
variants.emplace_back(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
variants.emplace_back(kAssetId2, GURL(kDummyUrl2),
backdrop::Image::IMAGE_TYPE_DARK_MODE);
variants.emplace_back(kAssetId3, GURL(kDummyUrl3),
backdrop::Image::IMAGE_TYPE_MORNING_MODE);
variants.emplace_back(kAssetId4, GURL(kDummyUrl4),
backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE);
const OnlineWallpaperParams& params = OnlineWallpaperParams(
kAccountId1, wallpaper_constants::kTimeOfDayWallpaperCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId, variants);
WallpaperInfo local_info = WallpaperInfo(params, variants.front());
local_info.unit_id = kUnitId;
pref_manager_->SetUserWallpaperInfo(kAccountId1, local_info);
RunAllTasksUntilIdle();
WallpaperInfo actual_info;
EXPECT_TRUE(pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &actual_info));
EXPECT_TRUE(actual_info.MatchesSelection(synced_info));
}
TEST_P(WallpaperControllerTest, SetGooglePhotosWallpaper) {
SimulateUserLogin(kAccountId1);
// First set the wallpaper to an Online one so we can tell for sure if setting
// a Google Photos wallpaper has failed.
base::test::TestFuture<bool> online_future;
controller_->SetOnlineWallpaper(
{kAccountId1,
TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false,
/*from_user=*/true,
/*daily_refresh_enabled=*/false,
kUnitId,
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}}},
online_future.GetCallback());
ASSERT_TRUE(online_future.Wait());
ASSERT_EQ(1, GetWallpaperCount());
ASSERT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
// Now attempt setting a Google Photos wallpaper.
ClearWallpaperCount();
int expected_wallpaper_count = 0;
ASSERT_EQ(expected_wallpaper_count, GetWallpaperCount());
GooglePhotosWallpaperParams params(kAccountId1, kFakeGooglePhotosPhotoId,
/*daily_refresh_enabled=*/false,
WallpaperLayout::WALLPAPER_LAYOUT_STRETCH,
/*preview_mode=*/false, "dedup_key");
controller_->SetGooglePhotosWallpaper(params, base::DoNothing());
++expected_wallpaper_count;
WaitForWallpaperCount(expected_wallpaper_count);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnceGooglePhotos);
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info(params);
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
}
TEST_P(WallpaperControllerTest, SetGooglePhotosWallpaperFails) {
SimulateUserLogin(kAccountId1);
// First set the wallpaper to an Online one so we can tell for sure if setting
// a Google Photos wallpaper has failed.
base::test::TestFuture<bool> online_future;
OnlineWallpaperParams online_params(
{kAccountId1,
TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false,
/*from_user=*/true,
/*daily_refresh_enabled=*/false,
kUnitId,
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}}});
controller_->SetOnlineWallpaper(online_params, online_future.GetCallback());
ASSERT_TRUE(online_future.Wait());
ASSERT_EQ(1, GetWallpaperCount());
ASSERT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
// Attempt to set a Google Photos wallpaper with the client set to fail to
// fetch the Google Photos photo data.
client_.set_fetch_google_photos_photo_fails(true);
ClearWallpaperCount();
ASSERT_EQ(0, GetWallpaperCount());
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, kFakeGooglePhotosPhotoId, false,
WallpaperLayout::WALLPAPER_LAYOUT_STRETCH, false, "dedup_key"},
google_photos_future.GetCallback());
EXPECT_FALSE(google_photos_future.Get());
EXPECT_NE(controller_->GetWallpaperType(), WallpaperType::kOnceGooglePhotos);
WallpaperInfo wallpaper_info;
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info));
WallpaperInfo expected_wallpaper_info(online_params,
online_params.variants.front());
EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
}
TEST_P(WallpaperControllerTest, ResetToDefaultForDeletedPhotoOnStalenessCheck) {
SimulateUserLogin(kAccountId1);
WallpaperInfo info = {kFakeGooglePhotosPhotoId, WALLPAPER_LAYOUT_CENTER,
WallpaperType::kOnceGooglePhotos,
DayBeforeYesterdayish()};
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
client_.set_google_photo_has_been_deleted(true);
// Trigger Google Photos wallpaper cache check.
controller_->OnActiveUserSessionChanged(kAccountId1);
WaitForWallpaperCount(1);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
}
TEST_P(WallpaperControllerTest, HandleSyncDeletedGooglePhotosPhoto) {
WallpaperInfo local_info = InfoWithType(WallpaperType::kOnline);
local_info.date -= base::Days(2);
pref_manager_->SetUserWallpaperInfo(kAccountId1, local_info);
WallpaperInfo synced_info = InfoWithType(WallpaperType::kOnceGooglePhotos);
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
// Just started and still loading wallpaper.
ASSERT_FALSE(controller_->HasShownAnyWallpaper());
ASSERT_THAT(client_.fetch_google_photos_photo_id(), testing::IsEmpty());
client_.set_google_photo_has_been_deleted(true);
SimulateUserLogin(kAccountId1);
EXPECT_EQ(synced_info.location, client_.fetch_google_photos_photo_id());
RunAllTasksUntilIdle();
WallpaperInfo final_local_info;
ASSERT_TRUE(
pref_manager_->GetLocalWallpaperInfo(kAccountId1, &final_local_info));
EXPECT_TRUE(final_local_info.MatchesAsset(local_info));
histogram_tester().ExpectUniqueSample(
"Ash.Wallpaper.OnceGooglePhotos.Result2",
SetWallpaperResult::kFileNotFound, 1);
}
TEST_P(WallpaperControllerTest, GooglePhotosAreCachedOnDisk) {
SimulateUserLogin(kAccountId1);
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, kFakeGooglePhotosPhotoId, /*daily_refresh_enabled=*/false,
WALLPAPER_LAYOUT_STRETCH,
/*preview_mode=*/false, "dedup_key"},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
base::FilePath saved_wallpaper = online_wallpaper_dir_.GetPath()
.Append("google_photos/")
.Append(kAccountId1.GetAccountIdKey())
.Append(kFakeGooglePhotosPhotoId);
ASSERT_TRUE(base::PathExists(saved_wallpaper));
}
TEST_P(WallpaperControllerTest, GooglePhotosAreCachedInMemory) {
SimulateUserLogin(kAccountId1);
base::FilePath path;
EXPECT_FALSE(controller_->GetPathFromCache(kAccountId1, &path));
gfx::ImageSkia cached_wallpaper;
EXPECT_FALSE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, kFakeGooglePhotosPhotoId, /*daily_refresh_enabled=*/false,
WALLPAPER_LAYOUT_STRETCH,
/*preview_mode=*/false, "dedup_key"},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
// We store an empty path for Google Photos wallpapers in the in-memory cache
// because storing the real path correctly would require updating the cache
// after the asynchronous save operation, and we have no use for it anyway.
EXPECT_TRUE(controller_->GetPathFromCache(kAccountId1, &path));
EXPECT_TRUE(path.empty());
EXPECT_TRUE(
controller_->GetWallpaperFromCache(kAccountId1, &cached_wallpaper));
}
TEST_P(WallpaperControllerTest, GooglePhotosAreReadFromCache) {
SimulateUserLogin(kAccountId1);
base::test::TestFuture<bool> google_photos_future;
GooglePhotosWallpaperParams params({kAccountId1, kFakeGooglePhotosPhotoId,
/*daily_refresh_enabled=*/false,
WALLPAPER_LAYOUT_STRETCH,
/*preview_mode=*/false, "dedup_key"});
controller_->SetGooglePhotosWallpaper(params,
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
// When Google Photos is disabled, the wallpaper will not be in disk cache,
// so it will attempt to read from disk, fail to find it, and then reset to
// the default wallpaper.
const size_t expected_decodes = 0;
const WallpaperType expected_type = WallpaperType::kOnceGooglePhotos;
EXPECT_EQ(expected_decodes, GetDecodeFilePaths().size());
EXPECT_EQ(expected_type, controller_->GetWallpaperType());
}
TEST_P(WallpaperControllerTest, ConfirmGooglePhotosPreviewWallpaper) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
// Set a Google Photos wallpaper for the user and enable preview. Verify that
// the wallpaper is a Google Photos image if the feature is enabled.
const WallpaperLayout layout = WALLPAPER_LAYOUT_STRETCH;
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ClearWallpaperCount();
std::string photo_id = "foobar";
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, photo_id, /*daily_refresh_enabled=*/false, layout,
/*preview_mode=*/true, "dedup_key"},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnceGooglePhotos);
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Preview.Show", 1);
// Now confirm the preview wallpaper, verify that there's no wallpaper
// change because the wallpaper is already shown.
ClearWallpaperCount();
controller_->ConfirmPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 0);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnceGooglePhotos);
// Verify that the user wallpaper info is now updated to the Google Photos
// wallpaper info.
WallpaperInfo google_photos_wallpaper_info(photo_id, layout,
WallpaperType::kOnceGooglePhotos,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(google_photos_wallpaper_info));
}
TEST_P(WallpaperControllerTest, CancelGooglePhotosPreviewWallpaper) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
// Set a Google Photos wallpaper for the user and enable preview. Verify that
// the wallpaper is a Google Photos image if the feature is enabled.
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ClearWallpaperCount();
std::string photo_id = "foobar";
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, photo_id, /*daily_refresh_enabled=*/false,
WALLPAPER_LAYOUT_STRETCH, /*preview_mode=*/true, "dedup_key"},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnceGooglePhotos);
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Preview.Show", 1);
// Now cancel the preview. Verify the wallpaper changes back to the default
// and the user wallpaper info remains unchanged.
ClearWallpaperCount();
controller_->CancelPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
}
TEST_P(WallpaperControllerTest, GooglePhotosWallpaperSyncedDuringPreview) {
// Verify the user starts with a default wallpaper and the user wallpaper info
// is initialized with default values.
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->ShowUserWallpaper(kAccountId1);
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
WallpaperInfo user_wallpaper_info;
WallpaperInfo default_wallpaper_info(
std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kDefault,
base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
// Simulate opening the wallpaper picker window.
std::unique_ptr<aura::Window> wallpaper_picker_window(
CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
WindowState::Get(wallpaper_picker_window.get())->Activate();
// Set a Google Photos wallpaper for the user and enable preview. Verify that
// the wallpaper is a Google Photos image if the feature is enabled.
const WallpaperLayout layout = WALLPAPER_LAYOUT_STRETCH;
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
ClearWallpaperCount();
std::string photo_id = "foobar";
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, photo_id, /*daily_refresh_enabled=*/false, layout,
/*preview_mode=*/true, "dedup_key"},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnceGooglePhotos);
// Verify that the user wallpaper info remains unchanged during the preview.
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(user_wallpaper_info.MatchesSelection(default_wallpaper_info));
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Preview.Show", 1);
// Now set a custom wallpaper for the user and disable preview (this happens
// if a custom wallpaper set on another device is being synced). Verify
// there's no wallpaper change since preview mode shouldn't be interrupted.
gfx::ImageSkia synced_custom_wallpaper =
CreateImage(640, 480, kWallpaperColor);
ClearWallpaperCount();
controller_->SetDecodedCustomWallpaper(
kAccountId1, kFileName1, layout,
/*preview_mode=*/false, base::DoNothing(),
/*file_path=*/"", synced_custom_wallpaper);
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 0);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnceGooglePhotos);
// However, the user wallpaper info should already be updated to the new
// info.
WallpaperInfo synced_custom_wallpaper_info(
base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(synced_custom_wallpaper_info));
// Now cancel the preview. Verify the synced custom wallpaper is shown
// instead of the initial default wallpaper, and the user wallpaper info is
// still correct.
ClearWallpaperCount();
controller_->CancelPreviewWallpaper();
RunAllTasksUntilIdle();
EXPECT_EQ(GetWallpaperCount(), 1);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kCustomized);
EXPECT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &user_wallpaper_info));
EXPECT_TRUE(
user_wallpaper_info.MatchesSelection(synced_custom_wallpaper_info));
}
TEST_P(WallpaperControllerTest, UpdateGooglePhotosDailyRefreshWallpaper) {
// The `TestWallpaperControllerClient` sends back the reversed
// `collection_id` when asked to fetch a daily photo.
std::string expected_photo_id = kFakeGooglePhotosAlbumId;
std::reverse(expected_photo_id.begin(), expected_photo_id.end());
SimulateUserLogin(kAccountId1);
GooglePhotosWallpaperParams params(
kAccountId1, kFakeGooglePhotosAlbumId,
/*daily_refresh_enabled=*/true, WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*dedup_key=*/std::nullopt);
WallpaperInfo info(params);
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
controller_->UpdateDailyRefreshWallpaper();
RunAllTasksUntilIdle();
WallpaperInfo expected_info;
EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &expected_info));
EXPECT_EQ(expected_photo_id, expected_info.location);
EXPECT_EQ(kFakeGooglePhotosAlbumId, expected_info.collection_id);
}
TEST_P(WallpaperControllerTest, EmptyDailyGooglePhotosAlbumsDoNothing) {
SimulateUserLogin(kAccountId1);
GooglePhotosWallpaperParams daily_google_photos_params(
kAccountId1, kFakeGooglePhotosAlbumId, /*daily_refresh_enabled=*/true,
WALLPAPER_LAYOUT_CENTER_CROPPED, /*preview_mode=*/false,
/*dedup_key=*/std::nullopt);
OnlineWallpaperParams online_params(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*from_user=*/true,
/*daily_refresh_enabled=*/false, kUnitId,
/*variants=*/
{{kAssetId, GURL(kDummyUrl), backdrop::Image::IMAGE_TYPE_UNKNOWN}});
WallpaperInfo online_info(online_params, online_params.variants.front());
pref_manager_->SetUserWallpaperInfo(kAccountId1, online_info);
client_.set_fetch_google_photos_photo_fails(true);
controller_->SetGooglePhotosWallpaper(daily_google_photos_params,
base::DoNothing());
RunAllTasksUntilIdle();
WallpaperInfo current_info;
pref_manager_->GetUserWallpaperInfo(kAccountId1, ¤t_info);
EXPECT_TRUE(online_info.MatchesSelection(current_info));
}
TEST_P(WallpaperControllerTest,
ResetToDefaultForDeletedDailyGooglePhotosAlbums) {
SimulateUserLogin(kAccountId1);
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, kFakeGooglePhotosAlbumId, /*daily_refresh_enabled=*/true,
WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*dedup_key=*/std::nullopt},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
WallpaperInfo current_info;
pref_manager_->GetUserWallpaperInfo(kAccountId1, ¤t_info);
EXPECT_EQ(WallpaperType::kDailyGooglePhotos, current_info.type);
// This makes the test fetch in `client_` return a null photo, but a
// successful call, which is the sign for a deleted or empty album.
client_.set_google_photo_has_been_deleted(true);
controller_->UpdateDailyRefreshWallpaper();
RunAllTasksUntilIdle();
pref_manager_->GetUserWallpaperInfo(kAccountId1, ¤t_info);
EXPECT_EQ(WallpaperType::kDefault, current_info.type);
}
TEST_P(WallpaperControllerTest, DailyGooglePhotosAreCached) {
SimulateUserLogin(kAccountId1);
// The `TestWallpaperControllerClient` sends back the reversed
// `collection_id` when asked to fetch a daily photo.
std::string expected_photo_id = kFakeGooglePhotosAlbumId;
std::reverse(expected_photo_id.begin(), expected_photo_id.end());
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, kFakeGooglePhotosAlbumId, /*daily_refresh_enabled=*/true,
WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*dedup_key=*/std::nullopt},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
base::FilePath saved_wallpaper = online_wallpaper_dir_.GetPath()
.Append("google_photos/")
.Append(kAccountId1.GetAccountIdKey())
.Append(expected_photo_id);
ASSERT_TRUE(base::PathExists(saved_wallpaper));
}
TEST_P(WallpaperControllerTest,
ResetToDefaultForDisabledGooglePhotosIntegrationPolicyOnStalenessCheck) {
SimulateUserLogin(kAccountId1);
WallpaperInfo info = {kFakeGooglePhotosPhotoId, WALLPAPER_LAYOUT_CENTER,
WallpaperType::kOnceGooglePhotos,
DayBeforeYesterdayish()};
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
client_.set_wallpaper_google_photos_integration_enabled_for_account_id(
kAccountId1, false);
// Trigger Google Photos wallpaper cache check.
controller_->OnActiveUserSessionChanged(kAccountId1);
WaitForWallpaperCount(1);
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
}
TEST_P(
WallpaperControllerTest,
ResetToDefaultForDisabledGooglePhotosIntegrationPolicyDailyGooglePhotosAlbums) {
SimulateUserLogin(kAccountId1);
base::test::TestFuture<bool> google_photos_future;
controller_->SetGooglePhotosWallpaper(
{kAccountId1, kFakeGooglePhotosAlbumId, /*daily_refresh_enabled=*/true,
WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED,
/*preview_mode=*/false, /*dedup_key=*/std::nullopt},
google_photos_future.GetCallback());
EXPECT_TRUE(google_photos_future.Get());
RunAllTasksUntilIdle();
WallpaperInfo current_info;
pref_manager_->GetUserWallpaperInfo(kAccountId1, ¤t_info);
EXPECT_EQ(WallpaperType::kDailyGooglePhotos, current_info.type);
// This makes the test fetch in `client_` return a null photo, but a
// successful call, which is the sign for the
// WallpaperGooglePhotosIntegrationEnabled policy disabled, or a deleted or
// empty album.
client_.set_wallpaper_google_photos_integration_enabled_for_account_id(
kAccountId1, false);
controller_->UpdateDailyRefreshWallpaper();
RunAllTasksUntilIdle();
pref_manager_->GetUserWallpaperInfo(kAccountId1, ¤t_info);
EXPECT_EQ(WallpaperType::kDefault, current_info.type);
}
class WallpaperControllerDailyRefreshSchedulerTest
: public WallpaperControllerTest,
public ScheduledFeature::Clock {
public:
WallpaperControllerDailyRefreshSchedulerTest() {
base::Time start_time = base::Time::Now();
clock_.SetNow(start_time);
tick_clock_.SetNowTicks(base::TimeTicks() + (start_time - base::Time()));
}
void SetUp() override {
WallpaperControllerTest::SetUp();
auto daily_refresh_scheduler =
controller_->daily_refresh_scheduler_for_testing();
// Disable any running timers to set a fake clock.
daily_refresh_scheduler->SetScheduleType(ScheduleType::kNone);
daily_refresh_scheduler->SetClockForTesting(this);
daily_refresh_scheduler->SetScheduleType(ScheduleType::kCustom);
}
void TearDown() override { WallpaperControllerTest::TearDown(); }
// ScheduledFeature::Clock:
base::Time Now() const override { return clock_.Now(); }
base::TimeTicks NowTicks() const override { return tick_clock_.NowTicks(); }
// Returns whether the total triggered a checkpoint change. This method only
// triggers the checkpoints and does not run any tasks.
bool AdvanceClock(base::TimeDelta total) {
const auto advance_time = [this](base::TimeDelta advancement) {
clock_.Advance(advancement);
tick_clock_.Advance(advancement);
};
bool checkpoint_reached = false;
auto* timer = Shell::Get()
->wallpaper_controller()
->daily_refresh_scheduler_for_testing()
->timer();
while (total.is_positive()) {
base::TimeDelta advance_increment;
if (timer->IsRunning() &&
timer->desired_run_time() <= NowTicks() + total) {
// Emulates the internal timer firing at its scheduled time.
advance_increment = timer->desired_run_time() - NowTicks();
advance_time(advance_increment);
timer->FireNow();
checkpoint_reached = true;
} else {
advance_increment = total;
advance_time(advance_increment);
}
CHECK_LE(advance_increment, total);
total -= advance_increment;
}
return checkpoint_reached;
}
private:
base::SimpleTestClock clock_;
base::SimpleTestTickClock tick_clock_;
};
INSTANTIATE_TEST_SUITE_P(
// Empty to simplify gtest output
,
WallpaperControllerDailyRefreshSchedulerTest,
::testing::Values(TimeOfDayFeatureCombination::kDisabled,
TimeOfDayFeatureCombination::kTimeOfDay),
WallpaperControllerTest::PrintToStringParamName());
TEST_P(WallpaperControllerDailyRefreshSchedulerTest,
OnCheckpointChanged_WallpaperDailyRefreshScheduler) {
TestWallpaperControllerObserver observer(controller_);
EXPECT_EQ(0, observer.daily_refresh_checkpoint_count());
// User's wallpaper info should exist.
pref_manager_->SetUserWallpaperInfo(kAccountId1,
InfoWithType(WallpaperType::kDefault));
SimulateUserLogin(kAccountId1);
// Clears signal on login.
observer.ClearDailyRefreshCheckpointCount();
EXPECT_TRUE(AdvanceClock(base::Days(1)));
// Expect that 2 signals are sent every day by WallpaperDailyRefreshScheduler.
EXPECT_EQ(2, observer.daily_refresh_checkpoint_count());
}
TEST_P(WallpaperControllerDailyRefreshSchedulerTest,
OnCheckpointChanged_CalledOnLogin) {
TestWallpaperControllerObserver observer(controller_);
EXPECT_EQ(0, observer.daily_refresh_checkpoint_count());
// User's wallpaper info should exist.
pref_manager_->SetUserWallpaperInfo(kAccountId1,
InfoWithType(WallpaperType::kDaily));
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
// Expect that at least one signal is sent on login. Other checkpoints may be
// due to the randomized start and end check times of the daily refresh
// scheduler.
EXPECT_GE(observer.daily_refresh_checkpoint_count(), 1);
}
TEST_P(WallpaperControllerDailyRefreshSchedulerTest,
SetDailyRefreshCollectionId_UpdatesCheckTimes) {
auto daily_refresh_scheduler =
controller_->daily_refresh_scheduler_for_testing();
auto first_check_time = daily_refresh_scheduler->GetCustomStartTime();
auto second_check_time = daily_refresh_scheduler->GetCustomEndTime();
// User's wallpaper info should exist.
pref_manager_->SetUserWallpaperInfo(kAccountId1,
InfoWithType(WallpaperType::kOnline));
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->SetDailyRefreshCollectionId(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId);
controller_->UpdateDailyRefreshWallpaper();
WaitForWallpaperCount(1);
EXPECT_EQ(TestWallpaperControllerClient::kDummyCollectionId,
client_.get_fetch_daily_refresh_wallpaper_param());
WallpaperInfo expected;
ASSERT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &expected));
EXPECT_EQ(WallpaperType::kDaily, expected.type);
// Expect that scheduler check times are updated.
EXPECT_NE(first_check_time, daily_refresh_scheduler->GetCustomStartTime());
EXPECT_NE(second_check_time, daily_refresh_scheduler->GetCustomEndTime());
}
TEST_P(WallpaperControllerDailyRefreshSchedulerTest,
SetGooglePhotosDailyRefreshAlbumId_UpdatesCheckTimes) {
auto daily_refresh_scheduler =
controller_->daily_refresh_scheduler_for_testing();
auto first_check_time = daily_refresh_scheduler->GetCustomStartTime();
auto second_check_time = daily_refresh_scheduler->GetCustomEndTime();
// User's wallpaper info should exist.
pref_manager_->SetUserWallpaperInfo(kAccountId1,
InfoWithType(WallpaperType::kOnline));
SimulateUserLogin(kAccountId1);
ClearWallpaperCount();
controller_->SetGooglePhotosDailyRefreshAlbumId(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId);
controller_->UpdateDailyRefreshWallpaper();
WaitForWallpaperCount(1);
WallpaperInfo expected;
ASSERT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &expected));
EXPECT_EQ(WallpaperType::kDailyGooglePhotos, expected.type);
// Expect that scheduler check times are updated.
EXPECT_NE(first_check_time, daily_refresh_scheduler->GetCustomStartTime());
EXPECT_NE(second_check_time, daily_refresh_scheduler->GetCustomEndTime());
}
TEST_P(WallpaperControllerDailyRefreshSchedulerTest,
UpdateDailyRefreshWallpaper_OnLogin) {
SimulateUserLogin(kAccountId1);
OnlineWallpaperVariant variant(kAssetId, GURL(kDummyUrl),
backdrop::Image::IMAGE_TYPE_UNKNOWN);
WallpaperInfo info = WallpaperInfo(
OnlineWallpaperParams(
kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
WALLPAPER_LAYOUT_CENTER_CROPPED, /*preview_mode=*/false,
/*from_user=*/false,
/*daily_refresh_enabled=*/true, kUnitId,
/*variants=*/{variant}),
variant);
info.date = DayBeforeYesterdayish();
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
ClearLogin();
SimulateUserLogin(kAccountId1);
// Info is set as over a day old so we expect one task to run in under an hour
// (due to fuzzing) then it will idle.
AdvanceClock(base::Hours(1));
// Make sure all the tasks such as syncing, setting wallpaper complete.
RunAllTasksUntilIdle();
EXPECT_EQ(TestWallpaperControllerClient::kDummyCollectionId,
client_.get_fetch_daily_refresh_wallpaper_param());
}
TEST_P(WallpaperControllerDailyRefreshSchedulerTest,
UpdateDailyRefreshWallpaper_OnCheckpointChanged) {
auto images = ImageSet();
std::string collection_id{"my_wallpaper_collection"};
client_.AddCollection(collection_id, images);
// User's wallpaper info should exist.
pref_manager_->SetUserWallpaperInfo(kAccountId1,
InfoWithType(WallpaperType::kDaily));
SimulateUserLogin(kAccountId1);
base::RunLoop run_loop;
ClearWallpaperCount();
controller_->SetDailyRefreshCollectionId(kAccountId1, collection_id);
controller_->UpdateDailyRefreshWallpaper(
base::BindLambdaForTesting([quit = run_loop.QuitClosure()](bool success) {
EXPECT_TRUE(success);
std::move(quit).Run();
}));
run_loop.Run();
EXPECT_EQ(1, GetWallpaperCount());
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDaily);
WallpaperInfo wallpaper_info_1;
ASSERT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info_1));
EXPECT_EQ(collection_id, wallpaper_info_1.collection_id);
EXPECT_EQ(WallpaperType::kDaily, wallpaper_info_1.type);
// Forward time to trigger checkpoints.
EXPECT_TRUE(AdvanceClock(base::Hours(25)));
RunAllTasksUntilIdle();
WallpaperInfo wallpaper_info_2;
ASSERT_TRUE(
pref_manager_->GetUserWallpaperInfo(kAccountId1, &wallpaper_info_2));
// Expect a new daily wallpaper is set.
EXPECT_FALSE(wallpaper_info_1.MatchesSelection(wallpaper_info_2));
EXPECT_EQ(collection_id, wallpaper_info_2.collection_id);
EXPECT_EQ(WallpaperType::kDaily, wallpaper_info_2.type);
}
TEST_P(WallpaperControllerDailyRefreshSchedulerTest,
CheckGooglePhotosStaleness_OnCheckpointChanged) {
SimulateUserLogin(kAccountId1);
WallpaperInfo info = {kFakeGooglePhotosPhotoId, WALLPAPER_LAYOUT_CENTER,
WallpaperType::kOnceGooglePhotos,
DayBeforeYesterdayish()};
pref_manager_->SetUserWallpaperInfo(kAccountId1, info);
client_.set_google_photo_has_been_deleted(true);
// Forward time to trigger checkpoints.
EXPECT_TRUE(AdvanceClock(base::Hours(25)));
RunAllTasksUntilIdle();
EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
}
class WallpaperControllerVersionedWallpaperInfoTest
: public WallpaperControllerTestBase {
public:
WallpaperControllerVersionedWallpaperInfoTest() {
scoped_feature_list_.InitWithFeatures(
{features::kVersionedWallpaperInfo,
features::kFeatureManagementTimeOfDayWallpaper},
{});
}
~WallpaperControllerVersionedWallpaperInfoTest() override = default;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
RecordNotSupportedNoLocationMigrationStatus) {
WallpaperInfo unmigrated_info = {"", WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
unmigrated_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
histogram_tester().ExpectBucketCount("Ash.Wallpaper.Online.MigrationStatus",
MigrationStatus::kNotSupportedNoLocation,
1);
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Online.MigrationLatency",
1);
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
RecordNotSupportedNoCollectionMigrationStatus) {
WallpaperInfo unmigrated_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
histogram_tester().ExpectBucketCount(
"Ash.Wallpaper.Online.MigrationStatus",
MigrationStatus::kNotSupportedNoCollection, 1);
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Online.MigrationLatency",
1);
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
OnlineWallpaperMigratedSuccessfullyOnLogin) {
WallpaperInfo unmigrated_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
unmigrated_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo migrated_info;
ASSERT_TRUE(
pref_manager_->GetLocalWallpaperInfo(kAccountId1, &migrated_info));
EXPECT_TRUE(migrated_info.version.IsValid());
EXPECT_TRUE(migrated_info.unit_id.has_value());
EXPECT_FALSE(migrated_info.variants.empty());
histogram_tester().ExpectBucketCount("Ash.Wallpaper.Online.MigrationStatus",
MigrationStatus::kSucceeded, 1);
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Online.MigrationLatency",
1);
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
GooglePhotosWallpaperMigratedSuccessfullyOnLogin) {
WallpaperInfo unmigrated_info =
InfoWithType(WallpaperType::kOnceGooglePhotos);
unmigrated_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo migrated_info;
ASSERT_TRUE(
pref_manager_->GetLocalWallpaperInfo(kAccountId1, &migrated_info));
EXPECT_TRUE(migrated_info.version.IsValid());
EXPECT_EQ(migrated_info.type, WallpaperType::kOnceGooglePhotos);
histogram_tester().ExpectBucketCount(
"Ash.Wallpaper.OnceGooglePhotos.MigrationStatus",
MigrationStatus::kSucceeded, 1);
histogram_tester().ExpectTotalCount(
"Ash.Wallpaper.OnceGooglePhotos.MigrationLatency", 1);
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
MigratedLocalWallpaperSyncOutSuccessfully) {
WallpaperInfo unmigrated_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
unmigrated_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo synced_info;
WallpaperInfo local_info;
ASSERT_TRUE(pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &synced_info));
ASSERT_TRUE(pref_manager_->GetLocalWallpaperInfo(kAccountId1, &local_info));
EXPECT_TRUE(synced_info.version.IsValid());
EXPECT_TRUE(synced_info.unit_id.has_value());
EXPECT_FALSE(synced_info.variants.empty());
EXPECT_TRUE(local_info.MatchesAsset(synced_info));
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
LocalWallpaperOverwrittenBySyncedInfoSuccessfully) {
WallpaperInfo unmigrated_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Min()};
unmigrated_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
WallpaperInfo synced_info = InfoWithType(WallpaperType::kOnceGooglePhotos);
pref_manager_->SetSyncedWallpaperInfo(kAccountId1, synced_info);
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo local_info;
ASSERT_TRUE(pref_manager_->GetLocalWallpaperInfo(kAccountId1, &local_info));
EXPECT_TRUE(local_info.version.IsValid());
EXPECT_TRUE(local_info.MatchesAsset(synced_info));
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
UnsuccessfullyMigratedWallpaperDoesNotSyncOut) {
WallpaperInfo unmigrated_info = {"https://expected_to_fail_url",
WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Min()};
unmigrated_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo synced_info;
EXPECT_FALSE(
pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &synced_info));
histogram_tester().ExpectUniqueSample("Ash.Wallpaper.Online.MigrationStatus",
MigrationStatus::kFailed, 1);
histogram_tester().ExpectBucketCount(
"Ash.Wallpaper.MigrationFailureReason",
MigrationFailureReason::kOnlineVariantsFetchFailure, 1);
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
SyncedInOnlineWallpaperMigratedSuccessfully) {
{
WallpaperInfo unmigrated_local_info =
InfoWithType(WallpaperType::kOnceGooglePhotos);
unmigrated_local_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(local_state(),
prefs::kUserWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(),
unmigrated_local_info.ToDict());
}
{
WallpaperInfo unmigrated_synced_info = {
kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kOnline,
base::Time::Now()};
unmigrated_synced_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_synced_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(
GetProfilePrefService(kAccountId1),
prefs::kSyncableVersionedWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(),
unmigrated_synced_info.ToDict());
}
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo migrated_info;
ASSERT_TRUE(
pref_manager_->GetLocalWallpaperInfo(kAccountId1, &migrated_info));
EXPECT_TRUE(migrated_info.version.IsValid());
EXPECT_TRUE(migrated_info.unit_id.has_value());
EXPECT_FALSE(migrated_info.variants.empty());
histogram_tester().ExpectBucketCount("Ash.Wallpaper.Online.MigrationStatus",
MigrationStatus::kSucceeded, 1);
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Online.MigrationLatency",
1);
histogram_tester().ExpectBucketCount(
"Ash.Wallpaper.OnceGooglePhotos.MigrationStatus",
MigrationStatus::kSucceeded, 1);
histogram_tester().ExpectTotalCount(
"Ash.Wallpaper.OnceGooglePhotos.MigrationLatency", 1);
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
ShouldNotSyncInForUnsuccessfullyMigratedWallpaper) {
WallpaperInfo unmigrated_info = {"https://expected_to_fail",
WALLPAPER_LAYOUT_CENTER_CROPPED,
WallpaperType::kOnline, base::Time::Now()};
unmigrated_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
unmigrated_info.version = base::Version();
ScopedDictPrefUpdate wallpaper_update(GetProfilePrefService(kAccountId1),
prefs::kSyncableVersionedWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), unmigrated_info.ToDict());
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo migrated_info;
EXPECT_FALSE(
pref_manager_->GetLocalWallpaperInfo(kAccountId1, &migrated_info));
histogram_tester().ExpectBucketCount("Ash.Wallpaper.Online.MigrationStatus",
MigrationStatus::kFailed, 1);
histogram_tester().ExpectTotalCount("Ash.Wallpaper.Online.MigrationLatency",
1);
}
TEST_F(WallpaperControllerVersionedWallpaperInfoTest,
ShowPreviouslySyncedWallpaperWhenUserLogsInANewDevice) {
WallpaperInfo prev_synced_info;
prev_synced_info.location = kDummyUrl;
prev_synced_info.layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
prev_synced_info.type = WallpaperType::kOnline;
prev_synced_info.collection_id =
TestWallpaperControllerClient::kDummyCollectionId;
prev_synced_info.date = base::Time::Now();
ScopedDictPrefUpdate wallpaper_update(GetProfilePrefService(kAccountId1),
prefs::kSyncableWallpaperInfo);
wallpaper_update->Set(kAccountId1.GetUserEmail(), prev_synced_info.ToDict());
ASSERT_TRUE(pref_manager_->GetSyncedWallpaperInfoFromDeprecatedPref(
kAccountId1, &prev_synced_info));
SimulateUserLogin(kAccountId1);
RunAllTasksUntilIdle();
WallpaperInfo local_info;
WallpaperInfo synced_info;
EXPECT_TRUE(pref_manager_->GetLocalWallpaperInfo(kAccountId1, &local_info));
EXPECT_TRUE(pref_manager_->GetSyncedWallpaperInfo(kAccountId1, &synced_info));
EXPECT_TRUE(local_info.MatchesAsset(synced_info));
EXPECT_TRUE(local_info.version.IsValid());
EXPECT_FALSE(local_info.variants.empty());
EXPECT_TRUE(local_info.unit_id.has_value());
// Expects deprecated pref to be cleared.
EXPECT_FALSE(pref_manager_->GetSyncedWallpaperInfoFromDeprecatedPref(
kAccountId1, &synced_info));
}
} // namespace ash