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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/supervised_user/child_accounts/child_account_service.cc
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..db64a83d0b035cadc8b675c99550848074c2abd5
--- /dev/null
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -0,0 +1,308 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
+
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/supervised_user/supervised_user_constants.h"
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
+#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
+#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "components/user_manager/user_manager.h"
+#endif
+
+const char kIsChildAccountServiceFlagName[] = "uca";
+const char kChildAccountSUID[] = "ChildAccountSUID";
+
+ChildAccountService::ChildAccountService(Profile* profile)
+ : profile_(profile), active_(false), weak_ptr_factory_(this) {}
+
+ChildAccountService::~ChildAccountService() {}
+
+void ChildAccountService::Init() {
+ SigninManagerFactory::GetForProfile(profile_)->AddObserver(this);
+ SupervisedUserServiceFactory::GetForProfile(profile_)->SetDelegate(this);
+
+ PropagateChildStatusToUser(IsChildAccount());
+
+ // If we're already signed in, fetch the flag again just to be sure.
+ // (Previously, the browser might have been closed before we got the flag.
+ // This also handles the graduation use case in a basic way.)
+ std::string account_id = SigninManagerFactory::GetForProfile(profile_)
+ ->GetAuthenticatedAccountId();
+ if (!account_id.empty())
+ StartFetchingServiceFlags(account_id);
+}
+
+void ChildAccountService::Shutdown() {
+ CancelFetchingServiceFlags();
+ SupervisedUserService* service =
+ SupervisedUserServiceFactory::GetForProfile(profile_);
+ service->SetDelegate(NULL);
+ DCHECK(!active_);
+ SigninManagerFactory::GetForProfile(profile_)->RemoveObserver(this);
+}
+
+bool ChildAccountService::IsChildAccount() const {
+ return profile_->GetPrefs()->GetString(prefs::kSupervisedUserId) ==
+ kChildAccountSUID;
+}
+
+bool ChildAccountService::SetActive(bool active) {
+ if (!IsChildAccount() && !active_)
+ return false;
+ if (active_ == active)
+ return true;
+ active_ = active;
+
+ if (active_) {
+ // In contrast to local SUs, child account SUs must sign in.
+ scoped_ptr<base::Value> allow_signin(new base::FundamentalValue(true));
+ SupervisedUserSettingsService* settings_service =
+ SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
+ settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
+ allow_signin.Pass());
+#if !defined(OS_CHROMEOS)
+ // This is also used by user policies (UserPolicySigninService), but since
+ // child accounts can not also be Dasher accounts, there shouldn't be any
+ // problems.
+ SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(true);
+#endif
+
+ // TODO(treib): Maybe only fetch the parents on the first start, and then
+ // refresh occasionally (like once every 24h)? That's what
+ // GAIAInfoUpdateService does.
+ family_fetcher_.reset(new FamilyInfoFetcher(
+ this,
+ SigninManagerFactory::GetForProfile(profile_)
+ ->GetAuthenticatedAccountId(),
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
+ profile_->GetRequestContext()));
+ family_fetcher_->StartGetFamilyMembers();
+
+ // Set the permission request API URL and scope, unless they have been
+ // explicitly specified on the command line.
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (!command_line->HasSwitch(switches::kPermissionRequestApiUrl)) {
+ command_line->AppendSwitchASCII(
+ switches::kPermissionRequestApiUrl,
+ "https://www.googleapis.com/"
+ "kidsmanagement/v1/people/me/permissionRequests");
+ }
+ if (!command_line->HasSwitch(switches::kPermissionRequestApiScope)) {
+ command_line->AppendSwitchASCII(
+ switches::kPermissionRequestApiScope,
+ "https://www.googleapis.com/auth/kid.permission");
+ }
+ } else {
+ SupervisedUserSettingsService* settings_service =
+ SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
+ settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
+ scoped_ptr<base::Value>());
+#if !defined(OS_CHROMEOS)
+ SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(false);
+#endif
+
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName);
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail);
+ }
+
+ // Trigger a sync reconfig to enable/disable the right SU data types.
+ // The logic to do this lives in the SupervisedUserSyncDataTypeController.
+ ProfileSyncService* sync_service =
+ ProfileSyncServiceFactory::GetForProfile(profile_);
+ if (sync_service->HasSyncSetupCompleted())
+ sync_service->ReconfigureDatatypeManager();
+
+ return true;
+}
+
+base::FilePath ChildAccountService::GetBlacklistPath() const {
+ if (!active_)
+ return base::FilePath();
+ base::FilePath blacklist_path;
+ PathService::Get(chrome::DIR_USER_DATA, &blacklist_path);
+ blacklist_path = blacklist_path.AppendASCII("su-blacklist.bin");
+ return blacklist_path;
+}
+
+GURL ChildAccountService::GetBlacklistURL() const {
+ if (!active_)
+ return GURL();
+ return GURL("https://www.gstatic.com/chrome/supervised_user/"
+ "blacklist-20141001-1k.bin");
+}
+
+std::string ChildAccountService::GetSafeSitesCx() const {
+ if (!active_)
+ return std::string();
+ return "017993620680222980993%3A1wdumejvx5i";
+}
+
+void ChildAccountService::GoogleSigninSucceeded(const std::string& account_id,
+ const std::string& username,
+ const std::string& password) {
+ DCHECK(!account_id.empty());
+
+ StartFetchingServiceFlags(account_id);
+}
+
+void ChildAccountService::GoogleSignedOut(const std::string& account_id,
+ const std::string& username) {
+ DCHECK(!IsChildAccount());
+ CancelFetchingServiceFlags();
+}
+
+void ChildAccountService::OnGetFamilyMembersSuccess(
+ const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
+ bool hoh_found = false;
+ bool parent_found = false;
+ for (const FamilyInfoFetcher::FamilyMember& member : members) {
+ if (member.role == FamilyInfoFetcher::HEAD_OF_HOUSEHOLD) {
+ hoh_found = true;
+ profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
+ member.display_name);
+ profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianEmail,
+ member.email);
+ profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianProfileURL,
+ member.profile_url);
+ profile_->GetPrefs()->SetString(
+ prefs::kSupervisedUserCustodianProfileImageURL,
+ member.profile_image_url);
+ } else if (member.role == FamilyInfoFetcher::PARENT) {
+ parent_found = true;
+ profile_->GetPrefs()->SetString(prefs::kSupervisedUserSecondCustodianName,
+ member.display_name);
+ profile_->GetPrefs()->SetString(
+ prefs::kSupervisedUserSecondCustodianEmail,
+ member.email);
+ profile_->GetPrefs()->SetString(
+ prefs::kSupervisedUserSecondCustodianProfileURL,
+ member.profile_url);
+ profile_->GetPrefs()->SetString(
+ prefs::kSupervisedUserSecondCustodianProfileImageURL,
+ member.profile_image_url);
+ }
+ if (hoh_found && parent_found)
+ break;
+ }
+ if (!hoh_found) {
+ DLOG(WARNING) << "GetFamilyMembers didn't return a HOH?!";
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianName);
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianEmail);
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserCustodianProfileURL);
+ profile_->GetPrefs()->ClearPref(
+ prefs::kSupervisedUserCustodianProfileImageURL);
+ }
+ if (!parent_found) {
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianName);
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserSecondCustodianEmail);
+ profile_->GetPrefs()->ClearPref(
+ prefs::kSupervisedUserSecondCustodianProfileURL);
+ profile_->GetPrefs()->ClearPref(
+ prefs::kSupervisedUserSecondCustodianProfileImageURL);
+ }
+}
+
+void ChildAccountService::OnFailure(FamilyInfoFetcher::ErrorCode error) {
+ DLOG(WARNING) << "GetFamilyMembers failed with code " << error;
+ // TODO(treib): Retry after a while?
+}
+
+void ChildAccountService::StartFetchingServiceFlags(
+ const std::string& account_id) {
+ account_id_ = account_id;
+ flag_fetcher_.reset(new AccountServiceFlagFetcher(
+ account_id_,
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
+ profile_->GetRequestContext(),
+ base::Bind(&ChildAccountService::OnFlagsFetched,
+ weak_ptr_factory_.GetWeakPtr())));
+}
+
+void ChildAccountService::CancelFetchingServiceFlags() {
+ flag_fetcher_.reset();
+ account_id_.clear();
+}
+
+void ChildAccountService::OnFlagsFetched(
+ AccountServiceFlagFetcher::ResultCode result,
+ const std::vector<std::string>& flags) {
+ // If we've been signed out again (or signed in to a different account),
+ // ignore the fetched flags.
+ const std::string& new_account_id =
+ SigninManagerFactory::GetForProfile(profile_)
+ ->GetAuthenticatedAccountId();
+ if (account_id_.empty() || account_id_ != new_account_id)
+ return;
+
+ // In case of an error, retry after a while.
+ if (result != AccountServiceFlagFetcher::SUCCESS) {
+ DLOG(WARNING) << "AccountServiceFlagFetcher returned error code " << result;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ChildAccountService::StartFetchingServiceFlags,
+ weak_ptr_factory_.GetWeakPtr(),
+ account_id_),
+ base::TimeDelta::FromSeconds(10));
+ return;
+ }
+
+ account_id_.clear();
+
+ bool is_child_account =
+ std::find(flags.begin(), flags.end(),
+ kIsChildAccountServiceFlagName) != flags.end();
+ SetIsChildAccount(is_child_account);
+}
+
+void ChildAccountService::SetIsChildAccount(bool is_child_account) {
+ if (IsChildAccount() == is_child_account)
+ return;
+
+ if (is_child_account) {
+ profile_->GetPrefs()->SetString(prefs::kSupervisedUserId,
+ kChildAccountSUID);
+ } else {
+ profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserId);
+ }
+ PropagateChildStatusToUser(is_child_account);
+}
+
+void ChildAccountService::PropagateChildStatusToUser(bool is_child) {
+#if defined(OS_CHROMEOS)
+ // TODO(merkulova,treib): Figure out why this causes tests to fail.
+// 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
+// chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
+// if (user) {
+// user_manager::UserManager::Get()->ChangeUserSupervisedStatus(
+// user, is_child);
+// } else {
+// LOG(WARNING) <<
+// "User instance wasn't found while setting child account flag.";
+// }
+#endif
+}

Powered by Google App Engine
This is Rietveld 408576698