Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / supervised_user / child_accounts / child_account_service.cc
blob64cf0c117452722d4d6f9ca29937ccc211f70db4
1 // Copyright 2014 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.
5 #include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/values.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/signin/account_tracker_service_factory.h"
14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.h"
17 #include "chrome/browser/supervised_user/supervised_user_constants.h"
18 #include "chrome/browser/supervised_user/supervised_user_service.h"
19 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
20 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
21 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
22 #include "chrome/browser/sync/profile_sync_service.h"
23 #include "chrome/browser/sync/profile_sync_service_factory.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "components/pref_registry/pref_registry_syncable.h"
27 #include "components/signin/core/browser/profile_oauth2_token_service.h"
28 #include "components/signin/core/browser/signin_manager.h"
30 #if defined(OS_ANDROID)
31 #include "base/android/jni_android.h"
32 #include "chrome/browser/supervised_user/child_accounts/child_account_service_android.h"
33 #endif
35 #if defined(OS_CHROMEOS)
36 #include "chrome/browser/chromeos/profiles/profile_helper.h"
37 #include "components/user_manager/user_manager.h"
38 #endif
40 const char kChildAccountDetectionFieldTrialName[] = "ChildAccountDetection";
42 // Normally, re-check the family info once per day.
43 const int kUpdateIntervalSeconds = 60 * 60 * 24;
45 // In case of an error while getting the family info, retry with exponential
46 // backoff.
47 const net::BackoffEntry::Policy kBackoffPolicy = {
48 // Number of initial errors (in sequence) to ignore before applying
49 // exponential back-off rules.
52 // Initial delay for exponential backoff in ms.
53 2000,
55 // Factor by which the waiting time will be multiplied.
58 // Fuzzing percentage. ex: 10% will spread requests randomly
59 // between 90%-100% of the calculated time.
60 0.2, // 20%
62 // Maximum amount of time we are willing to delay our request in ms.
63 1000 * 60 * 60 * 4, // 4 hours.
65 // Time to keep an entry from being discarded even when it
66 // has no significant state, -1 to never discard.
67 -1,
69 // Don't use initial delay unless the last request was an error.
70 false,
73 ChildAccountService::ChildAccountService(Profile* profile)
74 : profile_(profile), active_(false),
75 family_fetch_backoff_(&kBackoffPolicy),
76 weak_ptr_factory_(this) {}
78 ChildAccountService::~ChildAccountService() {}
80 // static
81 bool ChildAccountService::IsChildAccountDetectionEnabled() {
82 // Note: It's important to query the field trial state first, to ensure that
83 // UMA reports the correct group.
84 const std::string group_name =
85 base::FieldTrialList::FindFullName(kChildAccountDetectionFieldTrialName);
87 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
88 if (command_line->HasSwitch(switches::kDisableChildAccountDetection))
89 return false;
90 if (command_line->HasSwitch(switches::kEnableChildAccountDetection))
91 return true;
93 if (group_name == "Disabled")
94 return false;
95 return true;
98 void ChildAccountService::RegisterProfilePrefs(
99 user_prefs::PrefRegistrySyncable* registry) {
100 registry->RegisterBooleanPref(prefs::kChildAccountStatusKnown, false);
103 void ChildAccountService::SetIsChildAccount(bool is_child_account) {
104 PropagateChildStatusToUser(is_child_account);
105 if (profile_->IsChild() != is_child_account) {
106 if (is_child_account) {
107 profile_->GetPrefs()->SetString(prefs::kSupervisedUserId,
108 supervised_users::kChildAccountSUID);
109 } else {
110 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserId);
112 ClearFirstCustodianPrefs();
113 ClearSecondCustodianPrefs();
116 profile_->GetPrefs()->SetBoolean(prefs::kChildAccountStatusKnown, true);
118 for (const auto& callback : status_received_callback_list_)
119 callback.Run();
120 status_received_callback_list_.clear();
123 void ChildAccountService::Init() {
124 SupervisedUserServiceFactory::GetForProfile(profile_)->SetDelegate(this);
125 AccountTrackerServiceFactory::GetForProfile(profile_)->AddObserver(this);
127 #if defined(OS_ANDROID)
128 bool is_child_account = false;
129 if (GetJavaChildAccountStatus(&is_child_account))
130 SetIsChildAccount(is_child_account);
131 #endif
133 PropagateChildStatusToUser(profile_->IsChild());
135 // If we're already signed in, check the account immediately just to be sure.
136 // (We might have missed an update before registering as an observer.)
137 SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile_);
138 if (signin->IsAuthenticated()) {
139 OnAccountUpdated(
140 AccountTrackerServiceFactory::GetForProfile(profile_)->GetAccountInfo(
141 signin->GetAuthenticatedAccountId()));
145 bool ChildAccountService::IsChildAccountStatusKnown() {
146 return profile_->GetPrefs()->GetBoolean(prefs::kChildAccountStatusKnown);
149 void ChildAccountService::Shutdown() {
150 family_fetcher_.reset();
151 AccountTrackerServiceFactory::GetForProfile(profile_)->RemoveObserver(this);
152 SupervisedUserServiceFactory::GetForProfile(profile_)->SetDelegate(nullptr);
153 DCHECK(!active_);
156 void ChildAccountService::AddChildStatusReceivedCallback(
157 const base::Closure& callback) {
158 if (IsChildAccountStatusKnown())
159 callback.Run();
160 else
161 status_received_callback_list_.push_back(callback);
164 bool ChildAccountService::SetActive(bool active) {
165 if (!profile_->IsChild() && !active_)
166 return false;
167 if (active_ == active)
168 return true;
169 active_ = active;
171 if (active_) {
172 // In contrast to legacy SUs, child account SUs must sign in.
173 scoped_ptr<base::Value> allow_signin(new base::FundamentalValue(true));
174 SupervisedUserSettingsService* settings_service =
175 SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
176 settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
177 allow_signin.Pass());
178 #if !defined(OS_CHROMEOS)
179 // This is also used by user policies (UserPolicySigninService), but since
180 // child accounts can not also be Dasher accounts, there shouldn't be any
181 // problems.
182 SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(true);
183 #endif
185 // TODO(treib): Maybe store the last update time in a pref, so we don't
186 // have to re-fetch on every start.
187 StartFetchingFamilyInfo();
189 SupervisedUserService* service =
190 SupervisedUserServiceFactory::GetForProfile(profile_);
191 service->AddPermissionRequestCreator(
192 PermissionRequestCreatorApiary::CreateWithProfile(profile_));
193 } else {
194 SupervisedUserSettingsService* settings_service =
195 SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
196 settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
197 scoped_ptr<base::Value>());
198 #if !defined(OS_CHROMEOS)
199 SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(false);
200 #endif
202 CancelFetchingFamilyInfo();
205 // Trigger a sync reconfig to enable/disable the right SU data types.
206 // The logic to do this lives in the SupervisedUserSyncDataTypeController.
207 ProfileSyncService* sync_service =
208 ProfileSyncServiceFactory::GetForProfile(profile_);
209 if (sync_service->HasSyncSetupCompleted())
210 sync_service->ReconfigureDatatypeManager();
212 return true;
215 void ChildAccountService::OnAccountUpdated(const AccountInfo& info) {
216 std::string auth_account_id = SigninManagerFactory::GetForProfile(profile_)
217 ->GetAuthenticatedAccountId();
218 if (!info.IsValid() || info.account_id != auth_account_id)
219 return;
221 if (!IsChildAccountDetectionEnabled()) {
222 SetIsChildAccount(false);
223 return;
226 SetIsChildAccount(info.is_child_account);
229 void ChildAccountService::OnGetFamilyMembersSuccess(
230 const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
231 bool hoh_found = false;
232 bool parent_found = false;
233 for (const FamilyInfoFetcher::FamilyMember& member : members) {
234 if (member.role == FamilyInfoFetcher::HEAD_OF_HOUSEHOLD) {
235 hoh_found = true;
236 SetFirstCustodianPrefs(member);
237 } else if (member.role == FamilyInfoFetcher::PARENT) {
238 parent_found = true;
239 SetSecondCustodianPrefs(member);
241 if (hoh_found && parent_found)
242 break;
244 if (!hoh_found) {
245 DLOG(WARNING) << "GetFamilyMembers didn't return a HOH?!";
246 ClearFirstCustodianPrefs();
248 if (!parent_found)
249 ClearSecondCustodianPrefs();
250 family_fetcher_.reset();
252 family_fetch_backoff_.InformOfRequest(true);
254 ScheduleNextFamilyInfoUpdate(
255 base::TimeDelta::FromSeconds(kUpdateIntervalSeconds));
258 void ChildAccountService::OnFailure(FamilyInfoFetcher::ErrorCode error) {
259 DLOG(WARNING) << "GetFamilyMembers failed with code " << error;
260 family_fetch_backoff_.InformOfRequest(false);
261 ScheduleNextFamilyInfoUpdate(family_fetch_backoff_.GetTimeUntilRelease());
264 void ChildAccountService::StartFetchingFamilyInfo() {
265 family_fetcher_.reset(new FamilyInfoFetcher(
266 this,
267 SigninManagerFactory::GetForProfile(profile_)
268 ->GetAuthenticatedAccountId(),
269 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
270 profile_->GetRequestContext()));
271 family_fetcher_->StartGetFamilyMembers();
274 void ChildAccountService::CancelFetchingFamilyInfo() {
275 family_fetcher_.reset();
276 family_fetch_timer_.Stop();
279 void ChildAccountService::ScheduleNextFamilyInfoUpdate(base::TimeDelta delay) {
280 family_fetch_timer_.Start(
281 FROM_HERE, delay, this, &ChildAccountService::StartFetchingFamilyInfo);
284 void ChildAccountService::PropagateChildStatusToUser(bool is_child) {
285 #if defined(OS_CHROMEOS)
286 user_manager::User* user =
287 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
288 if (user) {
289 user_manager::UserManager::Get()->ChangeUserChildStatus(user, is_child);
290 } else {
291 LOG(WARNING) <<
292 "User instance wasn't found while setting child account flag.";
294 #endif
297 void ChildAccountService::SetFirstCustodianPrefs(
298 const FamilyInfoFetcher::FamilyMember& custodian) {
299 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
300 custodian.display_name);
301 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianEmail,
302 custodian.email);
303 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianProfileURL,
304 custodian.profile_url);
305 profile_->GetPrefs()->SetString(
306 prefs::kSupervisedUserCustodianProfileImageURL,
307 custodian.profile_image_url);
310 void ChildAccountService::SetSecondCustodianPrefs(
311 const FamilyInfoFetcher::FamilyMember& custodian) {
312 profile_->GetPrefs()->SetString(prefs::kSupervisedUserSecondCustodianName,
313 custodian.display_name);
314 profile_->GetPrefs()->SetString(prefs::kSupervisedUserSecondCustodianEmail,
315 custodian.email);
316 profile_->GetPrefs()->SetString(
317 prefs::kSupervisedUserSecondCustodianProfileURL,
318 custodian.profile_url);
319 profile_->GetPrefs()->SetString(
320 prefs::kSupervisedUserSecondCustodianProfileImageURL,
321 custodian.profile_image_url);
324 void ChildAccountService::ClearFirstCustodianPrefs() {
325 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName);
326 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail);
327 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianProfileURL);
328 profile_->GetPrefs()->ClearPref(
329 prefs::kSupervisedUserCustodianProfileImageURL);
332 void ChildAccountService::ClearSecondCustodianPrefs() {
333 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianName);
334 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianEmail);
335 profile_->GetPrefs()->ClearPref(
336 prefs::kSupervisedUserSecondCustodianProfileURL);
337 profile_->GetPrefs()->ClearPref(
338 prefs::kSupervisedUserSecondCustodianProfileImageURL);