reset_screen_handler.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright (c) 2012 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/ui/webui/chromeos/login/reset_screen_handler.h"
6
7#include <string>
8
9#include "base/command_line.h"
10#include "base/metrics/histogram.h"
11#include "base/prefs/pref_service.h"
12#include "base/values.h"
13#include "chrome/browser/browser_process.h"
14#include "chrome/browser/chromeos/login/help_app_launcher.h"
15#include "chrome/browser/chromeos/reset/metrics.h"
16#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
17#include "chrome/common/chrome_switches.h"
18#include "chrome/common/pref_names.h"
19#include "chromeos/chromeos_switches.h"
20#include "chromeos/dbus/dbus_thread_manager.h"
21#include "chromeos/dbus/power_manager_client.h"
22#include "chromeos/dbus/session_manager_client.h"
23#include "chromeos/dbus/update_engine_client.h"
24#include "grit/browser_resources.h"
25#include "grit/chromium_strings.h"
26#include "grit/generated_resources.h"
27#include "ui/base/l10n/l10n_util.h"
28
29namespace {
30
31const char kJsScreenPath[] = "login.ResetScreen";
32
33// Reset screen id.
34const char kResetScreen[] = "reset";
35
36const int kErrorUIStateRollback = 7;
37
38}  // namespace
39
40namespace chromeos {
41
42ResetScreenHandler::ResetScreenHandler()
43    : BaseScreenHandler(kJsScreenPath),
44      delegate_(NULL),
45      show_on_init_(false),
46      restart_required_(true),
47      reboot_was_requested_(false),
48      rollback_available_(false),
49      weak_ptr_factory_(this) {
50}
51
52ResetScreenHandler::~ResetScreenHandler() {
53  if (delegate_)
54    delegate_->OnActorDestroyed(this);
55  DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
56}
57
58void ResetScreenHandler::PrepareToShow() {
59}
60
61void ResetScreenHandler::ShowWithParams() {
62  int dialog_type;
63  if (reboot_was_requested_) {
64    dialog_type = rollback_available_ ?
65        reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_AND_ROLLBACK :
66        reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_ONLY;
67  } else {
68    dialog_type = rollback_available_ ?
69      reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_AVAILABLE :
70      reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_UNAVAILABLE;
71  }
72  UMA_HISTOGRAM_ENUMERATION("Reset.ChromeOS.PowerwashDialogShown",
73                            dialog_type,
74                            reset::DIALOG_VIEW_TYPE_SIZE);
75
76  base::DictionaryValue reset_screen_params;
77  reset_screen_params.SetBoolean("showRestartMsg", restart_required_);
78  reset_screen_params.SetBoolean(
79      "showRollbackOption", rollback_available_ && !reboot_was_requested_);
80  reset_screen_params.SetBoolean(
81      "simpleConfirm", reboot_was_requested_ && !rollback_available_);
82  reset_screen_params.SetBoolean(
83      "rollbackConfirm", reboot_was_requested_ && rollback_available_);
84
85  PrefService* prefs = g_browser_process->local_state();
86  prefs->SetBoolean(prefs::kFactoryResetRequested, false);
87  prefs->SetBoolean(prefs::kRollbackRequested, false);
88  prefs->CommitPendingWrite();
89  ShowScreen(kResetScreen, &reset_screen_params);
90}
91
92void ResetScreenHandler::Show() {
93  if (!page_is_ready()) {
94    show_on_init_ = true;
95    return;
96  }
97
98  PrefService* prefs = g_browser_process->local_state();
99  restart_required_ = !CommandLine::ForCurrentProcess()->HasSwitch(
100      switches::kFirstExecAfterBoot);
101  reboot_was_requested_ = false;
102  rollback_available_ = false;
103  if (!restart_required_)  // First exec after boot.
104    reboot_was_requested_ = prefs->GetBoolean(prefs::kFactoryResetRequested);
105  if (!restart_required_ && reboot_was_requested_) {
106    // First exec after boot.
107    rollback_available_ = prefs->GetBoolean(prefs::kRollbackRequested);
108    ShowWithParams();
109  } else {
110    chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
111        CanRollbackCheck(base::Bind(&ResetScreenHandler::OnRollbackCheck,
112        weak_ptr_factory_.GetWeakPtr()));
113  }
114}
115
116void ResetScreenHandler::Hide() {
117  DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
118}
119
120void ResetScreenHandler::SetDelegate(Delegate* delegate) {
121  delegate_ = delegate;
122  if (page_is_ready())
123    Initialize();
124}
125
126void ResetScreenHandler::DeclareLocalizedValues(
127    LocalizedValuesBuilder* builder) {
128  builder->Add("resetScreenTitle", IDS_RESET_SCREEN_TITLE);
129  builder->Add("cancelButton", IDS_CANCEL);
130
131  builder->Add("resetWarningDataDetails",
132               IDS_RESET_SCREEN_WARNING_DETAILS_DATA);
133  builder->Add("resetRestartMessage", IDS_RESET_SCREEN_RESTART_MSG);
134  builder->AddF("resetRollbackOption",
135                IDS_RESET_SCREEN_ROLLBACK_OPTION,
136                IDS_SHORT_PRODUCT_NAME);
137  builder->AddF("resetRevertPromise",
138               IDS_RESET_SCREEN_PREPARING_REVERT_PROMISE,
139               IDS_SHORT_PRODUCT_NAME);
140  builder->AddF("resetRevertSpinnerMessage",
141                IDS_RESET_SCREEN_PREPARING_REVERT_SPINNER_MESSAGE,
142                IDS_SHORT_PRODUCT_NAME);
143
144  // Different variants of the same UI elements for all dialog cases.
145  builder->Add("resetButtonReset", IDS_RESET_SCREEN_RESET);
146  builder->Add("resetButtonRelaunch", IDS_RELAUNCH_BUTTON);
147  builder->Add("resetButtonPowerwash", IDS_RESET_SCREEN_POWERWASH);
148
149  builder->AddF(
150      "resetAndRollbackWarningTextConfirmational",
151      IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_AND_ROLLBACK_MSG,
152      IDS_SHORT_PRODUCT_NAME);
153  builder->AddF("resetWarningTextConfirmational",
154                IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_MSG,
155                IDS_SHORT_PRODUCT_NAME);
156  builder->AddF("resetWarningTextInitial",
157                IDS_RESET_SCREEN_WARNING_MSG,
158                IDS_SHORT_PRODUCT_NAME);
159
160  builder->AddF(
161      "resetAndRollbackWarningDetailsConfirmational",
162      IDS_RESET_SCREEN_CONFIRMATION_WARNING_ROLLBACK_DETAILS,
163      IDS_SHORT_PRODUCT_NAME);
164  builder->AddF("resetWarningDetailsConfirmational",
165                IDS_RESET_SCREEN_CONFIRMATION_WARNING_DETAILS,
166                IDS_SHORT_PRODUCT_NAME);
167  builder->AddF("resetWarningDetailsInitial",
168                IDS_RESET_SCREEN_WARNING_DETAILS,
169                IDS_SHORT_PRODUCT_NAME);
170}
171
172// Invoked from call to CanRollbackCheck upon completion of the DBus call.
173void ResetScreenHandler::OnRollbackCheck(bool can_rollback) {
174  VLOG(1) << "Callback from CanRollbackCheck, result " << can_rollback;
175  rollback_available_ = can_rollback;
176  ShowWithParams();
177}
178
179void ResetScreenHandler::Initialize() {
180  if (!page_is_ready() || !delegate_)
181    return;
182
183  if (show_on_init_) {
184    Show();
185    show_on_init_ = false;
186  }
187}
188
189void ResetScreenHandler::RegisterMessages() {
190  AddCallback("cancelOnReset", &ResetScreenHandler::HandleOnCancel);
191  AddCallback("restartOnReset", &ResetScreenHandler::HandleOnRestart);
192  AddCallback("powerwashOnReset", &ResetScreenHandler::HandleOnPowerwash);
193  AddCallback("resetOnLearnMore", &ResetScreenHandler::HandleOnLearnMore);
194}
195
196void ResetScreenHandler::HandleOnCancel() {
197  if (delegate_)
198    delegate_->OnExit();
199  DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
200}
201
202void ResetScreenHandler::HandleOnRestart(bool should_rollback) {
203  PrefService* prefs = g_browser_process->local_state();
204  prefs->SetBoolean(prefs::kFactoryResetRequested, true);
205  prefs->SetBoolean(prefs::kRollbackRequested, should_rollback);
206  prefs->CommitPendingWrite();
207
208  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
209}
210
211void ResetScreenHandler::HandleOnPowerwash(bool rollback_checked) {
212  if (rollback_available_ && (rollback_checked || reboot_was_requested_)) {
213      CallJS("updateViewOnRollbackCall");
214      DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(this);
215      chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->Rollback();
216  } else {
217    if (rollback_checked && !rollback_available_) {
218      NOTREACHED() <<
219          "Rollback was checked but not available. Starting powerwash.";
220    }
221    chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
222        StartDeviceWipe();
223  }
224}
225
226void ResetScreenHandler::HandleOnLearnMore() {
227  if (!help_app_.get())
228    help_app_ = new HelpAppLauncher(GetNativeWindow());
229  help_app_->ShowHelpTopic(HelpAppLauncher::HELP_POWERWASH);
230}
231
232void ResetScreenHandler::UpdateStatusChanged(
233    const UpdateEngineClient::Status& status) {
234  if (status.status == UpdateEngineClient::UPDATE_STATUS_ERROR) {
235    // Show error screen.
236    base::DictionaryValue params;
237    params.SetInteger("uiState", kErrorUIStateRollback);
238    ShowScreen(OobeUI::kScreenErrorMessage, &params);
239  } else if (status.status ==
240      UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
241    DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
242  }
243}
244
245}  // namespace chromeos
246