| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_han
dler.h" | 5 #include "chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_han
dler.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/command_line.h" |
| 10 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 11 #include "base/sys_info.h" | 12 #include "base/sys_info.h" |
| 12 #include "base/task_scheduler/post_task.h" | 13 #include "base/task_scheduler/post_task.h" |
| 13 #include "chrome/browser/lifetime/application_lifetime.h" | 14 #include "chrome/browser/lifetime/application_lifetime.h" |
| 15 #include "chromeos/chromeos_switches.h" |
| 14 #include "chromeos/cryptohome/homedir_methods.h" | 16 #include "chromeos/cryptohome/homedir_methods.h" |
| 15 #include "chromeos/dbus/cryptohome_client.h" | 17 #include "chromeos/dbus/cryptohome_client.h" |
| 16 #include "chromeos/dbus/dbus_thread_manager.h" | 18 #include "chromeos/dbus/dbus_thread_manager.h" |
| 19 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" |
| 20 #include "chromeos/dbus/power_manager_client.h" |
| 17 | 21 |
| 18 namespace { | 22 namespace { |
| 19 | 23 |
| 20 constexpr char kJsScreenPath[] = "login.EncryptionMigrationScreen"; | 24 constexpr char kJsScreenPath[] = "login.EncryptionMigrationScreen"; |
| 21 | 25 |
| 22 // Path to the mount point to check the available space. | 26 // Path to the mount point to check the available space. |
| 23 constexpr char kCheckStoragePath[] = "/home"; | 27 constexpr char kCheckStoragePath[] = "/home"; |
| 24 | 28 |
| 25 // The minimum size of available space to start the migration. | 29 // The minimum size of available space to start the migration. |
| 26 constexpr int64_t kMinimumAvailableStorage = 10LL * 1024 * 1024; // 10MB | 30 constexpr int64_t kMinimumAvailableStorage = 10LL * 1024 * 1024; // 10MB |
| 27 | 31 |
| 32 // The minimum battery level to start the migration. |
| 33 constexpr double kMinimumBatteryPercent = 30; |
| 34 |
| 28 // JS API callbacks names. | 35 // JS API callbacks names. |
| 29 constexpr char kJsApiStartMigration[] = "startMigration"; | 36 constexpr char kJsApiStartMigration[] = "startMigration"; |
| 30 constexpr char kJsApiSkipMigration[] = "skipMigration"; | 37 constexpr char kJsApiSkipMigration[] = "skipMigration"; |
| 31 constexpr char kJsApiRequestRestart[] = "requestRestart"; | 38 constexpr char kJsApiRequestRestart[] = "requestRestart"; |
| 32 | 39 |
| 40 bool IsTestingUI() { |
| 41 return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 42 chromeos::switches::kTestEncryptionMigrationUI); |
| 43 } |
| 44 |
| 33 } // namespace | 45 } // namespace |
| 34 | 46 |
| 35 namespace chromeos { | 47 namespace chromeos { |
| 36 | 48 |
| 37 EncryptionMigrationScreenHandler::EncryptionMigrationScreenHandler() | 49 EncryptionMigrationScreenHandler::EncryptionMigrationScreenHandler() |
| 38 : BaseScreenHandler(kScreenId), weak_ptr_factory_(this) { | 50 : BaseScreenHandler(kScreenId), weak_ptr_factory_(this) { |
| 39 set_call_js_prefix(kJsScreenPath); | 51 set_call_js_prefix(kJsScreenPath); |
| 52 DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); |
| 40 } | 53 } |
| 41 | 54 |
| 42 EncryptionMigrationScreenHandler::~EncryptionMigrationScreenHandler() { | 55 EncryptionMigrationScreenHandler::~EncryptionMigrationScreenHandler() { |
| 56 DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); |
| 43 if (delegate_) | 57 if (delegate_) |
| 44 delegate_->OnViewDestroyed(this); | 58 delegate_->OnViewDestroyed(this); |
| 45 } | 59 } |
| 46 | 60 |
| 47 void EncryptionMigrationScreenHandler::Show() { | 61 void EncryptionMigrationScreenHandler::Show() { |
| 48 if (!page_is_ready() || !delegate_) { | 62 if (!page_is_ready() || !delegate_) { |
| 49 show_on_init_ = true; | 63 show_on_init_ = true; |
| 50 return; | 64 return; |
| 51 } | 65 } |
| 52 ShowScreen(kScreenId); | 66 ShowScreen(kScreenId); |
| 53 } | 67 } |
| 54 | 68 |
| 55 void EncryptionMigrationScreenHandler::Hide() { | 69 void EncryptionMigrationScreenHandler::Hide() { |
| 56 show_on_init_ = false; | 70 show_on_init_ = false; |
| 57 } | 71 } |
| 58 | 72 |
| 59 void EncryptionMigrationScreenHandler::SetDelegate(Delegate* delegate) { | 73 void EncryptionMigrationScreenHandler::SetDelegate(Delegate* delegate) { |
| 60 delegate_ = delegate; | 74 delegate_ = delegate; |
| 61 if (page_is_ready()) | 75 if (page_is_ready()) |
| 62 Initialize(); | 76 Initialize(); |
| 63 } | 77 } |
| 64 | 78 |
| 65 void EncryptionMigrationScreenHandler::SetUserContext( | 79 void EncryptionMigrationScreenHandler::SetUserContext( |
| 66 const UserContext& user_context) { | 80 const UserContext& user_context) { |
| 67 user_context_ = user_context; | 81 user_context_ = user_context; |
| 68 } | 82 } |
| 69 | 83 |
| 70 void EncryptionMigrationScreenHandler::SetShouldResume(bool should_resume) { | 84 void EncryptionMigrationScreenHandler::SetShouldResume(bool should_resume) { |
| 71 should_resume_ = should_resume; | 85 should_resume_ = should_resume; |
| 86 CallJS("setIsResuming", should_resume_); |
| 72 } | 87 } |
| 73 | 88 |
| 74 void EncryptionMigrationScreenHandler::SetContinueLoginCallback( | 89 void EncryptionMigrationScreenHandler::SetContinueLoginCallback( |
| 75 ContinueLoginCallback callback) { | 90 ContinueLoginCallback callback) { |
| 76 continue_login_callback_ = std::move(callback); | 91 continue_login_callback_ = std::move(callback); |
| 77 } | 92 } |
| 78 | 93 |
| 79 void EncryptionMigrationScreenHandler::SetupInitialView() { | 94 void EncryptionMigrationScreenHandler::SetupInitialView() { |
| 80 CheckAvailableStorage(); | 95 CheckAvailableStorage(); |
| 81 } | 96 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 95 | 110 |
| 96 void EncryptionMigrationScreenHandler::RegisterMessages() { | 111 void EncryptionMigrationScreenHandler::RegisterMessages() { |
| 97 AddCallback(kJsApiStartMigration, | 112 AddCallback(kJsApiStartMigration, |
| 98 &EncryptionMigrationScreenHandler::HandleStartMigration); | 113 &EncryptionMigrationScreenHandler::HandleStartMigration); |
| 99 AddCallback(kJsApiSkipMigration, | 114 AddCallback(kJsApiSkipMigration, |
| 100 &EncryptionMigrationScreenHandler::HandleSkipMigration); | 115 &EncryptionMigrationScreenHandler::HandleSkipMigration); |
| 101 AddCallback(kJsApiRequestRestart, | 116 AddCallback(kJsApiRequestRestart, |
| 102 &EncryptionMigrationScreenHandler::HandleRequestRestart); | 117 &EncryptionMigrationScreenHandler::HandleRequestRestart); |
| 103 } | 118 } |
| 104 | 119 |
| 120 void EncryptionMigrationScreenHandler::PowerChanged( |
| 121 const power_manager::PowerSupplyProperties& proto) { |
| 122 current_battery_percent_ = proto.battery_percent(); |
| 123 CallJS("setBatteryPercent", current_battery_percent_, |
| 124 current_battery_percent_ >= kMinimumBatteryPercent); |
| 125 |
| 126 // If the migration was already requested and the bettery level is enough now, |
| 127 // The migration should start immediately. |
| 128 if (current_battery_percent_ >= kMinimumBatteryPercent && |
| 129 should_migrate_on_enough_battery_) { |
| 130 should_migrate_on_enough_battery_ = false; |
| 131 StartMigration(); |
| 132 } |
| 133 } |
| 134 |
| 105 void EncryptionMigrationScreenHandler::HandleStartMigration() { | 135 void EncryptionMigrationScreenHandler::HandleStartMigration() { |
| 106 StartMigration(); | 136 CallJS("setIsMigrationAccepted", true); |
| 137 WaitBatteryAndMigrate(); |
| 107 } | 138 } |
| 108 | 139 |
| 109 void EncryptionMigrationScreenHandler::HandleSkipMigration() { | 140 void EncryptionMigrationScreenHandler::HandleSkipMigration() { |
| 110 // If the user skips migration, we mount the cryptohome without performing the | 141 // If the user skips migration, we mount the cryptohome without performing the |
| 111 // migration by reusing UserContext and LoginPerformer which were used in the | 142 // migration by reusing UserContext and LoginPerformer which were used in the |
| 112 // previous attempt and dropping |is_forcing_dircrypto| flag in UserContext. | 143 // previous attempt and dropping |is_forcing_dircrypto| flag in UserContext. |
| 113 // In this case, the user can not launch ARC apps in the session, and will be | 144 // In this case, the user can not launch ARC apps in the session, and will be |
| 114 // asked to do the migration again in the next log-in attempt. | 145 // asked to do the migration again in the next log-in attempt. |
| 115 if (!continue_login_callback_.is_null()) { | 146 if (!continue_login_callback_.is_null()) { |
| 116 user_context_.SetIsForcingDircrypto(false); | 147 user_context_.SetIsForcingDircrypto(false); |
| 117 std::move(continue_login_callback_).Run(user_context_); | 148 std::move(continue_login_callback_).Run(user_context_); |
| 118 } | 149 } |
| 119 } | 150 } |
| 120 | 151 |
| 121 void EncryptionMigrationScreenHandler::HandleRequestRestart() { | 152 void EncryptionMigrationScreenHandler::HandleRequestRestart() { |
| 122 // TODO(fukino): If the migration finished successfully, we don't need to | 153 // TODO(fukino): If the migration finished successfully, we don't need to |
| 123 // restart the device. Let's sign in to the desktop using the already-provided | 154 // restart the device. Let's sign in to the desktop using the already-provided |
| 124 // user credential. | 155 // user credential. |
| 125 chrome::AttemptRestart(); | 156 chrome::AttemptRestart(); |
| 126 } | 157 } |
| 127 | 158 |
| 128 void EncryptionMigrationScreenHandler::UpdateUIState(UIState state) { | 159 void EncryptionMigrationScreenHandler::UpdateUIState(UIState state) { |
| 129 if (state == current_ui_state_) | 160 if (state == current_ui_state_) |
| 130 return; | 161 return; |
| 131 | 162 |
| 132 current_ui_state_ = state; | 163 current_ui_state_ = state; |
| 133 CallJS("setUIState", static_cast<int>(state)); | 164 CallJS("setUIState", static_cast<int>(state)); |
| 165 |
| 166 // When this handler is about to show the READY screen, we should get the |
| 167 // latest battery status and show it on the screen. |
| 168 if (state == UIState::READY) |
| 169 DBusThreadManager::Get()->GetPowerManagerClient()->RequestStatusUpdate(); |
| 134 } | 170 } |
| 135 | 171 |
| 136 void EncryptionMigrationScreenHandler::CheckAvailableStorage() { | 172 void EncryptionMigrationScreenHandler::CheckAvailableStorage() { |
| 137 base::PostTaskWithTraitsAndReplyWithResult( | 173 base::PostTaskWithTraitsAndReplyWithResult( |
| 138 FROM_HERE, | 174 FROM_HERE, |
| 139 base::TaskTraits().MayBlock().WithPriority( | 175 base::TaskTraits().MayBlock().WithPriority( |
| 140 base::TaskPriority::USER_VISIBLE), | 176 base::TaskPriority::USER_VISIBLE), |
| 141 base::Bind(&base::SysInfo::AmountOfFreeDiskSpace, | 177 base::Bind(&base::SysInfo::AmountOfFreeDiskSpace, |
| 142 base::FilePath(kCheckStoragePath)), | 178 base::FilePath(kCheckStoragePath)), |
| 143 base::Bind(&EncryptionMigrationScreenHandler::OnGetAvailableStorage, | 179 base::Bind(&EncryptionMigrationScreenHandler::OnGetAvailableStorage, |
| 144 weak_ptr_factory_.GetWeakPtr())); | 180 weak_ptr_factory_.GetWeakPtr())); |
| 145 } | 181 } |
| 146 | 182 |
| 147 void EncryptionMigrationScreenHandler::OnGetAvailableStorage(int64_t size) { | 183 void EncryptionMigrationScreenHandler::OnGetAvailableStorage(int64_t size) { |
| 148 if (size < kMinimumAvailableStorage) { | 184 if (size >= kMinimumAvailableStorage || IsTestingUI()) { |
| 149 UpdateUIState(NOT_ENOUGH_STORAGE); | 185 if (should_resume_) { |
| 150 CallJS("setIsResuming", should_resume_); | 186 WaitBatteryAndMigrate(); |
| 187 } else { |
| 188 UpdateUIState(UIState::READY); |
| 189 } |
| 151 } else { | 190 } else { |
| 152 if (should_resume_) { | 191 UpdateUIState(UIState::NOT_ENOUGH_STORAGE); |
| 153 // TODO(fukino): Check the battery level. | |
| 154 StartMigration(); | |
| 155 } else { | |
| 156 UpdateUIState(READY); | |
| 157 } | |
| 158 } | 192 } |
| 159 } | 193 } |
| 160 | 194 |
| 195 void EncryptionMigrationScreenHandler::WaitBatteryAndMigrate() { |
| 196 if (current_battery_percent_ >= kMinimumBatteryPercent) { |
| 197 StartMigration(); |
| 198 return; |
| 199 } |
| 200 UpdateUIState(UIState::READY); |
| 201 |
| 202 should_migrate_on_enough_battery_ = true; |
| 203 DBusThreadManager::Get()->GetPowerManagerClient()->RequestStatusUpdate(); |
| 204 } |
| 205 |
| 161 void EncryptionMigrationScreenHandler::StartMigration() { | 206 void EncryptionMigrationScreenHandler::StartMigration() { |
| 207 UpdateUIState(UIState::MIGRATING); |
| 208 |
| 162 DBusThreadManager::Get() | 209 DBusThreadManager::Get() |
| 163 ->GetCryptohomeClient() | 210 ->GetCryptohomeClient() |
| 164 ->SetDircryptoMigrationProgressHandler( | 211 ->SetDircryptoMigrationProgressHandler( |
| 165 base::Bind(&EncryptionMigrationScreenHandler::OnMigrationProgress, | 212 base::Bind(&EncryptionMigrationScreenHandler::OnMigrationProgress, |
| 166 weak_ptr_factory_.GetWeakPtr())); | 213 weak_ptr_factory_.GetWeakPtr())); |
| 167 | 214 |
| 168 // |auth_key| is created in the same manner as CryptohomeAuthenticator. | 215 // |auth_key| is created in the same manner as CryptohomeAuthenticator. |
| 169 const Key* key = user_context_.GetKey(); | 216 const Key* key = user_context_.GetKey(); |
| 170 // If the |key| is a plain text password, crash rather than attempting to | 217 // If the |key| is a plain text password, crash rather than attempting to |
| 171 // mount the cryptohome with a plain text password. | 218 // mount the cryptohome with a plain text password. |
| 172 CHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType()); | 219 CHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType()); |
| 173 // Set the authentication's key label to an empty string, which is a wildcard | 220 // Set the authentication's key label to an empty string, which is a wildcard |
| 174 // allowing any key to match. This is necessary because cryptohomes created by | 221 // allowing any key to match. This is necessary because cryptohomes created by |
| 175 // Chrome OS M38 and older will have a legacy key with no label while those | 222 // Chrome OS M38 and older will have a legacy key with no label while those |
| 176 // created by Chrome OS M39 and newer will have a key with the label | 223 // created by Chrome OS M39 and newer will have a key with the label |
| 177 // kCryptohomeGAIAKeyLabel. | 224 // kCryptohomeGAIAKeyLabel. |
| 178 const cryptohome::KeyDefinition auth_key(key->GetSecret(), std::string(), | 225 const cryptohome::KeyDefinition auth_key(key->GetSecret(), std::string(), |
| 179 cryptohome::PRIV_DEFAULT); | 226 cryptohome::PRIV_DEFAULT); |
| 180 cryptohome::HomedirMethods::GetInstance()->MigrateToDircrypto( | 227 cryptohome::HomedirMethods::GetInstance()->MigrateToDircrypto( |
| 181 cryptohome::Identification(user_context_.GetAccountId()), | 228 cryptohome::Identification(user_context_.GetAccountId()), |
| 182 cryptohome::Authorization(auth_key), | 229 cryptohome::Authorization(auth_key), |
| 183 base::Bind(&EncryptionMigrationScreenHandler::OnMigrationRequested, | 230 base::Bind(&EncryptionMigrationScreenHandler::OnMigrationRequested, |
| 184 weak_ptr_factory_.GetWeakPtr())); | 231 weak_ptr_factory_.GetWeakPtr())); |
| 185 UpdateUIState(UIState::MIGRATING); | |
| 186 } | 232 } |
| 187 | 233 |
| 188 void EncryptionMigrationScreenHandler::OnMigrationProgress( | 234 void EncryptionMigrationScreenHandler::OnMigrationProgress( |
| 189 cryptohome::DircryptoMigrationStatus status, | 235 cryptohome::DircryptoMigrationStatus status, |
| 190 uint64_t current, | 236 uint64_t current, |
| 191 uint64_t total) { | 237 uint64_t total) { |
| 192 switch (status) { | 238 switch (status) { |
| 193 case cryptohome::DIRCRYPTO_MIGRATION_INITIALIZING: | 239 case cryptohome::DIRCRYPTO_MIGRATION_INITIALIZING: |
| 194 UpdateUIState(UIState::MIGRATING); | 240 UpdateUIState(UIState::MIGRATING); |
| 195 break; | 241 break; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 216 void EncryptionMigrationScreenHandler::OnMigrationRequested(bool success) { | 262 void EncryptionMigrationScreenHandler::OnMigrationRequested(bool success) { |
| 217 // This function is called when MigrateToDircrypto is correctly requested. | 263 // This function is called when MigrateToDircrypto is correctly requested. |
| 218 // It does not mean that the migration is completed. We should know the | 264 // It does not mean that the migration is completed. We should know the |
| 219 // completion by DircryptoMigrationProgressHandler. success == false means a | 265 // completion by DircryptoMigrationProgressHandler. success == false means a |
| 220 // failure in DBus communication. | 266 // failure in DBus communication. |
| 221 // TODO(fukino): Handle this case. Should we retry or restart? | 267 // TODO(fukino): Handle this case. Should we retry or restart? |
| 222 DCHECK(success); | 268 DCHECK(success); |
| 223 } | 269 } |
| 224 | 270 |
| 225 } // namespace chromeos | 271 } // namespace chromeos |
| OLD | NEW |