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