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