Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 } | |
| OLD | NEW |