Chromium Code Reviews| Index: chrome/browser/chromeos/login/saml_offline_signin_limiter.cc |
| diff --git a/chrome/browser/chromeos/login/saml_offline_signin_limiter.cc b/chrome/browser/chromeos/login/saml_offline_signin_limiter.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..dd36d550c928a8075b9fb9c299d292e6abb8747d |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/login/saml_offline_signin_limiter.cc |
| @@ -0,0 +1,145 @@ |
| +// 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/chromeos/login/saml_offline_signin_limiter.h" |
| + |
| +#include <string> |
| + |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/location.h" |
| +#include "base/logging.h" |
| +#include "base/prefs/pref_service.h" |
| +#include "base/time/clock.h" |
| +#include "base/time/time.h" |
| +#include "chrome/browser/chromeos/login/user_manager.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/common/pref_names.h" |
| +#include "components/user_prefs/pref_registry_syncable.h" |
| + |
| +namespace chromeos { |
| + |
| +// static |
| +void SAMLOfflineSigninLimiter::RegisterProfilePrefs( |
| + user_prefs::PrefRegistrySyncable* registry) { |
| + registry->RegisterIntegerPref( |
| + prefs::kSAMLOfflineSigninTimeLimit, |
| + 1209600, // 14 days, expressed in seconds. |
|
Mattias Nissler (ping if slow)
2014/01/23 08:49:15
nit: might be simpler to read if you just write 60
bartfab (slow)
2014/01/23 09:47:23
Done.
|
| + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| + registry->RegisterInt64Pref( |
| + prefs::kSAMLLastGAIASignInTime, |
| + 0, |
| + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| +} |
| + |
| +void SAMLOfflineSigninLimiter::SignedIn(UserContext::AuthFlow auth_flow) { |
| + PrefService* prefs = profile_->GetPrefs(); |
| + const User* user = UserManager::Get()->GetUserByProfile(profile_); |
| + if (!user) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + const std::string& user_id = user->email(); |
| + |
| + if (auth_flow == UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML) { |
| + // The user went through online authentication and GAIA did not redirect to |
| + // a SAML IdP. No limit applies in this case. Clear the time of last login |
| + // with SAML and the flag enforcing online login, then return. |
| + prefs->ClearPref(prefs::kSAMLLastGAIASignInTime); |
| + UserManager::Get()->SaveForceOnlineSignin(user_id, false); |
| + return; |
| + } |
| + |
| + if (auth_flow == UserContext::AUTH_FLOW_GAIA_WITH_SAML) { |
| + // The user went through online authentication and GAIA did redirect to a |
| + // SAML IdP. Update the time of last login with SAML and clear the flag |
| + // enforcing online login. The flag will be set again when the limit |
| + // expires. If the limit already expired (e.g. because it was set to zero), |
| + // the flag will be set again immediately. |
| + UserManager::Get()->SaveForceOnlineSignin(user_id, false); |
| + prefs->SetInt64(prefs::kSAMLLastGAIASignInTime, |
| + clock_->Now().ToInternalValue()); |
| + } |
| + |
| + // Start listening for pref changes. |
| + pref_change_registrar_.Init(prefs); |
| + pref_change_registrar_.Add(prefs::kSAMLOfflineSigninTimeLimit, |
| + base::Bind(&SAMLOfflineSigninLimiter::UpdateLimit, |
| + base::Unretained(this))); |
| + |
| + // Arm the |offline_signin_limit_timer_| if a limit is in force. |
| + UpdateLimit(); |
| +} |
| + |
| +void SAMLOfflineSigninLimiter::Shutdown() { |
| + pref_change_registrar_.RemoveAll(); |
| + offline_signin_limit_timer_.reset(); |
| +} |
| + |
| +SAMLOfflineSigninLimiter::SAMLOfflineSigninLimiter(Profile* profile, |
| + base::Clock* clock) |
| + : profile_(profile), |
| + clock_(clock ? clock : &default_clock_) { |
| +} |
| + |
| +SAMLOfflineSigninLimiter::~SAMLOfflineSigninLimiter() { |
| +} |
| + |
| +void SAMLOfflineSigninLimiter::UpdateLimit() { |
| + // Stop the |offline_signin_limit_timer_|. |
| + offline_signin_limit_timer_.reset(); |
| + |
| + PrefService* prefs = pref_change_registrar_.prefs(); |
| + const base::TimeDelta offline_signin_time_limit = |
| + base::TimeDelta::FromSeconds( |
| + prefs->GetInteger(prefs::kSAMLOfflineSigninTimeLimit)); |
| + base::Time last_gaia_signin_time = base::Time::FromInternalValue( |
| + prefs->GetInt64(prefs::kSAMLLastGAIASignInTime)); |
| + if (offline_signin_time_limit < base::TimeDelta() || |
| + last_gaia_signin_time.is_null()) { |
| + // If no limit is in force, return. |
| + return; |
| + } |
| + |
| + const base::Time now = clock_->Now(); |
| + if (last_gaia_signin_time > now) { |
| + // If the time of last login with SAML lies in the future, set it to the |
| + // current time. |
| + NOTREACHED(); |
| + last_gaia_signin_time = now; |
| + prefs->SetInt64(prefs::kSAMLLastGAIASignInTime, now.ToInternalValue()); |
| + } |
| + |
| + const base::TimeDelta time_since_last_gaia_signin = |
| + now - last_gaia_signin_time; |
| + if (time_since_last_gaia_signin >= offline_signin_time_limit) { |
| + // If the limit already expired, set the flag enforcing online login |
| + // immediately and return. |
| + ForceOnlineLogin(); |
| + return; |
| + } |
| + |
| + // Arm |offline_signin_limit_timer_| so that it sets the flag enforcing online |
| + // login when the limit expires. |
| + offline_signin_limit_timer_.reset( |
| + new base::OneShotTimer<SAMLOfflineSigninLimiter>); |
| + offline_signin_limit_timer_->Start( |
| + FROM_HERE, |
| + offline_signin_time_limit - time_since_last_gaia_signin, |
| + this, |
| + &SAMLOfflineSigninLimiter::ForceOnlineLogin); |
| +} |
| + |
| +void SAMLOfflineSigninLimiter::ForceOnlineLogin() { |
| + User* user = UserManager::Get()->GetUserByProfile(profile_); |
| + if (!user) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + |
| + UserManager::Get()->SaveForceOnlineSignin(user->email(), true); |
| + offline_signin_limit_timer_.reset(); |
| +} |
| + |
| +} // namespace chromeos |