This source file includes following definitions.
- user_has_selected_image_
- OnScreenReady
- OnPhotoTaken
- OnCameraPresenceCheckDone
- HideCurtain
- OnImageDecoded
- OnDecodeImageFailed
- OnInitialSync
- OnSyncTimeout
- IsWaitingForSync
- OnUserImagePolicyChanged
- OnImageSelected
- OnImageAccepted
- SetProfilePictureEnabled
- SetUserID
- PrepareToShow
- GetUser
- GetUserImageManager
- GetSyncObserver
- Show
- Hide
- GetName
- OnActorDestroyed
- Observe
- profile_picture_absent
- selected_image
- profile_picture_data_url
- ExitScreen
#include "chrome/browser/chromeos/login/screens/user_image_screen.h"
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/camera_presence_notifier.h"
#include "chrome/browser/chromeos/login/default_user_images.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/screens/screen_observer.h"
#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/chromeos/login/user_image_manager.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "policy/policy_constants.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/gfx/image/image_skia.h"
using content::BrowserThread;
namespace chromeos {
namespace {
const char kProfileDownloadReason[] = "OOBE";
const int kSyncTimeoutSeconds = 10;
}
UserImageScreen::UserImageScreen(ScreenObserver* screen_observer,
UserImageScreenActor* actor)
: WizardScreen(screen_observer),
actor_(actor),
accept_photo_after_decoding_(false),
selected_image_(User::kInvalidImageIndex),
profile_picture_enabled_(false),
profile_picture_data_url_(content::kAboutBlankURL),
profile_picture_absent_(false),
is_screen_ready_(false),
user_has_selected_image_(false) {
actor_->SetDelegate(this);
SetProfilePictureEnabled(true);
notification_registrar_.Add(this,
chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
content::NotificationService::AllSources());
}
UserImageScreen::~UserImageScreen() {
CameraPresenceNotifier::GetInstance()->RemoveObserver(this);
if (actor_)
actor_->SetDelegate(NULL);
if (image_decoder_.get())
image_decoder_->set_delegate(NULL);
}
void UserImageScreen::OnScreenReady() {
is_screen_ready_ = true;
if (!IsWaitingForSync())
HideCurtain();
}
void UserImageScreen::OnPhotoTaken(const std::string& raw_data) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
user_photo_ = gfx::ImageSkia();
if (image_decoder_.get())
image_decoder_->set_delegate(NULL);
image_decoder_ = new ImageDecoder(this, raw_data,
ImageDecoder::DEFAULT_CODEC);
scoped_refptr<base::MessageLoopProxy> task_runner =
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
image_decoder_->Start(task_runner);
}
void UserImageScreen::OnCameraPresenceCheckDone(bool is_camera_present) {
if (actor_)
actor_->SetCameraPresent(is_camera_present);
}
void UserImageScreen::HideCurtain() {
if (actor_)
actor_->HideCurtain();
}
void UserImageScreen::OnImageDecoded(const ImageDecoder* decoder,
const SkBitmap& decoded_image) {
DCHECK_EQ(image_decoder_.get(), decoder);
user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
if (accept_photo_after_decoding_)
OnImageAccepted();
}
void UserImageScreen::OnDecodeImageFailed(const ImageDecoder* decoder) {
NOTREACHED() << "Failed to decode PNG image from WebUI";
}
void UserImageScreen::OnInitialSync(bool local_image_updated) {
DCHECK(sync_timer_);
if (!local_image_updated) {
sync_timer_.reset();
GetSyncObserver()->RemoveObserver(this);
if (is_screen_ready_)
HideCurtain();
return;
}
ExitScreen();
}
void UserImageScreen::OnSyncTimeout() {
sync_timer_.reset();
GetSyncObserver()->RemoveObserver(this);
if (is_screen_ready_)
HideCurtain();
}
bool UserImageScreen::IsWaitingForSync() const {
return sync_timer_.get() && sync_timer_->IsRunning();
}
void UserImageScreen::OnUserImagePolicyChanged(const base::Value* previous,
const base::Value* current) {
if (current) {
base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE,
policy_registrar_.release());
ExitScreen();
}
}
void UserImageScreen::OnImageSelected(const std::string& image_type,
const std::string& image_url,
bool is_user_selection) {
if (is_user_selection) {
user_has_selected_image_ = true;
}
if (image_url.empty())
return;
int user_image_index = User::kInvalidImageIndex;
if (image_type == "default" &&
IsDefaultImageUrl(image_url, &user_image_index)) {
selected_image_ = user_image_index;
} else if (image_type == "camera") {
selected_image_ = User::kExternalImageIndex;
} else if (image_type == "profile") {
selected_image_ = User::kProfileImageIndex;
} else {
NOTREACHED() << "Unexpected image type: " << image_type;
}
}
void UserImageScreen::OnImageAccepted() {
UserImageManager* image_manager = GetUserImageManager();
int uma_index = 0;
switch (selected_image_) {
case User::kExternalImageIndex:
if (user_photo_.isNull()) {
accept_photo_after_decoding_ = true;
return;
}
image_manager->SaveUserImage(UserImage::CreateAndEncode(user_photo_));
uma_index = kHistogramImageFromCamera;
break;
case User::kProfileImageIndex:
image_manager->SaveUserImageFromProfileImage();
uma_index = kHistogramImageFromProfile;
break;
default:
DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
image_manager->SaveUserDefaultImageIndex(selected_image_);
uma_index = GetDefaultImageHistogramValue(selected_image_);
break;
}
if (user_has_selected_image_) {
UMA_HISTOGRAM_ENUMERATION("UserImage.FirstTimeChoice",
uma_index,
kHistogramImagesCount);
}
ExitScreen();
}
void UserImageScreen::SetProfilePictureEnabled(bool profile_picture_enabled) {
if (profile_picture_enabled_ == profile_picture_enabled)
return;
profile_picture_enabled_ = profile_picture_enabled;
if (profile_picture_enabled) {
notification_registrar_.Add(this,
chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED,
content::NotificationService::AllSources());
notification_registrar_.Add(
this,
chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
content::NotificationService::AllSources());
} else {
notification_registrar_.Remove(this,
chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED,
content::NotificationService::AllSources());
notification_registrar_.Remove(
this,
chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
content::NotificationService::AllSources());
}
if (actor_)
actor_->SetProfilePictureEnabled(profile_picture_enabled);
}
void UserImageScreen::SetUserID(const std::string& user_id) {
DCHECK(!user_id.empty());
user_id_ = user_id;
}
void UserImageScreen::PrepareToShow() {
if (actor_)
actor_->PrepareToShow();
}
const User* UserImageScreen::GetUser() {
if (user_id_.empty())
return UserManager::Get()->GetLoggedInUser();
return UserManager::Get()->FindUser(user_id_);
}
UserImageManager* UserImageScreen::GetUserImageManager() {
return UserManager::Get()->GetUserImageManager(GetUser()->email());
}
UserImageSyncObserver* UserImageScreen::GetSyncObserver() {
return GetUserImageManager()->GetSyncObserver();
}
void UserImageScreen::Show() {
if (!actor_)
return;
DCHECK(!policy_registrar_);
Profile* profile = UserManager::Get()->GetProfileByUser(GetUser());
if (profile) {
policy::PolicyService* policy_service =
policy::ProfilePolicyConnectorFactory::GetForProfile(profile)->
policy_service();
if (policy_service->GetPolicies(
policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME,
std::string()))
.Get(policy::key::kUserAvatarImage)) {
ExitScreen();
return;
}
policy_registrar_.reset(new policy::PolicyChangeRegistrar(
policy_service,
policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())));
policy_registrar_->Observe(
policy::key::kUserAvatarImage,
base::Bind(&UserImageScreen::OnUserImagePolicyChanged,
base::Unretained(this)));
} else {
NOTREACHED();
}
if (GetUser()->CanSyncImage()) {
if (UserImageSyncObserver* sync_observer = GetSyncObserver()) {
if (sync_observer->is_synced()) {
ExitScreen();
return;
}
sync_observer->AddObserver(this);
sync_timer_.reset(new base::Timer(
FROM_HERE,
base::TimeDelta::FromSeconds(kSyncTimeoutSeconds),
base::Bind(&UserImageScreen::OnSyncTimeout, base::Unretained(this)),
false));
sync_timer_->Reset();
}
}
CameraPresenceNotifier::GetInstance()->AddObserver(this);
actor_->Show();
actor_->SetProfilePictureEnabled(profile_picture_enabled_);
selected_image_ = GetUser()->image_index();
actor_->SelectImage(selected_image_);
if (profile_picture_enabled_) {
GetUserImageManager()->DownloadProfileImage(kProfileDownloadReason);
}
}
void UserImageScreen::Hide() {
CameraPresenceNotifier::GetInstance()->RemoveObserver(this);
if (actor_)
actor_->Hide();
}
std::string UserImageScreen::GetName() const {
return WizardController::kUserImageScreenName;
}
void UserImageScreen::OnActorDestroyed(UserImageScreenActor* actor) {
if (actor_ == actor)
actor_ = NULL;
}
void UserImageScreen::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK(profile_picture_enabled_);
switch (type) {
case chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED: {
profile_picture_data_url_ = webui::GetBitmapDataUrl(
*content::Details<const gfx::ImageSkia>(details).ptr()->bitmap());
if (actor_)
actor_->SendProfileImage(profile_picture_data_url_);
break;
}
case chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED: {
profile_picture_absent_ = true;
if (actor_)
actor_->OnProfileImageAbsent();
break;
}
case chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED: {
if (actor_)
actor_->SelectImage(GetUser()->image_index());
break;
}
default:
NOTREACHED();
}
}
bool UserImageScreen::profile_picture_absent() {
return profile_picture_absent_;
}
int UserImageScreen::selected_image() {
return selected_image_;
}
std::string UserImageScreen::profile_picture_data_url() {
return profile_picture_data_url_;
}
void UserImageScreen::ExitScreen() {
policy_registrar_.reset();
sync_timer_.reset();
if (UserImageSyncObserver* sync_observer = GetSyncObserver())
sync_observer->RemoveObserver(this);
get_screen_observer()->OnExit(ScreenObserver::USER_IMAGE_SELECTED);
}
}