diff options
author | rsorokin@chromium.org <rsorokin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-13 16:04:04 +0000 |
---|---|---|
committer | rsorokin@chromium.org <rsorokin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-13 16:05:23 +0000 |
commit | 815dfac97145b951ffd8c179d56f025371c8edd2 (patch) | |
tree | 527bcfdecfa76582c974b803631043f877ab0b63 | |
parent | bcd365e5495e53cc5e512fbc1fe87119af30e8e6 (diff) | |
download | chromium_src-815dfac97145b951ffd8c179d56f025371c8edd2.zip chromium_src-815dfac97145b951ffd8c179d56f025371c8edd2.tar.gz chromium_src-815dfac97145b951ffd8c179d56f025371c8edd2.tar.bz2 |
Providing more information on why certain users can't be added to multi-profile
session
BUG=388279
Review URL: https://codereview.chromium.org/374853002
Cr-Commit-Position: refs/heads/master@{#289304}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289304 0039d316-1c4b-4281-b951-d872f2087c98
17 files changed, 299 insertions, 84 deletions
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 11c3646..074cdb1 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd @@ -250,6 +250,9 @@ Press Ctrl+Alt+Z to disable. <message name="IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER" desc="The error message when the user has reached the limit of multi profile users."> You can only have up to three accounts in multiple sign-in. </message> + <message name="IDS_ASH_STATUS_TRAY_MESSAGE_NOT_ALLOWED_PRIMARY_USER" desc="The error message when the primary user forbids multiple signin because of not-allowed policy or because of usage policy-pushed certificates."> + The administrator for this account has disallowed multiple sign-in. + </message> <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH" desc="The label used as the header in the bluetooth popup."> Bluetooth diff --git a/ash/session/session_state_delegate.h b/ash/session/session_state_delegate.h index c1d4720..c1c0713 100644 --- a/ash/session/session_state_delegate.h +++ b/ash/session/session_state_delegate.h @@ -134,6 +134,9 @@ class ASH_EXPORT SessionStateDelegate { // ordering as GetLoggedInUsers. virtual void CycleActiveUser(CycleUser cycle_user) = 0; + // Returns true if primary user policy does not forbid multiple signin. + virtual bool IsMultiProfileAllowedByPrimaryUserPolicy() const = 0; + // Adds or removes sessions state observer. virtual void AddSessionStateObserver(SessionStateObserver* observer) = 0; virtual void RemoveSessionStateObserver(SessionStateObserver* observer) = 0; diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index 6261e1e..02c6a27 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc @@ -128,6 +128,9 @@ class SessionStateDelegateImpl : public SessionStateDelegate { } virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE {} virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE {} + virtual bool IsMultiProfileAllowedByPrimaryUserPolicy() const OVERRIDE { + return true; + } virtual void AddSessionStateObserver( ash::SessionStateObserver* observer) OVERRIDE {} virtual void RemoveSessionStateObserver( diff --git a/ash/system/user/user_view.cc b/ash/system/user/user_view.cc index f3646a7..689764f 100644 --- a/ash/system/user/user_view.cc +++ b/ash/system/user/user_view.cc @@ -493,8 +493,13 @@ void UserView::ToggleAddUserMenuOption() { const SessionStateDelegate* delegate = Shell::GetInstance()->session_state_delegate(); - add_user_disabled_ = delegate->NumberOfLoggedInUsers() >= - delegate->GetMaximumNumberOfLoggedInUsers(); + + bool multi_profile_allowed = + delegate->IsMultiProfileAllowedByPrimaryUserPolicy(); + add_user_disabled_ = (delegate->NumberOfLoggedInUsers() >= + delegate->GetMaximumNumberOfLoggedInUsers()) || + !multi_profile_allowed; + ButtonFromView* button = new ButtonFromView( add_user_view, add_user_disabled_ ? NULL : this, @@ -508,9 +513,15 @@ void UserView::ToggleAddUserMenuOption() { if (add_user_disabled_) { ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + int message_id; + if (!multi_profile_allowed) + message_id = IDS_ASH_STATUS_TRAY_MESSAGE_NOT_ALLOWED_PRIMARY_USER; + else + message_id = IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER; + popup_message_.reset(new PopupMessage( bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAPTION_CANNOT_ADD_USER), - bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER), + bundle.GetLocalizedString(message_id), PopupMessage::ICON_WARNING, add_user_view->anchor(), views::BubbleBorder::TOP_LEFT, diff --git a/ash/test/test_session_state_delegate.cc b/ash/test/test_session_state_delegate.cc index 4c76143..eac5576 100644 --- a/ash/test/test_session_state_delegate.cc +++ b/ash/test/test_session_state_delegate.cc @@ -227,6 +227,11 @@ void TestSessionStateDelegate::CycleActiveUser(CycleUser cycle_user) { SwitchActiveUser("someone@tray"); } +bool TestSessionStateDelegate::IsMultiProfileAllowedByPrimaryUserPolicy() + const { + return true; +} + void TestSessionStateDelegate::AddSessionStateObserver( SessionStateObserver* observer) { } diff --git a/ash/test/test_session_state_delegate.h b/ash/test/test_session_state_delegate.h index 478c340..c508299 100644 --- a/ash/test/test_session_state_delegate.h +++ b/ash/test/test_session_state_delegate.h @@ -48,6 +48,7 @@ class TestSessionStateDelegate : public SessionStateDelegate { virtual bool ShouldShowAvatar(aura::Window* window) const OVERRIDE; virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE; virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE; + virtual bool IsMultiProfileAllowedByPrimaryUserPolicy() const OVERRIDE; virtual void AddSessionStateObserver( ash::SessionStateObserver* observer) OVERRIDE; virtual void RemoveSessionStateObserver( diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index fec3c06..5c88570 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp @@ -1649,7 +1649,7 @@ Press any key to continue exploring. <message name="IDS_MULTI_PROFILES_RESTRICTED_POLICY_TITLE" desc="Text that is shown on the title of the bubble shown for user pod which is not allowed in multi-profiles session."> Can't set up multiple sign-in </message> - <message name="IDS_MULTI_PROFILES_NOT_ALLOWED_POLICY_MSG" desc="Text that is shown on the bubble shown for user pod which is not allowed in multi-profiles session because of not-allowed policy."> + <message name="IDS_MULTI_PROFILES_NOT_ALLOWED_POLICY_MSG" desc="Text that is shown on the bubble shown for user pod which is not allowed in multi-profiles session because of not-allowed policy or because of usage policy-pushed certificates."> The administrator for this account has disallowed multiple sign-in. </message> <message name="IDS_MULTI_PROFILES_PRIMARY_ONLY_POLICY_MSG" desc="Text that is shown on the bubble shown for user pod which is not allowed in multi-profiles session because of primary-only policy."> diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager.cc b/chrome/browser/chromeos/login/users/chrome_user_manager.cc index aec54c3..d7fdd8b 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager.cc +++ b/chrome/browser/chromeos/login/users/chrome_user_manager.cc @@ -211,7 +211,9 @@ user_manager::UserList ChromeUserManager::GetUsersAdmittedForMultiProfile() // Same applies to owner account (see http://crbug.com/385034). if (check == MultiProfileUserController::ALLOWED || check == MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS || - check == MultiProfileUserController::NOT_ALLOWED_OWNER_AS_SECONDARY) { + check == MultiProfileUserController::NOT_ALLOWED_OWNER_AS_SECONDARY || + check == + MultiProfileUserController::NOT_ALLOWED_POLICY_CERT_TAINTED) { result.push_back(*it); } } diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc b/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc index 1d315d3..6bb7114 100644 --- a/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc +++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc @@ -87,30 +87,19 @@ void MultiProfileUserController::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); } -bool MultiProfileUserController::IsUserAllowedInSession( - const std::string& user_email, - MultiProfileUserController::UserAllowedInSessionReason* reason) const { +// static +MultiProfileUserController::UserAllowedInSessionReason +MultiProfileUserController::GetPrimaryUserPolicy() { UserManager* user_manager = UserManager::Get(); CHECK(user_manager); const user_manager::User* primary_user = user_manager->GetPrimaryUser(); - std::string primary_user_email; - if (primary_user) - primary_user_email = primary_user->email(); - - // Always allow if there is no primary user or user being checked is the - // primary user. - if (primary_user_email.empty() || primary_user_email == user_email) - return SetUserAllowedReason(reason, ALLOWED); - - // Owner is not allowed to be secondary user. - if (user_manager->GetOwnerEmail() == user_email) - return SetUserAllowedReason(reason, NOT_ALLOWED_OWNER_AS_SECONDARY); + if (!primary_user) + return ALLOWED; + Profile* primary_user_profile = + ProfileHelper::Get()->GetProfileByUserUnsafe(primary_user); - // Don't allow profiles potentially tainted by data fetched with policy-pushed - // certificates to join a multiprofile session. - if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email)) - return SetUserAllowedReason(reason, NOT_ALLOWED_POLICY_CERT_TAINTED); + std::string primary_user_email = primary_user->email(); // Don't allow any secondary profiles if the primary profile is tainted. if (policy::PolicyCertServiceFactory::UsedPolicyCertificates( @@ -118,31 +107,57 @@ bool MultiProfileUserController::IsUserAllowedInSession( // Check directly in local_state before checking if the primary user has // a PolicyCertService. His profile may have been tainted previously though // he didn't get a PolicyCertService created for this session. - return SetUserAllowedReason(reason, - NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED); + return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED; } // If the primary profile already has policy certificates installed but hasn't // used them yet then it can become tainted at any time during this session; // disable secondary profiles in this case too. - Profile* primary_user_profile = - primary_user ? ProfileHelper::Get()->GetProfileByUserUnsafe(primary_user) - : NULL; policy::PolicyCertService* service = primary_user_profile ? policy::PolicyCertServiceFactory::GetForProfile( primary_user_profile) : NULL; if (service && service->has_policy_certificates()) - return SetUserAllowedReason(reason, - NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED); + return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED; // No user is allowed if the primary user policy forbids it. const std::string primary_user_behavior = primary_user_profile->GetPrefs()->GetString( prefs::kMultiProfileUserBehavior); if (primary_user_behavior == kBehaviorNotAllowed) - return SetUserAllowedReason(reason, - NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS); + return NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS; + + return ALLOWED; +} + +bool MultiProfileUserController::IsUserAllowedInSession( + const std::string& user_email, + MultiProfileUserController::UserAllowedInSessionReason* reason) const { + UserManager* user_manager = UserManager::Get(); + CHECK(user_manager); + + const user_manager::User* primary_user = user_manager->GetPrimaryUser(); + std::string primary_user_email; + if (primary_user) + primary_user_email = primary_user->email(); + + // Always allow if there is no primary user or user being checked is the + // primary user. + if (primary_user_email.empty() || primary_user_email == user_email) + return SetUserAllowedReason(reason, ALLOWED); + + // Owner is not allowed to be secondary user. + if (user_manager->GetOwnerEmail() == user_email) + return SetUserAllowedReason(reason, NOT_ALLOWED_OWNER_AS_SECONDARY); + + // Don't allow profiles potentially tainted by data fetched with policy-pushed + // certificates to join a multiprofile session. + if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email)) + return SetUserAllowedReason(reason, NOT_ALLOWED_POLICY_CERT_TAINTED); + + UserAllowedInSessionReason primary_user_policy = GetPrimaryUserPolicy(); + if (primary_user_policy != ALLOWED) + return SetUserAllowedReason(reason, primary_user_policy); // The user must have 'unrestricted' policy to be a secondary user. const std::string behavior = GetCachedValue(user_email); diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller.h b/chrome/browser/chromeos/login/users/multi_profile_user_controller.h index 628a955..506794f 100644 --- a/chrome/browser/chromeos/login/users/multi_profile_user_controller.h +++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller.h @@ -65,6 +65,11 @@ class MultiProfileUserController { // Returns the cached policy value for |user_email|. std::string GetCachedValue(const std::string& user_email) const; + // Returns primary user policy (only ALLOW, + // NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, + // NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS) + static UserAllowedInSessionReason GetPrimaryUserPolicy(); + // Returns true if user allowed to be in the current session. If |reason| not // null stores UserAllowedInSessionReason enum that describes actual reason. bool IsUserAllowedInSession(const std::string& user_email, diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc b/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc index 5f3258f..b93d73a 100644 --- a/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc +++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc @@ -34,55 +34,65 @@ const char* kUsers[] = {"a@gmail.com", "b@gmail.com" }; struct BehaviorTestCase { const char* primary; const char* secondary; - MultiProfileUserController::UserAllowedInSessionReason expected_allowed; + MultiProfileUserController::UserAllowedInSessionReason + expected_primary_policy; + MultiProfileUserController::UserAllowedInSessionReason + expected_secondary_allowed; }; const BehaviorTestCase kBehaviorTestCases[] = { - { - MultiProfileUserController::kBehaviorUnrestricted, - MultiProfileUserController::kBehaviorUnrestricted, - MultiProfileUserController::ALLOWED, - }, - { - MultiProfileUserController::kBehaviorUnrestricted, - MultiProfileUserController::kBehaviorPrimaryOnly, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, - }, - { - MultiProfileUserController::kBehaviorUnrestricted, - MultiProfileUserController::kBehaviorNotAllowed, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, - }, - { - MultiProfileUserController::kBehaviorPrimaryOnly, - MultiProfileUserController::kBehaviorUnrestricted, - MultiProfileUserController::ALLOWED, - }, - { - MultiProfileUserController::kBehaviorPrimaryOnly, - MultiProfileUserController::kBehaviorPrimaryOnly, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, - }, - { - MultiProfileUserController::kBehaviorPrimaryOnly, - MultiProfileUserController::kBehaviorNotAllowed, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, - }, - { - MultiProfileUserController::kBehaviorNotAllowed, - MultiProfileUserController::kBehaviorUnrestricted, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, - }, - { - MultiProfileUserController::kBehaviorNotAllowed, - MultiProfileUserController::kBehaviorPrimaryOnly, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, - }, - { - MultiProfileUserController::kBehaviorNotAllowed, - MultiProfileUserController::kBehaviorNotAllowed, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, - }, + { + MultiProfileUserController::kBehaviorUnrestricted, + MultiProfileUserController::kBehaviorUnrestricted, + MultiProfileUserController::ALLOWED, MultiProfileUserController::ALLOWED, + }, + { + MultiProfileUserController::kBehaviorUnrestricted, + MultiProfileUserController::kBehaviorPrimaryOnly, + MultiProfileUserController::ALLOWED, + MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + }, + { + MultiProfileUserController::kBehaviorUnrestricted, + MultiProfileUserController::kBehaviorNotAllowed, + MultiProfileUserController::ALLOWED, + MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + }, + { + MultiProfileUserController::kBehaviorPrimaryOnly, + MultiProfileUserController::kBehaviorUnrestricted, + MultiProfileUserController::ALLOWED, MultiProfileUserController::ALLOWED, + }, + { + MultiProfileUserController::kBehaviorPrimaryOnly, + MultiProfileUserController::kBehaviorPrimaryOnly, + MultiProfileUserController::ALLOWED, + MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + }, + { + MultiProfileUserController::kBehaviorPrimaryOnly, + MultiProfileUserController::kBehaviorNotAllowed, + MultiProfileUserController::ALLOWED, + MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + }, + { + MultiProfileUserController::kBehaviorNotAllowed, + MultiProfileUserController::kBehaviorUnrestricted, + MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + }, + { + MultiProfileUserController::kBehaviorNotAllowed, + MultiProfileUserController::kBehaviorPrimaryOnly, + MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + }, + { + MultiProfileUserController::kBehaviorNotAllowed, + MultiProfileUserController::kBehaviorNotAllowed, + MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + }, }; // Weak ptr to PolicyCertVerifier - object is freed in test destructor once @@ -216,6 +226,9 @@ TEST_F(MultiProfileUserControllerTest, AllAllowedBeforeLogin) { EXPECT_TRUE(controller()->IsUserAllowedInSession(kUsers[0], &reason)) << "Case " << i; EXPECT_EQ(MultiProfileUserController::ALLOWED, reason) << "Case " << i; + EXPECT_EQ(MultiProfileUserController::ALLOWED, + MultiProfileUserController::GetPrimaryUserPolicy()) + << "Case " << i; } } @@ -272,9 +285,13 @@ TEST_F(MultiProfileUserControllerTest, IsSecondaryAllowed) { for (size_t i = 0; i < arraysize(kBehaviorTestCases); ++i) { SetPrefBehavior(0, kBehaviorTestCases[i].primary); SetCachedBehavior(1, kBehaviorTestCases[i].secondary); + EXPECT_EQ(kBehaviorTestCases[i].expected_primary_policy, + MultiProfileUserController::GetPrimaryUserPolicy()) + << "Case " << i; MultiProfileUserController::UserAllowedInSessionReason reason; controller()->IsUserAllowedInSession(kUsers[1], &reason); - EXPECT_EQ(kBehaviorTestCases[i].expected_allowed, reason) << "Case " << i; + EXPECT_EQ(kBehaviorTestCases[i].expected_secondary_allowed, reason) + << "Case " << i; } } @@ -291,11 +308,13 @@ TEST_F(MultiProfileUserControllerTest, PrimaryBehaviorChange) { SetPrefBehavior(0, kBehaviorTestCases[i].primary); SetPrefBehavior(1, kBehaviorTestCases[i].secondary); if (user_not_allowed_count() == 0) { - EXPECT_EQ(kBehaviorTestCases[i].expected_allowed, - MultiProfileUserController::ALLOWED) << "Case " << i; + EXPECT_EQ(kBehaviorTestCases[i].expected_secondary_allowed, + MultiProfileUserController::ALLOWED) + << "Case " << i; } else { - EXPECT_NE(kBehaviorTestCases[i].expected_allowed, - MultiProfileUserController::ALLOWED) << "Case " << i; + EXPECT_NE(kBehaviorTestCases[i].expected_secondary_allowed, + MultiProfileUserController::ALLOWED) + << "Case " << i; } } } @@ -324,6 +343,8 @@ TEST_F(MultiProfileUserControllerTest, EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); EXPECT_TRUE(controller()->IsUserAllowedInSession(kUsers[1], &reason)); EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); + EXPECT_EQ(MultiProfileUserController::ALLOWED, + MultiProfileUserController::GetPrimaryUserPolicy()); } TEST_F(MultiProfileUserControllerTest, @@ -363,10 +384,14 @@ TEST_F(MultiProfileUserControllerTest, EXPECT_FALSE(controller()->IsUserAllowedInSession(kUsers[1], &reason)); EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, reason); + EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, + MultiProfileUserController::GetPrimaryUserPolicy()); policy::PolicyCertServiceFactory::SetUsedPolicyCertificates(kUsers[1]); EXPECT_FALSE(controller()->IsUserAllowedInSession(kUsers[1], &reason)); EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_POLICY_CERT_TAINTED, reason); + EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, + MultiProfileUserController::GetPrimaryUserPolicy()); // Flush tasks posted to IO. base::RunLoop().RunUntilIdle(); @@ -395,6 +420,8 @@ TEST_F(MultiProfileUserControllerTest, MultiProfileUserController::UserAllowedInSessionReason reason; EXPECT_TRUE(controller()->IsUserAllowedInSession(kUsers[1], &reason)); EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); + EXPECT_EQ(MultiProfileUserController::ALLOWED, + MultiProfileUserController::GetPrimaryUserPolicy()); net::CertificateList certificates; certificates.push_back(new net::X509Certificate( @@ -404,6 +431,8 @@ TEST_F(MultiProfileUserControllerTest, EXPECT_FALSE(controller()->IsUserAllowedInSession(kUsers[1], &reason)); EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, reason); + EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, + MultiProfileUserController::GetPrimaryUserPolicy()); // Flush tasks posted to IO. base::RunLoop().RunUntilIdle(); diff --git a/chrome/browser/chromeos/profiles/profile_helper.h b/chrome/browser/chromeos/profiles/profile_helper.h index 3048f17..04afba4 100644 --- a/chrome/browser/chromeos/profiles/profile_helper.h +++ b/chrome/browser/chromeos/profiles/profile_helper.h @@ -134,6 +134,7 @@ class ProfileHelper : public BrowsingDataRemover::Observer, friend class ParallelAuthenticatorTest; friend class ProfileHelperTest; friend class ProfileListChromeOSTest; + friend class SessionStateDelegateChromeOSTest; // BrowsingDataRemover::Observer implementation: virtual void OnBrowsingDataRemoverDone() OVERRIDE; diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc index 613c87aa..ef9f807 100644 --- a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc @@ -11,6 +11,7 @@ #include "base/prefs/pref_service.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" +#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" #include "chrome/browser/chromeos/login/users/user_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" @@ -208,6 +209,12 @@ void SessionStateDelegateChromeos::CycleActiveUser(CycleUser cycle_user) { chromeos::UserManager::Get()->SwitchActiveUser(user_id); } +bool SessionStateDelegateChromeos::IsMultiProfileAllowedByPrimaryUserPolicy() + const { + return chromeos::MultiProfileUserController::GetPrimaryUserPolicy() == + chromeos::MultiProfileUserController::ALLOWED; +} + void SessionStateDelegateChromeos::AddSessionStateObserver( ash::SessionStateObserver* observer) { session_state_observer_list_.AddObserver(observer); diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.h b/chrome/browser/ui/ash/session_state_delegate_chromeos.h index 0ec9622..93f9b7da 100644 --- a/chrome/browser/ui/ash/session_state_delegate_chromeos.h +++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.h @@ -48,6 +48,7 @@ class SessionStateDelegateChromeos virtual bool ShouldShowAvatar(aura::Window* window) const OVERRIDE; virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE; virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE; + virtual bool IsMultiProfileAllowedByPrimaryUserPolicy() const OVERRIDE; virtual void AddSessionStateObserver( ash::SessionStateObserver* observer) OVERRIDE; virtual void RemoveSessionStateObserver( diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos_unittest.cc b/chrome/browser/ui/ash/session_state_delegate_chromeos_unittest.cc index d0bd6bf..2bf05dd 100644 --- a/chrome/browser/ui/ash/session_state_delegate_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/session_state_delegate_chromeos_unittest.cc @@ -7,10 +7,38 @@ #include <string> #include <vector> +#include "base/run_loop.h" #include "chrome/browser/chromeos/login/users/fake_user_manager.h" +#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" +#include "chrome/browser/chromeos/policy/policy_cert_service.h" +#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" +#include "chrome/browser/chromeos/policy/policy_cert_verifier.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "net/cert/x509_certificate.h" #include "testing/gtest/include/gtest/gtest.h" +namespace chromeos { + +namespace { + +const char* kUser = "user@test.com"; + +// Weak ptr to PolicyCertVerifier - object is freed in test destructor once +// we've ensured the profile has been shut down. +policy::PolicyCertVerifier* g_policy_cert_verifier_for_factory = NULL; + +KeyedService* CreateTestPolicyCertService(content::BrowserContext* context) { + return policy::PolicyCertService::CreateForTesting( + kUser, + g_policy_cert_verifier_for_factory, + chromeos::UserManager::Get()).release(); +} + +} // namespace class SessionStateDelegateChromeOSTest : public testing::Test { protected: @@ -36,6 +64,17 @@ class SessionStateDelegateChromeOSTest : public testing::Test { session_state_delegate_.reset(); user_manager_enabler_.reset(); user_manager_ = NULL; + // Clear our cached pointer to the PolicyCertVerifier. + g_policy_cert_verifier_for_factory = NULL; + profile_manager_.reset(); + + // We must ensure that the PolicyCertVerifier outlives the + // PolicyCertService so shutdown the profile here. Additionally, we need + // to run the message loop between freeing the PolicyCertService and + // freeing the PolicyCertVerifier (see + // PolicyCertService::OnTrustAnchorsChanged() which is called from + // PolicyCertService::Shutdown()). + base::RunLoop().RunUntilIdle(); } // Add and log in a user to the session. @@ -54,6 +93,26 @@ class SessionStateDelegateChromeOSTest : public testing::Test { return session_state_delegate_.get(); } + void InitForMultiProfile() { + profile_manager_.reset( + new TestingProfileManager(TestingBrowserProcess::GetGlobal())); + ASSERT_TRUE(profile_manager_->SetUp()); + + const std::string user_email(kUser); + const user_manager::User* user = user_manager()->AddUser(user_email); + + // Note that user profiles are created after user login in reality. + user_profile_ = profile_manager_->CreateTestingProfile(user_email); + user_profile_->set_profile_name(user_email); + chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting( + user, user_profile_); + } + + content::TestBrowserThreadBundle threads_; + scoped_ptr<policy::PolicyCertVerifier> cert_verifier_; + scoped_ptr<TestingProfileManager> profile_manager_; + TestingProfile* user_profile_; + private: scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_; scoped_ptr<SessionStateDelegateChromeos> session_state_delegate_; @@ -104,3 +163,68 @@ TEST_F(SessionStateDelegateChromeOSTest, CyclingThreeUsers) { session_state_delegate()->CycleActiveUser(backward); EXPECT_EQ("firstuser@test.com", GetActiveUser()); } + +// Make sure MultiProfile disabled by primary user policy. +TEST_F(SessionStateDelegateChromeOSTest, MultiProfileDisallowedByUserPolicy) { + InitForMultiProfile(); + EXPECT_TRUE( + session_state_delegate()->IsMultiProfileAllowedByPrimaryUserPolicy()); + const std::string user_email(kUser); + user_manager()->LoginUser(user_email); + EXPECT_TRUE( + session_state_delegate()->IsMultiProfileAllowedByPrimaryUserPolicy()); + + user_profile_->GetPrefs()->SetString( + prefs::kMultiProfileUserBehavior, + chromeos::MultiProfileUserController::kBehaviorNotAllowed); + EXPECT_FALSE( + session_state_delegate()->IsMultiProfileAllowedByPrimaryUserPolicy()); +} + +// Make sure MultiProfile disabled by primary user policy certificates. +TEST_F(SessionStateDelegateChromeOSTest, + MultiProfileDisallowedByPolicyCertificates) { + InitForMultiProfile(); + const std::string user_email(kUser); + user_manager()->LoginUser(user_email); + EXPECT_TRUE( + session_state_delegate()->IsMultiProfileAllowedByPrimaryUserPolicy()); + policy::PolicyCertServiceFactory::SetUsedPolicyCertificates(user_email); + EXPECT_FALSE( + session_state_delegate()->IsMultiProfileAllowedByPrimaryUserPolicy()); + + // Flush tasks posted to IO. + base::RunLoop().RunUntilIdle(); +} + +// Make sure MultiProfile disabled by primary user certificates in memory. +TEST_F(SessionStateDelegateChromeOSTest, + MultiProfileDisallowedByPrimaryUserCertificatesInMemory) { + InitForMultiProfile(); + const std::string user_email(kUser); + user_manager()->LoginUser(user_email); + EXPECT_TRUE( + session_state_delegate()->IsMultiProfileAllowedByPrimaryUserPolicy()); + cert_verifier_.reset(new policy::PolicyCertVerifier(base::Closure())); + g_policy_cert_verifier_for_factory = cert_verifier_.get(); + ASSERT_TRUE( + policy::PolicyCertServiceFactory::GetInstance()->SetTestingFactoryAndUse( + user_profile_, CreateTestPolicyCertService)); + policy::PolicyCertService* service = + policy::PolicyCertServiceFactory::GetForProfile(user_profile_); + ASSERT_TRUE(service); + + EXPECT_FALSE(service->has_policy_certificates()); + net::CertificateList certificates; + certificates.push_back(new net::X509Certificate( + "subject", "issuer", base::Time(), base::Time())); + service->OnTrustAnchorsChanged(certificates); + EXPECT_TRUE(service->has_policy_certificates()); + EXPECT_FALSE( + session_state_delegate()->IsMultiProfileAllowedByPrimaryUserPolicy()); + + // Flush tasks posted to IO. + base::RunLoop().RunUntilIdle(); +} + +} // namespace chromeos diff --git a/chrome/browser/ui/ash/session_state_delegate_views.cc b/chrome/browser/ui/ash/session_state_delegate_views.cc index 9622319..de814bd 100644 --- a/chrome/browser/ui/ash/session_state_delegate_views.cc +++ b/chrome/browser/ui/ash/session_state_delegate_views.cc @@ -91,6 +91,10 @@ void SessionStateDelegate::CycleActiveUser(CycleUser cycle_user) { NOTIMPLEMENTED(); } +bool SessionStateDelegate::IsMultiProfileAllowedByPrimaryUserPolicy() const { + return true; +} + void SessionStateDelegate::AddSessionStateObserver( ash::SessionStateObserver* observer) { NOTIMPLEMENTED(); diff --git a/chrome/browser/ui/ash/session_state_delegate_views.h b/chrome/browser/ui/ash/session_state_delegate_views.h index 14e005e..421d11c 100644 --- a/chrome/browser/ui/ash/session_state_delegate_views.h +++ b/chrome/browser/ui/ash/session_state_delegate_views.h @@ -42,6 +42,7 @@ class SessionStateDelegate : public ash::SessionStateDelegate { virtual bool ShouldShowAvatar(aura::Window* window) const OVERRIDE; virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE; virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE; + virtual bool IsMultiProfileAllowedByPrimaryUserPolicy() const OVERRIDE; virtual void AddSessionStateObserver( ash::SessionStateObserver* observer) OVERRIDE; virtual void RemoveSessionStateObserver( |