Chromium Code Reviews| 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..ea24530824401b8a95471fc3e99681a5e8acd424 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_png_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,10 @@ const char kNewWallpaperLayoutNodeName[] = "layout"; |
| const char kNewWallpaperFileNodeName[] = "file"; |
| const char kNewWallpaperTypeNodeName[] = "type"; |
| +// File path suffices of resized small or large custom wallpaper. |
| +const char kSmallCustomWallpaperSuffix[] = "_small"; |
| +const char kLargeCustomWallpaperSuffix[] = "_large"; |
| + |
| gfx::ImageSkia GetWallpaperThumbnail(const gfx::ImageSkia& wallpaper) { |
| gfx::ImageSkia thumbnail = gfx::ImageSkiaOperations::CreateResizedImage( |
| wallpaper, |
| @@ -97,6 +102,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 +175,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 +207,18 @@ bool WallpaperManager::GetCustomWallpaperFromCache(const std::string& email, |
| return false; |
| } |
| +FilePath WallpaperManager::GetOriginalWallpaperPathForUser( |
| + const std::string& username) { |
| + std::string filename = username + "_wallpaper.png"; |
|
Ivan Korotkov
2012/08/30 10:53:15
This deserves a separate constant, too.
bshe
2012/08/30 16:39:02
Done.
|
| + 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 +408,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 +490,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 +510,7 @@ void WallpaperManager::SetUserWallpaper(const std::string& email) { |
| SetDefaultWallpaper(ash::GetDefaultWallpaperIndex(), false); |
| return; |
| } |
| + |
| LoadWallpaper(email, info); |
| } else { |
| User::WallpaperType type; |
| @@ -488,7 +528,7 @@ void WallpaperManager::SetUserWallpaper(const std::string& email) { |
| if (!UserManager::Get()->IsUserLoggedIn()) { |
| index = ash::GetDefaultWallpaperIndex(); |
| } else { |
| - FetchCustomWallpaper(email); |
| + GetCustomWallpaper(email); |
| return; |
| } |
| } |
| @@ -516,6 +556,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 +629,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 +692,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 +813,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 +894,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 +916,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. |
| + SimplePngEncoder* png_encoder = new SimplePngEncoder( |
| + data, *(resized_image.bitmap())); |
| + png_encoder->Run( |
| + base::Bind(&WallpaperManager::OnWallpaperEncoded, |
| + weak_factory_.GetWeakPtr(), |
| + path)); |
| } |
| void WallpaperManager::SaveWallpaperInternal(const FilePath& path, |
| @@ -862,35 +1009,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); |