locally_managed_user_creation_screen.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
6
7#include "ash/desktop_background/desktop_background_controller.h"
8#include "ash/shell.h"
9#include "base/values.h"
10#include "chrome/browser/chromeos/camera_detector.h"
11#include "chrome/browser/chromeos/login/existing_user_controller.h"
12#include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h"
13#include "chrome/browser/chromeos/login/screens/error_screen.h"
14#include "chrome/browser/chromeos/login/screens/screen_observer.h"
15#include "chrome/browser/chromeos/login/user_image.h"
16#include "chrome/browser/chromeos/login/user_image_manager.h"
17#include "chrome/browser/chromeos/login/wizard_controller.h"
18#include "chromeos/network/network_state.h"
19#include "content/public/browser/browser_thread.h"
20#include "grit/generated_resources.h"
21#include "third_party/skia/include/core/SkBitmap.h"
22#include "ui/base/l10n/l10n_util.h"
23#include "ui/gfx/image/image_skia.h"
24
25namespace chromeos {
26
27namespace {
28
29const char kNameOfIntroScreen[] = "intro";
30const char kNameOfNewUserParametersScreen[] = "username";
31
32void ConfigureErrorScreen(ErrorScreen* screen,
33    const NetworkState* network,
34    const NetworkPortalDetector::CaptivePortalStatus status) {
35  switch (status) {
36    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
37    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
38      NOTREACHED();
39      break;
40    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
41      screen->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
42                            std::string());
43      break;
44    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
45      screen->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
46                            network->name());
47      screen->FixCaptivePortal();
48      break;
49    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
50      screen->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
51                            std::string());
52      break;
53    default:
54      NOTREACHED();
55      break;
56  }
57}
58
59} // namespace
60
61LocallyManagedUserCreationScreen::LocallyManagedUserCreationScreen(
62    ScreenObserver* observer,
63    LocallyManagedUserCreationScreenHandler* actor)
64    : WizardScreen(observer),
65      weak_factory_(this),
66      actor_(actor),
67      on_error_screen_(false),
68      last_page_(kNameOfIntroScreen),
69      image_decoder_(NULL),
70      apply_photo_after_decoding_(false),
71      selected_image_(0) {
72  DCHECK(actor_);
73  if (actor_)
74    actor_->SetDelegate(this);
75}
76
77LocallyManagedUserCreationScreen::~LocallyManagedUserCreationScreen() {
78  if (actor_)
79    actor_->SetDelegate(NULL);
80  if (image_decoder_.get())
81    image_decoder_->set_delegate(NULL);
82}
83
84void LocallyManagedUserCreationScreen::PrepareToShow() {
85  if (actor_)
86    actor_->PrepareToShow();
87}
88
89void LocallyManagedUserCreationScreen::Show() {
90  if (actor_) {
91    actor_->Show();
92    // TODO(antrim) : temorary hack (until upcoming hackaton). Should be
93    // removed once we have screens reworked.
94    if (on_error_screen_)
95      actor_->ShowPage(last_page_);
96    else
97      actor_->ShowIntroPage();
98  }
99
100  NetworkPortalDetector* detector = NetworkPortalDetector::GetInstance();
101  if (detector && !on_error_screen_)
102    detector->AddAndFireObserver(this);
103  on_error_screen_ = false;
104}
105
106void LocallyManagedUserCreationScreen::OnPageSelected(const std::string& page) {
107  last_page_ = page;
108}
109
110void LocallyManagedUserCreationScreen::OnPortalDetectionCompleted(
111    const NetworkState* network,
112    const NetworkPortalDetector::CaptivePortalState& state)  {
113  if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) {
114    get_screen_observer()->HideErrorScreen(this);
115  } else {
116    on_error_screen_ = true;
117    ErrorScreen* screen = get_screen_observer()->GetErrorScreen();
118    ConfigureErrorScreen(screen, network, state.status);
119    screen->SetUIState(ErrorScreen::UI_STATE_LOCALLY_MANAGED);
120    get_screen_observer()->ShowErrorScreen();
121  }
122}
123
124void LocallyManagedUserCreationScreen::
125    ShowManagerInconsistentStateErrorScreen() {
126  if (!actor_)
127    return;
128  actor_->ShowErrorPage(
129      l10n_util::GetStringUTF16(
130          IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_TITLE),
131      l10n_util::GetStringUTF16(
132          IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE),
133      l10n_util::GetStringUTF16(
134          IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_BUTTON));
135}
136
137void LocallyManagedUserCreationScreen::ShowInitialScreen() {
138  if (actor_)
139    actor_->ShowIntroPage();
140}
141
142void LocallyManagedUserCreationScreen::Hide() {
143  if (actor_)
144    actor_->Hide();
145  NetworkPortalDetector* detector = NetworkPortalDetector::GetInstance();
146  if (detector && !on_error_screen_)
147    detector->RemoveObserver(this);
148}
149
150std::string LocallyManagedUserCreationScreen::GetName() const {
151  return WizardController::kLocallyManagedUserCreationScreenName;
152}
153
154void LocallyManagedUserCreationScreen::AbortFlow() {
155  controller_->CancelCreation();
156}
157
158void LocallyManagedUserCreationScreen::FinishFlow() {
159  controller_->FinishCreation();
160}
161
162void LocallyManagedUserCreationScreen::AuthenticateManager(
163    const std::string& manager_id,
164    const std::string& manager_password) {
165  // Make sure no two controllers exist at the same time.
166  controller_.reset();
167  controller_.reset(new LocallyManagedUserCreationController(this, manager_id));
168
169  ExistingUserController::current_controller()->
170      Login(UserContext(manager_id,
171                        manager_password,
172                        std::string()  /* auth_code */));
173}
174
175void LocallyManagedUserCreationScreen::CreateManagedUser(
176    const string16& display_name,
177    const std::string& managed_user_password) {
178  DCHECK(controller_.get());
179  controller_->SetUpCreation(display_name, managed_user_password);
180  controller_->StartCreation();
181}
182
183void LocallyManagedUserCreationScreen::OnManagerLoginFailure() {
184  if (actor_)
185    actor_->ShowManagerPasswordError();
186}
187
188void LocallyManagedUserCreationScreen::OnManagerFullyAuthenticated(
189    Profile* manager_profile) {
190  DCHECK(controller_.get());
191  // For manager user, move desktop to locked container so that windows created
192  // during the user image picker step are below it.
193  ash::Shell::GetInstance()->
194      desktop_background_controller()->MoveDesktopToLockedContainer();
195
196  controller_->SetManagerProfile(manager_profile);
197  if (actor_)
198    actor_->ShowUsernamePage();
199  last_page_ = kNameOfNewUserParametersScreen;
200}
201
202void LocallyManagedUserCreationScreen::OnManagerCryptohomeAuthenticated() {
203  if (actor_) {
204    actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
205            IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE));
206  }
207}
208
209void LocallyManagedUserCreationScreen::OnActorDestroyed(
210    LocallyManagedUserCreationScreenHandler* actor) {
211  if (actor_ == actor)
212    actor_ = NULL;
213}
214
215void LocallyManagedUserCreationScreen::OnCreationError(
216    LocallyManagedUserCreationController::ErrorCode code) {
217  string16 title;
218  string16 message;
219  string16 button;
220  // TODO(antrim) : find out which errors do we really have.
221  // We might reuse some error messages from ordinary user flow.
222  switch (code) {
223    case LocallyManagedUserCreationController::CRYPTOHOME_NO_MOUNT:
224    case LocallyManagedUserCreationController::CRYPTOHOME_FAILED_MOUNT:
225    case LocallyManagedUserCreationController::CRYPTOHOME_FAILED_TPM:
226      title = l10n_util::GetStringUTF16(
227          IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_TITLE);
228      message = l10n_util::GetStringUTF16(
229          IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR);
230      button = l10n_util::GetStringUTF16(
231          IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_BUTTON);
232      break;
233    case LocallyManagedUserCreationController::CLOUD_SERVER_ERROR:
234    case LocallyManagedUserCreationController::TOKEN_WRITE_FAILED:
235      title = l10n_util::GetStringUTF16(
236          IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE);
237      message = l10n_util::GetStringUTF16(
238          IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR);
239      button = l10n_util::GetStringUTF16(
240          IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON);
241      break;
242    case LocallyManagedUserCreationController::NO_ERROR:
243      NOTREACHED();
244  }
245  if (actor_)
246    actor_->ShowErrorPage(title, message, button);
247}
248
249void LocallyManagedUserCreationScreen::OnCreationTimeout() {
250  if (actor_) {
251    actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16(
252        IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE));
253  }
254}
255
256void LocallyManagedUserCreationScreen::OnLongCreationWarning() {
257  if (actor_) {
258    actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
259        IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
260  }
261}
262
263// TODO(antrim) : this is an explicit code duplications with UserImageScreen.
264// It should be removed by issue 251179.
265
266void LocallyManagedUserCreationScreen::ApplyPicture() {
267  UserManager* user_manager = UserManager::Get();
268  UserImageManager* image_manager = user_manager->GetUserImageManager();
269  std::string user_id = controller_->GetManagedUserId();
270  switch (selected_image_) {
271    case User::kExternalImageIndex:
272      // Photo decoding may not have been finished yet.
273      if (user_photo_.isNull()) {
274        apply_photo_after_decoding_ = true;
275        return;
276      }
277      image_manager->
278          SaveUserImage(user_id, UserImage::CreateAndEncode(user_photo_));
279      break;
280    case User::kProfileImageIndex:
281      NOTREACHED() << "Supervised users have no profile pictures";
282      break;
283    default:
284      DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
285      image_manager->SaveUserDefaultImageIndex(user_id, selected_image_);
286      break;
287  }
288  // Proceed to tutorial.
289  actor_->ShowTutorialPage();
290}
291
292void LocallyManagedUserCreationScreen::OnCreationSuccess() {
293  ApplyPicture();
294}
295
296void LocallyManagedUserCreationScreen::CheckCameraPresence() {
297  CameraDetector::StartPresenceCheck(
298      base::Bind(&LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone,
299                 weak_factory_.GetWeakPtr()));
300}
301
302void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone() {
303  if (actor_) {
304    actor_->SetCameraPresent(
305        CameraDetector::camera_presence() == CameraDetector::kCameraPresent);
306  }
307}
308
309void LocallyManagedUserCreationScreen::OnPhotoTaken(
310    const std::string& raw_data) {
311  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
312  user_photo_ = gfx::ImageSkia();
313  if (image_decoder_.get())
314    image_decoder_->set_delegate(NULL);
315  image_decoder_ = new ImageDecoder(this, raw_data,
316                                    ImageDecoder::DEFAULT_CODEC);
317  scoped_refptr<base::MessageLoopProxy> task_runner =
318      content::BrowserThread::GetMessageLoopProxyForThread(
319          content::BrowserThread::UI);
320  image_decoder_->Start(task_runner);
321}
322
323void LocallyManagedUserCreationScreen::OnImageDecoded(
324    const ImageDecoder* decoder,
325    const SkBitmap& decoded_image) {
326  DCHECK_EQ(image_decoder_.get(), decoder);
327  user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
328  if (apply_photo_after_decoding_)
329    ApplyPicture();
330}
331
332void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
333    const ImageDecoder* decoder) {
334  NOTREACHED() << "Failed to decode PNG image from WebUI";
335}
336
337void LocallyManagedUserCreationScreen::OnImageSelected(
338    const std::string& image_type,
339    const std::string& image_url) {
340  if (image_url.empty())
341    return;
342  int user_image_index = User::kInvalidImageIndex;
343  if (image_type == "default" &&
344      IsDefaultImageUrl(image_url, &user_image_index)) {
345    selected_image_ = user_image_index;
346  } else if (image_type == "camera") {
347    selected_image_ = User::kExternalImageIndex;
348  } else {
349    NOTREACHED() << "Unexpected image type: " << image_type;
350  }
351}
352
353void LocallyManagedUserCreationScreen::OnImageAccepted() {
354}
355
356}  // namespace chromeos
357