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

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

Issue 286933002: [cros login] Split login related classes into subfolders. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix includes in new tests Created 6 years, 7 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/user_image_manager_impl.cc
diff --git a/chrome/browser/chromeos/login/user_image_manager_impl.cc b/chrome/browser/chromeos/login/user_image_manager_impl.cc
deleted file mode 100644
index 5ead90da988dd2ba95170665ed5b67d77b642c47..0000000000000000000000000000000000000000
--- a/chrome/browser/chromeos/login/user_image_manager_impl.cc
+++ /dev/null
@@ -1,1003 +0,0 @@
-// Copyright (c) 2013 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_manager_impl.h"
-
-#include "base/bind.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 "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 {
-
-// A dictionary that maps user_ids to old user image data with images stored in
-// PNG format. Deprecated.
-// TODO(ivankr): remove this const char after migration is gone.
-const char kUserImages[] = "UserImages";
-
-// A dictionary that maps user_ids to user image data with images stored in
-// JPEG format.
-const char kUserImageProperties[] = "user_image_info";
-
-// Names of user image properties.
-const char kImagePathNodeName[] = "path";
-const char kImageIndexNodeName[] = "index";
-const char kImageURLNodeName[] = "url";
-
-// Delay betweeen user login and attempt to update user's profile data.
-const int kProfileDataDownloadDelaySec = 10;
-
-// Interval betweeen retries to update user's profile data.
-const int kProfileDataDownloadRetryIntervalSec = 300;
-
-// Delay betweeen subsequent profile refresh attempts (24 hrs).
-const int kProfileRefreshIntervalSec = 24 * 3600;
-
-const char kSafeImagePathExtension[] = ".jpg";
-
-// Enum for reporting histograms about profile picture download.
-enum ProfileDownloadResult {
- kDownloadSuccessChanged,
- kDownloadSuccess,
- kDownloadFailure,
- kDownloadDefault,
- kDownloadCached,
-
- // Must be the last, convenient count.
- kDownloadResultsCount
-};
-
-// Time histogram prefix for a cached profile image download.
-const char kProfileDownloadCachedTime[] =
- "UserImage.ProfileDownloadTime.Cached";
-// Time histogram prefix for the default profile image download.
-const char kProfileDownloadDefaultTime[] =
- "UserImage.ProfileDownloadTime.Default";
-// Time histogram prefix for a failed profile image download.
-const char kProfileDownloadFailureTime[] =
- "UserImage.ProfileDownloadTime.Failure";
-// Time histogram prefix for a successful profile image download.
-const char kProfileDownloadSuccessTime[] =
- "UserImage.ProfileDownloadTime.Success";
-// Time histogram suffix for a profile image download after login.
-const char kProfileDownloadReasonLoggedIn[] = "LoggedIn";
-// Time histogram suffix for a profile image download when the user chooses the
-// profile image but it has not been downloaded yet.
-const char kProfileDownloadReasonProfileImageChosen[] = "ProfileImageChosen";
-// Time histogram suffix for a scheduled profile image download.
-const char kProfileDownloadReasonScheduled[] = "Scheduled";
-// Time histogram suffix for a profile image download retry.
-const char kProfileDownloadReasonRetry[] = "Retry";
-
-static bool g_ignore_profile_data_download_delay_ = false;
-
-// Add a histogram showing the time it takes to download profile image.
-// Separate histograms are reported for each download |reason| and |result|.
-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();
-}
-
-// Converts |image_index| to UMA histogram value.
-int ImageIndexToHistogramIndex(int image_index) {
- switch (image_index) {
- case User::kExternalImageIndex:
- // TODO(ivankr): Distinguish this from selected from file.
- 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;
-}
-
-} // namespace
-
-// static
-void UserImageManager::RegisterPrefs(PrefRegistrySimple* registry) {
- registry->RegisterDictionaryPref(kUserImages);
- registry->RegisterDictionaryPref(kUserImageProperties);
-}
-
-// Every image load or update is encapsulated by a Job. The Job is allowed to
-// perform tasks on background threads or in helper processes but:
-// * Changes to User objects and local state as well as any calls to the
-// |parent_| must be performed on the thread that the Job is created on only.
-// * File writes and deletions must be performed via the |parent_|'s
-// |background_task_runner_| only.
-//
-// Only one of the Load*() and Set*() methods may be called per Job.
-class UserImageManagerImpl::Job {
- public:
- // The |Job| will update the user object corresponding to |parent|.
- explicit Job(UserImageManagerImpl* parent);
- ~Job();
-
- // Loads the image at |image_path| or one of the default images,
- // depending on |image_index|, and updates the user object with the
- // new image.
- void LoadImage(base::FilePath image_path,
- const int image_index,
- const GURL& image_url);
-
- // Sets the user image in local state to the default image indicated
- // by |default_image_index|. Also updates the user object with the
- // new image.
- void SetToDefaultImage(int default_image_index);
-
- // Saves the |user_image| to disk and sets the user image in local
- // state to that image. Also updates the user with the new image.
- void SetToImage(int image_index, const UserImage& user_image);
-
- // Decodes the JPEG image |data|, crops and resizes the image, saves
- // it to disk and sets the user image in local state to that image.
- // Also updates the user object with the new image.
- void SetToImageData(scoped_ptr<std::string> data);
-
- // Loads the image at |path|, transcodes it to JPEG format, saves
- // the image to disk and sets the user image in local state to that
- // image. If |resize| is true, the image is cropped and resized
- // before transcoding. Also updates the user object with the new
- // image.
- void SetToPath(const base::FilePath& path,
- int image_index,
- const GURL& image_url,
- bool resize);
-
- private:
- // Called back after an image has been loaded from disk.
- void OnLoadImageDone(bool save, const UserImage& user_image);
-
- // Updates the user object with |user_image_|.
- void UpdateUser();
-
- // Saves |user_image_| to disk in JPEG format. Local state will be updated
- // when a callback indicates that the image has been saved.
- void SaveImageAndUpdateLocalState();
-
- // Called back after the |user_image_| has been saved to
- // disk. Updates the user image information in local state. The
- // information is only updated if |success| is true (indicating that
- // the image was saved successfully) or the user image is the
- // profile image (indicating that even if the image could not be
- // saved because it is not available right now, it will be
- // downloaded eventually).
- void OnSaveImageDone(bool success);
-
- // Updates the user image in local state, setting it to one of the
- // default images or the saved |user_image_|, depending on
- // |image_index_|.
- void UpdateLocalState();
-
- // Notifies the |parent_| that the Job is done.
- void NotifyJobDone();
-
- const std::string& user_id() const { return parent_->user_id(); }
-
- UserImageManagerImpl* parent_;
-
- // Whether one of the Load*() or Set*() methods has been run already.
- 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) {
- // Load one of the default images. This happens synchronously.
- user_image_ = UserImage(GetDefaultImage(image_index_));
- UpdateUser();
- NotifyJobDone();
- } else if (image_index_ == User::kExternalImageIndex ||
- image_index_ == User::kProfileImageIndex) {
- // Load the user image from a file referenced by |image_path|. This happens
- // asynchronously. The JPEG image loader can be used here because
- // LoadImage() is called only for users whose user image has previously
- // been set by one of the Set*() methods, which transcode to JPEG format.
- 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;
-
- // This method uses the image_loader_, not the unsafe_image_loader_:
- // * This is necessary because the method is used to update the user image
- // whenever the policy for a user is set. In the case of device-local
- // accounts, policy may change at any time, even if the user is not
- // currently logged in (and thus, the unsafe_image_loader_ may not be used).
- // * This is possible because only JPEG |data| is accepted. No support for
- // other image file formats is needed.
- // * This is safe because the image_loader_ employs a hardened JPEG decoder
- // that protects against malicious invalid image data being used to attack
- // the login screen or another user session currently in progress.
- 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() {
- // Ignore if data stored or cached outside the user's cryptohome is to be
- // treated as ephemeral.
- 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;
-
- // If entries are found in both |prefs_images_unsafe| and |prefs_images|,
- // |prefs_images| is honored for now but |prefs_images_unsafe| will be
- // migrated, overwriting the |prefs_images| entry, when the user logs in.
- 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 the user image for |user_id| is managed by policy and the policy-set
- // image is being loaded and persisted right now, let that job continue. It
- // will update the user image when done.
- 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 if either of the following is true:
- // * The profile image is to be used but has not been downloaded yet. The
- // profile image will be downloaded after login.
- // * The image needs migration. Migration will be performed after login.
- 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());
- }
- }
- }
- }
-
- // Reset the downloaded profile image as a new user logged in.
- downloaded_profile_image_ = gfx::ImageSkia();
- profile_image_url_ = GURL();
- profile_image_requested_ = false;
-
- if (IsUserLoggedInAndRegular()) {
- TryToInitDownloadedProfileImage();
-
- // Schedule an initial download of the profile data (full name and
- // optionally image).
- 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));
- // Schedule periodic refreshes of the profile data.
- 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;
- // Use the profile image if it has been downloaded already. Otherwise, use a
- // stub image (gray avatar).
- job_.reset(new Job(this));
- job_->SetToImage(User::kProfileImageIndex,
- downloaded_profile_image_.isNull() ?
- UserImage() :
- UserImage::CreateAndEncode(downloaded_profile_image_));
- // If no profile image has been downloaded yet, ensure that a download is
- // started.
- 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 the user image for the currently logged-in user became managed, stop the
- // sync observer so that the policy-set image does not get synced out.
- 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());
- }
-}
-
-// static
-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) {
- // Ensure that the |profile_downloader_| is deleted when this method returns.
- 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_);
-
- // Ignore the image if it is no longer needed.
- 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;
- }
-
- // Nothing to do if the picture is cached or is the default avatar.
- 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);
- // This will persist |downloaded_profile_image_| to disk.
- 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) {
- // Retry download after a delay if a network error occurred.
- 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() {
- // Choose a random default image.
- 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()) {
- // Initialize the |downloaded_profile_image_| for the currently logged-in
- // user if it has not been initialized already, the user image is the
- // profile image and the user image has been loaded successfully.
- VLOG(1) << "Profile image initialized from disk.";
- downloaded_profile_image_ = user->GetImage();
- 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) {
- // GAIA profiles exist for regular users only.
- if (!IsUserLoggedInAndRegular())
- return;
-
- // If a download is already in progress, allow it to continue, with one
- // exception: If the current download does not include the profile image but
- // the image has since become necessary, start a new download that includes
- // the profile image.
- 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;
- // Migration completed for |user_id|.
- 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()) {
- // If an old image exists, delete it and remove |user_id| from the old prefs
- // dictionary only after the deletion has completed. This ensures that no
- // orphaned image is left behind if the browser crashes before the deletion
- // has been performed: In that case, local state will be unchanged and the
- // migration will be run again on the user's next login.
- 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 {
- // If no old image exists, remove |user_id| from the old prefs dictionary.
- 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 the currently logged-in user's user image is managed, the sync observer
- // must not be started so that the policy-set image does not get synced out.
- if (!user_image_sync_observer_ &&
- user && user->CanSyncImage() &&
- !IsUserImageManaged()) {
- 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;
-}
-
-} // namespace chromeos
« no previous file with comments | « chrome/browser/chromeos/login/user_image_manager_impl.h ('k') | chrome/browser/chromeos/login/user_image_manager_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698