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/chromeos/login/startup_utils.h"
6
7#include "base/bind.h"
8#include "base/files/file_util.h"
9#include "base/path_service.h"
10#include "base/prefs/pref_registry_simple.h"
11#include "base/prefs/pref_service.h"
12#include "base/sys_info.h"
13#include "base/threading/thread_restrictions.h"
14#include "chrome/browser/browser_process.h"
15#include "chrome/common/chrome_paths.h"
16#include "chrome/common/pref_names.h"
17#include "content/public/browser/browser_thread.h"
18#include "ui/base/l10n/l10n_util.h"
19
20using content::BrowserThread;
21
22namespace {
23
24// Saves boolean "Local State" preference and forces its persistence to disk.
25void SaveBoolPreferenceForced(const char* pref_name, bool value) {
26  PrefService* prefs = g_browser_process->local_state();
27  prefs->SetBoolean(pref_name, value);
28  prefs->CommitPendingWrite();
29}
30
31// Saves integer "Local State" preference and forces its persistence to disk.
32void SaveIntegerPreferenceForced(const char* pref_name, int value) {
33  PrefService* prefs = g_browser_process->local_state();
34  prefs->SetInteger(pref_name, value);
35  prefs->CommitPendingWrite();
36}
37
38// Saves string "Local State" preference and forces its persistence to disk.
39void SaveStringPreferenceForced(const char* pref_name,
40                                const std::string& value) {
41  PrefService* prefs = g_browser_process->local_state();
42  prefs->SetString(pref_name, value);
43  prefs->CommitPendingWrite();
44}
45
46}  // namespace
47
48namespace chromeos {
49
50// static
51void StartupUtils::RegisterPrefs(PrefRegistrySimple* registry) {
52  registry->RegisterBooleanPref(prefs::kOobeComplete, false);
53  registry->RegisterStringPref(prefs::kOobeScreenPending, "");
54  registry->RegisterIntegerPref(prefs::kDeviceRegistered, -1);
55  registry->RegisterBooleanPref(prefs::kEnrollmentRecoveryRequired, false);
56  registry->RegisterStringPref(prefs::kInitialLocale, "en-US");
57}
58
59// static
60bool StartupUtils::IsEulaAccepted() {
61  return g_browser_process->local_state()->GetBoolean(prefs::kEulaAccepted);
62}
63
64// static
65bool StartupUtils::IsOobeCompleted() {
66  return g_browser_process->local_state()->GetBoolean(prefs::kOobeComplete);
67}
68
69// static
70void StartupUtils::MarkEulaAccepted() {
71  SaveBoolPreferenceForced(prefs::kEulaAccepted, true);
72}
73
74// static
75void StartupUtils::MarkOobeCompleted() {
76  // Forcing the second pref will force this one as well. Even if this one
77  // doesn't end up synced it is only going to eat up a couple of bytes with no
78  // side-effects.
79  g_browser_process->local_state()->ClearPref(prefs::kOobeScreenPending);
80  SaveBoolPreferenceForced(prefs::kOobeComplete, true);
81
82  // Successful enrollment implies that recovery is not required.
83  SaveBoolPreferenceForced(prefs::kEnrollmentRecoveryRequired, false);
84}
85
86void StartupUtils::SaveOobePendingScreen(const std::string& screen) {
87  SaveStringPreferenceForced(prefs::kOobeScreenPending, screen);
88}
89
90// Returns the path to flag file indicating that both parts of OOBE were
91// completed.
92// On chrome device, returns /home/chronos/.oobe_completed.
93// On Linux desktop, returns {DIR_USER_DATA}/.oobe_completed.
94static base::FilePath GetOobeCompleteFlagPath() {
95  // The constant is defined here so it won't be referenced directly.
96  const char kOobeCompleteFlagFilePath[] = "/home/chronos/.oobe_completed";
97
98  if (base::SysInfo::IsRunningOnChromeOS()) {
99    return base::FilePath(kOobeCompleteFlagFilePath);
100  } else {
101    base::FilePath user_data_dir;
102    PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
103    return user_data_dir.AppendASCII(".oobe_completed");
104  }
105}
106
107static void CreateOobeCompleteFlagFile() {
108  // Create flag file for boot-time init scripts.
109  base::FilePath oobe_complete_path = GetOobeCompleteFlagPath();
110  if (!base::PathExists(oobe_complete_path)) {
111    FILE* oobe_flag_file = base::OpenFile(oobe_complete_path, "w+b");
112    if (oobe_flag_file == NULL)
113      DLOG(WARNING) << oobe_complete_path.value() << " doesn't exist.";
114    else
115      base::CloseFile(oobe_flag_file);
116  }
117}
118
119// static
120bool StartupUtils::IsDeviceRegistered() {
121  int value =
122      g_browser_process->local_state()->GetInteger(prefs::kDeviceRegistered);
123  if (value > 0) {
124    // Recreate flag file in case it was lost.
125    BrowserThread::PostTask(
126        BrowserThread::FILE,
127        FROM_HERE,
128        base::Bind(&CreateOobeCompleteFlagFile));
129    return true;
130  } else if (value == 0) {
131    return false;
132  } else {
133    // Pref is not set. For compatibility check flag file. It causes blocking
134    // IO on UI thread. But it's required for update from old versions.
135    base::ThreadRestrictions::ScopedAllowIO allow_io;
136    base::FilePath oobe_complete_flag_file_path = GetOobeCompleteFlagPath();
137    bool file_exists = base::PathExists(oobe_complete_flag_file_path);
138    SaveIntegerPreferenceForced(prefs::kDeviceRegistered, file_exists ? 1 : 0);
139    return file_exists;
140  }
141}
142
143// static
144void StartupUtils::MarkDeviceRegistered(const base::Closure& done_callback) {
145  SaveIntegerPreferenceForced(prefs::kDeviceRegistered, 1);
146  if (done_callback.is_null()) {
147    BrowserThread::PostTask(
148        BrowserThread::FILE,
149        FROM_HERE,
150        base::Bind(&CreateOobeCompleteFlagFile));
151  } else {
152    BrowserThread::PostTaskAndReply(
153        BrowserThread::FILE,
154        FROM_HERE,
155        base::Bind(&CreateOobeCompleteFlagFile),
156        done_callback);
157  }
158}
159
160// static
161bool StartupUtils::IsEnrollmentRecoveryRequired() {
162  return g_browser_process->local_state()
163      ->GetBoolean(prefs::kEnrollmentRecoveryRequired);
164}
165
166// static
167void StartupUtils::MarkEnrollmentRecoveryRequired() {
168  SaveBoolPreferenceForced(prefs::kEnrollmentRecoveryRequired, true);
169}
170
171// static
172std::string StartupUtils::GetInitialLocale() {
173  std::string locale =
174      g_browser_process->local_state()->GetString(prefs::kInitialLocale);
175  if (!l10n_util::IsValidLocaleSyntax(locale))
176    locale = "en-US";
177  return locale;
178}
179
180// static
181void StartupUtils::SetInitialLocale(const std::string& locale) {
182  if (l10n_util::IsValidLocaleSyntax(locale))
183    SaveStringPreferenceForced(prefs::kInitialLocale, locale);
184  else
185    NOTREACHED();
186}
187
188}  // namespace chromeos
189