login_utils.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/login/login_utils.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/compiler_specific.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/location.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/ref_counted.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/singleton.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/weak_ptr.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/path_service.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_member.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/prefs/pref_service.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_util.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/sys_info.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task_runner_util.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/worker_pool.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time/time.h"
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/about_flags.h"
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/app_mode/app_mode_utils.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/browser_shutdown.h"
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chrome_notification_types.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/boot_times_loader.h"
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/input_method/input_method_util.h"
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/chrome_restart_request.h"
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/input_events_blocker.h"
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/login_display_host.h"
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/oauth2_login_manager.h"
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h"
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/parallel_authenticator.h"
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/profile_auth_data.h"
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/screen_locker.h"
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/startup_utils.h"
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/supervised_user_manager.h"
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/user.h"
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/first_run/first_run.h"
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/google/google_util_chromeos.h"
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h"
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/pref_service_flags_storage.h"
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/rlz/rlz.h"
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/signin/signin_manager.h"
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/ui/app_list/start_page_service.h"
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/ui/startup/startup_browser_creator.h"
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/logging_chrome.h"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/chromeos_switches.h"
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/cryptohome/cryptohome_util.h"
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/cryptohome_client.h"
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/dbus_method_call_status.h"
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/dbus/session_manager_client.h"
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/ime/input_method_manager.h"
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/settings/cros_settings_names.h"
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/notification_service.h"
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h"
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/network_change_notifier.h"
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_request_context.h"
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "url/gurl.h"
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using content::BrowserThread;
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace chromeos {
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(ENABLE_RLZ)
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Flag file that disables RLZ tracking, when present.
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kRLZDisabledFlagName[] =
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FILE_PATH_LITERAL(".rlz_disabled");
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::FilePath GetRlzDisabledFlagPath() {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::GetHomeDir().Append(kRLZDisabledFlagName);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct DoBrowserLaunchOnLocaleLoadedData;
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class LoginUtilsImpl
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public LoginUtils,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public OAuth2LoginManager::Observer,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public net::NetworkChangeNotifier::ConnectionTypeObserver,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public base::SupportsWeakPtr<LoginUtilsImpl> {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoginUtilsImpl()
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : has_web_auth_cookies_(false),
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        delegate_(NULL),
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        exit_after_session_restore_(false),
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        session_restore_strategy_(
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN) {
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual ~LoginUtilsImpl() {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // LoginUtils implementation:
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void DoBrowserLaunch(Profile* profile,
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               LoginDisplayHost* login_host) OVERRIDE;
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void PrepareProfile(
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const UserContext& user_context,
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const std::string& display_email,
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bool has_cookies,
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bool has_active_session,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoginUtils::Delegate* delegate) OVERRIDE;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DelegateDeleted(LoginUtils::Delegate* delegate) OVERRIDE;
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void CompleteOffTheRecordLogin(const GURL& start_url) OVERRIDE;
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void SetFirstLoginPrefs(PrefService* prefs) OVERRIDE;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual scoped_refptr<Authenticator> CreateAuthenticator(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LoginStatusConsumer* consumer) OVERRIDE;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void RestoreAuthenticationSession(Profile* profile) OVERRIDE;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void InitRlzDelayed(Profile* user_profile) OVERRIDE;
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // OAuth2LoginManager::Observer overrides.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnSessionRestoreStateChanged(
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Profile* user_profile,
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      OAuth2LoginManager::SessionRestoreState state) OVERRIDE;
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void OnNewRefreshTokenAvaiable(Profile* user_profile) OVERRIDE;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // net::NetworkChangeNotifier::ConnectionTypeObserver overrides.
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void OnConnectionTypeChanged(
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::set<std::string> SessionRestoreStateSet;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // DoBrowserLaunch is split into two parts.
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This one is called after anynchronous locale switch.
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void DoBrowserLaunchOnLocaleLoadedImpl(Profile* profile,
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         LoginDisplayHost* login_host);
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Callback for locale_util::SwitchLanguage().
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static void DoBrowserLaunchOnLocaleLoaded(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<DoBrowserLaunchOnLocaleLoadedData> context,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& locale,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& loaded_locale,
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const bool success);
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Restarts OAuth session authentication check.
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void KickStartAuthentication(Profile* profile);
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Callback for Profile::CREATE_STATUS_CREATED profile state.
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Initializes basic preferences for newly created profile. Any other
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // early profile initialization that needs to happen before
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // ProfileManager::DoFinalInit() gets called is done here.
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void InitProfilePreferences(Profile* user_profile,
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const std::string& email);
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Callback for asynchronous profile creation.
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void OnProfileCreated(const std::string& email,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        Profile* profile,
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        Profile::CreateStatus status);
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for asynchronous off the record profile creation.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnOTRProfileCreated(const std::string& email,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        Profile* profile,
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        Profile::CreateStatus status);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Callback for Profile::CREATE_STATUS_INITIALIZED profile state.
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Profile is created, extensions and promo resources are initialized.
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void UserProfileInitialized(Profile* user_profile);
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Callback for Profile::CREATE_STATUS_INITIALIZED profile state for an OTR
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // login.
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void OTRProfileInitialized(Profile* user_profile);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Callback to resume profile creation after transferring auth data from
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // the authentication profile.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CompleteProfileCreate(Profile* user_profile);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Finalized profile preparation.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FinalizePrepareProfile(Profile* user_profile);
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Initializes member variables needed for session restore process via
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // OAuthLoginManager.
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void InitSessionRestoreStrategy();
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Restores GAIA auth cookies for the created user profile from OAuth2 token.
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void RestoreAuthSession(Profile* user_profile,
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          bool restore_from_auth_cookies);
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Initializes RLZ. If |disabled| is true, RLZ pings are disabled.
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void InitRlz(Profile* user_profile, bool disabled);
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Attempts restarting the browser process and esures that this does
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // not happen while we are still fetching new OAuth refresh tokens.
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void AttemptRestart(Profile* profile);
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UserContext user_context_;
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // True if the authentication profile's cookie jar should contain
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // authentication cookies from the authentication extension log in flow.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_web_auth_cookies_;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Has to be scoped_refptr, see comment for CreateAuthenticator(...).
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<Authenticator> authenticator_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delegate to be fired when the profile will be prepared.
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LoginUtils::Delegate* delegate_;
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set of user_id for those users that we should restore authentication
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // session when notified about online state change.
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SessionRestoreStateSet pending_restore_sessions_;
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // True if we should restart chrome right after session restore.
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool exit_after_session_restore_;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Sesion restore strategy.
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OAuth2LoginManager::SessionRestoreStrategy session_restore_strategy_;
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // OAuth2 refresh token for session restore.
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string oauth2_refresh_token_;
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class LoginUtilsWrapper {
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static LoginUtilsWrapper* GetInstance() {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return Singleton<LoginUtilsWrapper>::get();
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoginUtils* get() {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock create(create_lock_);
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!ptr_.get())
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      reset(new LoginUtilsImpl);
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return ptr_.get();
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void reset(LoginUtils* ptr) {
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ptr_.reset(ptr);
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  friend struct DefaultSingletonTraits<LoginUtilsWrapper>;
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LoginUtilsWrapper() {}
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::Lock create_lock_;
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LoginUtils> ptr_;
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct DoBrowserLaunchOnLocaleLoadedData {
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DoBrowserLaunchOnLocaleLoadedData(LoginUtilsImpl* login_utils_impl,
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    Profile* profile,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    LoginDisplayHost* display_host)
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : login_utils_impl(login_utils_impl),
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        profile(profile),
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        display_host(display_host) {}
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoginUtilsImpl* login_utils_impl;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile;
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::LoginDisplayHost* display_host;
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Block UI events untill ResourceBundle is reloaded.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InputEventsBlocker input_events_blocker;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LoginUtilsImpl::DoBrowserLaunchOnLocaleLoaded(
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<DoBrowserLaunchOnLocaleLoadedData> context,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& /* locale */,
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& /* loaded_locale */,
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const bool /* success */) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context->login_utils_impl->DoBrowserLaunchOnLocaleLoadedImpl(
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context->profile, context->display_host);
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called from DoBrowserLaunch() or from
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DoBrowserLaunchOnLocaleLoaded() depending on
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// if locale switch was needed.
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void LoginUtilsImpl::DoBrowserLaunchOnLocaleLoadedImpl(
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Profile* profile,
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LoginDisplayHost* login_host) {
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!UserManager::Get()->GetCurrentUserFlow()->ShouldLaunchBrowser()) {
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UserManager::Get()->GetCurrentUserFlow()->LaunchExtraSteps(profile);
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CommandLine user_flags(CommandLine::NO_PROGRAM);
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  about_flags::PrefServiceFlagsStorage flags_storage_(profile->GetPrefs());
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  about_flags::ConvertFlagsToSwitches(&flags_storage_, &user_flags,
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      about_flags::kAddSentinels);
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Only restart if needed and if not going into managed mode.
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Don't restart browser if it is not first profile in session.
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (UserManager::Get()->GetLoggedInUsers().size() == 1 &&
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !UserManager::Get()->IsLoggedInAsLocallyManagedUser() &&
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !about_flags::AreSwitchesIdenticalToCurrentCommandLine(
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          user_flags, *CommandLine::ForCurrentProcess())) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine::StringVector flags;
322    // argv[0] is the program name |CommandLine::NO_PROGRAM|.
323    flags.assign(user_flags.argv().begin() + 1, user_flags.argv().end());
324    VLOG(1) << "Restarting to apply per-session flags...";
325    DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
326        UserManager::Get()->GetActiveUser()->email(), flags);
327    AttemptRestart(profile);
328    return;
329  }
330
331  if (login_host) {
332    login_host->SetStatusAreaVisible(true);
333    login_host->BeforeSessionStart();
334  }
335
336  BootTimesLoader::Get()->AddLoginTimeMarker("BrowserLaunched", false);
337
338  VLOG(1) << "Launching browser...";
339  StartupBrowserCreator browser_creator;
340  int return_code;
341  chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ?
342      chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
343
344  browser_creator.LaunchBrowser(*CommandLine::ForCurrentProcess(),
345                                profile,
346                                base::FilePath(),
347                                chrome::startup::IS_PROCESS_STARTUP,
348                                first_run,
349                                &return_code);
350
351  // Triggers app launcher start page service to load start page web contents.
352  app_list::StartPageService::Get(profile);
353
354  // Mark login host for deletion after browser starts.  This
355  // guarantees that the message loop will be referenced by the
356  // browser before it is dereferenced by the login host.
357  if (login_host)
358    login_host->Finalize();
359  UserManager::Get()->SessionStarted();
360}
361
362void LoginUtilsImpl::DoBrowserLaunch(Profile* profile,
363                                     LoginDisplayHost* login_host) {
364  if (browser_shutdown::IsTryingToQuit())
365    return;
366
367  User* const user = UserManager::Get()->GetUserByProfile(profile);
368  scoped_ptr<DoBrowserLaunchOnLocaleLoadedData> data(
369      new DoBrowserLaunchOnLocaleLoadedData(this, profile, login_host));
370
371  scoped_ptr<locale_util::SwitchLanguageCallback> callback(
372      new locale_util::SwitchLanguageCallback(
373          base::Bind(&LoginUtilsImpl::DoBrowserLaunchOnLocaleLoaded,
374                     base::Passed(data.Pass()))));
375  if (!UserManager::Get()->
376      RespectLocalePreference(profile, user, callback.Pass())) {
377    DoBrowserLaunchOnLocaleLoadedImpl(profile, login_host);
378  }
379}
380
381void LoginUtilsImpl::PrepareProfile(
382    const UserContext& user_context,
383    const std::string& display_email,
384    bool has_cookies,
385    bool has_active_session,
386    LoginUtils::Delegate* delegate) {
387  BootTimesLoader* btl = BootTimesLoader::Get();
388
389  VLOG(1) << "Completing login for " << user_context.username;
390
391  if (!has_active_session) {
392    btl->AddLoginTimeMarker("StartSession-Start", false);
393    DBusThreadManager::Get()->GetSessionManagerClient()->StartSession(
394        user_context.username);
395    btl->AddLoginTimeMarker("StartSession-End", false);
396  }
397
398  btl->AddLoginTimeMarker("UserLoggedIn-Start", false);
399  UserManager* user_manager = UserManager::Get();
400  user_manager->UserLoggedIn(user_context.username,
401                             user_context.username_hash,
402                             false);
403  btl->AddLoginTimeMarker("UserLoggedIn-End", false);
404
405  // Switch log file as soon as possible.
406  if (base::SysInfo::IsRunningOnChromeOS())
407    logging::RedirectChromeLogging(*(CommandLine::ForCurrentProcess()));
408
409  // Update user's displayed email.
410  if (!display_email.empty())
411    user_manager->SaveUserDisplayEmail(user_context.username, display_email);
412
413  user_context_ = user_context;
414
415  has_web_auth_cookies_ = has_cookies;
416  delegate_ = delegate;
417  InitSessionRestoreStrategy();
418
419  if (DemoAppLauncher::IsDemoAppSession(user_context.username)) {
420    g_browser_process->profile_manager()->CreateProfileAsync(
421        user_manager->GetUserProfileDir(user_context.username),
422        base::Bind(&LoginUtilsImpl::OnOTRProfileCreated, AsWeakPtr(),
423                   user_context.username),
424        base::string16(), base::string16(), std::string());
425  } else {
426    // Can't use display_email because it is empty when existing user logs in
427    // using sing-in pod on login screen (i.e. user didn't type email).
428    g_browser_process->profile_manager()->CreateProfileAsync(
429        user_manager->GetUserProfileDir(user_context.username),
430        base::Bind(&LoginUtilsImpl::OnProfileCreated, AsWeakPtr(),
431                   user_context.username),
432        base::string16(), base::string16(), std::string());
433  }
434}
435
436void LoginUtilsImpl::DelegateDeleted(LoginUtils::Delegate* delegate) {
437  if (delegate_ == delegate)
438    delegate_ = NULL;
439}
440
441void LoginUtilsImpl::InitProfilePreferences(Profile* user_profile,
442                                            const std::string& user_id) {
443  if (UserManager::Get()->IsCurrentUserNew())
444    SetFirstLoginPrefs(user_profile->GetPrefs());
445
446  if (UserManager::Get()->IsLoggedInAsLocallyManagedUser()) {
447    User* active_user = UserManager::Get()->GetActiveUser();
448    std::string managed_user_sync_id =
449        UserManager::Get()->GetSupervisedUserManager()->
450            GetUserSyncId(active_user->email());
451
452    // TODO(ibraaaa): Remove that when 97% of our users are using M31.
453    // http://crbug.com/276163
454    if (managed_user_sync_id.empty())
455      managed_user_sync_id = "DUMMY_ID";
456
457    user_profile->GetPrefs()->SetString(prefs::kManagedUserId,
458                                        managed_user_sync_id);
459  } else {
460    // Make sure that the google service username is properly set (we do this
461    // on every sign in, not just the first login, to deal with existing
462    // profiles that might not have it set yet).
463    SigninManagerBase* signin_manager =
464        SigninManagerFactory::GetForProfile(user_profile);
465    signin_manager->SetAuthenticatedUsername(user_id);
466  }
467}
468
469void LoginUtilsImpl::InitSessionRestoreStrategy() {
470  CommandLine* command_line = CommandLine::ForCurrentProcess();
471  bool in_app_mode = chrome::IsRunningInForcedAppMode();
472
473  // Are we in kiosk app mode?
474  if (in_app_mode) {
475    if (command_line->HasSwitch(::switches::kAppModeOAuth2Token)) {
476      oauth2_refresh_token_ = command_line->GetSwitchValueASCII(
477          ::switches::kAppModeOAuth2Token);
478    }
479
480    if (command_line->HasSwitch(::switches::kAppModeAuthCode)) {
481      user_context_.auth_code = command_line->GetSwitchValueASCII(
482          ::switches::kAppModeAuthCode);
483    }
484
485    DCHECK(!has_web_auth_cookies_);
486    if (!user_context_.auth_code.empty()) {
487      session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
488    } else if (!oauth2_refresh_token_.empty()) {
489      session_restore_strategy_ =
490          OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN;
491    } else {
492      session_restore_strategy_ =
493          OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
494    }
495    return;
496  }
497
498  if (has_web_auth_cookies_) {
499    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR;
500  } else if (!user_context_.auth_code.empty()) {
501    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
502  } else {
503    session_restore_strategy_ =
504        OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
505  }
506}
507
508
509void LoginUtilsImpl::OnProfileCreated(
510    const std::string& user_id,
511    Profile* user_profile,
512    Profile::CreateStatus status) {
513  CHECK(user_profile);
514
515  switch (status) {
516    case Profile::CREATE_STATUS_CREATED:
517      InitProfilePreferences(user_profile, user_id);
518      break;
519    case Profile::CREATE_STATUS_INITIALIZED:
520      UserProfileInitialized(user_profile);
521      break;
522    case Profile::CREATE_STATUS_LOCAL_FAIL:
523    case Profile::CREATE_STATUS_REMOTE_FAIL:
524    case Profile::CREATE_STATUS_CANCELED:
525    case Profile::MAX_CREATE_STATUS:
526      NOTREACHED();
527      break;
528  }
529}
530
531void LoginUtilsImpl::OnOTRProfileCreated(
532    const std::string& user_id,
533    Profile* user_profile,
534    Profile::CreateStatus status) {
535  CHECK(user_profile);
536
537  switch (status) {
538    case Profile::CREATE_STATUS_CREATED:
539      InitProfilePreferences(user_profile, user_id);
540      break;
541    case Profile::CREATE_STATUS_INITIALIZED:
542      OTRProfileInitialized(user_profile);
543      break;
544    case Profile::CREATE_STATUS_LOCAL_FAIL:
545    case Profile::CREATE_STATUS_REMOTE_FAIL:
546    case Profile::CREATE_STATUS_CANCELED:
547    case Profile::MAX_CREATE_STATUS:
548      NOTREACHED();
549      break;
550  }
551}
552
553void LoginUtilsImpl::UserProfileInitialized(Profile* user_profile) {
554  BootTimesLoader* btl = BootTimesLoader::Get();
555  btl->AddLoginTimeMarker("UserProfileGotten", false);
556
557  if (user_context_.using_oauth) {
558    // Transfer proxy authentication cache, cookies (optionally) and server
559    // bound certs from the profile that was used for authentication.  This
560    // profile contains cookies that auth extension should have already put in
561    // place that will ensure that the newly created session is authenticated
562    // for the websites that work with the used authentication schema.
563    ProfileAuthData::Transfer(authenticator_->authentication_profile(),
564                              user_profile,
565                              has_web_auth_cookies_,  // transfer_cookies
566                              base::Bind(
567                                  &LoginUtilsImpl::CompleteProfileCreate,
568                                  AsWeakPtr(),
569                                  user_profile));
570    return;
571  }
572
573  FinalizePrepareProfile(user_profile);
574}
575
576void LoginUtilsImpl::OTRProfileInitialized(Profile* user_profile) {
577  user_profile->OnLogin();
578  // Send the notification before creating the browser so additional objects
579  // that need the profile (e.g. the launcher) can be created first.
580  content::NotificationService::current()->Notify(
581      chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
582      content::NotificationService::AllSources(),
583      content::Details<Profile>(user_profile));
584
585  if (delegate_)
586    delegate_->OnProfilePrepared(user_profile);
587}
588
589void LoginUtilsImpl::CompleteProfileCreate(Profile* user_profile) {
590  RestoreAuthSession(user_profile, has_web_auth_cookies_);
591  FinalizePrepareProfile(user_profile);
592}
593
594void LoginUtilsImpl::RestoreAuthSession(Profile* user_profile,
595                                        bool restore_from_auth_cookies) {
596  CHECK((authenticator_.get() && authenticator_->authentication_profile()) ||
597        !restore_from_auth_cookies);
598
599  if (chrome::IsRunningInForcedAppMode() ||
600      CommandLine::ForCurrentProcess()->HasSwitch(
601          chromeos::switches::kOobeSkipPostLogin)) {
602    return;
603  }
604
605  exit_after_session_restore_ = false;
606  // Remove legacy OAuth1 token if we have one. If it's valid, we should already
607  // have OAuth2 refresh token in OAuth2TokenService that could be used to
608  // retrieve all other tokens and user_context.
609  OAuth2LoginManager* login_manager =
610      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
611  login_manager->AddObserver(this);
612  login_manager->RestoreSession(
613      authenticator_.get() && authenticator_->authentication_profile()
614          ? authenticator_->authentication_profile()->GetRequestContext()
615          : NULL,
616      session_restore_strategy_,
617      oauth2_refresh_token_,
618      user_context_.auth_code);
619}
620
621void LoginUtilsImpl::FinalizePrepareProfile(Profile* user_profile) {
622  BootTimesLoader* btl = BootTimesLoader::Get();
623  // Own TPM device if, for any reason, it has not been done in EULA
624  // wizard screen.
625  CryptohomeClient* client = DBusThreadManager::Get()->GetCryptohomeClient();
626  btl->AddLoginTimeMarker("TPMOwn-Start", false);
627  if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) {
628    if (cryptohome_util::TpmIsOwned()) {
629      client->CallTpmClearStoredPasswordAndBlock();
630    } else {
631      client->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback());
632    }
633  }
634  btl->AddLoginTimeMarker("TPMOwn-End", false);
635
636  if (UserManager::Get()->IsLoggedInAsRegularUser()) {
637    SAMLOfflineSigninLimiter* saml_offline_signin_limiter =
638        SAMLOfflineSigninLimiterFactory::GetForProfile(user_profile);
639    if (saml_offline_signin_limiter)
640      saml_offline_signin_limiter->SignedIn(user_context_.auth_flow);
641  }
642
643  user_profile->OnLogin();
644
645  // Send the notification before creating the browser so additional objects
646  // that need the profile (e.g. the launcher) can be created first.
647  content::NotificationService::current()->Notify(
648      chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
649      content::NotificationService::AllSources(),
650      content::Details<Profile>(user_profile));
651
652  // Initialize RLZ only for primary user.
653  if (UserManager::Get()->GetPrimaryUser() ==
654      UserManager::Get()->GetUserByProfile(user_profile)) {
655    InitRlzDelayed(user_profile);
656  }
657  // TODO(altimofeev): This pointer should probably never be NULL, but it looks
658  // like LoginUtilsImpl::OnProfileCreated() may be getting called before
659  // LoginUtilsImpl::PrepareProfile() has set |delegate_| when Chrome is killed
660  // during shutdown in tests -- see http://crosbug.com/18269.  Replace this
661  // 'if' statement with a CHECK(delegate_) once the underlying issue is
662  // resolved.
663  if (delegate_)
664    delegate_->OnProfilePrepared(user_profile);
665}
666
667void LoginUtilsImpl::InitRlzDelayed(Profile* user_profile) {
668#if defined(ENABLE_RLZ)
669  if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand)) {
670    // Read brand code asynchronously from an OEM data and repost ourselves.
671    google_util::chromeos::InitBrand(
672        base::Bind(&LoginUtilsImpl::InitRlzDelayed, AsWeakPtr(), user_profile));
673    return;
674  }
675  base::PostTaskAndReplyWithResult(
676      base::WorkerPool::GetTaskRunner(false),
677      FROM_HERE,
678      base::Bind(&base::PathExists, GetRlzDisabledFlagPath()),
679      base::Bind(&LoginUtilsImpl::InitRlz, AsWeakPtr(), user_profile));
680#endif
681}
682
683void LoginUtilsImpl::InitRlz(Profile* user_profile, bool disabled) {
684#if defined(ENABLE_RLZ)
685  PrefService* local_state = g_browser_process->local_state();
686  if (disabled) {
687    // Empty brand code means an organic install (no RLZ pings are sent).
688    google_util::chromeos::ClearBrandForCurrentSession();
689  }
690  if (disabled != local_state->GetBoolean(prefs::kRLZDisabled)) {
691    // When switching to RLZ enabled/disabled state, clear all recorded events.
692    RLZTracker::ClearRlzState();
693    local_state->SetBoolean(prefs::kRLZDisabled, disabled);
694  }
695  // Init the RLZ library.
696  int ping_delay = user_profile->GetPrefs()->GetInteger(
697      first_run::GetPingDelayPrefName().c_str());
698  // Negative ping delay means to send ping immediately after a first search is
699  // recorded.
700  RLZTracker::InitRlzFromProfileDelayed(
701      user_profile, UserManager::Get()->IsCurrentUserNew(),
702      ping_delay < 0, base::TimeDelta::FromMilliseconds(abs(ping_delay)));
703  if (delegate_)
704    delegate_->OnRlzInitialized(user_profile);
705#endif
706}
707
708void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) {
709  VLOG(1) << "Completing incognito login";
710
711  // For guest session we ask session manager to restart Chrome with --bwsi
712  // flag. We keep only some of the arguments of this process.
713  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
714  CommandLine command_line(browser_command_line.GetProgram());
715  std::string cmd_line_str =
716      GetOffTheRecordCommandLine(start_url,
717                                 StartupUtils::IsOobeCompleted(),
718                                 browser_command_line,
719                                 &command_line);
720
721  RestartChrome(cmd_line_str);
722}
723
724void LoginUtilsImpl::SetFirstLoginPrefs(PrefService* prefs) {
725  VLOG(1) << "Setting first login prefs";
726  BootTimesLoader* btl = BootTimesLoader::Get();
727  std::string locale = g_browser_process->GetApplicationLocale();
728
729  // First, we'll set kLanguagePreloadEngines.
730  input_method::InputMethodManager* manager =
731      input_method::InputMethodManager::Get();
732  std::vector<std::string> input_method_ids;
733  manager->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
734      locale, manager->GetCurrentInputMethod(), &input_method_ids);
735  // Save the input methods in the user's preferences.
736  StringPrefMember language_preload_engines;
737  language_preload_engines.Init(prefs::kLanguagePreloadEngines,
738                                prefs);
739  language_preload_engines.SetValue(JoinString(input_method_ids, ','));
740  btl->AddLoginTimeMarker("IMEStarted", false);
741
742  // Second, we'll set kLanguagePreferredLanguages.
743  std::vector<std::string> language_codes;
744  // The current locale should be on the top.
745  language_codes.push_back(locale);
746
747  // Add input method IDs based on the input methods, as there may be
748  // input methods that are unrelated to the current locale. Example: the
749  // hardware keyboard layout xkb:us::eng is used for logging in, but the
750  // UI language is set to French. In this case, we should set "fr,en"
751  // to the preferred languages preference.
752  std::vector<std::string> candidates;
753  manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
754      input_method_ids, &candidates);
755  for (size_t i = 0; i < candidates.size(); ++i) {
756    const std::string& candidate = candidates[i];
757    // Skip if it's already in language_codes.
758    if (std::count(language_codes.begin(), language_codes.end(),
759                   candidate) == 0) {
760      language_codes.push_back(candidate);
761    }
762  }
763  // Save the preferred languages in the user's preferences.
764  StringPrefMember language_preferred_languages;
765  language_preferred_languages.Init(prefs::kLanguagePreferredLanguages,
766                                    prefs);
767  language_preferred_languages.SetValue(JoinString(language_codes, ','));
768}
769
770scoped_refptr<Authenticator> LoginUtilsImpl::CreateAuthenticator(
771    LoginStatusConsumer* consumer) {
772  // Screen locker needs new Authenticator instance each time.
773  if (ScreenLocker::default_screen_locker()) {
774    if (authenticator_.get())
775      authenticator_->SetConsumer(NULL);
776    authenticator_ = NULL;
777  }
778
779  if (authenticator_.get() == NULL) {
780    authenticator_ = new ParallelAuthenticator(consumer);
781  } else {
782    // TODO(nkostylev): Fix this hack by improving Authenticator dependencies.
783    authenticator_->SetConsumer(consumer);
784  }
785  return authenticator_;
786}
787
788void LoginUtilsImpl::RestoreAuthenticationSession(Profile* user_profile) {
789  UserManager* user_manager = UserManager::Get();
790  // We don't need to restore session for demo/guest/stub/public account users.
791  if (!user_manager->IsUserLoggedIn() ||
792      user_manager->IsLoggedInAsGuest() ||
793      user_manager->IsLoggedInAsPublicAccount() ||
794      user_manager->IsLoggedInAsDemoUser() ||
795      user_manager->IsLoggedInAsStub()) {
796    return;
797  }
798
799  User* user = user_manager->GetUserByProfile(user_profile);
800  DCHECK(user);
801  if (!net::NetworkChangeNotifier::IsOffline()) {
802    pending_restore_sessions_.erase(user->email());
803    RestoreAuthSession(user_profile, false);
804  } else {
805    // Even if we're online we should wait till initial
806    // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
807    // end up canceling all request when initial network connection type is
808    // processed. See http://crbug.com/121643.
809    pending_restore_sessions_.insert(user->email());
810  }
811}
812
813void LoginUtilsImpl::OnSessionRestoreStateChanged(
814    Profile* user_profile,
815    OAuth2LoginManager::SessionRestoreState state) {
816  User::OAuthTokenStatus user_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
817  OAuth2LoginManager* login_manager =
818      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
819
820  bool connection_error = false;
821  switch (state) {
822    case OAuth2LoginManager::SESSION_RESTORE_DONE:
823      user_status = User::OAUTH2_TOKEN_STATUS_VALID;
824      break;
825    case OAuth2LoginManager::SESSION_RESTORE_FAILED:
826      user_status = User::OAUTH2_TOKEN_STATUS_INVALID;
827      break;
828    case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED:
829      connection_error = true;
830      break;
831    case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
832    case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
833    case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
834      return;
835  }
836
837  // We should not be clearing existing token state if that was a connection
838  // error. http://crbug.com/295245
839  if (!connection_error) {
840    // We are in one of "done" states here.
841    UserManager::Get()->SaveUserOAuthStatus(
842        UserManager::Get()->GetLoggedInUser()->email(),
843        user_status);
844  }
845
846  login_manager->RemoveObserver(this);
847}
848
849void LoginUtilsImpl::OnNewRefreshTokenAvaiable(Profile* user_profile) {
850  // Check if we were waiting to restart chrome.
851  if (!exit_after_session_restore_)
852    return;
853
854  OAuth2LoginManager* login_manager =
855      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
856  login_manager->RemoveObserver(this);
857
858  // Mark user auth token status as valid.
859  UserManager::Get()->SaveUserOAuthStatus(
860      UserManager::Get()->GetLoggedInUser()->email(),
861      User::OAUTH2_TOKEN_STATUS_VALID);
862
863  LOG(WARNING) << "Exiting after new refresh token fetched";
864  // We need to restart cleanly in this case to make sure OAuth2 RT is actually
865  // saved.
866  chrome::AttemptRestart();
867}
868
869void LoginUtilsImpl::OnConnectionTypeChanged(
870    net::NetworkChangeNotifier::ConnectionType type) {
871  UserManager* user_manager = UserManager::Get();
872  if (type == net::NetworkChangeNotifier::CONNECTION_NONE ||
873      user_manager->IsLoggedInAsGuest() || !user_manager->IsUserLoggedIn()) {
874    return;
875  }
876
877  // Need to iterate over all users and their OAuth2 session state.
878  const UserList& users = user_manager->GetLoggedInUsers();
879  for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
880    Profile* user_profile = user_manager->GetProfileByUser(*it);
881    bool should_restore_session =
882        pending_restore_sessions_.find((*it)->email()) !=
883            pending_restore_sessions_.end();
884    OAuth2LoginManager* login_manager =
885        OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
886    if (login_manager->state() ==
887            OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS) {
888      // If we come online for the first time after successful offline login,
889      // we need to kick off OAuth token verification process again.
890      login_manager->ContinueSessionRestore();
891    } else if (should_restore_session) {
892      pending_restore_sessions_.erase((*it)->email());
893      RestoreAuthSession(user_profile, has_web_auth_cookies_);
894    }
895  }
896}
897
898void LoginUtilsImpl::AttemptRestart(Profile* profile) {
899  if (session_restore_strategy_ !=
900      OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR) {
901    chrome::AttemptRestart();
902    return;
903  }
904
905  // We can't really quit if the session restore process that mints new
906  // refresh token is still in progress.
907  OAuth2LoginManager* login_manager =
908      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile);
909  if (login_manager->state() !=
910          OAuth2LoginManager::SESSION_RESTORE_PREPARING &&
911      login_manager->state() !=
912          OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS) {
913    chrome::AttemptRestart();
914    return;
915  }
916
917  LOG(WARNING) << "Attempting browser restart during session restore.";
918  exit_after_session_restore_ = true;
919}
920
921// static
922void LoginUtils::RegisterPrefs(PrefRegistrySimple* registry) {
923  registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
924  registry->RegisterBooleanPref(prefs::kRollbackRequested, false);
925  registry->RegisterStringPref(prefs::kRLZBrand, std::string());
926  registry->RegisterBooleanPref(prefs::kRLZDisabled, false);
927}
928
929// static
930LoginUtils* LoginUtils::Get() {
931  return LoginUtilsWrapper::GetInstance()->get();
932}
933
934// static
935void LoginUtils::Set(LoginUtils* mock) {
936  LoginUtilsWrapper::GetInstance()->reset(mock);
937}
938
939// static
940bool LoginUtils::IsWhitelisted(const std::string& username,
941                               bool* wildcard_match) {
942  // Skip whitelist check for tests.
943  if (CommandLine::ForCurrentProcess()->HasSwitch(
944      chromeos::switches::kOobeSkipPostLogin)) {
945    return true;
946  }
947
948  CrosSettings* cros_settings = CrosSettings::Get();
949  bool allow_new_user = false;
950  cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
951  if (allow_new_user)
952    return true;
953  return cros_settings->FindEmailInList(
954      kAccountsPrefUsers, username, wildcard_match);
955}
956
957}  // namespace chromeos
958