This source file includes following definitions.
- AddProfileImageTimeHistogram
- ImageIndexToHistogramIndex
- SaveImage
- RegisterPrefs
- user_id
- weak_factory_
- LoadImage
- SetToDefaultImage
- SetToImage
- SetToImageData
- SetToPath
- OnLoadImageDone
- UpdateUser
- SaveImageAndUpdateLocalState
- OnSaveImageDone
- UpdateLocalState
- NotifyJobDone
- weak_factory_
- LoadUserImage
- UserLoggedIn
- SaveUserDefaultImageIndex
- SaveUserImage
- SaveUserImageFromFile
- SaveUserImageFromProfileImage
- DeleteUserImage
- DownloadProfileImage
- DownloadedProfileImage
- GetSyncObserver
- Shutdown
- OnExternalDataSet
- OnExternalDataCleared
- OnExternalDataFetched
- IgnoreProfileDataDownloadDelayForTesting
- NeedsProfilePicture
- GetDesiredImageSideLength
- GetBrowserProfile
- GetCachedPictureURL
- OnProfileDownloadSuccess
- OnProfileDownloadFailure
- IsUserImageManaged
- SetInitialUserImage
- TryToInitDownloadedProfileImage
- NeedProfileImage
- DownloadProfileData
- DeleteUserImageAndLocalStateEntry
- OnJobChangedUserImage
- OnJobDone
- UpdateLocalStateAfterMigration
- TryToCreateImageSyncObserver
- GetUser
- GetUserAndModify
- IsUserLoggedInAndRegular
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/rand_util.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/default_user_images.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/chromeos/login/user_image_sync_observer.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
#include "chrome/browser/profiles/profile_downloader.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chromeos/chromeos_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "policy/policy_constants.h"
#include "ui/gfx/image/image_skia.h"
namespace chromeos {
namespace {
const char kUserImages[] = "UserImages";
const char kUserImageProperties[] = "user_image_info";
const char kImagePathNodeName[] = "path";
const char kImageIndexNodeName[] = "index";
const char kImageURLNodeName[] = "url";
const int kProfileDataDownloadDelaySec = 10;
const int kProfileDataDownloadRetryIntervalSec = 300;
const int kProfileRefreshIntervalSec = 24 * 3600;
const char kSafeImagePathExtension[] = ".jpg";
enum ProfileDownloadResult {
kDownloadSuccessChanged,
kDownloadSuccess,
kDownloadFailure,
kDownloadDefault,
kDownloadCached,
kDownloadResultsCount
};
const char kProfileDownloadCachedTime[] =
"UserImage.ProfileDownloadTime.Cached";
const char kProfileDownloadDefaultTime[] =
"UserImage.ProfileDownloadTime.Default";
const char kProfileDownloadFailureTime[] =
"UserImage.ProfileDownloadTime.Failure";
const char kProfileDownloadSuccessTime[] =
"UserImage.ProfileDownloadTime.Success";
const char kProfileDownloadReasonLoggedIn[] = "LoggedIn";
const char kProfileDownloadReasonProfileImageChosen[] = "ProfileImageChosen";
const char kProfileDownloadReasonScheduled[] = "Scheduled";
const char kProfileDownloadReasonRetry[] = "Retry";
static bool g_ignore_profile_data_download_delay_ = false;
void AddProfileImageTimeHistogram(ProfileDownloadResult result,
const std::string& download_reason,
const base::TimeDelta& time_delta) {
std::string histogram_name;
switch (result) {
case kDownloadFailure:
histogram_name = kProfileDownloadFailureTime;
break;
case kDownloadDefault:
histogram_name = kProfileDownloadDefaultTime;
break;
case kDownloadSuccess:
histogram_name = kProfileDownloadSuccessTime;
break;
case kDownloadCached:
histogram_name = kProfileDownloadCachedTime;
break;
default:
NOTREACHED();
}
if (!download_reason.empty()) {
histogram_name += ".";
histogram_name += download_reason;
}
static const base::TimeDelta min_time = base::TimeDelta::FromMilliseconds(1);
static const base::TimeDelta max_time = base::TimeDelta::FromSeconds(50);
const size_t bucket_count(50);
base::HistogramBase* counter = base::Histogram::FactoryTimeGet(
histogram_name, min_time, max_time, bucket_count,
base::HistogramBase::kUmaTargetedHistogramFlag);
counter->AddTime(time_delta);
DVLOG(1) << "Profile image download time: " << time_delta.InSecondsF();
}
int ImageIndexToHistogramIndex(int image_index) {
switch (image_index) {
case User::kExternalImageIndex:
return kHistogramImageFromCamera;
case User::kProfileImageIndex:
return kHistogramImageFromProfile;
default:
return image_index;
}
}
bool SaveImage(const UserImage& user_image, const base::FilePath& image_path) {
UserImage safe_image;
const UserImage::RawImage* encoded_image = NULL;
if (!user_image.is_safe_format()) {
safe_image = UserImage::CreateAndEncode(user_image.image());
encoded_image = &safe_image.raw_image();
UMA_HISTOGRAM_MEMORY_KB("UserImage.RecodedJpegSize", encoded_image->size());
} else if (user_image.has_raw_image()) {
encoded_image = &user_image.raw_image();
} else {
NOTREACHED() << "Raw image missing.";
return false;
}
if (!encoded_image->size() ||
base::WriteFile(image_path,
reinterpret_cast<const char*>(&(*encoded_image)[0]),
encoded_image->size()) == -1) {
LOG(ERROR) << "Failed to save image to file.";
return false;
}
return true;
}
}
void UserImageManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(kUserImages);
registry->RegisterDictionaryPref(kUserImageProperties);
}
class UserImageManagerImpl::Job {
public:
explicit Job(UserImageManagerImpl* parent);
~Job();
void LoadImage(base::FilePath image_path,
const int image_index,
const GURL& image_url);
void SetToDefaultImage(int default_image_index);
void SetToImage(int image_index, const UserImage& user_image);
void SetToImageData(scoped_ptr<std::string> data);
void SetToPath(const base::FilePath& path,
int image_index,
const GURL& image_url,
bool resize);
private:
void OnLoadImageDone(bool save, const UserImage& user_image);
void UpdateUser();
void SaveImageAndUpdateLocalState();
void OnSaveImageDone(bool success);
void UpdateLocalState();
void NotifyJobDone();
const std::string& user_id() const { return parent_->user_id(); }
UserImageManagerImpl* parent_;
bool run_;
int image_index_;
GURL image_url_;
base::FilePath image_path_;
UserImage user_image_;
base::WeakPtrFactory<Job> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Job);
};
UserImageManagerImpl::Job::Job(UserImageManagerImpl* parent)
: parent_(parent),
run_(false),
weak_factory_(this) {
}
UserImageManagerImpl::Job::~Job() {
}
void UserImageManagerImpl::Job::LoadImage(base::FilePath image_path,
const int image_index,
const GURL& image_url) {
DCHECK(!run_);
run_ = true;
image_index_ = image_index;
image_url_ = image_url;
image_path_ = image_path;
if (image_index_ >= 0 && image_index_ < kDefaultImagesCount) {
user_image_ = UserImage(GetDefaultImage(image_index_));
UpdateUser();
NotifyJobDone();
} else if (image_index_ == User::kExternalImageIndex ||
image_index_ == User::kProfileImageIndex) {
DCHECK(!image_path_.empty());
parent_->image_loader_->Start(image_path_.value(),
0,
base::Bind(&Job::OnLoadImageDone,
weak_factory_.GetWeakPtr(),
false));
} else {
NOTREACHED();
NotifyJobDone();
}
}
void UserImageManagerImpl::Job::SetToDefaultImage(int default_image_index) {
DCHECK(!run_);
run_ = true;
DCHECK_LE(0, default_image_index);
DCHECK_GT(kDefaultImagesCount, default_image_index);
image_index_ = default_image_index;
user_image_ = UserImage(GetDefaultImage(image_index_));
UpdateUser();
UpdateLocalState();
NotifyJobDone();
}
void UserImageManagerImpl::Job::SetToImage(int image_index,
const UserImage& user_image) {
DCHECK(!run_);
run_ = true;
DCHECK(image_index == User::kExternalImageIndex ||
image_index == User::kProfileImageIndex);
image_index_ = image_index;
user_image_ = user_image;
UpdateUser();
SaveImageAndUpdateLocalState();
}
void UserImageManagerImpl::Job::SetToImageData(scoped_ptr<std::string> data) {
DCHECK(!run_);
run_ = true;
image_index_ = User::kExternalImageIndex;
parent_->image_loader_->Start(data.Pass(),
login::kMaxUserImageSize,
base::Bind(&Job::OnLoadImageDone,
weak_factory_.GetWeakPtr(),
true));
}
void UserImageManagerImpl::Job::SetToPath(const base::FilePath& path,
int image_index,
const GURL& image_url,
bool resize) {
DCHECK(!run_);
run_ = true;
image_index_ = image_index;
image_url_ = image_url;
DCHECK(!path.empty());
parent_->unsafe_image_loader_->Start(path.value(),
resize ? login::kMaxUserImageSize : 0,
base::Bind(&Job::OnLoadImageDone,
weak_factory_.GetWeakPtr(),
true));
}
void UserImageManagerImpl::Job::OnLoadImageDone(bool save,
const UserImage& user_image) {
user_image_ = user_image;
UpdateUser();
if (save)
SaveImageAndUpdateLocalState();
else
NotifyJobDone();
}
void UserImageManagerImpl::Job::UpdateUser() {
User* user = parent_->user_manager_->FindUserAndModify(user_id());
if (!user)
return;
if (!user_image_.image().isNull())
user->SetImage(user_image_, image_index_);
else
user->SetStubImage(image_index_, false);
user->SetImageURL(image_url_);
parent_->OnJobChangedUserImage();
}
void UserImageManagerImpl::Job::SaveImageAndUpdateLocalState() {
base::FilePath user_data_dir;
PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
image_path_ = user_data_dir.Append(user_id() + kSafeImagePathExtension);
base::PostTaskAndReplyWithResult(
parent_->background_task_runner_,
FROM_HERE,
base::Bind(&SaveImage, user_image_, image_path_),
base::Bind(&Job::OnSaveImageDone, weak_factory_.GetWeakPtr()));
}
void UserImageManagerImpl::Job::OnSaveImageDone(bool success) {
if (success || image_index_ == User::kProfileImageIndex)
UpdateLocalState();
NotifyJobDone();
}
void UserImageManagerImpl::Job::UpdateLocalState() {
if (parent_->user_manager_->IsUserNonCryptohomeDataEphemeral(user_id()))
return;
scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
entry->Set(kImagePathNodeName, new base::StringValue(image_path_.value()));
entry->Set(kImageIndexNodeName, new base::FundamentalValue(image_index_));
if (!image_url_.is_empty())
entry->Set(kImageURLNodeName, new base::StringValue(image_url_.spec()));
DictionaryPrefUpdate update(g_browser_process->local_state(),
kUserImageProperties);
update->SetWithoutPathExpansion(user_id(), entry.release());
parent_->user_manager_->NotifyLocalStateChanged();
}
void UserImageManagerImpl::Job::NotifyJobDone() {
parent_->OnJobDone();
}
UserImageManagerImpl::UserImageManagerImpl(const std::string& user_id,
UserManager* user_manager)
: UserImageManager(user_id),
user_manager_(user_manager),
downloading_profile_image_(false),
profile_image_requested_(false),
has_managed_image_(false),
user_needs_migration_(false),
weak_factory_(this) {
base::SequencedWorkerPool* blocking_pool =
content::BrowserThread::GetBlockingPool();
background_task_runner_ =
blocking_pool->GetSequencedTaskRunnerWithShutdownBehavior(
blocking_pool->GetSequenceToken(),
base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
image_loader_ = new UserImageLoader(ImageDecoder::ROBUST_JPEG_CODEC,
background_task_runner_);
unsafe_image_loader_ = new UserImageLoader(ImageDecoder::DEFAULT_CODEC,
background_task_runner_);
}
UserImageManagerImpl::~UserImageManagerImpl() {}
void UserImageManagerImpl::LoadUserImage() {
PrefService* local_state = g_browser_process->local_state();
const base::DictionaryValue* prefs_images_unsafe =
local_state->GetDictionary(kUserImages);
const base::DictionaryValue* prefs_images =
local_state->GetDictionary(kUserImageProperties);
if (!prefs_images && !prefs_images_unsafe)
return;
User* user = GetUserAndModify();
bool needs_migration = false;
const base::DictionaryValue* image_properties = NULL;
if (prefs_images_unsafe) {
needs_migration = prefs_images_unsafe->GetDictionaryWithoutPathExpansion(
user_id(), &image_properties);
if (needs_migration)
user_needs_migration_ = true;
}
if (prefs_images) {
prefs_images->GetDictionaryWithoutPathExpansion(user_id(),
&image_properties);
}
if (IsUserImageManaged() && job_.get())
return;
if (!image_properties) {
SetInitialUserImage();
return;
}
int image_index = User::kInvalidImageIndex;
image_properties->GetInteger(kImageIndexNodeName, &image_index);
if (image_index >= 0 && image_index < kDefaultImagesCount) {
user->SetImage(UserImage(GetDefaultImage(image_index)),
image_index);
return;
}
if (image_index != User::kExternalImageIndex &&
image_index != User::kProfileImageIndex) {
NOTREACHED();
return;
}
std::string image_url_string;
image_properties->GetString(kImageURLNodeName, &image_url_string);
GURL image_url(image_url_string);
std::string image_path;
image_properties->GetString(kImagePathNodeName, &image_path);
user->SetImageURL(image_url);
user->SetStubImage(image_index, true);
DCHECK(!image_path.empty() || image_index == User::kProfileImageIndex);
if (image_path.empty() || needs_migration) {
return;
}
job_.reset(new Job(this));
job_->LoadImage(base::FilePath(image_path), image_index, image_url);
}
void UserImageManagerImpl::UserLoggedIn(bool user_is_new,
bool user_is_local) {
const User* user = GetUser();
if (user_is_new) {
if (!user_is_local)
SetInitialUserImage();
} else {
UMA_HISTOGRAM_ENUMERATION("UserImage.LoggedIn",
ImageIndexToHistogramIndex(user->image_index()),
kHistogramImagesCount);
if (!IsUserImageManaged() && user_needs_migration_) {
const base::DictionaryValue* prefs_images_unsafe =
g_browser_process->local_state()->GetDictionary(kUserImages);
const base::DictionaryValue* image_properties = NULL;
if (prefs_images_unsafe->GetDictionaryWithoutPathExpansion(
user_id(), &image_properties)) {
std::string image_path;
image_properties->GetString(kImagePathNodeName, &image_path);
job_.reset(new Job(this));
if (!image_path.empty()) {
VLOG(0) << "Loading old user image, then migrating it.";
job_->SetToPath(base::FilePath(image_path),
user->image_index(),
user->image_url(),
false);
} else {
job_->SetToDefaultImage(user->image_index());
}
}
}
}
downloaded_profile_image_ = gfx::ImageSkia();
profile_image_url_ = GURL();
profile_image_requested_ = false;
if (IsUserLoggedInAndRegular()) {
TryToInitDownloadedProfileImage();
profile_download_one_shot_timer_.Start(
FROM_HERE,
g_ignore_profile_data_download_delay_ ?
base::TimeDelta() :
base::TimeDelta::FromSeconds(kProfileDataDownloadDelaySec),
base::Bind(&UserImageManagerImpl::DownloadProfileData,
base::Unretained(this),
kProfileDownloadReasonLoggedIn));
profile_download_periodic_timer_.Start(
FROM_HERE,
base::TimeDelta::FromSeconds(kProfileRefreshIntervalSec),
base::Bind(&UserImageManagerImpl::DownloadProfileData,
base::Unretained(this),
kProfileDownloadReasonScheduled));
} else {
profile_download_one_shot_timer_.Stop();
profile_download_periodic_timer_.Stop();
}
user_image_sync_observer_.reset();
TryToCreateImageSyncObserver();
}
void UserImageManagerImpl::SaveUserDefaultImageIndex(int default_image_index) {
if (IsUserImageManaged())
return;
job_.reset(new Job(this));
job_->SetToDefaultImage(default_image_index);
}
void UserImageManagerImpl::SaveUserImage(const UserImage& user_image) {
if (IsUserImageManaged())
return;
job_.reset(new Job(this));
job_->SetToImage(User::kExternalImageIndex, user_image);
}
void UserImageManagerImpl::SaveUserImageFromFile(const base::FilePath& path) {
if (IsUserImageManaged())
return;
job_.reset(new Job(this));
job_->SetToPath(path, User::kExternalImageIndex, GURL(), true);
}
void UserImageManagerImpl::SaveUserImageFromProfileImage() {
if (IsUserImageManaged())
return;
job_.reset(new Job(this));
job_->SetToImage(User::kProfileImageIndex,
downloaded_profile_image_.isNull() ?
UserImage() :
UserImage::CreateAndEncode(downloaded_profile_image_));
if (downloaded_profile_image_.isNull())
DownloadProfileData(kProfileDownloadReasonProfileImageChosen);
}
void UserImageManagerImpl::DeleteUserImage() {
job_.reset();
DeleteUserImageAndLocalStateEntry(kUserImages);
DeleteUserImageAndLocalStateEntry(kUserImageProperties);
}
void UserImageManagerImpl::DownloadProfileImage(const std::string& reason) {
profile_image_requested_ = true;
DownloadProfileData(reason);
}
const gfx::ImageSkia& UserImageManagerImpl::DownloadedProfileImage() const {
return downloaded_profile_image_;
}
UserImageSyncObserver* UserImageManagerImpl::GetSyncObserver() const {
return user_image_sync_observer_.get();
}
void UserImageManagerImpl::Shutdown() {
profile_downloader_.reset();
user_image_sync_observer_.reset();
}
void UserImageManagerImpl::OnExternalDataSet(const std::string& policy) {
DCHECK_EQ(policy::key::kUserAvatarImage, policy);
if (IsUserImageManaged())
return;
has_managed_image_ = true;
job_.reset();
const User* user = GetUser();
if (user && user->is_logged_in())
user_image_sync_observer_.reset();
}
void UserImageManagerImpl::OnExternalDataCleared(const std::string& policy) {
DCHECK_EQ(policy::key::kUserAvatarImage, policy);
has_managed_image_ = false;
TryToCreateImageSyncObserver();
}
void UserImageManagerImpl::OnExternalDataFetched(const std::string& policy,
scoped_ptr<std::string> data) {
DCHECK_EQ(policy::key::kUserAvatarImage, policy);
DCHECK(IsUserImageManaged());
if (data) {
job_.reset(new Job(this));
job_->SetToImageData(data.Pass());
}
}
void UserImageManagerImpl::IgnoreProfileDataDownloadDelayForTesting() {
g_ignore_profile_data_download_delay_ = true;
}
bool UserImageManagerImpl::NeedsProfilePicture() const {
return downloading_profile_image_;
}
int UserImageManagerImpl::GetDesiredImageSideLength() const {
return GetCurrentUserImageSize();
}
Profile* UserImageManagerImpl::GetBrowserProfile() {
return user_manager_->GetProfileByUser(GetUser());
}
std::string UserImageManagerImpl::GetCachedPictureURL() const {
return profile_image_url_.spec();
}
void UserImageManagerImpl::OnProfileDownloadSuccess(
ProfileDownloader* downloader) {
scoped_ptr<ProfileDownloader> profile_downloader(
profile_downloader_.release());
DCHECK_EQ(downloader, profile_downloader.get());
user_manager_->UpdateUserAccountData(
user_id(),
UserManager::UserAccountData(downloader->GetProfileFullName(),
downloader->GetProfileGivenName(),
downloader->GetProfileLocale()));
if (!downloading_profile_image_)
return;
ProfileDownloadResult result = kDownloadFailure;
switch (downloader->GetProfilePictureStatus()) {
case ProfileDownloader::PICTURE_SUCCESS:
result = kDownloadSuccess;
break;
case ProfileDownloader::PICTURE_CACHED:
result = kDownloadCached;
break;
case ProfileDownloader::PICTURE_DEFAULT:
result = kDownloadDefault;
break;
default:
NOTREACHED();
}
UMA_HISTOGRAM_ENUMERATION("UserImage.ProfileDownloadResult",
result,
kDownloadResultsCount);
DCHECK(!profile_image_load_start_time_.is_null());
AddProfileImageTimeHistogram(
result,
profile_image_download_reason_,
base::TimeTicks::Now() - profile_image_load_start_time_);
if (!NeedProfileImage())
return;
if (result == kDownloadDefault) {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
content::Source<UserImageManager>(this),
content::NotificationService::NoDetails());
} else {
profile_image_requested_ = false;
}
if (result != kDownloadSuccess)
return;
downloaded_profile_image_ = gfx::ImageSkia::CreateFrom1xBitmap(
downloader->GetProfilePicture());
profile_image_url_ = GURL(downloader->GetProfilePictureURL());
const User* user = GetUser();
if (user->image_index() == User::kProfileImageIndex) {
VLOG(1) << "Updating profile image for logged-in user.";
UMA_HISTOGRAM_ENUMERATION("UserImage.ProfileDownloadResult",
kDownloadSuccessChanged,
kDownloadResultsCount);
SaveUserImageFromProfileImage();
}
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED,
content::Source<UserImageManager>(this),
content::Details<const gfx::ImageSkia>(&downloaded_profile_image_));
}
void UserImageManagerImpl::OnProfileDownloadFailure(
ProfileDownloader* downloader,
ProfileDownloaderDelegate::FailureReason reason) {
DCHECK_EQ(downloader, profile_downloader_.get());
profile_downloader_.reset();
if (downloading_profile_image_) {
UMA_HISTOGRAM_ENUMERATION("UserImage.ProfileDownloadResult",
kDownloadFailure,
kDownloadResultsCount);
DCHECK(!profile_image_load_start_time_.is_null());
AddProfileImageTimeHistogram(
kDownloadFailure,
profile_image_download_reason_,
base::TimeTicks::Now() - profile_image_load_start_time_);
}
if (reason == ProfileDownloaderDelegate::NETWORK_ERROR) {
profile_download_one_shot_timer_.Start(
FROM_HERE,
base::TimeDelta::FromSeconds(kProfileDataDownloadRetryIntervalSec),
base::Bind(&UserImageManagerImpl::DownloadProfileData,
base::Unretained(this),
kProfileDownloadReasonRetry));
}
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
content::Source<UserImageManager>(this),
content::NotificationService::NoDetails());
}
bool UserImageManagerImpl::IsUserImageManaged() const {
return has_managed_image_;
}
void UserImageManagerImpl::SetInitialUserImage() {
SaveUserDefaultImageIndex(base::RandInt(kFirstDefaultImageIndex,
kDefaultImagesCount - 1));
}
void UserImageManagerImpl::TryToInitDownloadedProfileImage() {
const User* user = GetUser();
if (user->image_index() == User::kProfileImageIndex &&
downloaded_profile_image_.isNull() &&
!user->image_is_stub()) {
VLOG(1) << "Profile image initialized from disk.";
downloaded_profile_image_ = user->image();
profile_image_url_ = user->image_url();
}
}
bool UserImageManagerImpl::NeedProfileImage() const {
const User* user = GetUser();
return IsUserLoggedInAndRegular() &&
(user->image_index() == User::kProfileImageIndex ||
profile_image_requested_);
}
void UserImageManagerImpl::DownloadProfileData(const std::string& reason) {
if (!IsUserLoggedInAndRegular())
return;
if (profile_downloader_ &&
(downloading_profile_image_ || !NeedProfileImage())) {
return;
}
downloading_profile_image_ = NeedProfileImage();
profile_image_download_reason_ = reason;
profile_image_load_start_time_ = base::TimeTicks::Now();
profile_downloader_.reset(new ProfileDownloader(this));
profile_downloader_->Start();
}
void UserImageManagerImpl::DeleteUserImageAndLocalStateEntry(
const char* prefs_dict_root) {
DictionaryPrefUpdate update(g_browser_process->local_state(),
prefs_dict_root);
const base::DictionaryValue* image_properties;
if (!update->GetDictionaryWithoutPathExpansion(user_id(), &image_properties))
return;
std::string image_path;
image_properties->GetString(kImagePathNodeName, &image_path);
if (!image_path.empty()) {
background_task_runner_->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(&base::DeleteFile),
base::FilePath(image_path),
false));
}
update->RemoveWithoutPathExpansion(user_id(), NULL);
}
void UserImageManagerImpl::OnJobChangedUserImage() {
if (GetUser()->is_logged_in())
TryToInitDownloadedProfileImage();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
content::Source<UserImageManagerImpl>(this),
content::Details<const User>(GetUser()));
}
void UserImageManagerImpl::OnJobDone() {
if (job_.get())
base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, job_.release());
else
NOTREACHED();
if (!user_needs_migration_)
return;
user_needs_migration_ = false;
const base::DictionaryValue* prefs_images_unsafe =
g_browser_process->local_state()->GetDictionary(kUserImages);
const base::DictionaryValue* image_properties = NULL;
if (!prefs_images_unsafe->GetDictionaryWithoutPathExpansion(
user_id(), &image_properties)) {
NOTREACHED();
return;
}
int image_index = User::kInvalidImageIndex;
image_properties->GetInteger(kImageIndexNodeName, &image_index);
UMA_HISTOGRAM_ENUMERATION("UserImage.Migration",
ImageIndexToHistogramIndex(image_index),
kHistogramImagesCount);
std::string image_path;
image_properties->GetString(kImagePathNodeName, &image_path);
if (!image_path.empty()) {
background_task_runner_->PostTaskAndReply(
FROM_HERE,
base::Bind(base::IgnoreResult(&base::DeleteFile),
base::FilePath(image_path),
false),
base::Bind(&UserImageManagerImpl::UpdateLocalStateAfterMigration,
weak_factory_.GetWeakPtr()));
} else {
UpdateLocalStateAfterMigration();
}
}
void UserImageManagerImpl::UpdateLocalStateAfterMigration() {
DictionaryPrefUpdate update(g_browser_process->local_state(),
kUserImages);
update->RemoveWithoutPathExpansion(user_id(), NULL);
}
void UserImageManagerImpl::TryToCreateImageSyncObserver() {
const User* user = GetUser();
if (!user_image_sync_observer_ &&
user && user->CanSyncImage() &&
!IsUserImageManaged() &&
!CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kDisableUserImageSync)) {
user_image_sync_observer_.reset(new UserImageSyncObserver(user));
}
}
const User* UserImageManagerImpl::GetUser() const {
return user_manager_->FindUser(user_id());
}
User* UserImageManagerImpl::GetUserAndModify() const {
return user_manager_->FindUserAndModify(user_id());
}
bool UserImageManagerImpl::IsUserLoggedInAndRegular() const {
const User* user = GetUser();
if (!user)
return false;
return user->is_logged_in() && user->GetType() == User::USER_TYPE_REGULAR;
}
}