1// Copyright (c) 2012 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/login_performer.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/logging.h"
11#include "base/message_loop/message_loop.h"
12#include "base/metrics/histogram.h"
13#include "base/prefs/pref_service.h"
14#include "base/strings/utf_string_conversions.h"
15#include "base/threading/thread_restrictions.h"
16#include "chrome/browser/browser_process.h"
17#include "chrome/browser/chrome_notification_types.h"
18#include "chrome/browser/chromeos/boot_times_loader.h"
19#include "chrome/browser/chromeos/login/login_utils.h"
20#include "chrome/browser/chromeos/login/managed/locally_managed_user_login_flow.h"
21#include "chrome/browser/chromeos/login/user_manager.h"
22#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
23#include "chrome/browser/chromeos/profiles/profile_helper.h"
24#include "chrome/browser/chromeos/settings/cros_settings.h"
25#include "chrome/browser/chromeos/settings/cros_settings_names.h"
26#include "chrome/browser/policy/browser_policy_connector.h"
27#include "chrome/common/pref_names.h"
28#include "chromeos/dbus/dbus_thread_manager.h"
29#include "chromeos/dbus/session_manager_client.h"
30#include "content/public/browser/browser_thread.h"
31#include "content/public/browser/notification_service.h"
32#include "content/public/browser/notification_types.h"
33#include "content/public/browser/user_metrics.h"
34#include "google_apis/gaia/gaia_auth_util.h"
35#include "grit/generated_resources.h"
36#include "net/cookies/cookie_monster.h"
37#include "net/cookies/cookie_store.h"
38#include "net/url_request/url_request_context.h"
39#include "net/url_request/url_request_context_getter.h"
40#include "ui/base/l10n/l10n_util.h"
41#include "ui/base/resource/resource_bundle.h"
42
43using content::BrowserThread;
44using content::UserMetricsAction;
45
46namespace chromeos {
47
48LoginPerformer::LoginPerformer(Delegate* delegate)
49    : online_attempt_host_(this),
50      last_login_failure_(LoginFailure::LoginFailureNone()),
51      delegate_(delegate),
52      password_changed_(false),
53      password_changed_callback_count_(0),
54      auth_mode_(AUTH_MODE_INTERNAL),
55      weak_factory_(this) {
56}
57
58LoginPerformer::~LoginPerformer() {
59  DVLOG(1) << "Deleting LoginPerformer";
60  if (authenticator_.get())
61    authenticator_->SetConsumer(NULL);
62}
63
64////////////////////////////////////////////////////////////////////////////////
65// LoginPerformer, LoginStatusConsumer implementation:
66
67void LoginPerformer::OnLoginFailure(const LoginFailure& failure) {
68  content::RecordAction(UserMetricsAction("Login_Failure"));
69  UMA_HISTOGRAM_ENUMERATION("Login.FailureReason", failure.reason(),
70                            LoginFailure::NUM_FAILURE_REASONS);
71
72  DVLOG(1) << "failure.reason " << failure.reason();
73  DVLOG(1) << "failure.error.state " << failure.error().state();
74
75  last_login_failure_ = failure;
76  if (delegate_) {
77    delegate_->OnLoginFailure(failure);
78    return;
79  } else {
80    // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
81    // happens during offline auth only.
82    NOTREACHED();
83  }
84}
85
86void LoginPerformer::OnRetailModeLoginSuccess(
87    const UserContext& user_context) {
88  content::RecordAction(
89      UserMetricsAction("Login_DemoUserLoginSuccess"));
90  LoginStatusConsumer::OnRetailModeLoginSuccess(user_context);
91}
92
93void LoginPerformer::OnLoginSuccess(
94    const UserContext& user_context,
95    bool pending_requests,
96    bool using_oauth) {
97  content::RecordAction(UserMetricsAction("Login_Success"));
98  // The value of |pending_requests| indicates:
99  // 0 - New regular user, login success offline and online.
100  //     - or -
101  //     Existing regular user, login success offline and online, offline
102  //     authentication took longer than online authentication.
103  //     - or -
104  //     Public account user, login successful.
105  // 1 - Existing regular user, login success offline only.
106  UMA_HISTOGRAM_ENUMERATION("Login.SuccessReason", pending_requests, 2);
107
108  VLOG(1) << "LoginSuccess hash: " << user_context.username_hash
109          << ", pending_requests " << pending_requests;
110  DCHECK(delegate_);
111  // After delegate_->OnLoginSuccess(...) is called, delegate_ releases
112  // LoginPerformer ownership. LP now manages it's lifetime on its own.
113  DCHECK(!pending_requests);
114  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
115
116  delegate_->OnLoginSuccess(user_context,
117                            pending_requests,
118                            using_oauth);
119}
120
121void LoginPerformer::OnOffTheRecordLoginSuccess() {
122  content::RecordAction(
123      UserMetricsAction("Login_GuestLoginSuccess"));
124
125  if (delegate_)
126    delegate_->OnOffTheRecordLoginSuccess();
127  else
128    NOTREACHED();
129}
130
131void LoginPerformer::OnPasswordChangeDetected() {
132  password_changed_ = true;
133  password_changed_callback_count_++;
134  if (delegate_) {
135    delegate_->OnPasswordChangeDetected();
136  } else {
137    NOTREACHED();
138  }
139}
140
141void LoginPerformer::OnChecked(const std::string& username, bool success) {
142  if (!delegate_) {
143    // Delegate is reset in case of successful offline login.
144    // See ExistingUserConstoller::OnLoginSuccess().
145    // Case when user has changed password and enters old password
146    // does not block user from sign in yet.
147    return;
148  }
149  delegate_->OnOnlineChecked(username, success);
150}
151
152////////////////////////////////////////////////////////////////////////////////
153// LoginPerformer, public:
154
155void LoginPerformer::PerformLogin(const UserContext& user_context,
156                                  AuthorizationMode auth_mode) {
157  auth_mode_ = auth_mode;
158  user_context_ = user_context;
159
160  CrosSettings* cros_settings = CrosSettings::Get();
161
162  // Whitelist check is always performed during initial login.
163  CrosSettingsProvider::TrustedStatus status =
164      cros_settings->PrepareTrustedValues(
165          base::Bind(&LoginPerformer::PerformLogin,
166                     weak_factory_.GetWeakPtr(),
167                     user_context_, auth_mode));
168  // Must not proceed without signature verification.
169  if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
170    if (delegate_)
171      delegate_->PolicyLoadFailed();
172    else
173      NOTREACHED();
174    return;
175  } else if (status != CrosSettingsProvider::TRUSTED) {
176    // Value of AllowNewUser setting is still not verified.
177    // Another attempt will be invoked after verification completion.
178    return;
179  }
180
181  bool is_whitelisted = LoginUtils::IsWhitelisted(
182      gaia::CanonicalizeEmail(user_context.username));
183  if (is_whitelisted) {
184    switch (auth_mode_) {
185      case AUTH_MODE_EXTENSION:
186        StartLoginCompletion();
187        break;
188      case AUTH_MODE_INTERNAL:
189        StartAuthentication();
190        break;
191    }
192  } else {
193    if (delegate_)
194      delegate_->WhiteListCheckFailed(user_context.username);
195    else
196      NOTREACHED();
197  }
198}
199
200void LoginPerformer::LoginAsLocallyManagedUser(
201    const UserContext& user_context) {
202  DCHECK_EQ(UserManager::kLocallyManagedUserDomain,
203            gaia::ExtractDomainName(user_context.username));
204  // TODO(nkostylev): Check that policy allows locally managed user login.
205  UserFlow* new_flow = new LocallyManagedUserLoginFlow(user_context.username);
206  new_flow->set_host(
207      UserManager::Get()->GetUserFlow(user_context.username)->host());
208  UserManager::Get()->SetUserFlow(user_context.username, new_flow);
209
210  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
211  BrowserThread::PostTask(
212      BrowserThread::UI, FROM_HERE,
213      base::Bind(&Authenticator::LoginAsLocallyManagedUser,
214                 authenticator_.get(),
215                 user_context));
216}
217
218void LoginPerformer::LoginRetailMode() {
219  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
220  BrowserThread::PostTask(
221      BrowserThread::UI, FROM_HERE,
222      base::Bind(&Authenticator::LoginRetailMode, authenticator_.get()));
223}
224
225void LoginPerformer::LoginOffTheRecord() {
226  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
227  BrowserThread::PostTask(
228      BrowserThread::UI, FROM_HERE,
229      base::Bind(&Authenticator::LoginOffTheRecord, authenticator_.get()));
230}
231
232void LoginPerformer::LoginAsPublicAccount(const std::string& username) {
233  // Login is not allowed if policy could not be loaded for the account.
234  policy::DeviceLocalAccountPolicyService* policy_service =
235      g_browser_process->browser_policy_connector()->
236          GetDeviceLocalAccountPolicyService();
237  if (!policy_service || !policy_service->IsPolicyAvailableForUser(username)) {
238    DCHECK(delegate_);
239    if (delegate_)
240      delegate_->PolicyLoadFailed();
241    return;
242  }
243
244  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
245  BrowserThread::PostTask(
246      BrowserThread::UI, FROM_HERE,
247      base::Bind(&Authenticator::LoginAsPublicAccount, authenticator_.get(),
248                 username));
249}
250
251void LoginPerformer::RecoverEncryptedData(const std::string& old_password) {
252  BrowserThread::PostTask(
253      BrowserThread::UI, FROM_HERE,
254      base::Bind(&Authenticator::RecoverEncryptedData, authenticator_.get(),
255                 old_password));
256}
257
258void LoginPerformer::ResyncEncryptedData() {
259  BrowserThread::PostTask(
260      BrowserThread::UI, FROM_HERE,
261      base::Bind(&Authenticator::ResyncEncryptedData, authenticator_.get()));
262}
263
264////////////////////////////////////////////////////////////////////////////////
265// LoginPerformer, private:
266
267void LoginPerformer::StartLoginCompletion() {
268  DVLOG(1) << "Login completion started";
269  BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
270  Profile* profile = ProfileHelper::GetSigninProfile();
271
272  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
273  BrowserThread::PostTask(
274      BrowserThread::UI, FROM_HERE,
275      base::Bind(&Authenticator::CompleteLogin, authenticator_.get(),
276                 profile,
277                 user_context_));
278
279  user_context_.password.clear();
280  user_context_.auth_code.clear();
281}
282
283void LoginPerformer::StartAuthentication() {
284  DVLOG(1) << "Auth started";
285  BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
286  Profile* profile = ProfileHelper::GetSigninProfile();
287  if (delegate_) {
288    authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
289    BrowserThread::PostTask(
290        BrowserThread::UI, FROM_HERE,
291        base::Bind(&Authenticator::AuthenticateToLogin, authenticator_.get(),
292                   profile,
293                   user_context_));
294    // Make unobtrusive online check. It helps to determine password change
295    // state in the case when offline login fails.
296    online_attempt_host_.Check(profile, user_context_);
297  } else {
298    NOTREACHED();
299  }
300  user_context_.password.clear();
301  user_context_.auth_code.clear();
302}
303
304}  // namespace chromeos
305