summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 13:49:40 +0000
committerygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 13:49:40 +0000
commit44013f6828207c9b179f29cd8bb1559d6e81c28c (patch)
treeb15568d83a0ce114707f7d8790d3f4decee524c1
parent2eb6b89474c70bf69590fe07ab57bd95ca407b69 (diff)
downloadchromium_src-44013f6828207c9b179f29cd8bb1559d6e81c28c.zip
chromium_src-44013f6828207c9b179f29cd8bb1559d6e81c28c.tar.gz
chromium_src-44013f6828207c9b179f29cd8bb1559d6e81c28c.tar.bz2
Added support for animated/nonanimated user image. There are no
optimizations (for instance, image is still decoded to PNG at each request) and bug with replaying animation at each click on already active user pod, but CL is big enough, so we should start review. BUG=114083 TEST=none Review URL: https://chromiumcodereview.appspot.com/10454044 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139779 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/automation/automation_provider_observers_chromeos.cc3
-rw-r--r--chrome/browser/chromeos/login/mock_user_manager.h3
-rw-r--r--chrome/browser/chromeos/login/user.cc20
-rw-r--r--chrome/browser/chromeos/login/user.h11
-rw-r--r--chrome/browser/chromeos/login/user_image.cc48
-rw-r--r--chrome/browser/chromeos/login/user_image.h50
-rw-r--r--chrome/browser/chromeos/login/user_image_loader.cc20
-rw-r--r--chrome/browser/chromeos/login/user_image_loader.h12
-rw-r--r--chrome/browser/chromeos/login/user_image_screen.cc4
-rw-r--r--chrome/browser/chromeos/login/user_manager.h3
-rw-r--r--chrome/browser/chromeos/login/user_manager_impl.cc69
-rw-r--r--chrome/browser/chromeos/login/user_manager_impl.h17
-rw-r--r--chrome/browser/image_decoder.cc2
-rw-r--r--chrome/browser/image_decoder.h6
-rw-r--r--chrome/browser/resources/chromeos/login/user_pod_row.js2
-rw-r--r--chrome/browser/resources/options2/chromeos/change_picture_options.js3
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler2.cc7
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/user_image_source2.cc73
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/user_image_source2.h12
-rw-r--r--chrome/chrome_browser.gypi2
20 files changed, 289 insertions, 78 deletions
diff --git a/chrome/browser/automation/automation_provider_observers_chromeos.cc b/chrome/browser/automation/automation_provider_observers_chromeos.cc
index af0d864..16c5697 100644
--- a/chrome/browser/automation/automation_provider_observers_chromeos.cc
+++ b/chrome/browser/automation/automation_provider_observers_chromeos.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
+#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/common/chrome_notification_types.h"
@@ -450,7 +451,7 @@ void PhotoCaptureObserver::OnCapturingStopped(
// Set up an observer for UserManager (it will delete itself).
user_manager->AddObserver(this);
- user_manager->SaveUserImage(user.email(), photo);
+ user_manager->SaveUserImage(user.email(), chromeos::UserImage(photo));
}
void PhotoCaptureObserver::LocalStateChanged(
diff --git a/chrome/browser/chromeos/login/mock_user_manager.h b/chrome/browser/chromeos/login/mock_user_manager.h
index c99475d..d845da9 100644
--- a/chrome/browser/chromeos/login/mock_user_manager.h
+++ b/chrome/browser/chromeos/login/mock_user_manager.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/file_path.h"
+#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -41,7 +42,7 @@ class MockUserManager : public UserManager {
int));
MOCK_CONST_METHOD1(GetUserDisplayEmail, std::string(const std::string&));
MOCK_METHOD2(SaveUserDefaultImageIndex, void(const std::string&, int));
- MOCK_METHOD2(SaveUserImage, void(const std::string&, const SkBitmap&));
+ MOCK_METHOD2(SaveUserImage, void(const std::string&, const UserImage&));
MOCK_METHOD1(SetLoggedInUserCustomWallpaperLayout,void(
ash::WallpaperLayout));
MOCK_METHOD2(SaveUserImageFromFile, void(const std::string&,
diff --git a/chrome/browser/chromeos/login/user.cc b/chrome/browser/chromeos/login/user.cc
index 80d10e2..0d27050 100644
--- a/chrome/browser/chromeos/login/user.cc
+++ b/chrome/browser/chromeos/login/user.cc
@@ -30,6 +30,8 @@ std::string GetUserName(const std::string& email) {
User::User(const std::string& email, bool is_guest)
: email_(email),
+ user_image_(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ kDefaultImageResources[0])),
oauth_token_status_(OAUTH_TOKEN_STATUS_UNKNOWN),
image_index_(kInvalidImageIndex),
image_is_stub_(false),
@@ -42,21 +44,19 @@ User::User(const std::string& email, bool is_guest)
} else {
is_demo_user_ = true;
}
- image_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
- kDefaultImageResources[0]);
}
User::~User() {}
-void User::SetImage(const SkBitmap& image, int image_index) {
- image_ = image;
+void User::SetImage(const UserImage& user_image, int image_index) {
+ user_image_ = user_image;
image_index_ = image_index;
image_is_stub_ = false;
}
void User::SetStubImage(int image_index) {
- image_ = *ResourceBundle::GetSharedInstance().
- GetBitmapNamed(kStubImageResourceID);
+ user_image_.SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ kStubImageResourceID));
image_index_ = image_index;
image_is_stub_ = true;
}
@@ -77,6 +77,14 @@ bool User::NeedsNameTooltip() const {
return !UserManager::Get()->IsDisplayNameUnique(GetDisplayName());
}
+bool User::GetAnimatedImage(UserImage::RawImage* raw_image) const {
+ if (raw_image && has_animated_image()) {
+ *raw_image = user_image_.raw_image();
+ return true;
+ }
+ return false;
+}
+
std::string User::GetNameTooltip() const {
const std::string& user_email = display_email_;
size_t at_pos = user_email.rfind('@');
diff --git a/chrome/browser/chromeos/login/user.h b/chrome/browser/chromeos/login/user.h
index 24a926b..8b3f7dc 100644
--- a/chrome/browser/chromeos/login/user.h
+++ b/chrome/browser/chromeos/login/user.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "chrome/browser/chromeos/login/user_image.h"
#include "third_party/skia/include/core/SkBitmap.h"
// The demo user is represented by a domainless username.
@@ -62,8 +63,11 @@ class User {
bool NeedsNameTooltip() const;
// The image for this user.
- const SkBitmap& image() const { return image_; }
+ const SkBitmap& image() const { return user_image_.image(); }
int image_index() const { return image_index_; }
+ bool has_animated_image() const { return user_image_.has_animated_image(); }
+
+ bool GetAnimatedImage(UserImage::RawImage* raw_image) const;
// The thumbnail of user custom wallpaper.
const SkBitmap& wallpaper_thumbnail() const { return wallpaper_thumbnail_; }
@@ -90,7 +94,8 @@ class User {
~User();
// Setters are private so only UserManager can call them.
- void SetImage(const SkBitmap& image, int image_index);
+ void SetImage(const UserImage& user_image, int image_index);
+
// Sets a stub image until the next |SetImage| call. |image_index| may be
// one of |kExternalImageIndex| or |kProfileImageIndex|.
void SetStubImage(int image_index);
@@ -109,7 +114,7 @@ class User {
std::string email_;
// The displayed user email, defaults to |email_|.
std::string display_email_;
- SkBitmap image_;
+ UserImage user_image_;
OAuthTokenStatus oauth_token_status_;
SkBitmap wallpaper_thumbnail_;
diff --git a/chrome/browser/chromeos/login/user_image.cc b/chrome/browser/chromeos/login/user_image.cc
new file mode 100644
index 0000000..ecbae9e
--- /dev/null
+++ b/chrome/browser/chromeos/login/user_image.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/user_image.h"
+
+namespace chromeos {
+
+namespace {
+
+bool IsAnimatedImage(const UserImage::RawImage& data) {
+ const char kGIFStamp[] = "GIF";
+ const size_t kGIFStampLength = sizeof(kGIFStamp) - 1;
+
+ if (data.size() >= kGIFStampLength &&
+ memcmp(&data[0], kGIFStamp, kGIFStampLength) == 0) {
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+UserImage::UserImage(const SkBitmap& image)
+ : image_(image),
+ has_raw_image_(false),
+ has_animated_image_(false) {
+}
+
+UserImage::UserImage(const SkBitmap& image,
+ const RawImage& raw_image)
+ : image_(image),
+ has_raw_image_(true),
+ has_animated_image_(IsAnimatedImage(raw_image)),
+ raw_image_(raw_image) {
+}
+
+UserImage::~UserImage() {}
+
+void UserImage::SetImage(const SkBitmap& image) {
+ image_ = image;
+ has_raw_image_ = false;
+ has_animated_image_ = false;
+ // Clear |raw_image_|.
+ RawImage().swap(raw_image_);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_image.h b/chrome/browser/chromeos/login/user_image.h
new file mode 100644
index 0000000..5edbd7f
--- /dev/null
+++ b/chrome/browser/chromeos/login/user_image.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_H_
+#pragma once
+
+#include <vector>
+
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace chromeos {
+
+// Wrapper class for bitmaps and raw images when it's necessary. Could
+// be used for storing profile images (including animated profile
+// images) and user wallpapers.
+class UserImage {
+ public:
+ typedef std::vector<unsigned char> RawImage;
+
+ // Constructs UserImage from bitmap. Should be used where only
+ // static image is needed (e.g. wallpapers).
+ explicit UserImage(const SkBitmap& image);
+
+ // Constructs UserImage from raw image and bitmap that should
+ // represent single frame from that one. Can be used for wrapping
+ // animated images.
+ UserImage(const SkBitmap& image, const RawImage& raw_image);
+
+ virtual ~UserImage();
+
+ // Replaces already stored image to new |image|. Note, that
+ // |raw_image| will be reset after that operation.
+ void SetImage(const SkBitmap& image);
+ const SkBitmap& image() const { return image_; }
+ bool has_raw_image() const { return has_raw_image_; }
+ bool has_animated_image() const { return has_animated_image_; }
+ const RawImage& raw_image() const { return raw_image_; }
+
+ private:
+ SkBitmap image_;
+ bool has_raw_image_;
+ bool has_animated_image_;
+ RawImage raw_image_;
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_H_
diff --git a/chrome/browser/chromeos/login/user_image_loader.cc b/chrome/browser/chromeos/login/user_image_loader.cc
index 21b8813..143ee4a 100644
--- a/chrome/browser/chromeos/login/user_image_loader.cc
+++ b/chrome/browser/chromeos/login/user_image_loader.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,8 +7,10 @@
#include "base/bind.h"
#include "base/file_path.h"
#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/user_image.h"
#include "content/public/browser/browser_thread.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -19,8 +21,11 @@ using content::BrowserThread;
namespace chromeos {
-UserImageLoader::ImageInfo::ImageInfo(int size, const LoadedCallback& loaded_cb)
+UserImageLoader::ImageInfo::ImageInfo(int size,
+ bool load_raw_image,
+ const LoadedCallback& loaded_cb)
: size(size),
+ load_raw_image(load_raw_image),
loaded_cb(loaded_cb) {
}
@@ -36,10 +41,11 @@ UserImageLoader::~UserImageLoader() {
void UserImageLoader::Start(const std::string& filepath,
int size,
+ bool load_raw_image,
const LoadedCallback& loaded_cb) {
target_message_loop_ = MessageLoop::current();
- ImageInfo image_info(size, loaded_cb);
+ ImageInfo image_info(size, load_raw_image, loaded_cb);
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&UserImageLoader::LoadImage, this, filepath, image_info));
@@ -86,9 +92,15 @@ void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder,
image_info.size);
}
+ scoped_ptr<UserImage> user_image;
+ if (image_info.load_raw_image)
+ user_image.reset(new UserImage(final_image, decoder->get_image_data()));
+ else
+ user_image.reset(new UserImage(final_image));
+
target_message_loop_->PostTask(
FROM_HERE,
- base::Bind(image_info.loaded_cb, final_image));
+ base::Bind(image_info.loaded_cb, *user_image));
image_info_map_.erase(info_it);
}
diff --git a/chrome/browser/chromeos/login/user_image_loader.h b/chrome/browser/chromeos/login/user_image_loader.h
index ed8d889..9433a52 100644
--- a/chrome/browser/chromeos/login/user_image_loader.h
+++ b/chrome/browser/chromeos/login/user_image_loader.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -19,20 +19,23 @@ class SkBitmap;
namespace chromeos {
+class UserImage;
+
// A facility to read a file containing user image asynchronously in the IO
// thread. Returns the image in the form of an SkBitmap.
class UserImageLoader : public base::RefCountedThreadSafe<UserImageLoader>,
public ImageDecoder::Delegate {
public:
// Callback used to inidicate that image has been loaded.
- typedef base::Callback<void(const SkBitmap& image)> LoadedCallback;
+ typedef base::Callback<void(const UserImage& user_image)> LoadedCallback;
UserImageLoader();
// Start reading the image from |filepath| on the file thread. Calls
// |loaded_cb| when image has been successfully loaded.
// If |size| is positive, image is resized to |size|x|size| pixels.
- void Start(const std::string& filepath, int size,
+ // If |load_raw_image| is true, raw image is also passed to callback.
+ void Start(const std::string& filepath, int size, bool load_raw_image,
const LoadedCallback& loaded_cb);
private:
@@ -40,10 +43,11 @@ class UserImageLoader : public base::RefCountedThreadSafe<UserImageLoader>,
// Contains attributes we need to know about each image we decode.
struct ImageInfo {
- ImageInfo(int size, const LoadedCallback& loaded_cb);
+ ImageInfo(int size, bool load_raw_image, const LoadedCallback& loaded_cb);
~ImageInfo();
int size;
+ bool load_raw_image;
LoadedCallback loaded_cb;
};
diff --git a/chrome/browser/chromeos/login/user_image_screen.cc b/chrome/browser/chromeos/login/user_image_screen.cc
index 7f80c6b..25d7e59 100644
--- a/chrome/browser/chromeos/login/user_image_screen.cc
+++ b/chrome/browser/chromeos/login/user_image_screen.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/chromeos/login/default_user_images.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
+#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_service.h"
@@ -109,7 +110,8 @@ void UserImageScreen::StopCamera() {
void UserImageScreen::OnPhotoTaken(const SkBitmap& image) {
UserManager* user_manager = UserManager::Get();
- user_manager->SaveUserImage(user_manager->GetLoggedInUser().email(), image);
+ user_manager->SaveUserImage(user_manager->GetLoggedInUser().email(),
+ UserImage(image));
get_screen_observer()->OnExit(ScreenObserver::USER_IMAGE_SELECTED);
diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h
index e504317..31b2c30 100644
--- a/chrome/browser/chromeos/login/user_manager.h
+++ b/chrome/browser/chromeos/login/user_manager.h
@@ -20,6 +20,7 @@ class PrefService;
namespace chromeos {
class RemoveUserDelegate;
+class UserImage;
// Base class for UserManagerImpl - provides a mechanism for discovering users
// who have logged into this Chrome OS device before and updating that list.
@@ -174,7 +175,7 @@ class UserManager {
// Saves image to file, sends LOGIN_USER_IMAGE_CHANGED notification and
// updates Local State.
virtual void SaveUserImage(const std::string& username,
- const SkBitmap& image) = 0;
+ const UserImage& user_image) = 0;
// Updates custom wallpaper to selected layout and saves layout to Local
// State.
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index 611f211..1416a2d 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -35,6 +35,7 @@
#include "chrome/browser/chromeos/login/login_display.h"
#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/remove_user_delegate.h"
+#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
@@ -354,7 +355,7 @@ void UserManagerImpl::EphemeralUserLoggedIn(const std::string& email) {
void UserManagerImpl::StubUserLoggedIn() {
is_current_user_ephemeral_ = true;
logged_in_user_ = new User(kStubUser, false);
- logged_in_user_->SetImage(GetDefaultImage(kStubDefaultImageIndex),
+ logged_in_user_->SetImage(UserImage(GetDefaultImage(kStubDefaultImageIndex)),
kStubDefaultImageIndex);
}
@@ -376,9 +377,9 @@ void UserManagerImpl::UserSelected(const std::string& email) {
ash::WallpaperLayout layout = static_cast<ash::WallpaperLayout>(index);
// Load user image asynchronously.
image_loader_->Start(
- wallpaper_path, 0,
+ wallpaper_path, 0, false,
base::Bind(&UserManagerImpl::OnCustomWallpaperLoaded,
- base::Unretained(this), email, layout));
+ base::Unretained(this), email, layout));
return;
}
ash::Shell::GetInstance()->desktop_background_controller()->
@@ -520,13 +521,13 @@ std::string UserManagerImpl::GetUserDisplayEmail(
void UserManagerImpl::SaveUserDefaultImageIndex(const std::string& username,
int image_index) {
DCHECK(image_index >= 0 && image_index < kDefaultImagesCount);
- SetUserImage(username, image_index, GetDefaultImage(image_index));
+ SetUserImage(username, image_index, UserImage(GetDefaultImage(image_index)));
SaveImageToLocalState(username, "", image_index, false);
}
void UserManagerImpl::SaveUserImage(const std::string& username,
- const SkBitmap& image) {
- SaveUserImageInternal(username, User::kExternalImageIndex, image);
+ const UserImage& user_image) {
+ SaveUserImageInternal(username, User::kExternalImageIndex, user_image);
}
void UserManagerImpl::SetLoggedInUserCustomWallpaperLayout(
@@ -549,7 +550,7 @@ void UserManagerImpl::SetLoggedInUserCustomWallpaperLayout(
void UserManagerImpl::SaveUserImageFromFile(const std::string& username,
const FilePath& path) {
image_loader_->Start(
- path.value(), login::kUserImageSize,
+ path.value(), login::kUserImageSize, true,
base::Bind(&UserManagerImpl::SaveUserImage,
base::Unretained(this), username));
}
@@ -560,7 +561,7 @@ void UserManagerImpl::SaveUserWallpaperFromFile(const std::string& username,
WallpaperDelegate* delegate) {
// For wallpapers, save the image without resizing.
image_loader_->Start(
- path.value(), 0 /* Original size */,
+ path.value(), 0 /* Original size */, false,
base::Bind(&UserManagerImpl::SaveUserWallpaperInternal,
base::Unretained(this), username, layout, User::CUSTOMIZED,
delegate));
@@ -571,10 +572,10 @@ void UserManagerImpl::SaveUserImageFromProfileImage(
if (!downloaded_profile_image_.empty()) {
// Profile image has already been downloaded, so save it to file right now.
SaveUserImageInternal(username, User::kProfileImageIndex,
- downloaded_profile_image_);
+ UserImage(downloaded_profile_image_));
} else {
// No profile image - use the stub image (gray avatar).
- SetUserImage(username, User::kProfileImageIndex, SkBitmap());
+ SetUserImage(username, User::kProfileImageIndex, UserImage(SkBitmap()));
SaveImageToLocalState(username, "", User::kProfileImageIndex, false);
}
}
@@ -748,7 +749,7 @@ void UserManagerImpl::EnsureUsersLoaded() {
if (prefs_images->GetStringWithoutPathExpansion(email, &image_path)) {
int image_id = User::kInvalidImageIndex;
if (IsDefaultImagePath(image_path, &image_id)) {
- user->SetImage(GetDefaultImage(image_id), image_id);
+ user->SetImage(UserImage(GetDefaultImage(image_id)), image_id);
} else {
int image_index = User::kExternalImageIndex;
// Until image has been loaded, use the stub image.
@@ -756,7 +757,7 @@ void UserManagerImpl::EnsureUsersLoaded() {
DCHECK(!image_path.empty());
// Load user image asynchronously.
image_loader_->Start(
- image_path, 0,
+ image_path, 0, true,
base::Bind(&UserManagerImpl::SetUserImage,
base::Unretained(this), email, image_index));
}
@@ -766,7 +767,8 @@ void UserManagerImpl::EnsureUsersLoaded() {
image_properties->GetString(kImagePathNodeName, &image_path);
image_properties->GetInteger(kImageIndexNodeName, &image_index);
if (image_index >= 0 && image_index < kDefaultImagesCount) {
- user->SetImage(GetDefaultImage(image_index), image_index);
+ user->SetImage(UserImage(GetDefaultImage(image_index)),
+ image_index);
} else if (image_index == User::kExternalImageIndex ||
image_index == User::kProfileImageIndex) {
// Path may be empty for profile images (meaning that the image
@@ -780,7 +782,7 @@ void UserManagerImpl::EnsureUsersLoaded() {
if (!image_path.empty()) {
// Load user image asynchronously.
image_loader_->Start(
- image_path, 0,
+ image_path, 0, true,
base::Bind(&UserManagerImpl::SetUserImage,
base::Unretained(this), email, image_index));
}
@@ -986,7 +988,7 @@ void UserManagerImpl::SaveLoggedInUserWallpaperProperties(
void UserManagerImpl::SetUserImage(const std::string& username,
int image_index,
- const SkBitmap& image) {
+ const UserImage& user_image) {
User* user = const_cast<User*>(FindUser(username));
// User may have been removed by now.
if (user) {
@@ -995,8 +997,8 @@ void UserManagerImpl::SetUserImage(const std::string& username,
DCHECK(user->image_index() != User::kInvalidImageIndex ||
is_current_user_new_);
bool image_changed = user->image_index() != User::kInvalidImageIndex;
- if (!image.empty())
- user->SetImage(image, image_index);
+ if (!user_image.image().empty())
+ user->SetImage(user_image, image_index);
else
user->SetStubImage(image_index);
// For the logged-in user with a profile picture, initialize
@@ -1069,10 +1071,10 @@ void UserManagerImpl::SaveUserWallpaperProperties(const std::string& username,
void UserManagerImpl::SaveUserImageInternal(const std::string& username,
int image_index,
- const SkBitmap& image) {
+ const UserImage& user_image) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SetUserImage(username, image_index, image);
+ SetUserImage(username, image_index, user_image);
// Ignore for ephemeral users.
if (IsEphemeralUser(username))
@@ -1088,16 +1090,17 @@ void UserManagerImpl::SaveUserImageInternal(const std::string& username,
FROM_HERE,
base::Bind(&UserManagerImpl::SaveImageToFile,
base::Unretained(this),
- username, image, image_path, image_index));
+ username, user_image, image_path, image_index));
}
void UserManagerImpl::SaveUserWallpaperInternal(const std::string& username,
ash::WallpaperLayout layout,
User::WallpaperType type,
WallpaperDelegate* delegate,
- const SkBitmap& wallpaper) {
+ const UserImage& user_image) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ const SkBitmap& wallpaper = user_image.image();
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
@@ -1126,21 +1129,23 @@ void UserManagerImpl::SaveUserWallpaperInternal(const std::string& username,
void UserManagerImpl::OnCustomWallpaperLoaded(const std::string& email,
ash::WallpaperLayout layout,
- const SkBitmap& wallpaper) {
+ const UserImage& user_image) {
+ const SkBitmap& wallpaper = user_image.image();
ash::Shell::GetInstance()->desktop_background_controller()->
SetCustomWallpaper(wallpaper, layout);
// Starting to load wallpaper thumbnail
std::string wallpaper_thumbnail_path =
GetWallpaperPathForUser(email, true).value();
image_loader_->Start(
- wallpaper_thumbnail_path, 0,
+ wallpaper_thumbnail_path, 0, false,
base::Bind(&UserManagerImpl::OnCustomWallpaperThumbnailLoaded,
base::Unretained(this), email));
}
void UserManagerImpl::OnCustomWallpaperThumbnailLoaded(
const std::string& email,
- const SkBitmap& wallpaper) {
+ const UserImage& user_image) {
+ const SkBitmap& wallpaper = user_image.image();
User* user = const_cast<User*>(FindUser(email));
// User may have been removed by now.
if (user && !wallpaper.empty())
@@ -1176,14 +1181,14 @@ void UserManagerImpl::GenerateUserWallpaperThumbnail(
return;
FilePath thumbnail_path = GetWallpaperPathForUser(username, true);
- SaveBitmapToFile(thumbnail, thumbnail_path);
+ SaveBitmapToFile(UserImage(thumbnail), thumbnail_path);
}
void UserManagerImpl::SaveImageToFile(const std::string& username,
- const SkBitmap& image,
+ const UserImage& user_image,
const FilePath& image_path,
int image_index) {
- if (!SaveBitmapToFile(image, image_path))
+ if (!SaveBitmapToFile(user_image, image_path))
return;
BrowserThread::PostTask(
@@ -1201,7 +1206,7 @@ void UserManagerImpl::SaveWallpaperToFile(const std::string& username,
User::WallpaperType type) {
// TODO(bshe): We should save the original file unchanged instead of
// re-encoding it and saving it.
- if (!SaveBitmapToFile(wallpaper, wallpaper_path))
+ if (!SaveBitmapToFile(UserImage(wallpaper), wallpaper_path))
return;
BrowserThread::PostTask(
@@ -1253,12 +1258,16 @@ void UserManagerImpl::SaveWallpaperToLocalState(const std::string& username,
SaveUserWallpaperProperties(username, type, layout);
}
-bool UserManagerImpl::SaveBitmapToFile(const SkBitmap& image,
+bool UserManagerImpl::SaveBitmapToFile(const UserImage& user_image,
const FilePath& image_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
std::vector<unsigned char> encoded_image;
- if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &encoded_image)) {
+ if (user_image.has_raw_image()) {
+ encoded_image = user_image.raw_image();
+ } else if (!gfx::PNGCodec::EncodeBGRASkBitmap(user_image.image(),
+ false,
+ &encoded_image)) {
LOG(ERROR) << "Failed to PNG encode the image.";
return false;
}
diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h
index a68b333..21e033f 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_manager_impl.h
@@ -32,6 +32,7 @@ class ProfileSyncService;
namespace chromeos {
class RemoveUserDelegate;
+class UserImage;
// Implementation of the UserManager.
class UserManagerImpl : public UserManager,
@@ -73,7 +74,7 @@ class UserManagerImpl : public UserManager,
virtual void SaveUserDefaultImageIndex(const std::string& username,
int image_index) OVERRIDE;
virtual void SaveUserImage(const std::string& username,
- const SkBitmap& image) OVERRIDE;
+ const UserImage& user_image) OVERRIDE;
virtual void SetLoggedInUserCustomWallpaperLayout(
ash::WallpaperLayout layout) OVERRIDE;
virtual void SaveUserImageFromFile(const std::string& username,
@@ -176,7 +177,7 @@ class UserManagerImpl : public UserManager,
// If |image| is empty, sets a stub image for the user.
void SetUserImage(const std::string& username,
int image_index,
- const SkBitmap& image);
+ const UserImage& user_image);
void GetUserWallpaperProperties(const std::string& username,
User::WallpaperType* type,
@@ -189,7 +190,7 @@ class UserManagerImpl : public UserManager,
// and sends LOGIN_USER_IMAGE_CHANGED notification.
void SaveUserImageInternal(const std::string& username,
int image_index,
- const SkBitmap& image);
+ const UserImage& user_image);
// Saves wallpaper to file, post task to generate thumbnail and updates local
// state preferences.
@@ -197,17 +198,17 @@ class UserManagerImpl : public UserManager,
ash::WallpaperLayout layout,
User::WallpaperType type,
WallpaperDelegate* delegate,
- const SkBitmap& image);
+ const UserImage& user_image);
// Sets desktop background to custom wallpaper and loads wallpaper thumbnail
// asynchronously.
void OnCustomWallpaperLoaded(const std::string& email,
ash::WallpaperLayout layout,
- const SkBitmap& wallpaper);
+ const UserImage& wallpaper);
// Caches the loaded wallpaper for the given user.
void OnCustomWallpaperThumbnailLoaded(const std::string& email,
- const SkBitmap& wallpaper);
+ const UserImage& user_image);
// Updates the custom wallpaper thumbnail in wallpaper picker UI.
void OnThumbnailUpdated(WallpaperDelegate* delegate);
@@ -222,7 +223,7 @@ class UserManagerImpl : public UserManager,
// notification. Runs on FILE thread. Posts task for saving image info to
// Local State on UI thread.
void SaveImageToFile(const std::string& username,
- const SkBitmap& image,
+ const UserImage& user_image,
const FilePath& image_path,
int image_index);
@@ -249,7 +250,7 @@ class UserManagerImpl : public UserManager,
User::WallpaperType type);
// Saves |image| to the specified |image_path|. Runs on FILE thread.
- bool SaveBitmapToFile(const SkBitmap& image,
+ bool SaveBitmapToFile(const UserImage& user_image,
const FilePath& image_path);
// Initializes |downloaded_profile_picture_| with the picture of the logged-in
diff --git a/chrome/browser/image_decoder.cc b/chrome/browser/image_decoder.cc
index 8e3eb71..a345c77 100644
--- a/chrome/browser/image_decoder.cc
+++ b/chrome/browser/image_decoder.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chrome/browser/image_decoder.h b/chrome/browser/image_decoder.h
index 8c9c028..148454b 100644
--- a/chrome/browser/image_decoder.h
+++ b/chrome/browser/image_decoder.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -40,6 +40,10 @@ class ImageDecoder : public content::UtilityProcessHostClient {
// Starts image decoding.
void Start();
+ const std::vector<unsigned char>& get_image_data() const {
+ return image_data_;
+ }
+
private:
// It's a reference counted object, so destructor is private.
virtual ~ImageDecoder();
diff --git a/chrome/browser/resources/chromeos/login/user_pod_row.js b/chrome/browser/resources/chromeos/login/user_pod_row.js
index 2e564cb..9ed5841 100644
--- a/chrome/browser/resources/chromeos/login/user_pod_row.js
+++ b/chrome/browser/resources/chromeos/login/user_pod_row.js
@@ -352,7 +352,7 @@ cr.define('login', function() {
this.imageElement.src = this.isGuest ?
'chrome://theme/IDR_LOGIN_GUEST' :
'chrome://userimage/' + this.user.username +
- '?id=' + (new Date()).getTime();
+ '?id=' + (new Date()).getTime() + '&animated';
},
/**
diff --git a/chrome/browser/resources/options2/chromeos/change_picture_options.js b/chrome/browser/resources/options2/chromeos/change_picture_options.js
index abdfa63..87bb16a 100644
--- a/chrome/browser/resources/options2/chromeos/change_picture_options.js
+++ b/chrome/browser/resources/options2/chromeos/change_picture_options.js
@@ -186,7 +186,7 @@ cr.define('options', function() {
*/
get currentUserImageUrl() {
return 'chrome://userimage/' + BrowserOptions.getLoggedInUsername() +
- '?id=' + (new Date()).getTime();
+ '?id=' + (new Date()).getTime() + '&animated';
},
/**
@@ -295,4 +295,3 @@ cr.define('options', function() {
};
});
-
diff --git a/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler2.cc b/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler2.cc
index f2fa95e..8836814 100644
--- a/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler2.cc
+++ b/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler2.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "chrome/browser/chromeos/login/camera_detector.h"
#include "chrome/browser/chromeos/login/default_user_images.h"
+#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/options/take_photo_dialog.h"
#include "chrome/browser/profiles/profile.h"
@@ -258,7 +259,8 @@ void ChangePictureOptionsHandler::HandleSelectImage(const ListValue* args) {
// (profile image, current image from file) is easier.
DCHECK(!previous_image_.empty());
- user_manager->SaveUserImage(user.email(), previous_image_);
+ user_manager->SaveUserImage(user.email(),
+ chromeos::UserImage(previous_image_));
UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
kHistogramImageOld,
@@ -303,7 +305,8 @@ void ChangePictureOptionsHandler::FileSelected(const FilePath& path,
void ChangePictureOptionsHandler::OnPhotoAccepted(const SkBitmap& photo) {
UserManager* user_manager = UserManager::Get();
- user_manager->SaveUserImage(user_manager->GetLoggedInUser().email(), photo);
+ user_manager->SaveUserImage(user_manager->GetLoggedInUser().email(),
+ chromeos::UserImage(photo));
UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
kHistogramImageFromCamera,
kHistogramImagesCount);
diff --git a/chrome/browser/ui/webui/options2/chromeos/user_image_source2.cc b/chrome/browser/ui/webui/options2/chromeos/user_image_source2.cc
index 03d929b..3f8fe95 100644
--- a/chrome/browser/ui/webui/options2/chromeos/user_image_source2.cc
+++ b/chrome/browser/ui/webui/options2/chromeos/user_image_source2.cc
@@ -6,21 +6,69 @@
#include "base/memory/ref_counted_memory.h"
#include "base/message_loop.h"
+#include "base/string_split.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/common/url_constants.h"
+#include "googleurl/src/url_parse.h"
#include "grit/theme_resources.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/codec/png_codec.h"
+namespace {
+
+// Animated key is used in user image URL requests to specify that
+// animated version of user image is required. Without that key
+// non-animated version of user image should be returned.
+const char kKeyAnimated[] = "animated";
+
+// Extracts from user image request user email and type of requested
+// image (animated or non-animated). |path| is an user image request
+// and should look like "username@host?key1=value1&...&key_n=value_n".
+// So, "username@host" is stored into |email|. If a query part of
+// |path| contains "animated" key, |is_image_animated| is set to true,
+// otherwise |is_image_animated| is set to false.
+void ParseRequest(const std::string& path,
+ std::string* email,
+ bool* is_image_animated) {
+ url_parse::Parsed parsed;
+ url_parse::ParseStandardURL(path.c_str(), path.size(), &parsed);
+ DCHECK(parsed.username.is_valid());
+ DCHECK(parsed.host.is_valid());
+
+ DCHECK(email != NULL);
+ *email = path.substr(parsed.username.begin, parsed.username.len);
+ email->append("@");
+ email->append(path.substr(parsed.host.begin, parsed.host.len));
+
+ if (parsed.query.is_valid()) {
+ url_parse::Component query = parsed.query;
+ url_parse::Component key, value;
+
+ DCHECK(is_image_animated != NULL);
+ *is_image_animated = false;
+ while (ExtractQueryKeyValue(path.c_str(), &query, &key, &value)) {
+ if (path.substr(key.begin, key.len) == kKeyAnimated) {
+ *is_image_animated = true;
+ break;
+ }
+ }
+ }
+}
+
+} // namespace
+
namespace chromeos {
namespace options2 {
std::vector<unsigned char> UserImageSource::GetUserImage(
- const std::string& email) const {
+ const std::string& email, bool is_image_animated) const {
std::vector<unsigned char> user_image;
const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email);
if (user) {
- gfx::PNGCodec::EncodeBGRASkBitmap(user->image(), false, &user_image);
+ if (user->has_animated_image() && is_image_animated)
+ user->GetAnimatedImage(&user_image);
+ else
+ gfx::PNGCodec::EncodeBGRASkBitmap(user->image(), false, &user_image);
return user_image;
}
gfx::PNGCodec::EncodeBGRASkBitmap(
@@ -40,15 +88,26 @@ UserImageSource::~UserImageSource() {}
void UserImageSource::StartDataRequest(const std::string& path,
bool is_incognito,
int request_id) {
- // Strip the query param value - we only use it as a hack to ensure our
- // image gets reloaded instead of being pulled from the browser cache
- std::string email = path.substr(0, path.find_first_of("?"));
- SendResponse(request_id, new base::RefCountedBytes(GetUserImage(email)));
+ std::string email;
+ bool is_image_animated;
+ ParseRequest(path, &email, &is_image_animated);
+
+ std::vector<unsigned char> image = GetUserImage(email, is_image_animated);
+ SendResponse(request_id, new base::RefCountedBytes(image));
}
-std::string UserImageSource::GetMimeType(const std::string&) const {
+std::string UserImageSource::GetMimeType(const std::string& path) const {
// We need to explicitly return a mime type, otherwise if the user tries to
// drag the image they get no extension.
+ std::string email;
+ bool is_image_animated;
+ ParseRequest(path, &email, &is_image_animated);
+
+ if (is_image_animated) {
+ const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email);
+ if (user && user->has_animated_image())
+ return "image/gif";
+ }
return "image/png";
}
diff --git a/chrome/browser/ui/webui/options2/chromeos/user_image_source2.h b/chrome/browser/ui/webui/options2/chromeos/user_image_source2.h
index 6bea08e..b82078d 100644
--- a/chrome/browser/ui/webui/options2/chromeos/user_image_source2.h
+++ b/chrome/browser/ui/webui/options2/chromeos/user_image_source2.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -28,11 +28,13 @@ class UserImageSource : public ChromeURLDataManager::DataSource {
bool is_incognito,
int request_id) OVERRIDE;
- virtual std::string GetMimeType(const std::string&) const OVERRIDE;
+ virtual std::string GetMimeType(const std::string& path) const OVERRIDE;
- // Returns PNG encoded image for user with specified email.
- // If there's no user with such email, returns the default image.
- std::vector<unsigned char> GetUserImage(const std::string& email) const;
+ // Returns PNG or GIF (when possible and if |is_image_animated| flag
+ // is true) encoded image for user with specified email. If there's
+ // no user with such email, returns the default image.
+ std::vector<unsigned char> GetUserImage(const std::string& email,
+ bool is_image_animated) const;
private:
virtual ~UserImageSource();
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index ca2cfa3..95b127e 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -714,6 +714,8 @@
'browser/chromeos/login/update_screen_actor.h',
'browser/chromeos/login/user.cc',
'browser/chromeos/login/user.h',
+ 'browser/chromeos/login/user_image.cc',
+ 'browser/chromeos/login/user_image.h',
'browser/chromeos/login/user_image_loader.cc',
'browser/chromeos/login/user_image_loader.h',
'browser/chromeos/login/user_image_screen.cc',