Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Unified Diff: chrome/browser/chromeos/login/wallpaper_manager.cc

Issue 10883062: Resize and save custom wallpaper to large and small size (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/login/wallpaper_manager.cc
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.cc b/chrome/browser/chromeos/login/wallpaper_manager.cc
index 4f9351fa816dfd6323ae9aafcde387309ccdee12..54af05015a9490bcea5cb61f03ae7d4d829057da 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.cc
+++ b/chrome/browser/chromeos/login/wallpaper_manager.cc
@@ -19,6 +19,7 @@
#include "base/time.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/login/simple_jpeg_encoder.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
@@ -70,6 +71,14 @@ const char kNewWallpaperLayoutNodeName[] = "layout";
const char kNewWallpaperFileNodeName[] = "file";
const char kNewWallpaperTypeNodeName[] = "type";
+// TODO(bshe): Address the file extension issue. All custom wallpapers should be
+// jpeg files.
+// File path suffices of resized small or large custom wallpaper.
+const char kSmallCustomWallpaperSuffix[] = "_small";
+const char kLargeCustomWallpaperSuffix[] = "_large";
+// File path suffix of the original custom wallpaper.
+const char kOriginalCustomWallpaperSuffix[] = "_wallpaper.png";
+
gfx::ImageSkia GetWallpaperThumbnail(const gfx::ImageSkia& wallpaper) {
gfx::ImageSkia thumbnail = gfx::ImageSkiaOperations::CreateResizedImage(
wallpaper,
@@ -97,6 +106,11 @@ gfx::ImageSkia ImageSkiaDeepCopy(const gfx::ImageSkia& image) {
return copy;
}
+// For our scaling ratios we need to round positive numbers.
+int RoundPositive(double x) {
+ return static_cast<int>(floor(x + 0.5));
+}
+
} // namespace
namespace chromeos {
@@ -165,18 +179,25 @@ void WallpaperManager::EnsureLoggedInUserWallpaperLoaded() {
SetUserWallpaper(UserManager::Get()->GetLoggedInUser().email());
}
-void WallpaperManager::FetchCustomWallpaper(const std::string& email) {
+void WallpaperManager::GetCustomWallpaper(const std::string& email) {
User::WallpaperType type;
int index;
base::Time date;
+ // Get layout, type and date while on UI thread.
GetUserWallpaperProperties(email, &type, &index, &date);
ash::WallpaperLayout layout = static_cast<ash::WallpaperLayout>(index);
-
- std::string wallpaper_path = GetWallpaperPathForUser(email, false).value();
-
- wallpaper_loader_->Start(wallpaper_path, 0,
- base::Bind(&WallpaperManager::FetchWallpaper,
- base::Unretained(this), email, layout));
+ // Initializes file name to a dummy string here. The real file path will
+ // be set in GetCustomWallpaperInternal.
+ WallpaperInfo info = {
+ "DUMMY",
+ layout,
+ type,
+ date
+ };
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&WallpaperManager::GetCustomWallpaperInternal,
+ base::Unretained(this), email, info));
}
bool WallpaperManager::GetCustomWallpaperFromCache(const std::string& email,
@@ -190,9 +211,18 @@ bool WallpaperManager::GetCustomWallpaperFromCache(const std::string& email,
return false;
}
+FilePath WallpaperManager::GetOriginalWallpaperPathForUser(
+ const std::string& username) {
+ std::string filename = username + kOriginalCustomWallpaperSuffix;
+ FilePath user_data_dir;
+ PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
+ return user_data_dir.AppendASCII(filename);
+}
+
FilePath WallpaperManager::GetWallpaperPathForUser(const std::string& username,
- bool is_thumbnail) {
- const char* suffix = is_thumbnail ? "_thumb" : "";
+ bool is_small) {
+ const char* suffix = is_small ?
+ kSmallCustomWallpaperSuffix : kLargeCustomWallpaperSuffix;
std::string filename = base::StringPrintf("%s_wallpaper%s.png",
username.c_str(),
suffix);
@@ -382,7 +412,7 @@ void WallpaperManager::SetUserWallpaperFromFile(
// For wallpapers, save the image without resizing.
wallpaper_loader_->Start(
path.value(), 0,
- base::Bind(&WallpaperManager::SetWallpaper,
+ base::Bind(&WallpaperManager::SetCustomWallpaper,
base::Unretained(this), username, layout, User::CUSTOMIZED,
delegate));
}
@@ -464,6 +494,19 @@ void WallpaperManager::SetUserWallpaper(const std::string& email) {
if (new_wallpaper_ui_enabled &&
GetUserWallpaperInfo(email, &info)) {
+ if (info.type == User::CUSTOMIZED) {
+ if (!UserManager::Get()->IsUserLoggedIn()) {
+ ash::Shell::GetInstance()->desktop_background_controller()->
+ SetDefaultWallpaper(ash::GetDefaultWallpaperIndex(), false);
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&WallpaperManager::GetCustomWallpaperInternal,
+ base::Unretained(this), email, info));
+ }
+ return;
+ }
+
if (info.file_name.empty()) {
// Uses default built-in wallpaper when file name is empty. Eventually,
// we will only ship one built-in wallpaper in ChromeOS image.
@@ -471,6 +514,7 @@ void WallpaperManager::SetUserWallpaper(const std::string& email) {
SetDefaultWallpaper(ash::GetDefaultWallpaperIndex(), false);
return;
}
+
LoadWallpaper(email, info);
} else {
User::WallpaperType type;
@@ -488,7 +532,7 @@ void WallpaperManager::SetUserWallpaper(const std::string& email) {
if (!UserManager::Get()->IsUserLoggedIn()) {
index = ash::GetDefaultWallpaperIndex();
} else {
- FetchCustomWallpaper(email);
+ GetCustomWallpaper(email);
return;
}
}
@@ -516,6 +560,7 @@ void WallpaperManager::OnUserSelected(const std::string& email) {
WallpaperManager::~WallpaperManager() {
DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
system::TimezoneSettings::GetInstance()->RemoveObserver(this);
+ weak_factory_.InvalidateWeakPtrs();
}
void WallpaperManager::BatchUpdateWallpaper() {
@@ -588,11 +633,17 @@ void WallpaperManager::CacheUserWallpaper(const std::string& email) {
CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
&wallpaper_dir));
wallpaper_path = wallpaper_dir.Append(info.file_name);
- } else {
+ } else if (info.type == User::DEFAULT) {
+ // Current wallpaper is converted from built-in wallpaper.
ash::WallpaperResolution resolution = ash::Shell::GetInstance()->
desktop_background_controller()->GetAppropriateResolution();
bool small_resolution = (resolution == ash::SMALL);
wallpaper_path = GetWallpaperPathForUser(email, small_resolution);
+ } else {
+ // Cache default wallpaper when user selected a custom wallpaper.
+ ash::Shell::GetInstance()->desktop_background_controller()->
+ CacheDefaultWallpaper(ash::GetDefaultWallpaperIndex());
+ return;
}
wallpaper_loader_->Start(wallpaper_path.value(), 0,
base::Bind(&WallpaperManager::CacheWallpaper,
@@ -645,10 +696,9 @@ void WallpaperManager::LoadWallpaper(const std::string& email,
CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
wallpaper_path = wallpaper_dir.Append(info.file_name);
} else {
- ash::WallpaperResolution resolution = ash::Shell::GetInstance()->
- desktop_background_controller()->GetAppropriateResolution();
- bool small_resolution = (resolution == ash::SMALL);
- wallpaper_path = GetWallpaperPathForUser(email, small_resolution);
+ FilePath user_data_dir;
+ PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
+ wallpaper_path = user_data_dir.Append(info.file_name);
}
wallpaper_loader_->Start(wallpaper_path.value(), 0,
@@ -767,6 +817,32 @@ void WallpaperManager::GenerateUserWallpaperThumbnail(
base::Unretained(this), delegate));
}
+void WallpaperManager::GetCustomWallpaperInternal(const std::string& email,
+ const WallpaperInfo& info) {
+ ash::WallpaperResolution resolution = ash::Shell::GetInstance()->
+ desktop_background_controller()->GetAppropriateResolution();
+ bool is_small = (resolution == ash::SMALL);
+ FilePath wallpaper_path = GetWallpaperPathForUser(email, is_small);
+ std::string file_name = wallpaper_path.BaseName().value();
+ // Falls back on original file if the correct resoltuion file does not
+ // exist. This may happen when the original custom wallpaper is small or
+ // browser shutdown before resized wallpaper saved.
+ if (!file_util::PathExists(wallpaper_path))
+ file_name = GetOriginalWallpaperPathForUser(email).BaseName().value();
+
+ WallpaperInfo new_info = {
+ file_name,
+ info.layout,
+ info.type,
+ info.date
+ };
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&WallpaperManager::LoadWallpaper,
+ base::Unretained(this), email, new_info));
+}
+
void WallpaperManager::MigrateBuiltInWallpaper(const std::string& email) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!email.empty() && UserManager::Get()->IsKnownUser(email)) {
@@ -822,10 +898,6 @@ void WallpaperManager::MigrateBuiltInWallpaper(const std::string& email) {
base::Unretained(this), wallpaper_path,
reinterpret_cast<const char*>(wallpaper->front()),
wallpaper->size()));
- } else {
- // Since we only have one resolution for custom wallpaper, always
- // use LARGE resolution for custom wallpaper.
- resolution = ash::LARGE;
}
bool small_resolution = (resolution == ash::SMALL);
@@ -848,11 +920,90 @@ void WallpaperManager::OnThumbnailUpdated(
delegate->SetCustomWallpaperThumbnail();
}
-void WallpaperManager::SaveWallpaper(const FilePath& path,
- const UserImage& wallpaper) {
+void WallpaperManager::OnWallpaperEncoded(const FilePath& path,
+ scoped_refptr<base::RefCountedBytes> data) {
+ SaveWallpaperInternal(path,
+ reinterpret_cast<const char*>(data->front()),
+ data->size());
+}
+
+void WallpaperManager::SaveCustomWallpaper(const std::string& email,
+ const FilePath& path,
+ ash::WallpaperLayout layout,
+ const UserImage& wallpaper) {
+ FilePath small_wallpaper_path = GetWallpaperPathForUser(email, true);
+ // Delete previous saved wallpapers.
+ if (file_util::PathExists(small_wallpaper_path))
+ file_util::Delete(small_wallpaper_path, false);
+ FilePath large_wallpaper_path = GetWallpaperPathForUser(email, false);
+ if (file_util::PathExists(large_wallpaper_path))
+ file_util::Delete(large_wallpaper_path, false);
+
std::vector<unsigned char> image_data = wallpaper.raw_image();
+ // Saves the original file in case that resized wallpaper is not generated
+ // (i.e. chrome shutdown before resized wallpaper is saved).
SaveWallpaperInternal(path, reinterpret_cast<char*>(&*image_data.begin()),
image_data.size());
+
+ ResizeAndSaveCustomWallpaper(wallpaper, small_wallpaper_path, layout,
+ ash::kSmallWallpaperMaxWidth,
+ ash::kSmallWallpaperMaxHeight);
+ ResizeAndSaveCustomWallpaper(wallpaper, large_wallpaper_path, layout,
+ ash::kLargeWallpaperMaxWidth,
+ ash::kLargeWallpaperMaxHeight);
+}
+
+void WallpaperManager::ResizeAndSaveCustomWallpaper(const UserImage& wallpaper,
+ const FilePath& path,
+ ash::WallpaperLayout layout,
+ int preferred_width,
+ int preferred_height) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ int width = wallpaper.image().width();
+ int height = wallpaper.image().height();
+ int resized_width;
+ int resized_height;
+
+ if (layout == ash::CENTER_CROPPED) {
+ // Do not resize custom wallpaper if it is smaller than preferred size.
+ if (!(width > preferred_width && height > preferred_height))
+ return;
+
+ double horizontal_ratio = static_cast<double>(preferred_width) / width;
+ double vertical_ratio = static_cast<double>(preferred_height) / height;
+ if (vertical_ratio > horizontal_ratio) {
+ resized_width =
+ RoundPositive(static_cast<double>(width) * vertical_ratio);
+ resized_height = preferred_height;
+ } else {
+ resized_width = preferred_width;
+ resized_height =
+ RoundPositive(static_cast<double>(height) * horizontal_ratio);
+ }
+ } else if (layout == ash::STRETCH) {
+ resized_width = preferred_width;
+ resized_height = preferred_height;
+ } else {
+ // TODO(bshe): Generates cropped custom wallpaper for CENTER layout.
+ if (file_util::PathExists(path))
+ file_util::Delete(path, false);
+ return;
+ }
+
+ gfx::ImageSkia resized_image = gfx::ImageSkiaOperations::CreateResizedImage(
+ wallpaper.image(),
+ skia::ImageOperations::RESIZE_LANCZOS3,
+ gfx::Size(resized_width, resized_height));
+
+ scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes();
+ // Uses simple png encoder to encode image on worker pool. So we do not block
+ // chrome shutdown on image encoding.
+ SimpleJpegEncoder* jpeg_encoder = new SimpleJpegEncoder(
+ data, *(resized_image.bitmap()));
+ jpeg_encoder->Run(
+ base::Bind(&WallpaperManager::OnWallpaperEncoded,
+ weak_factory_.GetWeakPtr(),
+ path));
}
void WallpaperManager::SaveWallpaperInternal(const FilePath& path,
@@ -862,35 +1013,37 @@ void WallpaperManager::SaveWallpaperInternal(const FilePath& path,
DCHECK(written_bytes == size);
}
-void WallpaperManager::SetWallpaper(const std::string& username,
- ash::WallpaperLayout layout,
- User::WallpaperType type,
- base::WeakPtr<WallpaperDelegate> delegate,
- const UserImage& wallpaper) {
+void WallpaperManager::SetCustomWallpaper(const std::string& username,
+ ash::WallpaperLayout layout,
+ User::WallpaperType type,
+ base::WeakPtr<WallpaperDelegate> delegate,
+ const UserImage& wallpaper) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
std::string wallpaper_path =
- GetWallpaperPathForUser(username, false).value();
+ GetOriginalWallpaperPathForUser(username).value();
bool is_persistent = ShouldPersistDataForUser(username);
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&WallpaperManager::GenerateUserWallpaperThumbnail,
+ base::Unretained(this), username, type, delegate,
+ wallpaper.image()));
+
if (is_persistent) {
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
- base::Bind(&WallpaperManager::SaveWallpaper,
+ base::Bind(&WallpaperManager::SaveCustomWallpaper,
base::Unretained(this),
+ username,
FilePath(wallpaper_path),
+ layout,
wallpaper));
}
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&WallpaperManager::GenerateUserWallpaperThumbnail,
- base::Unretained(this), username, type, delegate,
- wallpaper.image()));
-
ash::Shell::GetInstance()->desktop_background_controller()->
SetCustomWallpaper(wallpaper.image(), layout);
SetUserWallpaperProperties(username, type, layout, is_persistent);

Powered by Google App Engine
This is Rietveld 408576698