ChildAccountService: Properly clear custodian prefs
[chromium-blink-merge.git] / chrome / browser / supervised_user / child_accounts / child_account_service.cc
blob4ab34adfc86c04b91fcdbf0691d44ac8807c8566
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/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/supervised_user/supervised_user_constants.h"
20 #include "chrome/browser/supervised_user/supervised_user_service.h"
21 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
22 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
23 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
24 #include "chrome/browser/sync/profile_sync_service.h"
25 #include "chrome/browser/sync/profile_sync_service_factory.h"
26 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/pref_names.h"
29 #include "components/signin/core/browser/profile_oauth2_token_service.h"
30 #include "components/signin/core/browser/signin_manager.h"
32 #if defined(OS_CHROMEOS)
33 #include "chrome/browser/chromeos/profiles/profile_helper.h"
34 #include "components/user_manager/user_manager.h"
35 #endif
37 const char kIsChildAccountServiceFlagName[] = "uca";
39 ChildAccountService::ChildAccountService(Profile* profile)
40 : profile_(profile), active_(false), weak_ptr_factory_(this) {}
42 ChildAccountService::~ChildAccountService() {}
44 void ChildAccountService::Init() {
45 SigninManagerFactory::GetForProfile(profile_)->AddObserver(this);
46 SupervisedUserServiceFactory::GetForProfile(profile_)->SetDelegate(this);
48 PropagateChildStatusToUser(IsChildAccount());
50 // If we're already signed in, fetch the flag again just to be sure.
51 // (Previously, the browser might have been closed before we got the flag.
52 // This also handles the graduation use case in a basic way.)
53 std::string account_id = SigninManagerFactory::GetForProfile(profile_)
54 ->GetAuthenticatedAccountId();
55 if (!account_id.empty())
56 StartFetchingServiceFlags(account_id);
59 void ChildAccountService::Shutdown() {
60 CancelFetchingServiceFlags();
61 SupervisedUserService* service =
62 SupervisedUserServiceFactory::GetForProfile(profile_);
63 service->SetDelegate(NULL);
64 DCHECK(!active_);
65 SigninManagerFactory::GetForProfile(profile_)->RemoveObserver(this);
68 bool ChildAccountService::IsChildAccount() const {
69 return profile_->GetPrefs()->GetString(prefs::kSupervisedUserId) ==
70 supervised_users::kChildAccountSUID;
73 bool ChildAccountService::SetActive(bool active) {
74 if (!IsChildAccount() && !active_)
75 return false;
76 if (active_ == active)
77 return true;
78 active_ = active;
80 if (active_) {
81 // In contrast to local SUs, child account SUs must sign in.
82 scoped_ptr<base::Value> allow_signin(new base::FundamentalValue(true));
83 SupervisedUserSettingsService* settings_service =
84 SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
85 settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
86 allow_signin.Pass());
87 #if !defined(OS_CHROMEOS)
88 // This is also used by user policies (UserPolicySigninService), but since
89 // child accounts can not also be Dasher accounts, there shouldn't be any
90 // problems.
91 SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(true);
92 #endif
94 // TODO(treib): Maybe only fetch the parents on the first start, and then
95 // refresh occasionally (like once every 24h)? That's what
96 // GAIAInfoUpdateService does.
97 family_fetcher_.reset(new FamilyInfoFetcher(
98 this,
99 SigninManagerFactory::GetForProfile(profile_)
100 ->GetAuthenticatedAccountId(),
101 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
102 profile_->GetRequestContext()));
103 family_fetcher_->StartGetFamilyMembers();
105 // Set the permission request API URL and scope, unless they have been
106 // explicitly specified on the command line.
107 CommandLine* command_line = CommandLine::ForCurrentProcess();
108 if (!command_line->HasSwitch(switches::kPermissionRequestApiUrl)) {
109 command_line->AppendSwitchASCII(
110 switches::kPermissionRequestApiUrl,
111 "https://www.googleapis.com/"
112 "kidsmanagement/v1/people/me/permissionRequests");
114 if (!command_line->HasSwitch(switches::kPermissionRequestApiScope)) {
115 command_line->AppendSwitchASCII(
116 switches::kPermissionRequestApiScope,
117 "https://www.googleapis.com/auth/kid.permission");
120 EnableExperimentalFiltering();
121 } else {
122 SupervisedUserSettingsService* settings_service =
123 SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
124 settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
125 scoped_ptr<base::Value>());
126 #if !defined(OS_CHROMEOS)
127 SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(false);
128 #endif
130 ClearFirstCustodianPrefs();
131 ClearSecondCustodianPrefs();
134 // Trigger a sync reconfig to enable/disable the right SU data types.
135 // The logic to do this lives in the SupervisedUserSyncDataTypeController.
136 ProfileSyncService* sync_service =
137 ProfileSyncServiceFactory::GetForProfile(profile_);
138 if (sync_service->HasSyncSetupCompleted())
139 sync_service->ReconfigureDatatypeManager();
141 return true;
144 base::FilePath ChildAccountService::GetBlacklistPath() const {
145 if (!active_)
146 return base::FilePath();
147 base::FilePath blacklist_path;
148 PathService::Get(chrome::DIR_USER_DATA, &blacklist_path);
149 blacklist_path = blacklist_path.AppendASCII("su-blacklist.bin");
150 return blacklist_path;
153 GURL ChildAccountService::GetBlacklistURL() const {
154 if (!active_)
155 return GURL();
156 return GURL("https://www.gstatic.com/chrome/supervised_user/"
157 "blacklist-20141001-1k.bin");
160 std::string ChildAccountService::GetSafeSitesCx() const {
161 if (!active_)
162 return std::string();
163 return "017993620680222980993%3A1wdumejvx5i";
166 void ChildAccountService::GoogleSigninSucceeded(const std::string& account_id,
167 const std::string& username,
168 const std::string& password) {
169 DCHECK(!account_id.empty());
171 StartFetchingServiceFlags(account_id);
174 void ChildAccountService::GoogleSignedOut(const std::string& account_id,
175 const std::string& username) {
176 DCHECK(!IsChildAccount());
177 CancelFetchingServiceFlags();
180 void ChildAccountService::OnGetFamilyMembersSuccess(
181 const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
182 bool hoh_found = false;
183 bool parent_found = false;
184 for (const FamilyInfoFetcher::FamilyMember& member : members) {
185 if (member.role == FamilyInfoFetcher::HEAD_OF_HOUSEHOLD) {
186 hoh_found = true;
187 SetFirstCustodianPrefs(member);
188 } else if (member.role == FamilyInfoFetcher::PARENT) {
189 parent_found = true;
190 SetSecondCustodianPrefs(member);
192 if (hoh_found && parent_found)
193 break;
195 if (!hoh_found) {
196 DLOG(WARNING) << "GetFamilyMembers didn't return a HOH?!";
197 ClearFirstCustodianPrefs();
199 if (!parent_found)
200 ClearSecondCustodianPrefs();
203 void ChildAccountService::OnFailure(FamilyInfoFetcher::ErrorCode error) {
204 DLOG(WARNING) << "GetFamilyMembers failed with code " << error;
205 // TODO(treib): Retry after a while?
208 void ChildAccountService::StartFetchingServiceFlags(
209 const std::string& account_id) {
210 account_id_ = account_id;
211 flag_fetcher_.reset(new AccountServiceFlagFetcher(
212 account_id_,
213 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
214 profile_->GetRequestContext(),
215 base::Bind(&ChildAccountService::OnFlagsFetched,
216 weak_ptr_factory_.GetWeakPtr())));
219 void ChildAccountService::CancelFetchingServiceFlags() {
220 flag_fetcher_.reset();
221 account_id_.clear();
224 void ChildAccountService::OnFlagsFetched(
225 AccountServiceFlagFetcher::ResultCode result,
226 const std::vector<std::string>& flags) {
227 // If we've been signed out again (or signed in to a different account),
228 // ignore the fetched flags.
229 const std::string& new_account_id =
230 SigninManagerFactory::GetForProfile(profile_)
231 ->GetAuthenticatedAccountId();
232 if (account_id_.empty() || account_id_ != new_account_id)
233 return;
235 // In case of an error, retry after a while.
236 if (result != AccountServiceFlagFetcher::SUCCESS) {
237 DLOG(WARNING) << "AccountServiceFlagFetcher returned error code " << result;
238 base::MessageLoop::current()->PostDelayedTask(
239 FROM_HERE,
240 base::Bind(&ChildAccountService::StartFetchingServiceFlags,
241 weak_ptr_factory_.GetWeakPtr(),
242 account_id_),
243 base::TimeDelta::FromSeconds(10));
244 return;
247 account_id_.clear();
249 bool is_child_account =
250 std::find(flags.begin(), flags.end(),
251 kIsChildAccountServiceFlagName) != flags.end();
252 SetIsChildAccount(is_child_account);
255 void ChildAccountService::SetIsChildAccount(bool is_child_account) {
256 if (IsChildAccount() == is_child_account)
257 return;
259 if (is_child_account) {
260 profile_->GetPrefs()->SetString(prefs::kSupervisedUserId,
261 supervised_users::kChildAccountSUID);
262 } else {
263 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserId);
265 PropagateChildStatusToUser(is_child_account);
268 void ChildAccountService::PropagateChildStatusToUser(bool is_child) {
269 #if defined(OS_CHROMEOS)
270 // TODO(merkulova,treib): Figure out why this causes tests to fail.
271 // user_manager::User* user =
272 // chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
273 // if (user) {
274 // user_manager::UserManager::Get()->ChangeUserSupervisedStatus(
275 // user, is_child);
276 // } else {
277 // LOG(WARNING) <<
278 // "User instance wasn't found while setting child account flag.";
279 // }
280 #endif
283 void ChildAccountService::SetFirstCustodianPrefs(
284 const FamilyInfoFetcher::FamilyMember& custodian) {
285 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
286 custodian.display_name);
287 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianEmail,
288 custodian.email);
289 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianProfileURL,
290 custodian.profile_url);
291 profile_->GetPrefs()->SetString(
292 prefs::kSupervisedUserCustodianProfileImageURL,
293 custodian.profile_image_url);
296 void ChildAccountService::SetSecondCustodianPrefs(
297 const FamilyInfoFetcher::FamilyMember& custodian) {
298 profile_->GetPrefs()->SetString(prefs::kSupervisedUserSecondCustodianName,
299 custodian.display_name);
300 profile_->GetPrefs()->SetString(prefs::kSupervisedUserSecondCustodianEmail,
301 custodian.email);
302 profile_->GetPrefs()->SetString(
303 prefs::kSupervisedUserSecondCustodianProfileURL,
304 custodian.profile_url);
305 profile_->GetPrefs()->SetString(
306 prefs::kSupervisedUserSecondCustodianProfileImageURL,
307 custodian.profile_image_url);
310 void ChildAccountService::ClearFirstCustodianPrefs() {
311 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName);
312 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail);
313 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianProfileURL);
314 profile_->GetPrefs()->ClearPref(
315 prefs::kSupervisedUserCustodianProfileImageURL);
318 void ChildAccountService::ClearSecondCustodianPrefs() {
319 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianName);
320 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianEmail);
321 profile_->GetPrefs()->ClearPref(
322 prefs::kSupervisedUserSecondCustodianProfileURL);
323 profile_->GetPrefs()->ClearPref(
324 prefs::kSupervisedUserSecondCustodianProfileImageURL);
327 void ChildAccountService::EnableExperimentalFiltering() {
328 CommandLine* command_line = CommandLine::ForCurrentProcess();
330 // Static blacklist defaults to enabled.
331 bool has_enable_blacklist =
332 command_line->HasSwitch(switches::kEnableSupervisedUserBlacklist);
333 bool has_disable_blacklist =
334 command_line->HasSwitch(switches::kDisableSupervisedUserBlacklist);
335 if (!has_enable_blacklist && !has_disable_blacklist)
336 command_line->AppendSwitch(switches::kEnableSupervisedUserBlacklist);
338 // Query-based filtering also defaults to enabled.
339 bool has_enable_safesites =
340 command_line->HasSwitch(switches::kEnableSupervisedUserSafeSites);
341 bool has_disable_safesites =
342 command_line->HasSwitch(switches::kDisableSupervisedUserSafeSites);
343 if (!has_enable_safesites && !has_disable_safesites)
344 command_line->AppendSwitch(switches::kEnableSupervisedUserSafeSites);