Index: ash/desktop_background/desktop_background_controller.cc |
diff --git a/ash/desktop_background/desktop_background_controller.cc b/ash/desktop_background/desktop_background_controller.cc |
index 83ffe466f9dd3a157a7e2c7c26619bfacfb91128..a4f367ba1b07a4c8789c6f80ae9c6499d563568f 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; |
} |