login_performer.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
121e463b2bf864671a87ebe386cb100ef9349a540Nate Begeman// Copyright (c) 2012 The Chromium Authors. All rights reserved.
27c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner// Use of this source code is governed by a BSD-style license that can be
37c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner// found in the LICENSE file.
47c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner
57c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "chrome/browser/chromeos/login/login_performer.h"
67c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner
77c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include <string>
87c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner
97c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "base/bind.h"
107c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "base/logging.h"
117c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "base/message_loop.h"
127c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "base/metrics/histogram.h"
137c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "base/prefs/pref_service.h"
147c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "base/threading/thread_restrictions.h"
157c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "base/utf_string_conversions.h"
167c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "chrome/browser/browser_process.h"
177c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "chrome/browser/chromeos/boot_times_loader.h"
187c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "chrome/browser/chromeos/login/login_utils.h"
190bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chrome/browser/chromeos/login/managed/locally_managed_user_login_flow.h"
202668959b8879097db368aec7d76c455260abc75bChris Lattner#include "chrome/browser/chromeos/login/screen_locker.h"
217c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "chrome/browser/chromeos/login/user_manager.h"
227c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
230bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chrome/browser/chromeos/profiles/profile_helper.h"
240bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chrome/browser/chromeos/settings/cros_settings.h"
250bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chrome/browser/chromeos/settings/cros_settings_names.h"
260bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chrome/browser/policy/browser_policy_connector.h"
270bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chrome/common/chrome_notification_types.h"
280bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chrome/common/pref_names.h"
290bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chromeos/dbus/dbus_thread_manager.h"
300bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner#include "chromeos/dbus/session_manager_client.h"
31f76053269ecc6c7bd3d0b1e90ebdd0cef1bb2bdcChris Lattner#include "content/public/browser/browser_thread.h"
32c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "content/public/browser/notification_service.h"
33c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "content/public/browser/notification_types.h"
34c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "content/public/browser/user_metrics.h"
35c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "google_apis/gaia/gaia_auth_util.h"
36c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "grit/generated_resources.h"
37c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "net/cookies/cookie_monster.h"
38c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "net/cookies/cookie_store.h"
39c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "net/url_request/url_request_context.h"
40c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#include "net/url_request/url_request_context_getter.h"
41860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner#include "ui/base/l10n/l10n_util.h"
425126984b1da4bda0e93961da07e883699f1f2d57Chris Lattner#include "ui/base/resource/resource_bundle.h"
435126984b1da4bda0e93961da07e883699f1f2d57Chris Lattner
445126984b1da4bda0e93961da07e883699f1f2d57Chris Lattnerusing content::BrowserThread;
455126984b1da4bda0e93961da07e883699f1f2d57Chris Lattnerusing content::UserMetricsAction;
465126984b1da4bda0e93961da07e883699f1f2d57Chris Lattner
47993aeb2ed93f99faf1438f1b67cd922989306828Nate Begemannamespace chromeos {
48993aeb2ed93f99faf1438f1b67cd922989306828Nate Begeman
49993aeb2ed93f99faf1438f1b67cd922989306828Nate Begeman// Initialize default LoginPerformer.
50993aeb2ed93f99faf1438f1b67cd922989306828Nate Begeman// static
51f1d0b2bedaa065972a5ba17259055c1176cd1497Chris LattnerLoginPerformer* LoginPerformer::default_performer_ = NULL;
52f1d0b2bedaa065972a5ba17259055c1176cd1497Chris Lattner
53f1d0b2bedaa065972a5ba17259055c1176cd1497Chris LattnerLoginPerformer::LoginPerformer(Delegate* delegate)
54f1d0b2bedaa065972a5ba17259055c1176cd1497Chris Lattner    : online_attempt_host_(this),
55860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      last_login_failure_(LoginFailure::LoginFailureNone()),
56860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      delegate_(delegate),
57860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      password_changed_(false),
58860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      password_changed_callback_count_(0),
59860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      screen_lock_requested_(false),
60860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      initial_online_auth_pending_(false),
61860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      auth_mode_(AUTH_MODE_INTERNAL),
62860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      weak_factory_(this) {
63860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner  DCHECK(default_performer_ == NULL)
64860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner      << "LoginPerformer should have only one instance.";
654172b10ca1adfc1026428e5f522aaab98bd939adChris Lattner  default_performer_ = this;
664172b10ca1adfc1026428e5f522aaab98bd939adChris Lattner}
674172b10ca1adfc1026428e5f522aaab98bd939adChris Lattner
684172b10ca1adfc1026428e5f522aaab98bd939adChris LattnerLoginPerformer::~LoginPerformer() {
694172b10ca1adfc1026428e5f522aaab98bd939adChris Lattner  DVLOG(1) << "Deleting LoginPerformer";
70ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner  DCHECK(default_performer_ != NULL) << "Default instance should exist.";
71ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner  default_performer_ = NULL;
72ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner  if (authenticator_)
73ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner    authenticator_->SetConsumer(NULL);
749e4dd9dfc97f3930f58ca6e47bebbd8eb5cdd8a1Nate Begeman}
75ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner
76ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner////////////////////////////////////////////////////////////////////////////////
77ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner// LoginPerformer, LoginStatusConsumer implementation:
78281b55ebeccd3f0d723888c1bb9ec6e476f708f1Chris Lattner
79281b55ebeccd3f0d723888c1bb9ec6e476f708f1Chris Lattnervoid LoginPerformer::OnLoginFailure(const LoginFailure& failure) {
80281b55ebeccd3f0d723888c1bb9ec6e476f708f1Chris Lattner  content::RecordAction(UserMetricsAction("Login_Failure"));
819e4dd9dfc97f3930f58ca6e47bebbd8eb5cdd8a1Nate Begeman  UMA_HISTOGRAM_ENUMERATION("Login.FailureReason", failure.reason(),
829e4dd9dfc97f3930f58ca6e47bebbd8eb5cdd8a1Nate Begeman                            LoginFailure::NUM_FAILURE_REASONS);
836d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner
846d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  DVLOG(1) << "failure.reason " << failure.reason();
856d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  DVLOG(1) << "failure.error.state " << failure.error().state();
866d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner
876d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  last_login_failure_ = failure;
88a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner  if (delegate_) {
89a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner    delegate_->OnLoginFailure(failure);
90a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner    return;
91a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner  }
92a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner
93a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner  // Consequent online login failure with blocking UI on.
946d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  // No difference between cases whether screen was locked by the user or
956d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  // by LoginPerformer except for the very first screen lock while waiting
966d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  // for online auth. Otherwise it will be SL active > timeout > screen unlock.
976d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  // Display recoverable error message using ScreenLocker,
986d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner  // force sign out otherwise.
9990564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner  if (ScreenLocker::default_screen_locker() && !initial_online_auth_pending_) {
10090564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner    ResolveLockLoginFailure();
10190564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner    return;
10290564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner  }
10390564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner  initial_online_auth_pending_ = false;
10490564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner
10590564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner  // Offline auth - OK, online auth - failed.
10690564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner  if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED) {
107281b55ebeccd3f0d723888c1bb9ec6e476f708f1Chris Lattner    ResolveInitialNetworkAuthFailure();
1083c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner  } else if (failure.reason() == LoginFailure::LOGIN_TIMED_OUT) {
1093c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner    VLOG(1) << "Online login timed out. "
1103c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner            << "Granting user access based on offline auth only.";
1113c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner    // ScreenLock is not active, it's ok to delete itself.
112ddb739e5ea6ccf6fa4f4e2a23e3da550868efaa1Chris Lattner    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
113ddb739e5ea6ccf6fa4f4e2a23e3da550868efaa1Chris Lattner  } else {
114f24380e78ecc8a2db1b2116867d878b1e7c6f6edChris Lattner    // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
115ddb739e5ea6ccf6fa4f4e2a23e3da550868efaa1Chris Lattner    // happens during offline auth only.
116ddb739e5ea6ccf6fa4f4e2a23e3da550868efaa1Chris Lattner    // UNLOCK_FAILED is used during normal screen lock case.
117ddb739e5ea6ccf6fa4f4e2a23e3da550868efaa1Chris Lattner    // TODO(nkostylev) DATA_REMOVAL_FAILED - ?
118f24380e78ecc8a2db1b2116867d878b1e7c6f6edChris Lattner    NOTREACHED();
119116cc48e30b9c307bf3eec29c890b4ba25cd18dbChris Lattner  }
120116cc48e30b9c307bf3eec29c890b4ba25cd18dbChris Lattner}
121116cc48e30b9c307bf3eec29c890b4ba25cd18dbChris Lattner
122caad163496a3ad207a75009f4ad16bae1b1527aeChris Lattnervoid LoginPerformer::OnRetailModeLoginSuccess(
123116cc48e30b9c307bf3eec29c890b4ba25cd18dbChris Lattner    const UserContext& user_context) {
124116cc48e30b9c307bf3eec29c890b4ba25cd18dbChris Lattner  content::RecordAction(
125116cc48e30b9c307bf3eec29c890b4ba25cd18dbChris Lattner      UserMetricsAction("Login_DemoUserLoginSuccess"));
126caad163496a3ad207a75009f4ad16bae1b1527aeChris Lattner  LoginStatusConsumer::OnRetailModeLoginSuccess(user_context);
127ddb739e5ea6ccf6fa4f4e2a23e3da550868efaa1Chris Lattner}
128d0608e191ff9c00af68985f246410c219d1bec57Chris Lattner
129d0608e191ff9c00af68985f246410c219d1bec57Chris Lattnervoid LoginPerformer::OnLoginSuccess(
130f24380e78ecc8a2db1b2116867d878b1e7c6f6edChris Lattner    const UserContext& user_context,
131d0608e191ff9c00af68985f246410c219d1bec57Chris Lattner    bool pending_requests,
1323c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner    bool using_oauth) {
1333c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner  content::RecordAction(UserMetricsAction("Login_Success"));
1343c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner  // The value of |pending_requests| indicates:
1357ff7e674580adad7a5bccdbd74cf9c9f05e46d0fChris Lattner  // 0 - New regular user, login success offline and online.
1363c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner  //     - or -
1373c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner  //     Existing regular user, login success offline and online, offline
1383c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner  //     authentication took longer than online authentication.
1397ff7e674580adad7a5bccdbd74cf9c9f05e46d0fChris Lattner  //     - or -
14064b3a08bc696b2ef8733d72ce81e49be175cbbffChris Lattner  //     Public account user, login successful.
141e87192a854ff0f2f1904dd9ea282eb36059bb5afChris Lattner  // 1 - Existing regular user, login success offline only.
142140a58f9dfda30dbb80edd3da1b5632c178f7efcChris Lattner  UMA_HISTOGRAM_ENUMERATION("Login.SuccessReason", pending_requests, 2);
143140a58f9dfda30dbb80edd3da1b5632c178f7efcChris Lattner
144140a58f9dfda30dbb80edd3da1b5632c178f7efcChris Lattner  VLOG(1) << "LoginSuccess hash: " << user_context.username_hash
145e87192a854ff0f2f1904dd9ea282eb36059bb5afChris Lattner          << ", pending_requests " << pending_requests;
1463c0f9cc90cdcb70caf0dc517b9f9206d731aeb70Chris Lattner  DCHECK(delegate_);
1470bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner  // After delegate_->OnLoginSuccess(...) is called, delegate_ releases
14821e463b2bf864671a87ebe386cb100ef9349a540Nate Begeman  // LoginPerformer ownership. LP now manages it's lifetime on its own.
1497c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  // 2 things could make it exist longer:
1507c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  // 1. ScreenLock active (pending correct new password input)
1517c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  // 2. Pending online auth request.
15221e463b2bf864671a87ebe386cb100ef9349a540Nate Begeman  if (!pending_requests)
1537c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
154da6d20f0c15205923cb2c3ef4bf9b5d77de88881Chris Lattner  else
155da6d20f0c15205923cb2c3ef4bf9b5d77de88881Chris Lattner    initial_online_auth_pending_ = true;
156da6d20f0c15205923cb2c3ef4bf9b5d77de88881Chris Lattner
157da6d20f0c15205923cb2c3ef4bf9b5d77de88881Chris Lattner  delegate_->OnLoginSuccess(user_context,
158e4bc9ea0a560d8a0ba42f5a2da617e1f1f834710Chris Lattner                            pending_requests,
159e4bc9ea0a560d8a0ba42f5a2da617e1f1f834710Chris Lattner                            using_oauth);
160e4bc9ea0a560d8a0ba42f5a2da617e1f1f834710Chris Lattner}
161e4bc9ea0a560d8a0ba42f5a2da617e1f1f834710Chris Lattner
1628c13d0a5734a2f9d2b1c3870732cafffb20e3a55Chris Lattnervoid LoginPerformer::OnOffTheRecordLoginSuccess() {
1638c13d0a5734a2f9d2b1c3870732cafffb20e3a55Chris Lattner  content::RecordAction(
164bbe77de450ef36b4f83cc3b57705a9758adbd925Chris Lattner      UserMetricsAction("Login_GuestLoginSuccess"));
165bbe77de450ef36b4f83cc3b57705a9758adbd925Chris Lattner
166bbe77de450ef36b4f83cc3b57705a9758adbd925Chris Lattner  if (delegate_)
167bbe77de450ef36b4f83cc3b57705a9758adbd925Chris Lattner    delegate_->OnOffTheRecordLoginSuccess();
168bbe77de450ef36b4f83cc3b57705a9758adbd925Chris Lattner  else
1697c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner    NOTREACHED();
1707c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner}
1717c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner
1727c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattnervoid LoginPerformer::OnPasswordChangeDetected() {
1737c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  password_changed_ = true;
1747c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  password_changed_callback_count_++;
1757c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  if (delegate_) {
1767c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner    delegate_->OnPasswordChangeDetected();
1777c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  } else {
1787c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner    last_login_failure_ =
1797c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner        LoginFailure::FromNetworkAuthFailure(GoogleServiceAuthError(
1807c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner            GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
1814a95945fa5aa431110f50092f4a45d24772a553bNate Begeman    DVLOG(1) << "Password change detected - locking screen.";
1828a2d3ca7dff8f37ee0f1fc0042f47c194045183dChris Lattner    RequestScreenLock();
1838a2d3ca7dff8f37ee0f1fc0042f47c194045183dChris Lattner  }
184ddc787dfdc75fb2d78eb3e5793ca0f417ad74fd3Chris Lattner}
185ad3bc8d8add8204195aeb5106036eb7992541bdbChris Lattner
186ddc787dfdc75fb2d78eb3e5793ca0f417ad74fd3Chris Lattnervoid LoginPerformer::OnChecked(const std::string& username, bool success) {
1871efa40f6a4b561cf8f80fe018684236010645cd0Chris Lattner  if (!delegate_) {
1881efa40f6a4b561cf8f80fe018684236010645cd0Chris Lattner    // Delegate is reset in case of successful offline login.
189763317de1bda41581b12915b31ba06c2e16450feChris Lattner    // See ExistingUserConstoller::OnLoginSuccess().
190c4c6257c1a154279bf10e9498d46d6c1793dbaa7Evan Cheng    // Case when user has changed password and enters old password
191c4c6257c1a154279bf10e9498d46d6c1793dbaa7Evan Cheng    // does not block user from sign in yet.
192c4c6257c1a154279bf10e9498d46d6c1793dbaa7Evan Cheng    return;
193c4c6257c1a154279bf10e9498d46d6c1793dbaa7Evan Cheng  }
1947c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner  delegate_->OnOnlineChecked(username, success);
1957c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner}
1967c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner
1977c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner////////////////////////////////////////////////////////////////////////////////
198// LoginPerformer, content::NotificationObserver implementation:
199//
200
201void LoginPerformer::Observe(int type,
202                             const content::NotificationSource& source,
203                             const content::NotificationDetails& details) {
204  if (type != chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED)
205    return;
206
207  bool is_screen_locked = *content::Details<bool>(details).ptr();
208  if (is_screen_locked) {
209    if (screen_lock_requested_) {
210      screen_lock_requested_ = false;
211      ResolveScreenLocked();
212    }
213  } else {
214    ResolveScreenUnlocked();
215  }
216}
217
218////////////////////////////////////////////////////////////////////////////////
219// LoginPerformer, public:
220
221void LoginPerformer::PerformLogin(const UserContext& user_context,
222                                  AuthorizationMode auth_mode) {
223  auth_mode_ = auth_mode;
224  user_context_ = user_context;
225
226  CrosSettings* cros_settings = CrosSettings::Get();
227
228  // Whitelist check is always performed during initial login and
229  // should not be performed when ScreenLock is active (pending online auth).
230  if (!ScreenLocker::default_screen_locker()) {
231    CrosSettingsProvider::TrustedStatus status =
232        cros_settings->PrepareTrustedValues(
233            base::Bind(&LoginPerformer::PerformLogin,
234                       weak_factory_.GetWeakPtr(),
235                       user_context_, auth_mode));
236    // Must not proceed without signature verification.
237    if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
238      if (delegate_)
239        delegate_->PolicyLoadFailed();
240      else
241        NOTREACHED();
242      return;
243    } else if (status != CrosSettingsProvider::TRUSTED) {
244      // Value of AllowNewUser setting is still not verified.
245      // Another attempt will be invoked after verification completion.
246      return;
247    }
248  }
249
250  bool is_whitelisted = LoginUtils::IsWhitelisted(
251      gaia::CanonicalizeEmail(user_context.username));
252  if (ScreenLocker::default_screen_locker() || is_whitelisted) {
253    switch (auth_mode_) {
254      case AUTH_MODE_EXTENSION:
255        StartLoginCompletion();
256        break;
257      case AUTH_MODE_INTERNAL:
258        StartAuthentication();
259        break;
260    }
261  } else {
262    if (delegate_)
263      delegate_->WhiteListCheckFailed(user_context.username);
264    else
265      NOTREACHED();
266  }
267}
268
269void LoginPerformer::LoginAsLocallyManagedUser(
270    const UserContext& user_context) {
271  DCHECK_EQ(UserManager::kLocallyManagedUserDomain,
272            gaia::ExtractDomainName(user_context.username));
273  // TODO(nkostylev): Check that policy allows locally managed user login.
274  UserFlow* new_flow = new LocallyManagedUserLoginFlow(user_context.username);
275  new_flow->set_host(
276      UserManager::Get()->GetUserFlow(user_context.username)->host());
277  UserManager::Get()->SetUserFlow(user_context.username, new_flow);
278
279  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
280  BrowserThread::PostTask(
281      BrowserThread::UI, FROM_HERE,
282      base::Bind(&Authenticator::LoginAsLocallyManagedUser,
283                 authenticator_.get(),
284                 user_context));
285}
286
287void LoginPerformer::LoginRetailMode() {
288  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
289  BrowserThread::PostTask(
290      BrowserThread::UI, FROM_HERE,
291      base::Bind(&Authenticator::LoginRetailMode, authenticator_.get()));
292}
293
294void LoginPerformer::LoginOffTheRecord() {
295  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
296  BrowserThread::PostTask(
297      BrowserThread::UI, FROM_HERE,
298      base::Bind(&Authenticator::LoginOffTheRecord, authenticator_.get()));
299}
300
301void LoginPerformer::LoginAsPublicAccount(const std::string& username) {
302  // Login is not allowed if policy could not be loaded for the account.
303  policy::DeviceLocalAccountPolicyService* policy_service =
304      g_browser_process->browser_policy_connector()->
305          GetDeviceLocalAccountPolicyService();
306  if (!policy_service || !policy_service->IsPolicyAvailableForUser(username)) {
307    DCHECK(delegate_);
308    if (delegate_)
309      delegate_->PolicyLoadFailed();
310    return;
311  }
312
313  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
314  BrowserThread::PostTask(
315      BrowserThread::UI, FROM_HERE,
316      base::Bind(&Authenticator::LoginAsPublicAccount, authenticator_.get(),
317                 username));
318}
319
320void LoginPerformer::RecoverEncryptedData(const std::string& old_password) {
321  BrowserThread::PostTask(
322      BrowserThread::UI, FROM_HERE,
323      base::Bind(&Authenticator::RecoverEncryptedData, authenticator_.get(),
324                 old_password));
325}
326
327void LoginPerformer::ResyncEncryptedData() {
328  BrowserThread::PostTask(
329      BrowserThread::UI, FROM_HERE,
330      base::Bind(&Authenticator::ResyncEncryptedData, authenticator_.get()));
331}
332
333////////////////////////////////////////////////////////////////////////////////
334// LoginPerformer, private:
335
336void LoginPerformer::RequestScreenLock() {
337  DVLOG(1) << "Screen lock requested";
338  // Will receive notifications on screen unlock and delete itself.
339  registrar_.Add(this,
340                 chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
341                 content::NotificationService::AllSources());
342  if (ScreenLocker::default_screen_locker()) {
343    DVLOG(1) << "Screen already locked";
344    ResolveScreenLocked();
345  } else {
346    screen_lock_requested_ = true;
347    // TODO(antrim) : additional logging for crbug/173178
348    LOG(WARNING) << "Requesting screen lock from LoginPerformer";
349    DBusThreadManager::Get()->GetSessionManagerClient()->RequestLockScreen();
350  }
351}
352
353void LoginPerformer::RequestScreenUnlock() {
354  DVLOG(1) << "Screen unlock requested";
355  if (ScreenLocker::default_screen_locker()) {
356    DBusThreadManager::Get()->GetSessionManagerClient()->RequestUnlockScreen();
357    // Will unsubscribe from notifications once unlock is successful.
358  } else {
359    LOG(ERROR) << "Screen is not locked";
360    NOTREACHED();
361  }
362}
363
364void LoginPerformer::ResolveInitialNetworkAuthFailure() {
365  DVLOG(1) << "auth_error: " << last_login_failure_.error().state();
366
367  switch (last_login_failure_.error().state()) {
368    case GoogleServiceAuthError::CONNECTION_FAILED:
369    case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
370    case GoogleServiceAuthError::TWO_FACTOR:
371    case GoogleServiceAuthError::REQUEST_CANCELED:
372      // Offline auth already done. Online auth will be done next time
373      // or once user accesses web property.
374      VLOG(1) << "Granting user access based on offline auth only. "
375              << "Online login failed with "
376              << last_login_failure_.error().state();
377      // Resolving initial online auth failure, no ScreenLock is active.
378      base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
379      return;
380    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
381      // Offline auth OK, so it might be the case of changed password.
382      password_changed_ = true;
383    case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
384    case GoogleServiceAuthError::ACCOUNT_DELETED:
385    case GoogleServiceAuthError::ACCOUNT_DISABLED:
386      // Access not granted. User has to sign out.
387      // Request screen lock & show error message there.
388    case GoogleServiceAuthError::CAPTCHA_REQUIRED:
389    default:
390      // Unless there's new GoogleServiceAuthErrors state has been added.
391      NOTREACHED();
392      return;
393  }
394}
395
396void LoginPerformer::ResolveLockLoginFailure() {
397  if (last_login_failure_.reason() == LoginFailure::LOGIN_TIMED_OUT) {
398    LOG(WARNING) << "Online login timed out - unlocking screen. "
399                 << "Granting user access based on offline auth only.";
400    RequestScreenUnlock();
401    return;
402  } else if (last_login_failure_.reason() ==
403             LoginFailure::NETWORK_AUTH_FAILED) {
404    ResolveLockNetworkAuthFailure();
405    return;
406  } else if (last_login_failure_.reason() ==
407             LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME ||
408             last_login_failure_.reason() ==
409             LoginFailure::DATA_REMOVAL_FAILED) {
410    LOG(ERROR) << "Cryptohome error, forcing sign out.";
411  } else {
412    // COULD_NOT_MOUNT_TMPFS, UNLOCK_FAILED should not happen here.
413    NOTREACHED();
414  }
415  ScreenLocker::default_screen_locker()->Signout();
416}
417
418void LoginPerformer::ResolveLockNetworkAuthFailure() {
419  DCHECK(ScreenLocker::default_screen_locker())
420      << "ScreenLocker instance doesn't exist.";
421  DCHECK(last_login_failure_.reason() == LoginFailure::NETWORK_AUTH_FAILED);
422
423  int msg_id = IDS_LOGIN_ERROR_AUTHENTICATING;
424  HelpAppLauncher::HelpTopic help_topic =
425      HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
426  bool sign_out_only = false;
427
428  DVLOG(1) << "auth_error: " << last_login_failure_.error().state();
429
430  switch (last_login_failure_.error().state()) {
431    case GoogleServiceAuthError::CONNECTION_FAILED:
432    case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
433    case GoogleServiceAuthError::TWO_FACTOR:
434    case GoogleServiceAuthError::REQUEST_CANCELED:
435      // Offline auth already done. Online auth will be done next time
436      // or once user accesses web property.
437      LOG(WARNING) << "Granting user access based on offline auth only. "
438                   << "Online login failed with "
439                   << last_login_failure_.error().state();
440      RequestScreenUnlock();
441      return;
442    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
443      // Password change detected.
444      msg_id = IDS_LOGIN_ERROR_PASSWORD_CHANGED;
445      break;
446    case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
447    case GoogleServiceAuthError::ACCOUNT_DELETED:
448    case GoogleServiceAuthError::ACCOUNT_DISABLED:
449      // Access not granted. User has to sign out.
450      // Show error message using existing screen lock.
451      msg_id = IDS_LOGIN_ERROR_RESTRICTED;
452      help_topic = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
453      sign_out_only = true;
454      break;
455    case GoogleServiceAuthError::CAPTCHA_REQUIRED:
456    default:
457      // Unless there's new GoogleServiceAuthError state has been added.
458      NOTREACHED();
459      break;
460  }
461
462  ScreenLocker::default_screen_locker()->ShowErrorMessage(msg_id,
463                                                          help_topic,
464                                                          sign_out_only);
465}
466
467void LoginPerformer::ResolveScreenLocked() {
468  DVLOG(1) << "Screen locked";
469  ResolveLockNetworkAuthFailure();
470}
471
472void LoginPerformer::ResolveScreenUnlocked() {
473  DVLOG(1) << "Screen unlocked";
474  registrar_.RemoveAll();
475  // If screen was unlocked that was for a reason, should delete itself now.
476  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
477}
478
479void LoginPerformer::StartLoginCompletion() {
480  DVLOG(1) << "Login completion started";
481  BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
482  Profile* profile = ProfileHelper::GetSigninProfile();
483
484  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
485  BrowserThread::PostTask(
486      BrowserThread::UI, FROM_HERE,
487      base::Bind(&Authenticator::CompleteLogin, authenticator_.get(),
488                 profile,
489                 user_context_));
490
491  user_context_.password.clear();
492  user_context_.auth_code.clear();
493}
494
495void LoginPerformer::StartAuthentication() {
496  DVLOG(1) << "Auth started";
497  BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
498  Profile* profile = ProfileHelper::GetSigninProfile();
499  if (delegate_) {
500    authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
501    BrowserThread::PostTask(
502        BrowserThread::UI, FROM_HERE,
503        base::Bind(&Authenticator::AuthenticateToLogin, authenticator_.get(),
504                   profile,
505                   user_context_,
506                   std::string(),
507                   std::string()));
508    // Make unobtrusive online check. It helps to determine password change
509    // state in the case when offline login fails.
510    online_attempt_host_.Check(profile, user_context_);
511  } else {
512    DCHECK(authenticator_.get())
513        << "Authenticator instance doesn't exist for login attempt retry.";
514    // At this point offline auth has been successful,
515    // retry online auth, using existing Authenticator instance.
516    BrowserThread::PostTask(
517        BrowserThread::UI, FROM_HERE,
518        base::Bind(&Authenticator::RetryAuth, authenticator_.get(),
519                   profile,
520                   user_context_,
521                   std::string(),
522                   std::string()));
523  }
524  user_context_.password.clear();
525  user_context_.auth_code.clear();
526}
527
528}  // namespace chromeos
529