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"
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
);
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_
)
76 if (active_
== 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
,
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
91 SigninManagerFactory::GetForProfile(profile_
)->ProhibitSignout(true);
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(
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 SupervisedUserSettingsService
* settings_service
=
121 SupervisedUserSettingsServiceFactory::GetForProfile(profile_
);
122 settings_service
->SetLocalSetting(supervised_users::kSigninAllowed
,
123 scoped_ptr
<base::Value
>());
124 #if !defined(OS_CHROMEOS)
125 SigninManagerFactory::GetForProfile(profile_
)->ProhibitSignout(false);
128 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName
);
129 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail
);
132 // Trigger a sync reconfig to enable/disable the right SU data types.
133 // The logic to do this lives in the SupervisedUserSyncDataTypeController.
134 ProfileSyncService
* sync_service
=
135 ProfileSyncServiceFactory::GetForProfile(profile_
);
136 if (sync_service
->HasSyncSetupCompleted())
137 sync_service
->ReconfigureDatatypeManager();
142 base::FilePath
ChildAccountService::GetBlacklistPath() const {
144 return base::FilePath();
145 base::FilePath blacklist_path
;
146 PathService::Get(chrome::DIR_USER_DATA
, &blacklist_path
);
147 blacklist_path
= blacklist_path
.AppendASCII("su-blacklist.bin");
148 return blacklist_path
;
151 GURL
ChildAccountService::GetBlacklistURL() const {
154 return GURL("https://www.gstatic.com/chrome/supervised_user/"
155 "blacklist-20141001-1k.bin");
158 std::string
ChildAccountService::GetSafeSitesCx() const {
160 return std::string();
161 return "017993620680222980993%3A1wdumejvx5i";
164 void ChildAccountService::GoogleSigninSucceeded(const std::string
& account_id
,
165 const std::string
& username
,
166 const std::string
& password
) {
167 DCHECK(!account_id
.empty());
169 StartFetchingServiceFlags(account_id
);
172 void ChildAccountService::GoogleSignedOut(const std::string
& account_id
,
173 const std::string
& username
) {
174 DCHECK(!IsChildAccount());
175 CancelFetchingServiceFlags();
178 void ChildAccountService::OnGetFamilyMembersSuccess(
179 const std::vector
<FamilyInfoFetcher::FamilyMember
>& members
) {
180 bool hoh_found
= false;
181 bool parent_found
= false;
182 for (const FamilyInfoFetcher::FamilyMember
& member
: members
) {
183 if (member
.role
== FamilyInfoFetcher::HEAD_OF_HOUSEHOLD
) {
185 profile_
->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName
,
186 member
.display_name
);
187 profile_
->GetPrefs()->SetString(prefs::kSupervisedUserCustodianEmail
,
189 profile_
->GetPrefs()->SetString(prefs::kSupervisedUserCustodianProfileURL
,
191 profile_
->GetPrefs()->SetString(
192 prefs::kSupervisedUserCustodianProfileImageURL
,
193 member
.profile_image_url
);
194 } else if (member
.role
== FamilyInfoFetcher::PARENT
) {
196 profile_
->GetPrefs()->SetString(prefs::kSupervisedUserSecondCustodianName
,
197 member
.display_name
);
198 profile_
->GetPrefs()->SetString(
199 prefs::kSupervisedUserSecondCustodianEmail
,
201 profile_
->GetPrefs()->SetString(
202 prefs::kSupervisedUserSecondCustodianProfileURL
,
204 profile_
->GetPrefs()->SetString(
205 prefs::kSupervisedUserSecondCustodianProfileImageURL
,
206 member
.profile_image_url
);
208 if (hoh_found
&& parent_found
)
212 DLOG(WARNING
) << "GetFamilyMembers didn't return a HOH?!";
213 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName
);
214 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail
);
215 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianProfileURL
);
216 profile_
->GetPrefs()->ClearPref(
217 prefs::kSupervisedUserCustodianProfileImageURL
);
220 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianName
);
221 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianEmail
);
222 profile_
->GetPrefs()->ClearPref(
223 prefs::kSupervisedUserSecondCustodianProfileURL
);
224 profile_
->GetPrefs()->ClearPref(
225 prefs::kSupervisedUserSecondCustodianProfileImageURL
);
229 void ChildAccountService::OnFailure(FamilyInfoFetcher::ErrorCode error
) {
230 DLOG(WARNING
) << "GetFamilyMembers failed with code " << error
;
231 // TODO(treib): Retry after a while?
234 void ChildAccountService::StartFetchingServiceFlags(
235 const std::string
& account_id
) {
236 account_id_
= account_id
;
237 flag_fetcher_
.reset(new AccountServiceFlagFetcher(
239 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
),
240 profile_
->GetRequestContext(),
241 base::Bind(&ChildAccountService::OnFlagsFetched
,
242 weak_ptr_factory_
.GetWeakPtr())));
245 void ChildAccountService::CancelFetchingServiceFlags() {
246 flag_fetcher_
.reset();
250 void ChildAccountService::OnFlagsFetched(
251 AccountServiceFlagFetcher::ResultCode result
,
252 const std::vector
<std::string
>& flags
) {
253 // If we've been signed out again (or signed in to a different account),
254 // ignore the fetched flags.
255 const std::string
& new_account_id
=
256 SigninManagerFactory::GetForProfile(profile_
)
257 ->GetAuthenticatedAccountId();
258 if (account_id_
.empty() || account_id_
!= new_account_id
)
261 // In case of an error, retry after a while.
262 if (result
!= AccountServiceFlagFetcher::SUCCESS
) {
263 DLOG(WARNING
) << "AccountServiceFlagFetcher returned error code " << result
;
264 base::MessageLoop::current()->PostDelayedTask(
266 base::Bind(&ChildAccountService::StartFetchingServiceFlags
,
267 weak_ptr_factory_
.GetWeakPtr(),
269 base::TimeDelta::FromSeconds(10));
275 bool is_child_account
=
276 std::find(flags
.begin(), flags
.end(),
277 kIsChildAccountServiceFlagName
) != flags
.end();
278 SetIsChildAccount(is_child_account
);
281 void ChildAccountService::SetIsChildAccount(bool is_child_account
) {
282 if (IsChildAccount() == is_child_account
)
285 if (is_child_account
) {
286 profile_
->GetPrefs()->SetString(prefs::kSupervisedUserId
,
287 supervised_users::kChildAccountSUID
);
289 profile_
->GetPrefs()->ClearPref(prefs::kSupervisedUserId
);
291 PropagateChildStatusToUser(is_child_account
);
294 void ChildAccountService::PropagateChildStatusToUser(bool is_child
) {
295 #if defined(OS_CHROMEOS)
296 // TODO(merkulova,treib): Figure out why this causes tests to fail.
297 // user_manager::User* user =
298 // chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
300 // user_manager::UserManager::Get()->ChangeUserSupervisedStatus(
304 // "User instance wasn't found while setting child account flag.";