blob: 3b82a39db616884912bea3aa92b41931aae8d688 [file] [log] [blame]
// 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/managed/locally_managed_user_creation_screen.h"
#include "ash/desktop_background/desktop_background_controller.h"
#include "ash/shell.h"
#include "base/values.h"
#include "chrome/browser/chromeos/camera_detector.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h"
#include "chrome/browser/chromeos/login/screens/error_screen.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/wizard_controller.h"
#include "chromeos/network/network_state.h"
#include "content/public/browser/browser_thread.h"
#include "grit/generated_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image_skia.h"
namespace chromeos {
namespace {
void ConfigureErrorScreen(ErrorScreen* screen,
const NetworkState* network,
const NetworkPortalDetector::CaptivePortalStatus status) {
switch (status) {
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
NOTREACHED();
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
screen->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
std::string());
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
screen->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
network->name());
screen->FixCaptivePortal();
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
screen->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
std::string());
break;
default:
NOTREACHED();
break;
}
}
} // namespace
LocallyManagedUserCreationScreen::LocallyManagedUserCreationScreen(
ScreenObserver* observer,
LocallyManagedUserCreationScreenHandler* actor)
: WizardScreen(observer),
weak_factory_(this),
actor_(actor),
on_error_screen_(false),
on_image_screen_(false),
image_decoder_(NULL),
apply_photo_after_decoding_(false),
selected_image_(0) {
DCHECK(actor_);
if (actor_)
actor_->SetDelegate(this);
}
LocallyManagedUserCreationScreen::~LocallyManagedUserCreationScreen() {
if (actor_)
actor_->SetDelegate(NULL);
if (image_decoder_.get())
image_decoder_->set_delegate(NULL);
}
void LocallyManagedUserCreationScreen::PrepareToShow() {
if (actor_)
actor_->PrepareToShow();
}
void LocallyManagedUserCreationScreen::Show() {
if (actor_) {
actor_->Show();
// TODO(antrim) : temorary hack (until upcoming hackaton). Should be
// removed once we have screens reworked.
if (on_image_screen_)
actor_->ShowTutorialPage();
else
actor_->ShowIntroPage();
}
NetworkPortalDetector* detector = NetworkPortalDetector::GetInstance();
if (detector && !on_error_screen_)
detector->AddAndFireObserver(this);
on_error_screen_ = false;
}
void LocallyManagedUserCreationScreen::OnPortalDetectionCompleted(
const NetworkState* network,
const NetworkPortalDetector::CaptivePortalState& state) {
if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) {
get_screen_observer()->HideErrorScreen(this);
} else {
on_error_screen_ = true;
ErrorScreen* screen = get_screen_observer()->GetErrorScreen();
ConfigureErrorScreen(screen, network, state.status);
screen->SetUIState(ErrorScreen::UI_STATE_LOCALLY_MANAGED);
get_screen_observer()->ShowErrorScreen();
}
}
void LocallyManagedUserCreationScreen::
ShowManagerInconsistentStateErrorScreen() {
if (!actor_)
return;
actor_->ShowErrorPage(
l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_TITLE),
l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE),
l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_BUTTON));
}
void LocallyManagedUserCreationScreen::ShowInitialScreen() {
if (actor_)
actor_->ShowIntroPage();
}
void LocallyManagedUserCreationScreen::Hide() {
if (actor_)
actor_->Hide();
NetworkPortalDetector* detector = NetworkPortalDetector::GetInstance();
if (detector && !on_error_screen_)
detector->RemoveObserver(this);
}
std::string LocallyManagedUserCreationScreen::GetName() const {
return WizardController::kLocallyManagedUserCreationScreenName;
}
void LocallyManagedUserCreationScreen::AbortFlow() {
controller_->CancelCreation();
}
void LocallyManagedUserCreationScreen::FinishFlow() {
controller_->FinishCreation();
}
void LocallyManagedUserCreationScreen::AuthenticateManager(
const std::string& manager_id,
const std::string& manager_password) {
// Make sure no two controllers exist at the same time.
controller_.reset();
controller_.reset(new LocallyManagedUserCreationController(this, manager_id));
ExistingUserController::current_controller()->
Login(UserContext(manager_id,
manager_password,
std::string() /* auth_code */));
}
void LocallyManagedUserCreationScreen::CreateManagedUser(
const string16& display_name,
const std::string& managed_user_password) {
DCHECK(controller_.get());
controller_->SetUpCreation(display_name, managed_user_password);
controller_->StartCreation();
}
void LocallyManagedUserCreationScreen::OnManagerLoginFailure() {
if (actor_)
actor_->ShowManagerPasswordError();
}
void LocallyManagedUserCreationScreen::OnManagerFullyAuthenticated(
Profile* manager_profile) {
DCHECK(controller_.get());
// For manager user, move desktop to locked container so that windows created
// during the user image picker step are below it.
ash::Shell::GetInstance()->
desktop_background_controller()->MoveDesktopToLockedContainer();
controller_->SetManagerProfile(manager_profile);
if (actor_)
actor_->ShowUsernamePage();
}
void LocallyManagedUserCreationScreen::OnManagerCryptohomeAuthenticated() {
if (actor_) {
actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE));
}
}
void LocallyManagedUserCreationScreen::OnExit() {}
void LocallyManagedUserCreationScreen::OnActorDestroyed(
LocallyManagedUserCreationScreenHandler* actor) {
if (actor_ == actor)
actor_ = NULL;
}
void LocallyManagedUserCreationScreen::OnCreationError(
LocallyManagedUserCreationController::ErrorCode code) {
string16 title;
string16 message;
string16 button;
// TODO(antrim) : find out which errors do we really have.
// We might reuse some error messages from ordinary user flow.
switch (code) {
case LocallyManagedUserCreationController::CRYPTOHOME_NO_MOUNT:
case LocallyManagedUserCreationController::CRYPTOHOME_FAILED_MOUNT:
case LocallyManagedUserCreationController::CRYPTOHOME_FAILED_TPM:
title = l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_TITLE);
message = l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR);
button = l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_BUTTON);
break;
case LocallyManagedUserCreationController::CLOUD_SERVER_ERROR:
case LocallyManagedUserCreationController::TOKEN_WRITE_FAILED:
title = l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE);
message = l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR);
button = l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON);
break;
case LocallyManagedUserCreationController::NO_ERROR:
NOTREACHED();
}
if (actor_)
actor_->ShowErrorPage(title, message, button);
}
void LocallyManagedUserCreationScreen::OnCreationTimeout() {
if (actor_) {
actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE));
}
}
void LocallyManagedUserCreationScreen::OnLongCreationWarning() {
if (actor_) {
actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
}
}
// TODO(antrim) : this is an explicit code duplications with UserImageScreen.
// It should be removed by issue 251179.
void LocallyManagedUserCreationScreen::ApplyPicture() {
UserManager* user_manager = UserManager::Get();
UserImageManager* image_manager = user_manager->GetUserImageManager();
std::string user_id = controller_->GetManagedUserId();
switch (selected_image_) {
case User::kExternalImageIndex:
// Photo decoding may not have been finished yet.
if (user_photo_.isNull()) {
apply_photo_after_decoding_ = true;
return;
}
image_manager->
SaveUserImage(user_id, UserImage::CreateAndEncode(user_photo_));
break;
case User::kProfileImageIndex:
NOTREACHED() << "Supervised users have no profile pictures";
break;
default:
DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
image_manager->SaveUserDefaultImageIndex(user_id, selected_image_);
break;
}
// Proceed to tutorial.
actor_->ShowTutorialPage();
}
void LocallyManagedUserCreationScreen::OnCreationSuccess() {
ApplyPicture();
}
void LocallyManagedUserCreationScreen::CheckCameraPresence() {
CameraDetector::StartPresenceCheck(
base::Bind(&LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone,
weak_factory_.GetWeakPtr()));
}
void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone() {
if (actor_) {
actor_->SetCameraPresent(
CameraDetector::camera_presence() == CameraDetector::kCameraPresent);
}
}
void LocallyManagedUserCreationScreen::OnPhotoTaken(
const std::string& raw_data) {
DCHECK(content::BrowserThread::CurrentlyOn(content::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 =
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::UI);
image_decoder_->Start(task_runner);
}
void LocallyManagedUserCreationScreen::OnImageDecoded(
const ImageDecoder* decoder,
const SkBitmap& decoded_image) {
DCHECK_EQ(image_decoder_.get(), decoder);
user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
if (apply_photo_after_decoding_)
ApplyPicture();
}
void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
const ImageDecoder* decoder) {
NOTREACHED() << "Failed to decode PNG image from WebUI";
}
void LocallyManagedUserCreationScreen::OnImageSelected(
const std::string& image_type,
const std::string& image_url) {
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 {
NOTREACHED() << "Unexpected image type: " << image_type;
}
}
void LocallyManagedUserCreationScreen::OnImageAccepted() {
}
} // namespace chromeos