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