Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / saml / saml_offline_signin_limiter.cc
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/chromeos/login/saml/saml_offline_signin_limiter.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/time/clock.h"
15 #include "base/time/time.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/pref_registry/pref_registry_syncable.h"
20 #include "components/user_manager/user.h"
21 #include "components/user_manager/user_manager.h"
22
23 namespace chromeos {
24
25 namespace {
26
27 const int kDefaultSAMLOfflineSigninTimeLimit = 14 * 24 * 60 * 60;  // 14 days.
28
29 }  // namespace
30
31 // static
32 void SAMLOfflineSigninLimiter::RegisterProfilePrefs(
33     user_prefs::PrefRegistrySyncable* registry) {
34   registry->RegisterIntegerPref(
35       prefs::kSAMLOfflineSigninTimeLimit,
36       kDefaultSAMLOfflineSigninTimeLimit,
37       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
38   registry->RegisterInt64Pref(
39       prefs::kSAMLLastGAIASignInTime,
40       0,
41       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
42 }
43
44 void SAMLOfflineSigninLimiter::SignedIn(UserContext::AuthFlow auth_flow) {
45   PrefService* prefs = profile_->GetPrefs();
46   const user_manager::User* user =
47       ProfileHelper::Get()->GetUserByProfile(profile_);
48   if (!user) {
49     NOTREACHED();
50     return;
51   }
52   const std::string& user_id = user->email();
53
54   if (auth_flow == UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML) {
55     // The user went through online authentication and GAIA did not redirect to
56     // a SAML IdP. No limit applies in this case. Clear the time of last login
57     // with SAML and the flag enforcing online login, then return.
58     prefs->ClearPref(prefs::kSAMLLastGAIASignInTime);
59     user_manager::UserManager::Get()->SaveForceOnlineSignin(user_id, false);
60     return;
61   }
62
63   if (auth_flow == UserContext::AUTH_FLOW_GAIA_WITH_SAML) {
64     // The user went through online authentication and GAIA did redirect to a
65     // SAML IdP. Update the time of last login with SAML and clear the flag
66     // enforcing online login. The flag will be set again when the limit
67     // expires. If the limit already expired (e.g. because it was set to zero),
68     // the flag will be set again immediately.
69     user_manager::UserManager::Get()->SaveForceOnlineSignin(user_id, false);
70     prefs->SetInt64(prefs::kSAMLLastGAIASignInTime,
71                     clock_->Now().ToInternalValue());
72   }
73
74   // Start listening for pref changes.
75   pref_change_registrar_.Init(prefs);
76   pref_change_registrar_.Add(prefs::kSAMLOfflineSigninTimeLimit,
77                              base::Bind(&SAMLOfflineSigninLimiter::UpdateLimit,
78                                         base::Unretained(this)));
79
80   // Arm the |offline_signin_limit_timer_| if a limit is in force.
81   UpdateLimit();
82 }
83
84 void SAMLOfflineSigninLimiter::Shutdown() {
85   pref_change_registrar_.RemoveAll();
86   offline_signin_limit_timer_.reset();
87 }
88
89 SAMLOfflineSigninLimiter::SAMLOfflineSigninLimiter(Profile* profile,
90                                                    base::Clock* clock)
91     : profile_(profile),
92       clock_(clock ? clock : &default_clock_) {
93 }
94
95 SAMLOfflineSigninLimiter::~SAMLOfflineSigninLimiter() {
96 }
97
98 void SAMLOfflineSigninLimiter::UpdateLimit() {
99   // Stop the |offline_signin_limit_timer_|.
100   offline_signin_limit_timer_.reset();
101
102   PrefService* prefs = pref_change_registrar_.prefs();
103   const base::TimeDelta offline_signin_time_limit =
104       base::TimeDelta::FromSeconds(
105           prefs->GetInteger(prefs::kSAMLOfflineSigninTimeLimit));
106   base::Time last_gaia_signin_time = base::Time::FromInternalValue(
107       prefs->GetInt64(prefs::kSAMLLastGAIASignInTime));
108   if (offline_signin_time_limit < base::TimeDelta() ||
109       last_gaia_signin_time.is_null()) {
110     // If no limit is in force, return.
111     return;
112   }
113
114   const base::Time now = clock_->Now();
115   if (last_gaia_signin_time > now) {
116     // If the time of last login with SAML lies in the future, set it to the
117     // current time.
118     NOTREACHED();
119     last_gaia_signin_time = now;
120     prefs->SetInt64(prefs::kSAMLLastGAIASignInTime, now.ToInternalValue());
121   }
122
123   const base::TimeDelta time_since_last_gaia_signin =
124       now - last_gaia_signin_time;
125   if (time_since_last_gaia_signin >= offline_signin_time_limit) {
126     // If the limit already expired, set the flag enforcing online login
127     // immediately and return.
128     ForceOnlineLogin();
129     return;
130   }
131
132   // Arm |offline_signin_limit_timer_| so that it sets the flag enforcing online
133   // login when the limit expires.
134   offline_signin_limit_timer_.reset(
135       new base::OneShotTimer<SAMLOfflineSigninLimiter>);
136   offline_signin_limit_timer_->Start(
137       FROM_HERE,
138       offline_signin_time_limit - time_since_last_gaia_signin,
139       this,
140       &SAMLOfflineSigninLimiter::ForceOnlineLogin);
141 }
142
143 void SAMLOfflineSigninLimiter::ForceOnlineLogin() {
144   user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile_);
145   if (!user) {
146     NOTREACHED();
147     return;
148   }
149
150   user_manager::UserManager::Get()->SaveForceOnlineSignin(user->email(), true);
151   offline_signin_limit_timer_.reset();
152 }
153
154 }  // namespace chromeos