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