Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: chrome/browser/supervised_user/child_accounts/child_account_service.cc

Issue 783083002: Add support for child accounts. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove CrOS for now Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
6
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_factor y.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"
31
32 #if defined(OS_CHROMEOS)
33 #include "chrome/browser/chromeos/profiles/profile_helper.h"
34 #include "components/user_manager/user_manager.h"
35 #endif
36
37 const char kIsChildAccountServiceFlagName[] = "uca";
38 const char kChildAccountSUID[] = "ChildAccountSUID";
39
40 ChildAccountService::ChildAccountService(Profile* profile)
41 : profile_(profile), active_(false), weak_ptr_factory_(this) {}
42
43 ChildAccountService::~ChildAccountService() {}
44
45 void ChildAccountService::Init() {
46 SigninManagerFactory::GetForProfile(profile_)->AddObserver(this);
47 SupervisedUserServiceFactory::GetForProfile(profile_)->SetDelegate(this);
48
49 PropagateChildStatusToUser(IsChildAccount());
50
51 // If we're already signed in, fetch the flag again just to be sure.
52 // (Previously, the browser might have been closed before we got the flag.
53 // This also handles the graduation use case in a basic way.)
54 std::string account_id = SigninManagerFactory::GetForProfile(profile_)
55 ->GetAuthenticatedAccountId();
56 if (!account_id.empty())
57 StartFetchingServiceFlags(account_id);
58 }
59
60 void ChildAccountService::Shutdown() {
61 CancelFetchingServiceFlags();
62 SupervisedUserService* service =
63 SupervisedUserServiceFactory::GetForProfile(profile_);
64 service->SetDelegate(NULL);
65 DCHECK(!active_);
66 SigninManagerFactory::GetForProfile(profile_)->RemoveObserver(this);
67 }
68
69 bool ChildAccountService::IsChildAccount() const {
70 return profile_->GetPrefs()->GetString(prefs::kSupervisedUserId) ==
71 kChildAccountSUID;
72 }
73
74 bool ChildAccountService::SetActive(bool active) {
75 if (!IsChildAccount() && !active_)
76 return false;
77 if (active_ == active)
78 return true;
79 active_ = active;
80
81 if (active_) {
82 // In contrast to local SUs, child account SUs must sign in.
83 scoped_ptr<base::Value> allow_signin(new base::FundamentalValue(true));
84 SupervisedUserSettingsService* settings_service =
85 SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
86 settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
87 allow_signin.Pass());
88 #if !defined(OS_CHROMEOS)
89 // This is also used by user policies (UserPolicySigninService), but since
90 // child accounts can not also be Dasher accounts, there shouldn't be any
91 // problems.
92 SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(true);
93 #endif
94
95 // TODO(treib): Maybe only fetch the parents on the first start, and then
96 // refresh occasionally (like once every 24h)? That's what
97 // GAIAInfoUpdateService does.
98 family_fetcher_.reset(new FamilyInfoFetcher(
99 this,
100 SigninManagerFactory::GetForProfile(profile_)
101 ->GetAuthenticatedAccountId(),
102 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
103 profile_->GetRequestContext()));
104 family_fetcher_->StartGetFamilyMembers();
105
106 // Set the permission request API URL and scope, unless they have been
107 // explicitly specified on the command line.
108 CommandLine* command_line = CommandLine::ForCurrentProcess();
109 if (!command_line->HasSwitch(switches::kPermissionRequestApiUrl)) {
110 command_line->AppendSwitchASCII(
111 switches::kPermissionRequestApiUrl,
112 "https://www.googleapis.com/"
113 "kidsmanagement/v1/people/me/permissionRequests");
114 }
115 if (!command_line->HasSwitch(switches::kPermissionRequestApiScope)) {
116 command_line->AppendSwitchASCII(
117 switches::kPermissionRequestApiScope,
118 "https://www.googleapis.com/auth/kid.permission");
119 }
120 } else {
121 SupervisedUserSettingsService* settings_service =
122 SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
123 settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
124 scoped_ptr<base::Value>());
125 #if !defined(OS_CHROMEOS)
126 SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(false);
127 #endif
128
129 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName);
130 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail);
131 }
132
133 // Trigger a sync reconfig to enable/disable the right SU data types.
134 // The logic to do this lives in the SupervisedUserSyncDataTypeController.
135 ProfileSyncService* sync_service =
136 ProfileSyncServiceFactory::GetForProfile(profile_);
137 if (sync_service->HasSyncSetupCompleted())
138 sync_service->ReconfigureDatatypeManager();
139
140 return true;
141 }
142
143 base::FilePath ChildAccountService::GetBlacklistPath() const {
144 if (!active_)
145 return base::FilePath();
146 base::FilePath blacklist_path;
147 PathService::Get(chrome::DIR_USER_DATA, &blacklist_path);
148 blacklist_path = blacklist_path.AppendASCII("su-blacklist.bin");
149 return blacklist_path;
150 }
151
152 GURL ChildAccountService::GetBlacklistURL() const {
153 if (!active_)
154 return GURL();
155 return GURL("https://www.gstatic.com/chrome/supervised_user/"
156 "blacklist-20141001-1k.bin");
157 }
158
159 std::string ChildAccountService::GetSafeSitesCx() const {
160 if (!active_)
161 return std::string();
162 return "017993620680222980993%3A1wdumejvx5i";
163 }
164
165 void ChildAccountService::GoogleSigninSucceeded(const std::string& account_id,
166 const std::string& username,
167 const std::string& password) {
168 DCHECK(!account_id.empty());
169
170 StartFetchingServiceFlags(account_id);
171 }
172
173 void ChildAccountService::GoogleSignedOut(const std::string& account_id,
174 const std::string& username) {
175 DCHECK(!IsChildAccount());
176 CancelFetchingServiceFlags();
177 }
178
179 void ChildAccountService::OnGetFamilyMembersSuccess(
180 const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
181 bool hoh_found = false;
182 bool parent_found = false;
183 for (const FamilyInfoFetcher::FamilyMember& member : members) {
184 if (member.role == FamilyInfoFetcher::HEAD_OF_HOUSEHOLD) {
185 hoh_found = true;
186 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
187 member.display_name);
188 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianEmail,
189 member.email);
190 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianProfileURL,
191 member.profile_url);
192 profile_->GetPrefs()->SetString(
193 prefs::kSupervisedUserCustodianProfileImageURL,
194 member.profile_image_url);
195 } else if (member.role == FamilyInfoFetcher::PARENT) {
196 parent_found = true;
197 profile_->GetPrefs()->SetString(prefs::kSupervisedUserSecondCustodianName,
198 member.display_name);
199 profile_->GetPrefs()->SetString(
200 prefs::kSupervisedUserSecondCustodianEmail,
201 member.email);
202 profile_->GetPrefs()->SetString(
203 prefs::kSupervisedUserSecondCustodianProfileURL,
204 member.profile_url);
205 profile_->GetPrefs()->SetString(
206 prefs::kSupervisedUserSecondCustodianProfileImageURL,
207 member.profile_image_url);
208 }
209 if (hoh_found && parent_found)
210 break;
211 }
212 if (!hoh_found) {
213 DLOG(WARNING) << "GetFamilyMembers didn't return a HOH?!";
214 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName);
215 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail);
216 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianProfileURL);
217 profile_->GetPrefs()->ClearPref(
218 prefs::kSupervisedUserCustodianProfileImageURL);
219 }
220 if (!parent_found) {
221 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianName);
222 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianEmail);
223 profile_->GetPrefs()->ClearPref(
224 prefs::kSupervisedUserSecondCustodianProfileURL);
225 profile_->GetPrefs()->ClearPref(
226 prefs::kSupervisedUserSecondCustodianProfileImageURL);
227 }
228 }
229
230 void ChildAccountService::OnFailure(FamilyInfoFetcher::ErrorCode error) {
231 DLOG(WARNING) << "GetFamilyMembers failed with code " << error;
232 // TODO(treib): Retry after a while?
233 }
234
235 void ChildAccountService::StartFetchingServiceFlags(
236 const std::string& account_id) {
237 account_id_ = account_id;
238 flag_fetcher_.reset(new AccountServiceFlagFetcher(
239 account_id_,
240 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
241 profile_->GetRequestContext(),
242 base::Bind(&ChildAccountService::OnFlagsFetched,
243 weak_ptr_factory_.GetWeakPtr())));
244 }
245
246 void ChildAccountService::CancelFetchingServiceFlags() {
247 flag_fetcher_.reset();
248 account_id_.clear();
249 }
250
251 void ChildAccountService::OnFlagsFetched(
252 AccountServiceFlagFetcher::ResultCode result,
253 const std::vector<std::string>& flags) {
254 // If we've been signed out again (or signed in to a different account),
255 // ignore the fetched flags.
256 const std::string& new_account_id =
257 SigninManagerFactory::GetForProfile(profile_)
258 ->GetAuthenticatedAccountId();
259 if (account_id_.empty() || account_id_ != new_account_id)
260 return;
261
262 // In case of an error, retry after a while.
263 if (result != AccountServiceFlagFetcher::SUCCESS) {
264 DLOG(WARNING) << "AccountServiceFlagFetcher returned error code " << result;
265 base::MessageLoop::current()->PostDelayedTask(
266 FROM_HERE,
267 base::Bind(&ChildAccountService::StartFetchingServiceFlags,
268 weak_ptr_factory_.GetWeakPtr(),
269 account_id_),
270 base::TimeDelta::FromSeconds(10));
271 return;
272 }
273
274 account_id_.clear();
275
276 bool is_child_account =
277 std::find(flags.begin(), flags.end(),
278 kIsChildAccountServiceFlagName) != flags.end();
279 SetIsChildAccount(is_child_account);
280 }
281
282 void ChildAccountService::SetIsChildAccount(bool is_child_account) {
283 if (IsChildAccount() == is_child_account)
284 return;
285
286 if (is_child_account) {
287 profile_->GetPrefs()->SetString(prefs::kSupervisedUserId,
288 kChildAccountSUID);
289 } else {
290 profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserId);
291 }
292 PropagateChildStatusToUser(is_child_account);
293 }
294
295 void ChildAccountService::PropagateChildStatusToUser(bool is_child) {
296 #if defined(OS_CHROMEOS)
297 // TODO(merkulova,treib): Figure out why this causes tests to fail.
298 // user_manager::User* user =
Bernhard Bauer 2014/12/08 10:55:20 Can you remove this instead of commenting it out?
Marc Treib 2014/12/08 10:58:54 It'll be added back very soon (hopefully), so it s
299 // chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
300 // if (user) {
301 // user_manager::UserManager::Get()->ChangeUserSupervisedStatus(
302 // user, is_child);
303 // } else {
304 // LOG(WARNING) <<
305 // "User instance wasn't found while setting child account flag.";
306 // }
307 #endif
308 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698