diff options
-rw-r--r-- | ash/ash_switches.cc | 11 | ||||
-rw-r--r-- | ash/ash_switches.h | 4 | ||||
-rw-r--r-- | ash/desktop_background/desktop_background_controller.cc | 217 | ||||
-rw-r--r-- | ash/desktop_background/desktop_background_controller.h | 69 | ||||
-rw-r--r-- | ash/desktop_background/desktop_background_controller_unittest.cc | 339 | ||||
-rw-r--r-- | ash/desktop_background/wallpaper_resizer.cc | 122 | ||||
-rw-r--r-- | ash/desktop_background/wallpaper_resizer.h | 30 | ||||
-rw-r--r-- | ash/desktop_background/wallpaper_resizer_unittest.cc | 46 | ||||
-rw-r--r-- | ash/display/display_manager.cc | 2 | ||||
-rw-r--r-- | ash/shell/content_client/shell_browser_main_parts.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/chrome_restart_request.cc | 9 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/wallpaper_manager.cc | 21 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc | 107 |
13 files changed, 662 insertions, 323 deletions
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc index 7f9b99b..2e67ee5 100644 --- a/ash/ash_switches.cc +++ b/ash/ash_switches.cc @@ -29,6 +29,17 @@ const char kAshCopyHostBackgroundAtBoot[] = "ash-copy-host-background-at-boot"; // Enable keyboard shortcuts useful for debugging. const char kAshDebugShortcuts[] = "ash-debug-shortcuts"; +// Default wallpaper to use in guest mode (as paths to trusted, +// non-user-writable JPEG files). +const char kAshDefaultGuestWallpaperLarge[] = + "ash-default-guest-wallpaper-large"; +const char kAshDefaultGuestWallpaperSmall[] = + "ash-default-guest-wallpaper-small"; + +// Default wallpaper to use (as paths to trusted, non-user-writable JPEG files). +const char kAshDefaultWallpaperLarge[] = "ash-default-wallpaper-large"; +const char kAshDefaultWallpaperSmall[] = "ash-default-wallpaper-small"; + // Disable auto window maximization logic. const char kAshDisableAutoMaximizing[] = "ash-disable-auto-maximizing"; diff --git a/ash/ash_switches.h b/ash/ash_switches.h index f94a01f..23eacfc 100644 --- a/ash/ash_switches.h +++ b/ash/ash_switches.h @@ -21,6 +21,10 @@ ASH_EXPORT extern const char kAshAnimateFromBootSplashScreen[]; ASH_EXPORT extern const char kAshConstrainPointerToRoot[]; ASH_EXPORT extern const char kAshCopyHostBackgroundAtBoot[]; ASH_EXPORT extern const char kAshDebugShortcuts[]; +ASH_EXPORT extern const char kAshDefaultGuestWallpaperLarge[]; +ASH_EXPORT extern const char kAshDefaultGuestWallpaperSmall[]; +ASH_EXPORT extern const char kAshDefaultWallpaperLarge[]; +ASH_EXPORT extern const char kAshDefaultWallpaperSmall[]; ASH_EXPORT extern const char kAshDisableAutoMaximizing[]; ASH_EXPORT extern const char kAshDisableAutoWindowPlacement[]; ASH_EXPORT extern const char kAshDisableDisplayChangeLimiter[]; diff --git a/ash/desktop_background/desktop_background_controller.cc b/ash/desktop_background/desktop_background_controller.cc index 83ffe46..a4f367b 100644 --- a/ash/desktop_background/desktop_background_controller.cc +++ b/ash/desktop_background/desktop_background_controller.cc @@ -4,6 +4,7 @@ #include "ash/desktop_background/desktop_background_controller.h" +#include "ash/ash_switches.h" #include "ash/desktop_background/desktop_background_controller_observer.h" #include "ash/desktop_background/desktop_background_view.h" #include "ash/desktop_background/desktop_background_widget_controller.h" @@ -15,6 +16,8 @@ #include "ash/shell_window_ids.h" #include "ash/wm/root_window_layout_manager.h" #include "base/bind.h" +#include "base/command_line.h" +#include "base/file_util.h" #include "base/logging.h" #include "base/synchronization/cancellation_flag.h" #include "base/threading/worker_pool.h" @@ -23,8 +26,9 @@ #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" +#include "ui/gfx/codec/jpeg_codec.h" +#include "ui/gfx/image/image_skia.h" #include "ui/gfx/rect.h" -#include "ui/gfx/image/image.h" #include "ui/views/widget/widget.h" using ash::internal::DesktopBackgroundWidgetController; @@ -61,24 +65,6 @@ gfx::Size GetRootWindowsSize() { } // namespace -#if defined(GOOGLE_CHROME_BUILD) -const WallpaperInfo kDefaultLargeWallpaper = - { IDR_AURA_WALLPAPERS_2_LANDSCAPE8_LARGE, WALLPAPER_LAYOUT_CENTER_CROPPED }; -const WallpaperInfo kDefaultSmallWallpaper = - { IDR_AURA_WALLPAPERS_2_LANDSCAPE8_SMALL, WALLPAPER_LAYOUT_CENTER }; -const WallpaperInfo kGuestLargeWallpaper = - { IDR_AURA_WALLPAPERS_2_LANDSCAPE7_LARGE, WALLPAPER_LAYOUT_CENTER_CROPPED }; -const WallpaperInfo kGuestSmallWallpaper = - { IDR_AURA_WALLPAPERS_2_LANDSCAPE7_SMALL, WALLPAPER_LAYOUT_CENTER }; -#else -const WallpaperInfo kDefaultLargeWallpaper = - { IDR_AURA_WALLPAPERS_5_GRADIENT5_LARGE, WALLPAPER_LAYOUT_TILE }; -const WallpaperInfo kDefaultSmallWallpaper = - { IDR_AURA_WALLPAPERS_5_GRADIENT5_SMALL, WALLPAPER_LAYOUT_TILE }; -const WallpaperInfo kGuestLargeWallpaper = kDefaultLargeWallpaper; -const WallpaperInfo kGuestSmallWallpaper = kDefaultSmallWallpaper; -#endif - const int kSmallWallpaperMaxWidth = 1366; const int kSmallWallpaperMaxHeight = 800; const int kLargeWallpaperMaxWidth = 2560; @@ -92,23 +78,30 @@ class DesktopBackgroundController::WallpaperLoader : public base::RefCountedThreadSafe< DesktopBackgroundController::WallpaperLoader> { public: - explicit WallpaperLoader(const WallpaperInfo& info) - : info_(info) { + // If set, |file_path| must be a trusted (i.e. read-only, + // non-user-controlled) file containing a JPEG image. + WallpaperLoader(const base::FilePath& file_path, + WallpaperLayout file_layout, + int resource_id, + WallpaperLayout resource_layout) + : file_path_(file_path), + file_layout_(file_layout), + resource_id_(resource_id), + resource_layout_(resource_layout) { } - static void LoadOnWorkerPoolThread(scoped_refptr<WallpaperLoader> wl) { + static void LoadOnWorkerPoolThread(scoped_refptr<WallpaperLoader> loader) { DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); - wl->LoadingWallpaper(); + loader->LoadWallpaper(); } + const base::FilePath& file_path() const { return file_path_; } + int resource_id() const { return resource_id_; } + void Cancel() { cancel_flag_.Set(); } - int idr() const { - return info_.idr; - } - WallpaperResizer* ReleaseWallpaperResizer() { return wallpaper_resizer_.release(); } @@ -117,27 +110,74 @@ class DesktopBackgroundController::WallpaperLoader friend class base::RefCountedThreadSafe< DesktopBackgroundController::WallpaperLoader>; - void LoadingWallpaper() { + // Loads a JPEG image from |path|, a trusted file -- note that the image + // is not loaded in a sandboxed process. Returns an empty pointer on + // error. + static scoped_ptr<SkBitmap> LoadSkBitmapFromJPEGFile( + const base::FilePath& path) { + std::string data; + if (!file_util::ReadFileToString(path, &data)) { + LOG(ERROR) << "Unable to read data from " << path.value(); + return scoped_ptr<SkBitmap>(); + } + + scoped_ptr<SkBitmap> bitmap(gfx::JPEGCodec::Decode( + reinterpret_cast<const unsigned char*>(data.data()), data.size())); + if (!bitmap) + LOG(ERROR) << "Unable to decode JPEG data from " << path.value(); + return bitmap.Pass(); + } + + void LoadWallpaper() { if (cancel_flag_.IsSet()) return; - wallpaper_resizer_.reset(new WallpaperResizer(info_, GetRootWindowsSize())); + + if (!file_path_.empty()) + file_bitmap_ = LoadSkBitmapFromJPEGFile(file_path_); + + if (cancel_flag_.IsSet()) + return; + + if (file_bitmap_) { + gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(*file_bitmap_); + wallpaper_resizer_.reset(new WallpaperResizer( + image, GetRootWindowsSize(), file_layout_)); + } else { + wallpaper_resizer_.reset(new WallpaperResizer( + resource_id_, GetRootWindowsSize(), resource_layout_)); + } } ~WallpaperLoader() {} base::CancellationFlag cancel_flag_; + // Bitmap loaded from |file_path_|. + scoped_ptr<SkBitmap> file_bitmap_; + scoped_ptr<WallpaperResizer> wallpaper_resizer_; - const WallpaperInfo info_; + // Path to a trusted JPEG file. + base::FilePath file_path_; + + // Layout to be used when displaying the image from |file_path_|. + WallpaperLayout file_layout_; + + // ID of an image resource to use if |file_path_| is empty or unloadable. + int resource_id_; + + // Layout to be used when displaying |resource_id_|. + WallpaperLayout resource_layout_; DISALLOW_COPY_AND_ASSIGN(WallpaperLoader); }; DesktopBackgroundController::DesktopBackgroundController() - : locked_(false), + : command_line_for_testing_(NULL), + locked_(false), desktop_background_mode_(BACKGROUND_NONE), background_color_(kTransparentColor), + current_default_wallpaper_resource_id_(-1), weak_ptr_factory_(this) { } @@ -163,25 +203,10 @@ void DesktopBackgroundController::RemoveObserver( WallpaperLayout DesktopBackgroundController::GetWallpaperLayout() const { if (current_wallpaper_) - return current_wallpaper_->wallpaper_info().layout; + return current_wallpaper_->layout(); return WALLPAPER_LAYOUT_CENTER_CROPPED; } -gfx::ImageSkia DesktopBackgroundController::GetCurrentWallpaperImage() { - if (desktop_background_mode_ != BACKGROUND_IMAGE) - return gfx::ImageSkia(); - return GetWallpaper(); -} - -int DesktopBackgroundController::GetWallpaperIDR() const { - if (wallpaper_loader_.get()) - return wallpaper_loader_->idr(); - else if (current_wallpaper_) - return current_wallpaper_->wallpaper_info().idr; - else - return -1; -} - void DesktopBackgroundController::OnRootWindowAdded( aura::RootWindow* root_window) { // The background hasn't been set yet. @@ -199,6 +224,8 @@ void DesktopBackgroundController::OnRootWindowAdded( if (width < root_window_size.width() || height < root_window_size.height()) { current_wallpaper_.reset(NULL); + current_default_wallpaper_path_ = base::FilePath(); + current_default_wallpaper_resource_id_ = -1; ash::Shell::GetInstance()->user_wallpaper_delegate()-> UpdateWallpaper(); } @@ -207,34 +234,71 @@ void DesktopBackgroundController::OnRootWindowAdded( InstallDesktopController(root_window); } -void DesktopBackgroundController::SetDefaultWallpaper( - const WallpaperInfo& info) { - DCHECK_NE(GetWallpaperIDR(), info.idr); +bool DesktopBackgroundController::SetDefaultWallpaper(bool is_guest) { + const bool use_large = + GetAppropriateResolution() == WALLPAPER_RESOLUTION_LARGE; + + base::FilePath file_path; + WallpaperLayout file_layout = use_large ? WALLPAPER_LAYOUT_CENTER_CROPPED : + WALLPAPER_LAYOUT_CENTER; + int resource_id = -1; + WallpaperLayout resource_layout = WALLPAPER_LAYOUT_TILE; + +#if defined(GOOGLE_CHROME_BUILD) + if (use_large) { + resource_id = is_guest ? IDR_AURA_WALLPAPERS_2_LANDSCAPE7_LARGE : + IDR_AURA_WALLPAPERS_2_LANDSCAPE8_LARGE; + resource_layout = WALLPAPER_LAYOUT_CENTER_CROPPED; + } else { + resource_id = is_guest ? IDR_AURA_WALLPAPERS_2_LANDSCAPE7_SMALL : + IDR_AURA_WALLPAPERS_2_LANDSCAPE8_SMALL; + resource_layout = WALLPAPER_LAYOUT_CENTER; + } +#else + resource_id = use_large ? IDR_AURA_WALLPAPERS_5_GRADIENT5_LARGE : + IDR_AURA_WALLPAPERS_5_GRADIENT5_SMALL; + resource_layout = WALLPAPER_LAYOUT_TILE; +#endif + + const char* switch_name = is_guest ? + (use_large ? switches::kAshDefaultGuestWallpaperLarge : + switches::kAshDefaultGuestWallpaperSmall) : + (use_large ? switches::kAshDefaultWallpaperLarge : + switches::kAshDefaultWallpaperSmall); + CommandLine* command_line = command_line_for_testing_ ? + command_line_for_testing_ : CommandLine::ForCurrentProcess(); + file_path = command_line->GetSwitchValuePath(switch_name); + + if (DefaultWallpaperIsAlreadyLoadingOrLoaded(file_path, resource_id)) + return false; CancelPendingWallpaperOperation(); - wallpaper_loader_ = new WallpaperLoader(info); + wallpaper_loader_ = new WallpaperLoader( + file_path, file_layout, resource_id, resource_layout); base::WorkerPool::PostTaskAndReply( FROM_HERE, base::Bind(&WallpaperLoader::LoadOnWorkerPoolThread, wallpaper_loader_), - base::Bind(&DesktopBackgroundController::OnWallpaperLoadCompleted, + base::Bind(&DesktopBackgroundController::OnDefaultWallpaperLoadCompleted, weak_ptr_factory_.GetWeakPtr(), wallpaper_loader_), true /* task_is_slow */); + return true; } void DesktopBackgroundController::SetCustomWallpaper( - const gfx::ImageSkia& wallpaper, + const gfx::ImageSkia& image, WallpaperLayout layout) { CancelPendingWallpaperOperation(); - if (current_wallpaper_.get() && - current_wallpaper_->wallpaper_image().BackedBySameObjectAs(wallpaper)) { + if (CustomWallpaperIsAlreadyLoaded(image)) return; - } - WallpaperInfo info = { -1, layout }; - current_wallpaper_.reset(new WallpaperResizer(info, GetRootWindowsSize(), - wallpaper)); + current_wallpaper_.reset(new WallpaperResizer( + image, GetRootWindowsSize(), layout)); current_wallpaper_->StartResize(); + + current_default_wallpaper_path_ = base::FilePath(); + current_default_wallpaper_resource_id_ = -1; + FOR_EACH_OBSERVER(DesktopBackgroundControllerObserver, observers_, OnWallpaperDataChanged()); SetDesktopBackgroundImageMode(); @@ -264,7 +328,6 @@ void DesktopBackgroundController::CreateEmptyWallpaper() { WallpaperResolution DesktopBackgroundController::GetAppropriateResolution() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - WallpaperResolution resolution = WALLPAPER_RESOLUTION_SMALL; Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); for (Shell::RootWindowList::iterator iter = root_windows.begin(); iter != root_windows.end(); ++iter) { @@ -274,11 +337,10 @@ WallpaperResolution DesktopBackgroundController::GetAppropriateResolution() { // scenario. Revisit and fix if necessary. gfx::Size host_window_size = (*iter)->GetHostSize(); if (host_window_size.width() > kSmallWallpaperMaxWidth || - host_window_size.height() > kSmallWallpaperMaxHeight) { - resolution = WALLPAPER_RESOLUTION_LARGE; - } + host_window_size.height() > kSmallWallpaperMaxHeight) + return WALLPAPER_RESOLUTION_LARGE; } - return resolution; + return WALLPAPER_RESOLUTION_SMALL; } bool DesktopBackgroundController::MoveDesktopToLockedContainer() { @@ -304,20 +366,39 @@ void DesktopBackgroundController::OnWindowDestroying(aura::Window* window) { static_cast<internal::AnimatingDesktopController*>(NULL)); } +bool DesktopBackgroundController::DefaultWallpaperIsAlreadyLoadingOrLoaded( + const base::FilePath& image_file, int image_resource_id) const { + return (wallpaper_loader_ && + wallpaper_loader_->file_path() == image_file && + wallpaper_loader_->resource_id() == image_resource_id) || + (current_wallpaper_.get() && + current_default_wallpaper_path_ == image_file && + current_default_wallpaper_resource_id_ == image_resource_id); +} + +bool DesktopBackgroundController::CustomWallpaperIsAlreadyLoaded( + const gfx::ImageSkia& image) const { + return current_wallpaper_.get() && + current_wallpaper_->wallpaper_image().BackedBySameObjectAs(image); +} + void DesktopBackgroundController::SetDesktopBackgroundImageMode() { desktop_background_mode_ = BACKGROUND_IMAGE; InstallDesktopControllerForAllWindows(); } -void DesktopBackgroundController::OnWallpaperLoadCompleted( - scoped_refptr<WallpaperLoader> wl) { - current_wallpaper_.reset(wl->ReleaseWallpaperResizer()); +void DesktopBackgroundController::OnDefaultWallpaperLoadCompleted( + scoped_refptr<WallpaperLoader> loader) { + current_wallpaper_.reset(loader->ReleaseWallpaperResizer()); + current_wallpaper_->StartResize(); + current_default_wallpaper_path_ = loader->file_path(); + current_default_wallpaper_resource_id_ = loader->resource_id(); FOR_EACH_OBSERVER(DesktopBackgroundControllerObserver, observers_, OnWallpaperDataChanged()); SetDesktopBackgroundImageMode(); - DCHECK(wl.get() == wallpaper_loader_.get()); + DCHECK(loader.get() == wallpaper_loader_.get()); wallpaper_loader_ = NULL; } diff --git a/ash/desktop_background/desktop_background_controller.h b/ash/desktop_background/desktop_background_controller.h index b877898..d89f3f7 100644 --- a/ash/desktop_background/desktop_background_controller.h +++ b/ash/desktop_background/desktop_background_controller.h @@ -7,6 +7,7 @@ #include "ash/ash_export.h" #include "base/basictypes.h" +#include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" @@ -17,6 +18,8 @@ typedef unsigned int SkColor; +class CommandLine; + namespace aura { class RootWindow; } @@ -27,9 +30,16 @@ class DesktopBackgroundControllerTest; } // namespace internal enum WallpaperLayout { + // Center the wallpaper on the desktop without scaling it. The wallpaper + // may be cropped. WALLPAPER_LAYOUT_CENTER, + // Scale the wallpaper (while preserving its aspect ratio) to cover the + // desktop; the wallpaper may be cropped. WALLPAPER_LAYOUT_CENTER_CROPPED, + // Scale the wallpaper (without preserving its aspect ratio) to match the + // desktop's size. WALLPAPER_LAYOUT_STRETCH, + // Tile the wallpaper over the background without scaling it. WALLPAPER_LAYOUT_TILE, }; @@ -40,17 +50,6 @@ enum WallpaperResolution { const SkColor kLoginWallpaperColor = 0xFEFEFE; -// Encapsulates wallpaper infomation needed by desktop background controller. -struct ASH_EXPORT WallpaperInfo { - int idr; - WallpaperLayout layout; -}; - -ASH_EXPORT extern const WallpaperInfo kDefaultLargeWallpaper; -ASH_EXPORT extern const WallpaperInfo kDefaultSmallWallpaper; -ASH_EXPORT extern const WallpaperInfo kGuestLargeWallpaper; -ASH_EXPORT extern const WallpaperInfo kGuestSmallWallpaper; - // The width and height of small/large resolution wallpaper. When screen size is // smaller than |kSmallWallpaperMaxWidth| and |kSmallWallpaperMaxHeight|, the // small resolution wallpaper should be used. Otherwise, uses the large @@ -80,38 +79,36 @@ class ASH_EXPORT DesktopBackgroundController : public aura::WindowObserver { DesktopBackgroundController(); virtual ~DesktopBackgroundController(); - // Gets the desktop background mode. BackgroundMode desktop_background_mode() const { return desktop_background_mode_; } + void set_command_line_for_testing(CommandLine* command_line) { + command_line_for_testing_ = command_line; + } + // Add/Remove observers. void AddObserver(DesktopBackgroundControllerObserver* observer); void RemoveObserver(DesktopBackgroundControllerObserver* observer); - gfx::ImageSkia GetWallpaper() const; - - WallpaperLayout GetWallpaperLayout() const; - // Provides current image on the background, or empty gfx::ImageSkia if there // is no image, e.g. background is solid color. - gfx::ImageSkia GetCurrentWallpaperImage(); + gfx::ImageSkia GetWallpaper() const; - // Gets the IDR of current wallpaper. Returns -1 if current wallpaper is not - // a builtin wallpaper. - int GetWallpaperIDR() const; + WallpaperLayout GetWallpaperLayout() const; // Initialize root window's background. void OnRootWindowAdded(aura::RootWindow* root_window); - // Loads builtin wallpaper asynchronously and sets to current wallpaper after - // loaded. - void SetDefaultWallpaper(const WallpaperInfo& info); + // Loads builtin wallpaper asynchronously and sets to current wallpaper + // after loaded. Returns true if the controller started loading the + // wallpaper and false otherwise (i.e. the appropriate wallpaper was + // already loading or loaded). + bool SetDefaultWallpaper(bool is_guest); // Sets the user selected custom wallpaper. Called when user selected a file // from file system or changed the layout of wallpaper. - void SetCustomWallpaper(const gfx::ImageSkia& wallpaper, - WallpaperLayout layout); + void SetCustomWallpaper(const gfx::ImageSkia& image, WallpaperLayout layout); // Cancels the current wallpaper loading operation. void CancelPendingWallpaperOperation(); @@ -148,13 +145,22 @@ class ASH_EXPORT DesktopBackgroundController : public aura::WindowObserver { // An operation to asynchronously loads wallpaper. class WallpaperLoader; + // Returns true if the specified default wallpaper is already being + // loaded by |wallpaper_loader_| or stored in |current_wallpaper_|. + bool DefaultWallpaperIsAlreadyLoadingOrLoaded( + const base::FilePath& image_file, int image_resource_id) const; + + // Returns true if the specified custom wallpaper is already stored + // in |current_wallpaper_|. + bool CustomWallpaperIsAlreadyLoaded(const gfx::ImageSkia& image) const; + // Creates view for all root windows, or notifies them to repaint if they // already exist. void SetDesktopBackgroundImageMode(); // Creates a new background widget and sets the background mode to image mode. - // Called after wallpaper loaded successfully. - void OnWallpaperLoadCompleted(scoped_refptr<WallpaperLoader> wl); + // Called after a default wallpaper has been loaded successfully. + void OnDefaultWallpaperLoadCompleted(scoped_refptr<WallpaperLoader> loader); // Adds layer with solid |color| to container |container_id| in |root_window|. ui::Layer* SetColorLayerForContainer(SkColor color, @@ -179,6 +185,9 @@ class ASH_EXPORT DesktopBackgroundController : public aura::WindowObserver { // Send notification that background animation finished. void NotifyAnimationFinished(); + // If non-NULL, used in place of the real command line. + CommandLine* command_line_for_testing_; + // Can change at runtime. bool locked_; @@ -191,6 +200,12 @@ class ASH_EXPORT DesktopBackgroundController : public aura::WindowObserver { // The current wallpaper. scoped_ptr<WallpaperResizer> current_wallpaper_; + // If a default wallpaper is stored in |current_wallpaper_|, the path and + // resource ID that were passed to WallpaperLoader when loading it. + // Otherwise, empty and -1, respectively. + base::FilePath current_default_wallpaper_path_; + int current_default_wallpaper_resource_id_; + scoped_refptr<WallpaperLoader> wallpaper_loader_; base::WeakPtrFactory<DesktopBackgroundController> weak_ptr_factory_; diff --git a/ash/desktop_background/desktop_background_controller_unittest.cc b/ash/desktop_background/desktop_background_controller_unittest.cc index d513a9c..be85341 100644 --- a/ash/desktop_background/desktop_background_controller_unittest.cc +++ b/ash/desktop_background/desktop_background_controller_unittest.cc @@ -4,17 +4,37 @@ #include "ash/desktop_background/desktop_background_controller.h" +#include <cmath> +#include <cstdlib> + +#include "ash/ash_switches.h" +#include "ash/desktop_background/desktop_background_controller_observer.h" #include "ash/desktop_background/desktop_background_widget_controller.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" +#include "ash/test/display_manager_test_api.h" +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/files/scoped_temp_dir.h" +#include "base/message_loop/message_loop.h" +#include "content/public/test/test_browser_thread.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/aura/root_window.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/test/layer_animator_test_controller.h" +#include "ui/gfx/codec/jpeg_codec.h" +#include "ui/gfx/point.h" +#include "ui/gfx/rect.h" using aura::RootWindow; using aura::Window; +namespace ash { +namespace internal { + namespace { // Containers IDs used for tests. @@ -30,6 +50,31 @@ int ChildCountForContainer(int container_id) { return static_cast<int>(container->children().size()); } +class TestObserver : public DesktopBackgroundControllerObserver { + public: + explicit TestObserver(DesktopBackgroundController* controller) + : controller_(controller) { + DCHECK(controller_); + controller_->AddObserver(this); + } + + virtual ~TestObserver() { + controller_->RemoveObserver(this); + } + + void WaitForWallpaperDataChanged() { + base::MessageLoop::current()->Run(); + } + + // DesktopBackgroundControllerObserver overrides: + virtual void OnWallpaperDataChanged() OVERRIDE { + base::MessageLoop::current()->Quit(); + } + + private: + DesktopBackgroundController* controller_; +}; + // Steps a widget's layer animation until it is completed. Animations must be // enabled. void RunAnimationForWidget(views::Widget* widget) { @@ -51,12 +96,13 @@ void RunAnimationForWidget(views::Widget* widget) { } // namespace -namespace ash { -namespace internal { - class DesktopBackgroundControllerTest : public test::AshTestBase { public: - DesktopBackgroundControllerTest() {} + DesktopBackgroundControllerTest() + : ui_thread_(content::BrowserThread::UI, base::MessageLoop::current()), + command_line_(CommandLine::NO_PROGRAM), + controller_(NULL) { + } virtual ~DesktopBackgroundControllerTest() {} virtual void SetUp() OVERRIDE { @@ -68,8 +114,152 @@ class DesktopBackgroundControllerTest : public test::AshTestBase { static_cast<DesktopBackgroundWidgetController*>(NULL)); root->SetProperty(kAnimatingDesktopController, static_cast<AnimatingDesktopController*>(NULL)); + + controller_ = Shell::GetInstance()->desktop_background_controller(); + } + + protected: + // Colors used for different default wallpapers by + // WriteWallpapersAndSetFlags(). + static const SkColor kLargeWallpaperColor = SK_ColorRED; + static const SkColor kSmallWallpaperColor = SK_ColorGREEN; + static const SkColor kLargeGuestWallpaperColor = SK_ColorBLUE; + static const SkColor kSmallGuestWallpaperColor = SK_ColorYELLOW; + + // Dimension used for width and height of default wallpaper images. A + // small value is used to minimize the amount of time spent compressing + // and writing images. + static const int kWallpaperSize = 2; + + // Runs kAnimatingDesktopController's animation to completion. + // TODO(bshe): Don't require tests to run animations; it's slow. + void RunDesktopControllerAnimation() { + RootWindow* root = Shell::GetPrimaryRootWindow(); + DesktopBackgroundWidgetController* controller = + root->GetProperty(kAnimatingDesktopController)->GetController(false); + ASSERT_NO_FATAL_FAILURE(RunAnimationForWidget(controller->widget())); } + // Returns true if the color at the center of |image| is close to + // |expected_color|. (The center is used so small wallpaper images can be + // used.) + bool ImageIsNearColor(gfx::ImageSkia image, SkColor expected_color) { + if (image.size().IsEmpty()) { + LOG(ERROR) << "Image is empty"; + return false; + } + + const SkBitmap* bitmap = image.bitmap(); + if (!bitmap) { + LOG(ERROR) << "Unable to get bitmap from image"; + return false; + } + + bitmap->lockPixels(); + gfx::Point center = gfx::Rect(image.size()).CenterPoint(); + SkColor image_color = bitmap->getColor(center.x(), center.y()); + bitmap->unlockPixels(); + + const int kDiff = 3; + if (std::abs(static_cast<int>(SkColorGetA(image_color)) - + static_cast<int>(SkColorGetA(expected_color))) > kDiff || + std::abs(static_cast<int>(SkColorGetR(image_color)) - + static_cast<int>(SkColorGetR(expected_color))) > kDiff || + std::abs(static_cast<int>(SkColorGetG(image_color)) - + static_cast<int>(SkColorGetG(expected_color))) > kDiff || + std::abs(static_cast<int>(SkColorGetB(image_color)) - + static_cast<int>(SkColorGetB(expected_color))) > kDiff) { + LOG(ERROR) << "Expected color near 0x" << std::hex << expected_color + << " but got 0x" << image_color; + return false; + } + + return true; + } + + // 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) { + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0); + bitmap.allocPixels(); + bitmap.eraseColor(color); + + const int kQuality = 80; + std::vector<unsigned char> output; + if (!gfx::JPEGCodec::Encode( + static_cast<const unsigned char*>(bitmap.getPixels()), + gfx::JPEGCodec::FORMAT_SkBitmap, width, height, bitmap.rowBytes(), + kQuality, &output)) { + LOG(ERROR) << "Unable to encode " << width << "x" << height << " bitmap"; + return false; + } + + size_t bytes_written = file_util::WriteFile( + path, reinterpret_cast<const char*>(&output[0]), output.size()); + if (bytes_written != output.size()) { + LOG(ERROR) << "Wrote " << bytes_written << " byte(s) instead of " + << output.size() << " to " << path.value(); + return false; + } + + return true; + } + + // Initializes |wallpaper_dir_|, writes JPEG wallpaper images to it, and + // passes |controller_| a command line instructing it to use the images. + // Only needs to be called (once) by tests that want to test loading of + // default wallpapers. + void WriteWallpapersAndSetFlags() { + wallpaper_dir_.reset(new base::ScopedTempDir); + ASSERT_TRUE(wallpaper_dir_->CreateUniqueTempDir()); + + const base::FilePath kLargePath = + wallpaper_dir_->path().Append(FILE_PATH_LITERAL("large.jpg")); + ASSERT_TRUE(WriteJPEGFile(kLargePath, kWallpaperSize, kWallpaperSize, + kLargeWallpaperColor)); + command_line_.AppendSwitchPath( + switches::kAshDefaultWallpaperLarge, kLargePath); + + const base::FilePath kSmallPath = + wallpaper_dir_->path().Append(FILE_PATH_LITERAL("small.jpg")); + ASSERT_TRUE(WriteJPEGFile(kSmallPath, kWallpaperSize, kWallpaperSize, + kSmallWallpaperColor)); + command_line_.AppendSwitchPath( + switches::kAshDefaultWallpaperSmall, kSmallPath); + + const base::FilePath kLargeGuestPath = + wallpaper_dir_->path().Append(FILE_PATH_LITERAL("guest_large.jpg")); + ASSERT_TRUE(WriteJPEGFile(kLargeGuestPath, kWallpaperSize, kWallpaperSize, + kLargeGuestWallpaperColor)); + command_line_.AppendSwitchPath( + switches::kAshDefaultGuestWallpaperLarge, kLargeGuestPath); + + const base::FilePath kSmallGuestPath = + wallpaper_dir_->path().Append(FILE_PATH_LITERAL("guest_small.jpg")); + ASSERT_TRUE(WriteJPEGFile(kSmallGuestPath, kWallpaperSize, kWallpaperSize, + kSmallGuestWallpaperColor)); + command_line_.AppendSwitchPath( + switches::kAshDefaultGuestWallpaperSmall, kSmallGuestPath); + + controller_->set_command_line_for_testing(&command_line_); + } + + content::TestBrowserThread ui_thread_; + + // Custom command line passed to DesktopBackgroundController by + // WriteWallpapersAndSetFlags(). + CommandLine command_line_; + + // Directory created by WriteWallpapersAndSetFlags() to store default + // wallpaper images. + scoped_ptr<base::ScopedTempDir> wallpaper_dir_; + + DesktopBackgroundController* controller_; // Not owned. + private: DISALLOW_COPY_AND_ASSIGN(DesktopBackgroundControllerTest); }; @@ -123,10 +313,7 @@ TEST_F(DesktopBackgroundControllerTest, ControllerOwnership) { EXPECT_FALSE(root->GetProperty(kDesktopController)); // Force the widget's layer animation to play to completion. - ASSERT_NO_FATAL_FAILURE( - RunAnimationForWidget( - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> - widget())); + RunDesktopControllerAnimation(); // Ownership has moved from kAnimatingDesktopController to kDesktopController. EXPECT_FALSE( @@ -147,11 +334,7 @@ TEST_F(DesktopBackgroundControllerTest, BackgroundMovementDuringUnlock) { controller->CreateEmptyWallpaper(); // Run wallpaper show animation to completion. - RootWindow* root = Shell::GetPrimaryRootWindow(); - ASSERT_NO_FATAL_FAILURE( - RunAnimationForWidget( - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> - widget())); + RunDesktopControllerAnimation(); // User locks the screen, which moves the background forward. controller->MoveDesktopToLockedContainer(); @@ -162,6 +345,7 @@ TEST_F(DesktopBackgroundControllerTest, BackgroundMovementDuringUnlock) { // In this state we have two desktop background views stored in different // properties. Both are in the lock screen background container. + RootWindow* root = Shell::GetPrimaryRootWindow(); EXPECT_TRUE( root->GetProperty(kAnimatingDesktopController)->GetController(false)); EXPECT_TRUE(root->GetProperty(kDesktopController)); @@ -177,10 +361,7 @@ TEST_F(DesktopBackgroundControllerTest, BackgroundMovementDuringUnlock) { EXPECT_EQ(0, ChildCountForContainer(kLockScreenBackgroundId)); // Finish the new desktop background animation. - ASSERT_NO_FATAL_FAILURE( - RunAnimationForWidget( - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> - widget())); + RunDesktopControllerAnimation(); // Now there is one desktop background, in the back. EXPECT_EQ(1, ChildCountForContainer(kDesktopBackgroundId)); @@ -200,28 +381,25 @@ TEST_F(DesktopBackgroundControllerTest, ChangeWallpaperQuick) { controller->CreateEmptyWallpaper(); // Run wallpaper show animation to completion. - RootWindow* root = Shell::GetPrimaryRootWindow(); - ASSERT_NO_FATAL_FAILURE( - RunAnimationForWidget( - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> - widget())); + RunDesktopControllerAnimation(); // Change to a new wallpaper. controller->CreateEmptyWallpaper(); - DesktopBackgroundWidgetController* animatingController = + RootWindow* root = Shell::GetPrimaryRootWindow(); + DesktopBackgroundWidgetController* animating_controller = root->GetProperty(kAnimatingDesktopController)->GetController(false); - EXPECT_TRUE(animatingController); + EXPECT_TRUE(animating_controller); EXPECT_TRUE(root->GetProperty(kDesktopController)); // Change to another wallpaper before animation finished. controller->CreateEmptyWallpaper(); // The animating controller should immediately move to desktop controller. - EXPECT_EQ(animatingController, root->GetProperty(kDesktopController)); + EXPECT_EQ(animating_controller, root->GetProperty(kDesktopController)); // Cache the new animating controller. - animatingController = + animating_controller = root->GetProperty(kAnimatingDesktopController)->GetController(false); // Run wallpaper show animation to completion. @@ -234,7 +412,114 @@ TEST_F(DesktopBackgroundControllerTest, ChangeWallpaperQuick) { EXPECT_FALSE( root->GetProperty(kAnimatingDesktopController)->GetController(false)); // The desktop controller should be the last created animating controller. - EXPECT_EQ(animatingController, root->GetProperty(kDesktopController)); + EXPECT_EQ(animating_controller, root->GetProperty(kDesktopController)); +} + +TEST_F(DesktopBackgroundControllerTest, GetAppropriateResolution) { + // TODO(derat|oshima|bshe): Configuring desktops seems busted on Win8, + // even when just a single display is being used -- the small wallpaper + // is used instead of the large one. Track down the cause of the problem + // and only use a SupportsMultipleDisplays() clause for the dual-display + // code below. + if (!SupportsMultipleDisplays()) + return; + + test::DisplayManagerTestApi display_manager_test_api( + Shell::GetInstance()->display_manager()); + + // Small wallpaper images should be used for configurations less than or + // equal to kSmallWallpaperMaxWidth by kSmallWallpaperMaxHeight, even if + // multiple displays are connected. + display_manager_test_api.UpdateDisplay("800x600"); + EXPECT_EQ(WALLPAPER_RESOLUTION_SMALL, + controller_->GetAppropriateResolution()); + display_manager_test_api.UpdateDisplay("800x600,800x600"); + EXPECT_EQ(WALLPAPER_RESOLUTION_SMALL, + controller_->GetAppropriateResolution()); + display_manager_test_api.UpdateDisplay("1366x800"); + EXPECT_EQ(WALLPAPER_RESOLUTION_SMALL, + controller_->GetAppropriateResolution()); + + // At larger sizes, large wallpapers should be used. + display_manager_test_api.UpdateDisplay("1367x800"); + EXPECT_EQ(WALLPAPER_RESOLUTION_LARGE, + controller_->GetAppropriateResolution()); + display_manager_test_api.UpdateDisplay("1367x801"); + EXPECT_EQ(WALLPAPER_RESOLUTION_LARGE, + controller_->GetAppropriateResolution()); + display_manager_test_api.UpdateDisplay("2560x1700"); + EXPECT_EQ(WALLPAPER_RESOLUTION_LARGE, + controller_->GetAppropriateResolution()); +} + +// Test that DesktopBackgroundController loads the appropriate wallpaper +// images as specified via command-line flags in various situations. +// Splitting these into separate tests avoids needing to run animations. +// TODO(derat): Combine these into a single test -- see +// RunDesktopControllerAnimation()'s TODO. +TEST_F(DesktopBackgroundControllerTest, SmallDefaultWallpaper) { + if (!SupportsMultipleDisplays()) + return; + + WriteWallpapersAndSetFlags(); + TestObserver observer(controller_); + + // At 800x600, the small wallpaper should be loaded. + test::DisplayManagerTestApi display_manager_test_api( + Shell::GetInstance()->display_manager()); + display_manager_test_api.UpdateDisplay("800x600"); + ASSERT_TRUE(controller_->SetDefaultWallpaper(false)); + observer.WaitForWallpaperDataChanged(); + EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(), + kSmallWallpaperColor)); + + // Requesting the same wallpaper again should be a no-op. + ASSERT_FALSE(controller_->SetDefaultWallpaper(false)); +} + +TEST_F(DesktopBackgroundControllerTest, LargeDefaultWallpaper) { + if (!SupportsMultipleDisplays()) + return; + + WriteWallpapersAndSetFlags(); + TestObserver observer(controller_); + test::DisplayManagerTestApi display_manager_test_api( + Shell::GetInstance()->display_manager()); + display_manager_test_api.UpdateDisplay("1600x1200"); + ASSERT_TRUE(controller_->SetDefaultWallpaper(false)); + observer.WaitForWallpaperDataChanged(); + EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(), + kLargeWallpaperColor)); +} + +TEST_F(DesktopBackgroundControllerTest, SmallGuestWallpaper) { + if (!SupportsMultipleDisplays()) + return; + + WriteWallpapersAndSetFlags(); + TestObserver observer(controller_); + test::DisplayManagerTestApi display_manager_test_api( + Shell::GetInstance()->display_manager()); + display_manager_test_api.UpdateDisplay("800x600"); + ASSERT_TRUE(controller_->SetDefaultWallpaper(true)); + observer.WaitForWallpaperDataChanged(); + EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(), + kSmallGuestWallpaperColor)); +} + +TEST_F(DesktopBackgroundControllerTest, LargeGuestWallpaper) { + if (!SupportsMultipleDisplays()) + return; + + WriteWallpapersAndSetFlags(); + TestObserver observer(controller_); + test::DisplayManagerTestApi display_manager_test_api( + Shell::GetInstance()->display_manager()); + display_manager_test_api.UpdateDisplay("1600x1200"); + ASSERT_TRUE(controller_->SetDefaultWallpaper(true)); + observer.WaitForWallpaperDataChanged(); + EXPECT_TRUE(ImageIsNearColor(controller_->GetWallpaper(), + kLargeGuestWallpaperColor)); } } // namespace internal diff --git a/ash/desktop_background/wallpaper_resizer.cc b/ash/desktop_background/wallpaper_resizer.cc index c7e1dda..b75e262 100644 --- a/ash/desktop_background/wallpaper_resizer.cc +++ b/ash/desktop_background/wallpaper_resizer.cc @@ -18,91 +18,95 @@ using content::BrowserThread; namespace ash { namespace { -// Callback used to indicate that wallpaper has been resized. -typedef base::Callback<void(const SkBitmap&)> ResizedCallback; - // For our scaling ratios we need to round positive numbers. int RoundPositive(double x) { return static_cast<int>(floor(x + 0.5)); } -// Resizes |wallpaper| to |target_size| and calls the callback. -void Resize(const SkBitmap& wallpaper, - WallpaperLayout layout, +// Resizes |orig_bitmap| to |target_size| using |layout| and stores the +// resulting bitmap at |resized_bitmap_out|. +void Resize(SkBitmap orig_bitmap, const gfx::Size& target_size, - base::MessageLoop* origin_loop, - const ResizedCallback& callback) { - SkBitmap resized_wallpaper = wallpaper; - int width = target_size.width(); - int height = target_size.height(); - if (wallpaper.width() > width || wallpaper.height() > height) { - gfx::Rect wallpaper_rect(0, 0, wallpaper.width(), wallpaper.height()); - gfx::Size cropped_size = gfx::Size(std::min(width, wallpaper.width()), - std::min(height, wallpaper.height())); + WallpaperLayout layout, + SkBitmap* resized_bitmap_out) { + DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); + SkBitmap new_bitmap = orig_bitmap; + + const int orig_width = orig_bitmap.width(); + const int orig_height = orig_bitmap.height(); + const int new_width = target_size.width(); + const int new_height = target_size.height(); + + if (orig_width > new_width || orig_height > new_height) { + gfx::Rect wallpaper_rect(0, 0, orig_width, orig_height); + gfx::Size cropped_size = gfx::Size(std::min(new_width, orig_width), + std::min(new_height, orig_height)); switch (layout) { case WALLPAPER_LAYOUT_CENTER: wallpaper_rect.ClampToCenteredSize(cropped_size); - wallpaper.extractSubset(&resized_wallpaper, - gfx::RectToSkIRect(wallpaper_rect)); + orig_bitmap.extractSubset(&new_bitmap, + gfx::RectToSkIRect(wallpaper_rect)); break; case WALLPAPER_LAYOUT_TILE: wallpaper_rect.set_size(cropped_size); - wallpaper.extractSubset(&resized_wallpaper, - gfx::RectToSkIRect(wallpaper_rect)); + orig_bitmap.extractSubset(&new_bitmap, + gfx::RectToSkIRect(wallpaper_rect)); break; case WALLPAPER_LAYOUT_STRETCH: - resized_wallpaper = skia::ImageOperations::Resize( - wallpaper, skia::ImageOperations::RESIZE_LANCZOS3, - width, height); + new_bitmap = skia::ImageOperations::Resize( + orig_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, + new_width, new_height); break; case WALLPAPER_LAYOUT_CENTER_CROPPED: - if (wallpaper.width() > width && wallpaper.height() > height) { + if (orig_width > new_width && orig_height > new_height) { // The dimension with the smallest ratio must be cropped, the other // one is preserved. Both are set in gfx::Size cropped_size. - double horizontal_ratio = static_cast<double>(width) / - static_cast<double>(wallpaper.width()); - double vertical_ratio = static_cast<double>(height) / - static_cast<double>(wallpaper.height()); + double horizontal_ratio = static_cast<double>(new_width) / + static_cast<double>(orig_width); + double vertical_ratio = static_cast<double>(new_height) / + static_cast<double>(orig_height); if (vertical_ratio > horizontal_ratio) { cropped_size = gfx::Size( - RoundPositive(static_cast<double>(width) / vertical_ratio), - wallpaper.height()); + RoundPositive(static_cast<double>(new_width) / vertical_ratio), + orig_height); } else { - cropped_size = gfx::Size(wallpaper.width(), - RoundPositive(static_cast<double>(height) / horizontal_ratio)); + cropped_size = gfx::Size(orig_width, RoundPositive( + static_cast<double>(new_height) / horizontal_ratio)); } wallpaper_rect.ClampToCenteredSize(cropped_size); SkBitmap sub_image; - wallpaper.extractSubset(&sub_image, - gfx::RectToSkIRect(wallpaper_rect)); - resized_wallpaper = skia::ImageOperations::Resize( + orig_bitmap.extractSubset(&sub_image, + gfx::RectToSkIRect(wallpaper_rect)); + new_bitmap = skia::ImageOperations::Resize( sub_image, skia::ImageOperations::RESIZE_LANCZOS3, - width, height); + new_width, new_height); } } } - resized_wallpaper.setImmutable(); - origin_loop->PostTask(FROM_HERE, base::Bind(callback, resized_wallpaper)); + + *resized_bitmap_out = new_bitmap; + resized_bitmap_out->setImmutable(); } } // namespace -WallpaperResizer::WallpaperResizer(const WallpaperInfo& info, - const gfx::Size& target_size) - : wallpaper_info_(info), +WallpaperResizer::WallpaperResizer(int image_resource_id, + const gfx::Size& target_size, + WallpaperLayout layout) + : wallpaper_image_(*(ui::ResourceBundle::GetSharedInstance(). + GetImageNamed(image_resource_id).ToImageSkia())), target_size_(target_size), - wallpaper_image_(*(ui::ResourceBundle::GetSharedInstance(). - GetImageNamed(info.idr).ToImageSkia())), + layout_(layout), weak_ptr_factory_(this) { } -WallpaperResizer::WallpaperResizer(const WallpaperInfo& info, +WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image, const gfx::Size& target_size, - const gfx::ImageSkia& image) - : wallpaper_info_(info), + WallpaperLayout layout) + : wallpaper_image_(image), target_size_(target_size), - wallpaper_image_(image), + layout_(layout), weak_ptr_factory_(this) { } @@ -110,18 +114,17 @@ WallpaperResizer::~WallpaperResizer() { } void WallpaperResizer::StartResize() { - if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + SkBitmap* resized_bitmap = new SkBitmap; + if (!content::BrowserThread::PostBlockingPoolTaskAndReply( FROM_HERE, - base::Bind(&Resize, - *wallpaper_image_.bitmap(), - wallpaper_info_.layout, - target_size_, - base::MessageLoop::current(), - base::Bind(&WallpaperResizer::OnResizeFinished, - weak_ptr_factory_.GetWeakPtr())), - base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) { - LOG(WARNING) << "PostSequencedWorkerTask failed. " << - "Wallpaper may not be resized."; + base::Bind(&Resize, *wallpaper_image_.bitmap(), target_size_, + layout_, resized_bitmap), + base::Bind(&WallpaperResizer::OnResizeFinished, + weak_ptr_factory_.GetWeakPtr(), + base::Owned(resized_bitmap)))) { + LOG(WARNING) << "PostSequencedWorkerTask failed. " + << "Wallpaper may not be resized."; } } @@ -133,8 +136,9 @@ void WallpaperResizer::RemoveObserver(WallpaperResizerObserver* observer) { observers_.RemoveObserver(observer); } -void WallpaperResizer::OnResizeFinished(const SkBitmap& resized_wallpaper) { - wallpaper_image_ = gfx::ImageSkia::CreateFrom1xBitmap(resized_wallpaper); +void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + wallpaper_image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap); FOR_EACH_OBSERVER(WallpaperResizerObserver, observers_, OnWallpaperResized()); } diff --git a/ash/desktop_background/wallpaper_resizer.h b/ash/desktop_background/wallpaper_resizer.h index 9b47b7c..e39dcd5 100644 --- a/ash/desktop_background/wallpaper_resizer.h +++ b/ash/desktop_background/wallpaper_resizer.h @@ -10,6 +10,7 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "skia/ext/image_operations.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/size.h" @@ -20,18 +21,21 @@ class WallpaperResizerObserver; // Stores the current wallpaper data and resize it to |target_size| if needed. class ASH_EXPORT WallpaperResizer { public: - WallpaperResizer(const WallpaperInfo& info, const gfx::Size& target_size); + WallpaperResizer(int image_resource_id, + const gfx::Size& target_size, + WallpaperLayout layout); - WallpaperResizer(const WallpaperInfo& info, const gfx::Size& target_size, - const gfx::ImageSkia& image); + WallpaperResizer(const gfx::ImageSkia& image, + const gfx::Size& target_size, + WallpaperLayout layout); - virtual ~WallpaperResizer(); - - const WallpaperInfo& wallpaper_info() const { return wallpaper_info_; } + ~WallpaperResizer(); const gfx::ImageSkia& wallpaper_image() const { return wallpaper_image_; } + const WallpaperLayout layout() const { return layout_; } - // Starts resize task on UI thread. It posts task to worker pool. + // Called on the UI thread to run Resize() on the worker pool and post an + // OnResizeFinished() task back to the UI thread on completion. void StartResize(); // Add/Remove observers. @@ -39,16 +43,20 @@ class ASH_EXPORT WallpaperResizer { void RemoveObserver(WallpaperResizerObserver* observer); private: - // Replaces the orginal uncompressed wallpaper to |resized_wallpaper|. - void OnResizeFinished(const SkBitmap& resized_wallpaper); + // Copies |resized_bitmap| to |wallpaper_image_| and notifies observers + // after Resize() has finished running. + void OnResizeFinished(SkBitmap* resized_bitmap); ObserverList<WallpaperResizerObserver> observers_; - const WallpaperInfo wallpaper_info_; + // Image that should currently be used for wallpaper. It initially + // contains the original image and is updated to contain the resized + // image by OnResizeFinished(). + gfx::ImageSkia wallpaper_image_; gfx::Size target_size_; - gfx::ImageSkia wallpaper_image_; + WallpaperLayout layout_; base::WeakPtrFactory<WallpaperResizer> weak_ptr_factory_; diff --git a/ash/desktop_background/wallpaper_resizer_unittest.cc b/ash/desktop_background/wallpaper_resizer_unittest.cc index 0093ade..5761b67 100644 --- a/ash/desktop_background/wallpaper_resizer_unittest.cc +++ b/ash/desktop_background/wallpaper_resizer_unittest.cc @@ -5,7 +5,9 @@ #include "ash/desktop_background/wallpaper_resizer.h" #include "ash/desktop_background/wallpaper_resizer_observer.h" -#include "ash/test/ash_test_base.h" +#include "base/message_loop/message_loop.h" +#include "content/public/test/test_browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/image/image_skia_rep.h" using aura::RootWindow; @@ -55,17 +57,19 @@ bool IsColor(const gfx::ImageSkia& image, const uint32_t expect) { namespace ash { namespace internal { -class WallpaperResizerTest : public test::AshTestBase, +class WallpaperResizerTest : public testing::Test, public WallpaperResizerObserver { public: - WallpaperResizerTest() {} + WallpaperResizerTest() + : ui_thread_(content::BrowserThread::UI, &message_loop_) { + } virtual ~WallpaperResizerTest() {} - gfx::ImageSkia Resize(const WallpaperInfo& info, + gfx::ImageSkia Resize(const gfx::ImageSkia& image, const gfx::Size& target_size, - const gfx::ImageSkia& image) { + WallpaperLayout layout) { scoped_ptr<WallpaperResizer> resizer; - resizer.reset(new WallpaperResizer(info, target_size, image)); + resizer.reset(new WallpaperResizer(image, target_size, layout)); resizer->AddObserver(this); resizer->StartResize(); WaitForResize(); @@ -74,14 +78,17 @@ class WallpaperResizerTest : public test::AshTestBase, } void WaitForResize() { - base::MessageLoop::current()->Run(); + message_loop_.Run(); } virtual void OnWallpaperResized() OVERRIDE { - base::MessageLoop::current()->Quit(); + message_loop_.Quit(); } private: + base::MessageLoop message_loop_; + content::TestBrowserThread ui_thread_; + DISALLOW_COPY_AND_ASSIGN(WallpaperResizerTest); }; @@ -97,19 +104,18 @@ TEST_F(WallpaperResizerTest, BasicResize) { for (int i = 0; i < length; i++) { WallpaperLayout layout = layouts[i]; - WallpaperInfo info = { 0, layout }; gfx::ImageSkia small_image(gfx::ImageSkiaRep(gfx::Size(10, 20), ui::SCALE_FACTOR_100P)); - gfx::ImageSkia resized_small = Resize(info, gfx::Size(800, 600), - small_image); + gfx::ImageSkia resized_small = Resize(small_image, gfx::Size(800, 600), + layout); EXPECT_EQ(10, resized_small.width()); EXPECT_EQ(20, resized_small.height()); gfx::ImageSkia large_image(gfx::ImageSkiaRep(gfx::Size(1000, 1000), ui::SCALE_FACTOR_100P)); - gfx::ImageSkia resized_large = Resize(info, gfx::Size(800, 600), - large_image); + gfx::ImageSkia resized_large = Resize(large_image, gfx::Size(800, 600), + layout); EXPECT_EQ(800, resized_large.width()); EXPECT_EQ(600, resized_large.height()); } @@ -122,18 +128,14 @@ TEST_F(WallpaperResizerTest, AllLayoutDifferent) { gfx::Size(kTestImageWidth, kTestImageHeight)); gfx::Size target_size = gfx::Size(kTargetWidth, kTargetHeight); - WallpaperInfo info_center = { 0, WALLPAPER_LAYOUT_CENTER }; - gfx::ImageSkia center = Resize(info_center, target_size, image); + gfx::ImageSkia center = Resize(image, target_size, WALLPAPER_LAYOUT_CENTER); - WallpaperInfo info_center_cropped = { 0, WALLPAPER_LAYOUT_CENTER_CROPPED }; - gfx::ImageSkia center_cropped = Resize(info_center_cropped, target_size, - image); + gfx::ImageSkia center_cropped = Resize(image, target_size, + WALLPAPER_LAYOUT_CENTER_CROPPED); - WallpaperInfo info_stretch = { 0, WALLPAPER_LAYOUT_STRETCH }; - gfx::ImageSkia stretch = Resize(info_stretch, target_size, image); + gfx::ImageSkia stretch = Resize(image, target_size, WALLPAPER_LAYOUT_STRETCH); - WallpaperInfo info_tile = { 0, WALLPAPER_LAYOUT_TILE }; - gfx::ImageSkia tile = Resize(info_tile, target_size, image); + gfx::ImageSkia tile = Resize(image, target_size, WALLPAPER_LAYOUT_TILE); EXPECT_TRUE(IsColor(center, kExpectedCenter)); EXPECT_TRUE(IsColor(center_cropped, kExpectedCenterCropped)); diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc index 5a24505..d5454ce 100644 --- a/ash/display/display_manager.cc +++ b/ash/display/display_manager.cc @@ -470,7 +470,7 @@ void DisplayManager::UpdateDisplays( if (base::win::GetVersion() >= base::win::VERSION_WIN8) { DCHECK_EQ(1u, updated_display_info_list.size()) << "Multiple display test does not work on Win8 bots. Please " - "skip (don't disable) the test using |SupportMultipleDisplay()|"; + "skip (don't disable) the test using SupportsMultipleDisplays()"; } #endif diff --git a/ash/shell/content_client/shell_browser_main_parts.cc b/ash/shell/content_client/shell_browser_main_parts.cc index d6a7deb..19380a6 100644 --- a/ash/shell/content_client/shell_browser_main_parts.cc +++ b/ash/shell/content_client/shell_browser_main_parts.cc @@ -131,12 +131,8 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() { ash::shell::InitWindowTypeLauncher(); - DesktopBackgroundController* controller = - Shell::GetInstance()->desktop_background_controller(); - if (controller->GetAppropriateResolution() == WALLPAPER_RESOLUTION_LARGE) - controller->SetDefaultWallpaper(kDefaultLargeWallpaper); - else - controller->SetDefaultWallpaper(kDefaultSmallWallpaper); + Shell::GetInstance()->desktop_background_controller()->SetDefaultWallpaper( + false /* is_guest */); ash::Shell::GetPrimaryRootWindow()->ShowRootWindow(); } diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index fcf7e27..7d5b859 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc @@ -130,10 +130,15 @@ std::string DeriveCommandLine(const GURL& start_url, ::switches::kUseExynosVda, ::switches::kV, ::switches::kEnableWebGLDraftExtensions, - ash::switches::kAshTouchHud, - ash::switches::kAuraLegacyPowerButton, + ash::switches::kAshDefaultGuestWallpaperLarge, + ash::switches::kAshDefaultGuestWallpaperSmall, + ash::switches::kAshDefaultWallpaperLarge, + ash::switches::kAshDefaultWallpaperSmall, ash::switches::kAshDisableNewAudioHandler, ash::switches::kAshEnableAudioDeviceMenu, + ash::switches::kAshHostWindowBounds, + ash::switches::kAshTouchHud, + ash::switches::kAuraLegacyPowerButton, // Please keep these in alphabetical order. Non-UI Compositor switches // here should also be added to // content/browser/renderer_host/render_process_host_impl.cc. diff --git a/chrome/browser/chromeos/login/wallpaper_manager.cc b/chrome/browser/chromeos/login/wallpaper_manager.cc index 9a0cc85..623588f 100644 --- a/chrome/browser/chromeos/login/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/wallpaper_manager.cc @@ -490,25 +490,10 @@ void WallpaperManager::SetCustomWallpaper(const std::string& username, } void WallpaperManager::SetDefaultWallpaper() { - ash::DesktopBackgroundController* controller = - ash::Shell::GetInstance()->desktop_background_controller(); - ash::WallpaperResolution resolution = controller->GetAppropriateResolution(); - ash::WallpaperInfo info; - if (UserManager::Get()->IsLoggedInAsGuest()) { - info = (resolution == ash::WALLPAPER_RESOLUTION_LARGE) ? - ash::kGuestLargeWallpaper : ash::kGuestSmallWallpaper; - } else { - info = (resolution == ash::WALLPAPER_RESOLUTION_LARGE) ? - ash::kDefaultLargeWallpaper : ash::kDefaultSmallWallpaper; - } - - // Prevents loading of the same wallpaper as the currently loading/loaded one. - if (controller->GetWallpaperIDR() == info.idr) - return; - current_wallpaper_path_.clear(); - loaded_wallpapers_++; - controller->SetDefaultWallpaper(info); + if (ash::Shell::GetInstance()->desktop_background_controller()-> + SetDefaultWallpaper(UserManager::Get()->IsLoggedInAsGuest())) + loaded_wallpapers_++; } void WallpaperManager::SetInitialUserWallpaper(const std::string& username, diff --git a/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc b/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc index 0bb93e6..916d254 100644 --- a/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc +++ b/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc @@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/login/wallpaper_manager.h" +#include "ash/ash_resources/grit/ash_wallpaper_resources.h" #include "ash/desktop_background/desktop_background_controller.h" #include "ash/desktop_background/desktop_background_controller_observer.h" #include "ash/display/display_manager.h" @@ -31,19 +32,13 @@ namespace chromeos { namespace { -#if defined(GOOGLE_CHROME_BUILD) -int kExpectedSmallWallpaperWidth = ash::kSmallWallpaperMaxWidth; -int kExpectedSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight; -int kExpectedLargeWallpaperWidth = ash::kLargeWallpaperMaxWidth; -int kExpectedLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight; -#else -// The defualt wallpaper for non official build is a gradient wallpaper which -// stretches to fit screen. -int kExpectedSmallWallpaperWidth = 256; -int kExpectedSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight; -int kExpectedLargeWallpaperWidth = 256; -int kExpectedLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight; -#endif +const int kLargeWallpaperResourceId = IDR_AURA_WALLPAPERS_5_GRADIENT5_LARGE; +const int kSmallWallpaperResourceId = IDR_AURA_WALLPAPERS_5_GRADIENT5_SMALL; + +int kLargeWallpaperWidth = 256; +int kLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight; +int kSmallWallpaperWidth = 256; +int kSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight; const char kTestUser1[] = "test@domain.com"; @@ -95,8 +90,8 @@ class WallpaperManagerBrowserTest : public CrosInProcessBrowserTest, protected: // Return custom wallpaper path. Create directory if not exist. base::FilePath GetCustomWallpaperPath(const char* sub_dir, - const std::string& email, - const std::string& id) { + const std::string& email, + const std::string& id) { base::FilePath wallpaper_path = WallpaperManager::Get()->GetCustomWallpaperPath(sub_dir, email, id); if (!file_util::DirectoryExists(wallpaper_path.DirName())) @@ -135,57 +130,8 @@ class WallpaperManagerBrowserTest : public CrosInProcessBrowserTest, DISALLOW_COPY_AND_ASSIGN(WallpaperManagerBrowserTest); }; -// The large resolution wallpaper should be loaded when a large external screen -// is hooked up. If the external screen is smaller than small wallpaper -// resolution, do not load large resolution wallpaper. -IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, - LoadLargeWallpaperForLargeExternalScreen) { - LogIn(kTestUser1); - WaitAsyncWallpaperLoad(); - gfx::ImageSkia wallpaper = controller_->GetWallpaper(); - - // Display is initialized to 800x600. The small resolution default wallpaper - // is expected. - EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height()); - - // Hook up another 800x600 display. - UpdateDisplay("800x600,800x600"); -#if !defined(GOOGLE_CHROME_BUILD) - // wallpaper.width() < 800, expect to reload wallpaper. - WaitAsyncWallpaperLoad(); -#endif - // The small resolution wallpaper is expected. - EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height()); - - // Detach the secondary display. - UpdateDisplay("800x600"); - // Hook up a 2000x2000 display. The large resolution default wallpaper should - // be loaded. - UpdateDisplay("800x600,2000x2000"); - WaitAsyncWallpaperLoad(); - wallpaper = controller_->GetWallpaper(); - - // The large resolution default wallpaper is expected. - EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height()); - - // Detach the secondary display. - UpdateDisplay("800x600"); - // Hook up the 2000x2000 display again. The large resolution default wallpaper - // should persist. Test for crbug/165788. - UpdateDisplay("800x600,2000x2000"); - WaitAsyncWallpaperLoad(); - wallpaper = controller_->GetWallpaper(); - - // The large resolution default wallpaper is expected. - EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height()); -} - -// This test is similar to LoadLargeWallpaperForExternalScreen test. Instead of -// testing default wallpaper, it tests custom wallpaper. +// Tests that the appropriate custom wallpaper (large vs. small) is loaded +// depending on the desktop resolution. IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, LoadCustomLargeWallpaperForLargeExternalScreen) { WallpaperManager* wallpaper_manager = WallpaperManager::Get(); @@ -206,10 +152,10 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, // wallpaper paths. SaveUserWallpaperData(kTestUser1, small_wallpaper_path, - ash::kDefaultSmallWallpaper.idr); + kSmallWallpaperResourceId); SaveUserWallpaperData(kTestUser1, large_wallpaper_path, - ash::kDefaultLargeWallpaper.idr); + kLargeWallpaperResourceId); // Saves wallpaper info to local state for user |kTestUser1|. WallpaperInfo info = { @@ -227,18 +173,15 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, // Display is initialized to 800x600. The small resolution custom wallpaper is // expected. - EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height()); + EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width()); + EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height()); // Hook up another 800x600 display. UpdateDisplay("800x600,800x600"); -#if !defined(GOOGLE_CHROME_BUILD) - // wallpaper.width() < 800, expect to reload wallpaper. WaitAsyncWallpaperLoad(); -#endif // The small resolution custom wallpaper is expected. - EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height()); + EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width()); + EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height()); // Detach the secondary display. UpdateDisplay("800x600"); @@ -249,8 +192,8 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, wallpaper = controller_->GetWallpaper(); // The large resolution custom wallpaper is expected. - EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height()); + EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width()); + EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height()); // Detach the secondary display. UpdateDisplay("800x600"); @@ -261,8 +204,8 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, wallpaper = controller_->GetWallpaper(); // The large resolution custom wallpaper is expected. - EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width()); - EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height()); + EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width()); + EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height()); } // If chrome tries to reload the same wallpaper twice, the latter request should @@ -293,7 +236,7 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, id); SaveUserWallpaperData(kTestUser1, small_wallpaper_path, - ash::kDefaultSmallWallpaper.idr); + kSmallWallpaperResourceId); // Saves wallpaper info to local state for user |kTestUser1|. WallpaperInfo info = { @@ -328,7 +271,7 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, GetOriginalWallpaperPathForUser(kTestUser1); SaveUserWallpaperData(kTestUser1, old_wallpaper_path, - ash::kDefaultSmallWallpaper.idr); + kSmallWallpaperResourceId); // Saves wallpaper info to local state for user |kTestUser1|. WallpaperInfo info = { "DUMMY", @@ -463,4 +406,4 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation, // can not handle pre migrated user profile (M21 profile or older). } -} // namepace chromeos +} // namespace chromeos |