Introduce SessionManager that will contain code to start user session on Chrome OS

Move profile creation / session initialization (prefs/RLZ) as well as some of OAuth session init
related code from LoginUtils to SessionManager. LoginUtils will temporarily implement
SessionManager::Delegate interface till existing test coverage is migrated from LoginUtils interface.
SessionManager will later use concept of UserSession (see design proposal at http://goto/cros-login-c14n).

LoginUtils::OnPrepareProfile() is split into
StartSession()
--PreStartSession() - things like switching logging dest
--CreateUserSession() - will eventually create UserSession instance
--StartCrosSession() - notify cros::SessionManager
--NotifyUserLoggedIn() - UserManager::UserLoggedIn()
--PrepareProfile()

PrepareProfile() - calls PM::CreateProfileAsync()
--OnProfileCreated()
----InitProfilePreferences() - early initialization
----UserProfileInitialized()
------transfer signin profile auth date (cookies/proxy auth/certs)
------RestoreAuthSessionImpl() - OAuth2LoginManager::RestoreSession()
----FinalizePrepareProfile(()
------Own TPM (if it didn't happen for some reason)
------Notify SAML offline signin limiter
------Notify ProfileImpl
------chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED
------InitRLZ (for primary user)
  

Minor cleanup
* Unify DemoApp profile initialization flow with regular one
* Don't pass display_email to LoginUtils::PrepareProfile
* Move powerwash related prefs registration to ResetScreenHandler
* Cleanup M31 migration code for |prefs::kProfileIsManaged| in LoginUtilsImpl::InitProfilePreferences()

BUG=370175,276163

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=276626

Review URL: https://codereview.chromium.org/318853004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277238 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
index 0b4d80d..911757d 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
@@ -160,7 +160,6 @@
   if (context.GetUserID() == UserManager::kGuestUserName)
     context.SetUserID(DemoAppLauncher::kDemoUserName);
   LoginUtils::Get()->PrepareProfile(context,
-                                    std::string(),  // display email
                                     false,  // has_cookies
                                     false,  // has_active_session
                                     this);
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 79f4d84c..fa32096 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -50,6 +50,7 @@
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/login_wizard.h"
+#include "chrome/browser/chromeos/login/session/session_manager.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/users/user.h"
 #include "chrome/browser/chromeos/login/users/user_manager.h"
@@ -161,7 +162,6 @@
     if (!profile_prepared_) {
       // Will call OnProfilePrepared in the end.
       LoginUtils::Get()->PrepareProfile(user_context,
-                                        std::string(),  // display_email
                                         false,          // has_cookies
                                         true,           // has_active_session
                                         this);
@@ -236,7 +236,7 @@
 
       // We did not log in (we crashed or are debugging), so we need to
       // restore Sync.
-      LoginUtils::Get()->RestoreAuthenticationSession(profile);
+      SessionManager::GetInstance()->RestoreAuthenticationSession(profile);
     }
   }
 }
@@ -632,8 +632,8 @@
                                        login_user);
     }
 
-    // This is done in LoginUtils::OnProfileCreated during normal login.
-    LoginUtils::Get()->InitRlzDelayed(profile());
+    // This is done in SessionManager::OnProfileCreated during normal login.
+    SessionManager::GetInstance()->InitRlz(profile());
 
     // Send the PROFILE_PREPARED notification and call SessionStarted()
     // so that the Launcher and other Profile dependent classes are created.
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index b2bdbc6..2d92d55 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -775,14 +775,18 @@
   login_performer_->set_delegate(NULL);
   ignore_result(login_performer_.release());
 
+  // Update user's displayed email.
+  if (!display_email_.empty()) {
+    UserManager::Get()->SaveUserDisplayEmail(user_context.GetUserID(),
+                                             display_email_);
+    display_email_.clear();
+  }
+
   // Will call OnProfilePrepared() in the end.
   LoginUtils::Get()->PrepareProfile(user_context,
-                                    display_email_,
                                     has_cookies,
                                     false,          // Start session for user.
                                     this);
-
-  display_email_.clear();
 }
 
 void ExistingUserController::OnProfilePrepared(Profile* profile) {
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index 9b55d2d..49f9ea2 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -242,7 +242,7 @@
   EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_))
       .Times(1)
       .WillOnce(WithArg<0>(CreateAuthenticator(user_context)));
-  EXPECT_CALL(*mock_login_utils_, PrepareProfile(user_context, _, _, _, _))
+  EXPECT_CALL(*mock_login_utils_, PrepareProfile(user_context, _, _, _))
       .Times(1)
       .WillOnce(InvokeWithoutArgs(&profile_prepared_cb_,
                                   &base::Callback<void(void)>::Run));
@@ -308,7 +308,7 @@
       base::Bind(&MockUserManager::AddUser,
                  base::Unretained(mock_user_manager_),
                  kNewUsername);
-  EXPECT_CALL(*mock_login_utils_, PrepareProfile(user_context, _, _, _, _))
+  EXPECT_CALL(*mock_login_utils_, PrepareProfile(user_context, _, _, _))
       .Times(1)
       .WillOnce(DoAll(
           InvokeWithoutArgs(&add_user_cb,
@@ -432,7 +432,7 @@
     EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_))
         .Times(1)
         .WillOnce(WithArg<0>(CreateAuthenticator(user_context)));
-    EXPECT_CALL(*mock_login_utils_, PrepareProfile(user_context, _, _, _, _))
+    EXPECT_CALL(*mock_login_utils_, PrepareProfile(user_context, _, _, _))
         .Times(1)
         .WillOnce(InvokeWithoutArgs(&profile_prepared_cb_,
                                     &base::Callback<void(void)>::Run));
diff --git a/chrome/browser/chromeos/login/fake_login_utils.cc b/chrome/browser/chromeos/login/fake_login_utils.cc
index 8cc12ac..ffb8cff 100644
--- a/chrome/browser/chromeos/login/fake_login_utils.cc
+++ b/chrome/browser/chromeos/login/fake_login_utils.cc
@@ -55,7 +55,6 @@
 }
 
 void FakeLoginUtils::PrepareProfile(const UserContext& user_context,
-                                    const std::string& display_email,
                                     bool has_cookies,
                                     bool has_active_session,
                                     LoginUtils::Delegate* delegate) {
@@ -95,24 +94,12 @@
   NOTREACHED() << "Method not implemented.";
 }
 
-void FakeLoginUtils::SetFirstLoginPrefs(PrefService* prefs) {
-  NOTREACHED() << "Method not implemented.";
-}
-
 scoped_refptr<Authenticator> FakeLoginUtils::CreateAuthenticator(
     LoginStatusConsumer* consumer) {
   authenticator_ = new MockAuthenticator(consumer, expected_user_context_);
   return authenticator_;
 }
 
-void FakeLoginUtils::RestoreAuthenticationSession(Profile* profile) {
-  NOTREACHED() << "Method not implemented.";
-}
-
-void FakeLoginUtils::InitRlzDelayed(Profile* user_profile) {
-  NOTREACHED() << "Method not implemented.";
-}
-
 void FakeLoginUtils::SetExpectedCredentials(const UserContext& user_context) {
   expected_user_context_ = user_context;
   if (authenticator_) {
diff --git a/chrome/browser/chromeos/login/fake_login_utils.h b/chrome/browser/chromeos/login/fake_login_utils.h
index fe512489..43549c9 100644
--- a/chrome/browser/chromeos/login/fake_login_utils.h
+++ b/chrome/browser/chromeos/login/fake_login_utils.h
@@ -24,17 +24,13 @@
   virtual void DoBrowserLaunch(Profile* profile,
                                LoginDisplayHost* login_host) OVERRIDE;
   virtual void PrepareProfile(const UserContext& user_context,
-                              const std::string& display_email,
                               bool has_cookies,
                               bool has_active_session,
                               LoginUtils::Delegate* delegate) OVERRIDE;
   virtual void DelegateDeleted(LoginUtils::Delegate* delegate) OVERRIDE;
   virtual void CompleteOffTheRecordLogin(const GURL& start_url) OVERRIDE;
-  virtual void SetFirstLoginPrefs(PrefService* prefs) OVERRIDE;
   virtual scoped_refptr<Authenticator> CreateAuthenticator(
       LoginStatusConsumer* consumer) OVERRIDE;
-  virtual void RestoreAuthenticationSession(Profile* profile) OVERRIDE;
-  virtual void InitRlzDelayed(Profile* user_profile) OVERRIDE;
 
   void SetExpectedCredentials(const UserContext& user_context);
   void set_should_launch_browser(bool should_launch_browser) {
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index b369abb5..f5946418 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -21,7 +21,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/path_service.h"
 #include "base/prefs/pref_member.h"
-#include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -36,7 +35,6 @@
 #include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/boot_times_loader.h"
-#include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/login/auth/parallel_authenticator.h"
 #include "chrome/browser/chromeos/login/auth/user_context.h"
 #include "chrome/browser/chromeos/login/chrome_restart_request.h"
@@ -45,6 +43,7 @@
 #include "chrome/browser/chromeos/login/profile_auth_data.h"
 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
+#include "chrome/browser/chromeos/login/session/session_manager.h"
 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
@@ -76,7 +75,6 @@
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
-#include "chromeos/ime/input_method_manager.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/browser_thread.h"
@@ -111,21 +109,14 @@
 
 class LoginUtilsImpl
     : public LoginUtils,
-      public OAuth2LoginManager::Observer,
-      public net::NetworkChangeNotifier::ConnectionTypeObserver,
-      public base::SupportsWeakPtr<LoginUtilsImpl> {
+      public base::SupportsWeakPtr<LoginUtilsImpl>,
+      public SessionManager::Delegate {
  public:
   LoginUtilsImpl()
-      : has_web_auth_cookies_(false),
-        delegate_(NULL),
-        exit_after_session_restore_(false),
-        session_restore_strategy_(
-            OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN) {
-    net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+      : delegate_(NULL) {
   }
 
   virtual ~LoginUtilsImpl() {
-    net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
   }
 
   // LoginUtils implementation:
@@ -133,33 +124,23 @@
                                LoginDisplayHost* login_host) OVERRIDE;
   virtual void PrepareProfile(
       const UserContext& user_context,
-      const std::string& display_email,
       bool has_cookies,
       bool has_active_session,
       LoginUtils::Delegate* delegate) OVERRIDE;
   virtual void DelegateDeleted(LoginUtils::Delegate* delegate) OVERRIDE;
   virtual void CompleteOffTheRecordLogin(const GURL& start_url) OVERRIDE;
-  virtual void SetFirstLoginPrefs(PrefService* prefs) OVERRIDE;
   virtual scoped_refptr<Authenticator> CreateAuthenticator(
       LoginStatusConsumer* consumer) OVERRIDE;
-  virtual void RestoreAuthenticationSession(Profile* profile) OVERRIDE;
-  virtual void InitRlzDelayed(Profile* user_profile) OVERRIDE;
 
-  // OAuth2LoginManager::Observer overrides.
-  virtual void OnSessionRestoreStateChanged(
-      Profile* user_profile,
-      OAuth2LoginManager::SessionRestoreState state) OVERRIDE;
-  virtual void OnNewRefreshTokenAvaiable(Profile* user_profile) OVERRIDE;
-
-  // net::NetworkChangeNotifier::ConnectionTypeObserver overrides.
-  virtual void OnConnectionTypeChanged(
-      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
+  // SessionManager::Delegate implementation:
+   virtual void OnProfilePrepared(Profile* profile) OVERRIDE;
+ #if defined(ENABLE_RLZ)
+   virtual void OnRlzInitialized() OVERRIDE;
+ #endif
 
  private:
-  typedef std::set<std::string> SessionRestoreStateSet;
-
   // DoBrowserLaunch is split into two parts.
-  // This one is called after anynchronous locale switch.
+  // This one is called after asynchronous locale switch.
   void DoBrowserLaunchOnLocaleLoadedImpl(Profile* profile,
                                          LoginDisplayHost* login_host);
 
@@ -170,79 +151,16 @@
       const std::string& loaded_locale,
       const bool success);
 
-  // Restarts OAuth session authentication check.
-  void KickStartAuthentication(Profile* profile);
-
-  // Callback for Profile::CREATE_STATUS_CREATED profile state.
-  // Initializes basic preferences for newly created profile. Any other
-  // early profile initialization that needs to happen before
-  // ProfileManager::DoFinalInit() gets called is done here.
-  void InitProfilePreferences(Profile* user_profile,
-                              const std::string& email);
-
-  // Callback for asynchronous profile creation.
-  void OnProfileCreated(const std::string& email,
-                        Profile* profile,
-                        Profile::CreateStatus status);
-
-  // Callback for asynchronous off the record profile creation.
-  void OnOTRProfileCreated(const std::string& email,
-                        Profile* profile,
-                        Profile::CreateStatus status);
-
-  // Callback for Profile::CREATE_STATUS_INITIALIZED profile state.
-  // Profile is created, extensions and promo resources are initialized.
-  void UserProfileInitialized(Profile* user_profile);
-
-  // Callback for Profile::CREATE_STATUS_INITIALIZED profile state for an OTR
-  // login.
-  void OTRProfileInitialized(Profile* user_profile);
-
-  // Callback to resume profile creation after transferring auth data from
-  // the authentication profile.
-  void CompleteProfileCreate(Profile* user_profile);
-
-  // Finalized profile preparation.
-  void FinalizePrepareProfile(Profile* user_profile);
-
-  // Initializes member variables needed for session restore process via
-  // OAuthLoginManager.
-  void InitSessionRestoreStrategy();
-
-  // Restores GAIA auth cookies for the created user profile from OAuth2 token.
-  void RestoreAuthSession(Profile* user_profile,
-                          bool restore_from_auth_cookies);
-
-  // Initializes RLZ. If |disabled| is true, RLZ pings are disabled.
-  void InitRlz(Profile* user_profile, bool disabled);
-
   // Attempts restarting the browser process and esures that this does
   // not happen while we are still fetching new OAuth refresh tokens.
   void AttemptRestart(Profile* profile);
 
-  UserContext user_context_;
-
-  // True if the authentication profile's cookie jar should contain
-  // authentication cookies from the authentication extension log in flow.
-  bool has_web_auth_cookies_;
   // Has to be scoped_refptr, see comment for CreateAuthenticator(...).
   scoped_refptr<Authenticator> authenticator_;
 
   // Delegate to be fired when the profile will be prepared.
   LoginUtils::Delegate* delegate_;
 
-  // Set of user_id for those users that we should restore authentication
-  // session when notified about online state change.
-  SessionRestoreStateSet pending_restore_sessions_;
-
-  // True if we should restart chrome right after session restore.
-  bool exit_after_session_restore_;
-
-  // Sesion restore strategy.
-  OAuth2LoginManager::SessionRestoreStrategy session_restore_strategy_;
-  // OAuth2 refresh token for session restore.
-  std::string oauth2_refresh_token_;
-
   DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
 };
 
@@ -385,57 +303,22 @@
 
 void LoginUtilsImpl::PrepareProfile(
     const UserContext& user_context,
-    const std::string& display_email,
     bool has_cookies,
     bool has_active_session,
     LoginUtils::Delegate* delegate) {
-  BootTimesLoader* btl = BootTimesLoader::Get();
-
-  VLOG(1) << "Completing login for " << user_context.GetUserID();
-
-  if (!has_active_session) {
-    btl->AddLoginTimeMarker("StartSession-Start", false);
-    DBusThreadManager::Get()->GetSessionManagerClient()->StartSession(
-        user_context.GetUserID());
-    btl->AddLoginTimeMarker("StartSession-End", false);
-  }
-
-  btl->AddLoginTimeMarker("UserLoggedIn-Start", false);
-  UserManager* user_manager = UserManager::Get();
-  user_manager->UserLoggedIn(user_context.GetUserID(),
-                             user_context.GetUserIDHash(),
-                             false);
-  btl->AddLoginTimeMarker("UserLoggedIn-End", false);
-
-  // Switch log file as soon as possible.
-  if (base::SysInfo::IsRunningOnChromeOS())
-    logging::RedirectChromeLogging(*(CommandLine::ForCurrentProcess()));
-
-  // Update user's displayed email.
-  if (!display_email.empty())
-    user_manager->SaveUserDisplayEmail(user_context.GetUserID(), display_email);
-
-  user_context_ = user_context;
-
-  has_web_auth_cookies_ = has_cookies;
+  // TODO(nkostylev): We have to initialize LoginUtils delegate as long
+  // as it coexist with SessionManager.
   delegate_ = delegate;
-  InitSessionRestoreStrategy();
 
-  if (DemoAppLauncher::IsDemoAppSession(user_context.GetUserID())) {
-    g_browser_process->profile_manager()->CreateProfileAsync(
-        user_manager->GetUserProfileDir(user_context.GetUserID()),
-        base::Bind(&LoginUtilsImpl::OnOTRProfileCreated, AsWeakPtr(),
-                   user_context.GetUserID()),
-        base::string16(), base::string16(), std::string());
-  } else {
-    // Can't use display_email because it is empty when existing user logs in
-    // using sing-in pod on login screen (i.e. user didn't type email).
-    g_browser_process->profile_manager()->CreateProfileAsync(
-        user_manager->GetUserProfileDir(user_context.GetUserID()),
-        base::Bind(&LoginUtilsImpl::OnProfileCreated, AsWeakPtr(),
-                   user_context.GetUserID()),
-        base::string16(), base::string16(), std::string());
-  }
+  // For the transition part LoginUtils will just delegate profile
+  // creation and initialization to SessionManager. Later LoginUtils will be
+  // removed and all LoginUtils clients will just work with SessionManager
+  // directly.
+  SessionManager::GetInstance()->StartSession(user_context,
+                                              authenticator_,
+                                              has_cookies,
+                                              has_active_session,
+                                              this);
 }
 
 void LoginUtilsImpl::DelegateDeleted(LoginUtils::Delegate* delegate) {
@@ -443,273 +326,6 @@
     delegate_ = NULL;
 }
 
-void LoginUtilsImpl::InitProfilePreferences(Profile* user_profile,
-                                            const std::string& user_id) {
-  if (UserManager::Get()->IsCurrentUserNew())
-    SetFirstLoginPrefs(user_profile->GetPrefs());
-
-  if (UserManager::Get()->IsLoggedInAsLocallyManagedUser()) {
-    User* active_user = UserManager::Get()->GetActiveUser();
-    std::string managed_user_sync_id =
-        UserManager::Get()->GetSupervisedUserManager()->
-            GetUserSyncId(active_user->email());
-
-    // TODO(ibraaaa): Remove that when 97% of our users are using M31.
-    // http://crbug.com/276163
-    if (managed_user_sync_id.empty())
-      managed_user_sync_id = "DUMMY_ID";
-
-    user_profile->GetPrefs()->SetString(prefs::kSupervisedUserId,
-                                        managed_user_sync_id);
-  } else if (UserManager::Get()->IsLoggedInAsRegularUser()) {
-    // Make sure that the google service username is properly set (we do this
-    // on every sign in, not just the first login, to deal with existing
-    // profiles that might not have it set yet).
-    SigninManagerBase* signin_manager =
-        SigninManagerFactory::GetForProfile(user_profile);
-    signin_manager->SetAuthenticatedUsername(user_id);
-  }
-}
-
-void LoginUtilsImpl::InitSessionRestoreStrategy() {
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  bool in_app_mode = chrome::IsRunningInForcedAppMode();
-
-  // Are we in kiosk app mode?
-  if (in_app_mode) {
-    if (command_line->HasSwitch(::switches::kAppModeOAuth2Token)) {
-      oauth2_refresh_token_ = command_line->GetSwitchValueASCII(
-          ::switches::kAppModeOAuth2Token);
-    }
-
-    if (command_line->HasSwitch(::switches::kAppModeAuthCode)) {
-      user_context_.SetAuthCode(command_line->GetSwitchValueASCII(
-          ::switches::kAppModeAuthCode));
-    }
-
-    DCHECK(!has_web_auth_cookies_);
-    if (!user_context_.GetAuthCode().empty()) {
-      session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
-    } else if (!oauth2_refresh_token_.empty()) {
-      session_restore_strategy_ =
-          OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN;
-    } else {
-      session_restore_strategy_ =
-          OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
-    }
-    return;
-  }
-
-  if (has_web_auth_cookies_) {
-    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR;
-  } else if (!user_context_.GetAuthCode().empty()) {
-    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
-  } else {
-    session_restore_strategy_ =
-        OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
-  }
-}
-
-
-void LoginUtilsImpl::OnProfileCreated(
-    const std::string& user_id,
-    Profile* user_profile,
-    Profile::CreateStatus status) {
-  CHECK(user_profile);
-
-  switch (status) {
-    case Profile::CREATE_STATUS_CREATED:
-      InitProfilePreferences(user_profile, user_id);
-      break;
-    case Profile::CREATE_STATUS_INITIALIZED:
-      UserProfileInitialized(user_profile);
-      break;
-    case Profile::CREATE_STATUS_LOCAL_FAIL:
-    case Profile::CREATE_STATUS_REMOTE_FAIL:
-    case Profile::CREATE_STATUS_CANCELED:
-    case Profile::MAX_CREATE_STATUS:
-      NOTREACHED();
-      break;
-  }
-}
-
-void LoginUtilsImpl::OnOTRProfileCreated(
-    const std::string& user_id,
-    Profile* user_profile,
-    Profile::CreateStatus status) {
-  CHECK(user_profile);
-
-  switch (status) {
-    case Profile::CREATE_STATUS_CREATED:
-      InitProfilePreferences(user_profile, user_id);
-      break;
-    case Profile::CREATE_STATUS_INITIALIZED:
-      OTRProfileInitialized(user_profile);
-      break;
-    case Profile::CREATE_STATUS_LOCAL_FAIL:
-    case Profile::CREATE_STATUS_REMOTE_FAIL:
-    case Profile::CREATE_STATUS_CANCELED:
-    case Profile::MAX_CREATE_STATUS:
-      NOTREACHED();
-      break;
-  }
-}
-
-void LoginUtilsImpl::UserProfileInitialized(Profile* user_profile) {
-  BootTimesLoader* btl = BootTimesLoader::Get();
-  btl->AddLoginTimeMarker("UserProfileGotten", false);
-
-  if (user_context_.IsUsingOAuth()) {
-    // Transfer proxy authentication cache, cookies (optionally) and server
-    // bound certs from the profile that was used for authentication.  This
-    // profile contains cookies that auth extension should have already put in
-    // place that will ensure that the newly created session is authenticated
-    // for the websites that work with the used authentication schema.
-    ProfileAuthData::Transfer(authenticator_->authentication_profile(),
-                              user_profile,
-                              has_web_auth_cookies_,  // transfer_cookies
-                              base::Bind(
-                                  &LoginUtilsImpl::CompleteProfileCreate,
-                                  AsWeakPtr(),
-                                  user_profile));
-    return;
-  }
-
-  FinalizePrepareProfile(user_profile);
-}
-
-void LoginUtilsImpl::OTRProfileInitialized(Profile* user_profile) {
-  user_profile->OnLogin();
-  // Send the notification before creating the browser so additional objects
-  // that need the profile (e.g. the launcher) can be created first.
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
-      content::NotificationService::AllSources(),
-      content::Details<Profile>(user_profile));
-
-  if (delegate_)
-    delegate_->OnProfilePrepared(user_profile);
-}
-
-void LoginUtilsImpl::CompleteProfileCreate(Profile* user_profile) {
-  RestoreAuthSession(user_profile, has_web_auth_cookies_);
-  FinalizePrepareProfile(user_profile);
-}
-
-void LoginUtilsImpl::RestoreAuthSession(Profile* user_profile,
-                                        bool restore_from_auth_cookies) {
-  CHECK((authenticator_.get() && authenticator_->authentication_profile()) ||
-        !restore_from_auth_cookies);
-
-  if (chrome::IsRunningInForcedAppMode() ||
-      CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kOobeSkipPostLogin)) {
-    return;
-  }
-
-  exit_after_session_restore_ = false;
-  // Remove legacy OAuth1 token if we have one. If it's valid, we should already
-  // have OAuth2 refresh token in OAuth2TokenService that could be used to
-  // retrieve all other tokens and user_context.
-  OAuth2LoginManager* login_manager =
-      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
-  login_manager->AddObserver(this);
-  login_manager->RestoreSession(
-      authenticator_.get() && authenticator_->authentication_profile()
-          ? authenticator_->authentication_profile()->GetRequestContext()
-          : NULL,
-      session_restore_strategy_,
-      oauth2_refresh_token_,
-      user_context_.GetAuthCode());
-}
-
-void LoginUtilsImpl::FinalizePrepareProfile(Profile* user_profile) {
-  BootTimesLoader* btl = BootTimesLoader::Get();
-  // Own TPM device if, for any reason, it has not been done in EULA
-  // wizard screen.
-  CryptohomeClient* client = DBusThreadManager::Get()->GetCryptohomeClient();
-  btl->AddLoginTimeMarker("TPMOwn-Start", false);
-  if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) {
-    if (cryptohome_util::TpmIsOwned()) {
-      client->CallTpmClearStoredPasswordAndBlock();
-    } else {
-      client->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback());
-    }
-  }
-  btl->AddLoginTimeMarker("TPMOwn-End", false);
-
-  if (UserManager::Get()->IsLoggedInAsRegularUser()) {
-    SAMLOfflineSigninLimiter* saml_offline_signin_limiter =
-        SAMLOfflineSigninLimiterFactory::GetForProfile(user_profile);
-    if (saml_offline_signin_limiter)
-      saml_offline_signin_limiter->SignedIn(user_context_.GetAuthFlow());
-  }
-
-  user_profile->OnLogin();
-
-  // Send the notification before creating the browser so additional objects
-  // that need the profile (e.g. the launcher) can be created first.
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
-      content::NotificationService::AllSources(),
-      content::Details<Profile>(user_profile));
-
-  // Initialize RLZ only for primary user.
-  if (UserManager::Get()->GetPrimaryUser() ==
-      UserManager::Get()->GetUserByProfile(user_profile)) {
-    InitRlzDelayed(user_profile);
-  }
-  // TODO(altimofeev): This pointer should probably never be NULL, but it looks
-  // like LoginUtilsImpl::OnProfileCreated() may be getting called before
-  // LoginUtilsImpl::PrepareProfile() has set |delegate_| when Chrome is killed
-  // during shutdown in tests -- see http://crosbug.com/18269.  Replace this
-  // 'if' statement with a CHECK(delegate_) once the underlying issue is
-  // resolved.
-  if (delegate_)
-    delegate_->OnProfilePrepared(user_profile);
-}
-
-void LoginUtilsImpl::InitRlzDelayed(Profile* user_profile) {
-#if defined(ENABLE_RLZ)
-  if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand)) {
-    // Read brand code asynchronously from an OEM data and repost ourselves.
-    google_brand::chromeos::InitBrand(
-        base::Bind(&LoginUtilsImpl::InitRlzDelayed, AsWeakPtr(), user_profile));
-    return;
-  }
-  base::PostTaskAndReplyWithResult(
-      base::WorkerPool::GetTaskRunner(false),
-      FROM_HERE,
-      base::Bind(&base::PathExists, GetRlzDisabledFlagPath()),
-      base::Bind(&LoginUtilsImpl::InitRlz, AsWeakPtr(), user_profile));
-#endif
-}
-
-void LoginUtilsImpl::InitRlz(Profile* user_profile, bool disabled) {
-#if defined(ENABLE_RLZ)
-  PrefService* local_state = g_browser_process->local_state();
-  if (disabled) {
-    // Empty brand code means an organic install (no RLZ pings are sent).
-    google_brand::chromeos::ClearBrandForCurrentSession();
-  }
-  if (disabled != local_state->GetBoolean(prefs::kRLZDisabled)) {
-    // When switching to RLZ enabled/disabled state, clear all recorded events.
-    RLZTracker::ClearRlzState();
-    local_state->SetBoolean(prefs::kRLZDisabled, disabled);
-  }
-  // Init the RLZ library.
-  int ping_delay = user_profile->GetPrefs()->GetInteger(
-      first_run::GetPingDelayPrefName().c_str());
-  // Negative ping delay means to send ping immediately after a first search is
-  // recorded.
-  RLZTracker::InitRlzFromProfileDelayed(
-      user_profile, UserManager::Get()->IsCurrentUserNew(),
-      ping_delay < 0, base::TimeDelta::FromMilliseconds(abs(ping_delay)));
-  if (delegate_)
-    delegate_->OnRlzInitialized(user_profile);
-#endif
-}
-
 void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) {
   VLOG(1) << "Completing incognito login";
 
@@ -726,52 +342,6 @@
   RestartChrome(cmd_line_str);
 }
 
-void LoginUtilsImpl::SetFirstLoginPrefs(PrefService* prefs) {
-  VLOG(1) << "Setting first login prefs";
-  BootTimesLoader* btl = BootTimesLoader::Get();
-  std::string locale = g_browser_process->GetApplicationLocale();
-
-  // First, we'll set kLanguagePreloadEngines.
-  input_method::InputMethodManager* manager =
-      input_method::InputMethodManager::Get();
-  std::vector<std::string> input_method_ids;
-  manager->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
-      locale, manager->GetCurrentInputMethod(), &input_method_ids);
-  // Save the input methods in the user's preferences.
-  StringPrefMember language_preload_engines;
-  language_preload_engines.Init(prefs::kLanguagePreloadEngines,
-                                prefs);
-  language_preload_engines.SetValue(JoinString(input_method_ids, ','));
-  btl->AddLoginTimeMarker("IMEStarted", false);
-
-  // Second, we'll set kLanguagePreferredLanguages.
-  std::vector<std::string> language_codes;
-  // The current locale should be on the top.
-  language_codes.push_back(locale);
-
-  // Add input method IDs based on the input methods, as there may be
-  // input methods that are unrelated to the current locale. Example: the
-  // hardware keyboard layout xkb:us::eng is used for logging in, but the
-  // UI language is set to French. In this case, we should set "fr,en"
-  // to the preferred languages preference.
-  std::vector<std::string> candidates;
-  manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
-      input_method_ids, &candidates);
-  for (size_t i = 0; i < candidates.size(); ++i) {
-    const std::string& candidate = candidates[i];
-    // Skip if it's already in language_codes.
-    if (std::count(language_codes.begin(), language_codes.end(),
-                   candidate) == 0) {
-      language_codes.push_back(candidate);
-    }
-  }
-  // Save the preferred languages in the user's preferences.
-  StringPrefMember language_preferred_languages;
-  language_preferred_languages.Init(prefs::kLanguagePreferredLanguages,
-                                    prefs);
-  language_preferred_languages.SetValue(JoinString(language_codes, ','));
-}
-
 scoped_refptr<Authenticator> LoginUtilsImpl::CreateAuthenticator(
     LoginStatusConsumer* consumer) {
   // Screen locker needs new Authenticator instance each time.
@@ -790,118 +360,20 @@
   return authenticator_;
 }
 
-void LoginUtilsImpl::RestoreAuthenticationSession(Profile* user_profile) {
-  UserManager* user_manager = UserManager::Get();
-  // We don't need to restore session for demo/guest/stub/public account users.
-  if (!user_manager->IsUserLoggedIn() ||
-      user_manager->IsLoggedInAsGuest() ||
-      user_manager->IsLoggedInAsPublicAccount() ||
-      user_manager->IsLoggedInAsDemoUser() ||
-      user_manager->IsLoggedInAsStub()) {
-    return;
-  }
-
-  User* user = user_manager->GetUserByProfile(user_profile);
-  DCHECK(user);
-  if (!net::NetworkChangeNotifier::IsOffline()) {
-    pending_restore_sessions_.erase(user->email());
-    RestoreAuthSession(user_profile, false);
-  } else {
-    // Even if we're online we should wait till initial
-    // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
-    // end up canceling all request when initial network connection type is
-    // processed. See http://crbug.com/121643.
-    pending_restore_sessions_.insert(user->email());
-  }
+void LoginUtilsImpl::OnProfilePrepared(Profile* profile) {
+  if (delegate_)
+    delegate_->OnProfilePrepared(profile);
 }
 
-void LoginUtilsImpl::OnSessionRestoreStateChanged(
-    Profile* user_profile,
-    OAuth2LoginManager::SessionRestoreState state) {
-  User::OAuthTokenStatus user_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
-  OAuth2LoginManager* login_manager =
-      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
-
-  bool connection_error = false;
-  switch (state) {
-    case OAuth2LoginManager::SESSION_RESTORE_DONE:
-      user_status = User::OAUTH2_TOKEN_STATUS_VALID;
-      break;
-    case OAuth2LoginManager::SESSION_RESTORE_FAILED:
-      user_status = User::OAUTH2_TOKEN_STATUS_INVALID;
-      break;
-    case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED:
-      connection_error = true;
-      break;
-    case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
-    case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
-    case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
-      return;
-  }
-
-  // We should not be clearing existing token state if that was a connection
-  // error. http://crbug.com/295245
-  if (!connection_error) {
-    // We are in one of "done" states here.
-    UserManager::Get()->SaveUserOAuthStatus(
-        UserManager::Get()->GetLoggedInUser()->email(),
-        user_status);
-  }
-
-  login_manager->RemoveObserver(this);
+#if defined(ENABLE_RLZ)
+void LoginUtilsImpl::OnRlzInitialized() {
+  if (delegate_)
+    delegate_->OnRlzInitialized();
 }
-
-void LoginUtilsImpl::OnNewRefreshTokenAvaiable(Profile* user_profile) {
-  // Check if we were waiting to restart chrome.
-  if (!exit_after_session_restore_)
-    return;
-
-  OAuth2LoginManager* login_manager =
-      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
-  login_manager->RemoveObserver(this);
-
-  // Mark user auth token status as valid.
-  UserManager::Get()->SaveUserOAuthStatus(
-      UserManager::Get()->GetLoggedInUser()->email(),
-      User::OAUTH2_TOKEN_STATUS_VALID);
-
-  LOG(WARNING) << "Exiting after new refresh token fetched";
-  // We need to restart cleanly in this case to make sure OAuth2 RT is actually
-  // saved.
-  chrome::AttemptRestart();
-}
-
-void LoginUtilsImpl::OnConnectionTypeChanged(
-    net::NetworkChangeNotifier::ConnectionType type) {
-  UserManager* user_manager = UserManager::Get();
-  if (type == net::NetworkChangeNotifier::CONNECTION_NONE ||
-      user_manager->IsLoggedInAsGuest() || !user_manager->IsUserLoggedIn()) {
-    return;
-  }
-
-  // Need to iterate over all users and their OAuth2 session state.
-  const UserList& users = user_manager->GetLoggedInUsers();
-  for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
-    Profile* user_profile = user_manager->GetProfileByUser(*it);
-    bool should_restore_session =
-        pending_restore_sessions_.find((*it)->email()) !=
-            pending_restore_sessions_.end();
-    OAuth2LoginManager* login_manager =
-        OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
-    if (login_manager->state() ==
-            OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS) {
-      // If we come online for the first time after successful offline login,
-      // we need to kick off OAuth token verification process again.
-      login_manager->ContinueSessionRestore();
-    } else if (should_restore_session) {
-      pending_restore_sessions_.erase((*it)->email());
-      RestoreAuthSession(user_profile, has_web_auth_cookies_);
-    }
-  }
-}
+#endif
 
 void LoginUtilsImpl::AttemptRestart(Profile* profile) {
-  if (session_restore_strategy_ !=
+  if (SessionManager::GetInstance()->GetSigninSessionRestoreStrategy() !=
       OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR) {
     chrome::AttemptRestart();
     return;
@@ -920,15 +392,7 @@
   }
 
   LOG(WARNING) << "Attempting browser restart during session restore.";
-  exit_after_session_restore_ = true;
-}
-
-// static
-void LoginUtils::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
-  registry->RegisterBooleanPref(prefs::kRollbackRequested, false);
-  registry->RegisterStringPref(prefs::kRLZBrand, std::string());
-  registry->RegisterBooleanPref(prefs::kRLZDisabled, false);
+  SessionManager::GetInstance()->set_exit_after_session_restore(true);
 }
 
 // static
diff --git a/chrome/browser/chromeos/login/login_utils.h b/chrome/browser/chromeos/login/login_utils.h
index bda1e0a..4867cc2 100644
--- a/chrome/browser/chromeos/login/login_utils.h
+++ b/chrome/browser/chromeos/login/login_utils.h
@@ -10,7 +10,6 @@
 #include "base/memory/ref_counted.h"
 
 class GURL;
-class PrefRegistrySimple;
 class PrefService;
 class Profile;
 
@@ -34,15 +33,12 @@
 
 #if defined(ENABLE_RLZ)
     // Called after post-profile RLZ initialization.
-    virtual void OnRlzInitialized(Profile* profile) {}
+    virtual void OnRlzInitialized() {}
 #endif
    protected:
     virtual ~Delegate() {}
   };
 
-  // Registers log-in related preferences.
-  static void RegisterPrefs(PrefRegistrySimple* registry);
-
   // Get LoginUtils singleton object. If it was not set before, new default
   // instance will be created.
   static LoginUtils* Get();
@@ -64,15 +60,12 @@
                                LoginDisplayHost* login_host) = 0;
 
   // Loads and prepares profile for the session. Fires |delegate| in the end.
-  // If |display_email| is not empty, user's displayed email will be set to
-  // this value, shown in UI.
   // |user_context.username_hash| defines when user homedir is mounted.
   // Also see DelegateDeleted method.
   // If |has_active_session| is true than this is a case of restoring user
   // session after browser crash so no need to start new session.
   virtual void PrepareProfile(
       const UserContext& user_context,
-      const std::string& display_email,
       bool has_cookies,
       bool has_active_session,
       Delegate* delegate) = 0;
@@ -85,10 +78,6 @@
   // |start_url| is url for launched browser to open.
   virtual void CompleteOffTheRecordLogin(const GURL& start_url) = 0;
 
-  // Invoked when the user is logging in for the first time, or is logging in as
-  // a guest user.
-  virtual void SetFirstLoginPrefs(PrefService* prefs) = 0;
-
   // Creates and returns the authenticator to use.
   // Before WebUI login (Up to R14) the caller owned the returned
   // Authenticator instance and had to delete it when done.
@@ -100,12 +89,6 @@
   // TODO(nkostylev): Cleanup after WebUI login migration is complete.
   virtual scoped_refptr<Authenticator> CreateAuthenticator(
       LoginStatusConsumer* consumer) = 0;
-
-  // Restores authentication session after crash.
-  virtual void RestoreAuthenticationSession(Profile* profile) = 0;
-
-  // Initialize RLZ.
-  virtual void InitRlzDelayed(Profile* user_profile) = 0;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index 3acd197..f34d541e 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -358,7 +358,7 @@
   }
 
 #if defined(ENABLE_RLZ)
-  virtual void OnRlzInitialized(Profile* profile) OVERRIDE {
+  virtual void OnRlzInitialized() OVERRIDE {
     rlz_initialized_cb_.Run();
   }
 #endif
@@ -411,7 +411,6 @@
     const bool kHasActiveSession = false;
     user_context.SetAuthFlow(UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML);
     LoginUtils::Get()->PrepareProfile(user_context,
-                                      std::string(),
                                       kHasCookies,
                                       kHasActiveSession,
                                       this);
diff --git a/chrome/browser/chromeos/login/mock_login_utils.cc b/chrome/browser/chromeos/login/mock_login_utils.cc
index 2a63092b..e52c72e 100644
--- a/chrome/browser/chromeos/login/mock_login_utils.cc
+++ b/chrome/browser/chromeos/login/mock_login_utils.cc
@@ -21,7 +21,7 @@
   FakeLoginUtils* fake = fake_login_utils_.get();
   ON_CALL(*this, DoBrowserLaunch(_, _))
       .WillByDefault(Invoke(fake, &FakeLoginUtils::DoBrowserLaunch));
-  ON_CALL(*this, PrepareProfile(_, _, _, _, _))
+  ON_CALL(*this, PrepareProfile(_, _, _, _))
       .WillByDefault(Invoke(fake, &FakeLoginUtils::PrepareProfile));
   ON_CALL(*this, CreateAuthenticator(_))
       .WillByDefault(Invoke(fake, &FakeLoginUtils::CreateAuthenticator));
diff --git a/chrome/browser/chromeos/login/mock_login_utils.h b/chrome/browser/chromeos/login/mock_login_utils.h
index 636d8eb..f4f6e5c 100644
--- a/chrome/browser/chromeos/login/mock_login_utils.h
+++ b/chrome/browser/chromeos/login/mock_login_utils.h
@@ -31,21 +31,18 @@
   virtual ~MockLoginUtils();
 
   MOCK_METHOD2(DoBrowserLaunch, void(Profile*, LoginDisplayHost*));
-  MOCK_METHOD5(PrepareProfile,
-               void(const UserContext&, const std::string&,
+  MOCK_METHOD4(PrepareProfile,
+               void(const UserContext&,
                     bool, bool, LoginUtils::Delegate*));
   MOCK_METHOD1(DelegateDeleted, void(LoginUtils::Delegate*));
   MOCK_METHOD1(CompleteOffTheRecordLogin, void(const GURL&));
-  MOCK_METHOD1(SetFirstLoginPrefs, void(PrefService*));
   MOCK_METHOD1(CreateAuthenticator,
                scoped_refptr<Authenticator>(LoginStatusConsumer*));
-  MOCK_METHOD1(RestoreAuthenticationSession, void(Profile*));
   MOCK_METHOD1(StartTokenServices, void(Profile*));
   MOCK_METHOD2(TransferDefaultCookiesAndServerBoundCerts,
                void(Profile*, Profile*));
   MOCK_METHOD2(TransferDefaultAuthCache, void(Profile*, Profile*));
   MOCK_METHOD0(StopBackgroundFetchers, void(void));
-  MOCK_METHOD1(InitRlzDelayed, void(Profile*));
 
   void DelegateToFake();
   FakeLoginUtils* GetFakeLoginUtils();
diff --git a/chrome/browser/chromeos/login/session/session_manager.cc b/chrome/browser/chromeos/login/session/session_manager.cc
new file mode 100644
index 0000000..b54c7c00
--- /dev/null
+++ b/chrome/browser/chromeos/login/session/session_manager.cc
@@ -0,0 +1,578 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/session/session_manager.h"
+
+#include <string>
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_member.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string16.h"
+#include "base/sys_info.h"
+#include "base/task_runner_util.h"
+#include "base/threading/worker_pool.h"
+#include "chrome/browser/app_mode/app_mode_utils.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/boot_times_loader.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
+#include "chrome/browser/chromeos/login/profile_auth_data.h"
+#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
+#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
+#include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
+#include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
+#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
+#include "chrome/browser/chromeos/login/users/user.h"
+#include "chrome/browser/chromeos/login/users/user_manager.h"
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/google/google_brand_chromeos.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/rlz/rlz.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
+#include "chromeos/dbus/cryptohome_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/session_manager_client.h"
+#include "chromeos/ime/input_method_manager.h"
+#include "components/signin/core/browser/signin_manager_base.h"
+#include "content/public/browser/notification_service.h"
+
+namespace chromeos {
+
+namespace {
+
+void InitLocaleAndInputMethodsForNewUser(PrefService* prefs) {
+  // First, we'll set kLanguagePreloadEngines.
+  std::string locale = g_browser_process->GetApplicationLocale();
+  input_method::InputMethodManager* manager =
+      input_method::InputMethodManager::Get();
+  std::vector<std::string> input_method_ids;
+  manager->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
+      locale, manager->GetCurrentInputMethod(), &input_method_ids);
+
+  // Save the input methods in the user's preferences.
+  StringPrefMember language_preload_engines;
+  language_preload_engines.Init(prefs::kLanguagePreloadEngines, prefs);
+  language_preload_engines.SetValue(JoinString(input_method_ids, ','));
+  BootTimesLoader::Get()->AddLoginTimeMarker("IMEStarted", false);
+
+  // Second, we'll set kLanguagePreferredLanguages.
+  std::vector<std::string> language_codes;
+
+  // The current locale should be on the top.
+  language_codes.push_back(locale);
+
+  // Add input method IDs based on the input methods, as there may be
+  // input methods that are unrelated to the current locale. Example: the
+  // hardware keyboard layout xkb:us::eng is used for logging in, but the
+  // UI language is set to French. In this case, we should set "fr,en"
+  // to the preferred languages preference.
+  std::vector<std::string> candidates;
+  manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
+      input_method_ids, &candidates);
+  for (size_t i = 0; i < candidates.size(); ++i) {
+    const std::string& candidate = candidates[i];
+    // Skip if it's already in language_codes.
+    if (std::count(language_codes.begin(), language_codes.end(),
+                   candidate) == 0) {
+      language_codes.push_back(candidate);
+    }
+  }
+
+  // Save the preferred languages in the user's preferences.
+  StringPrefMember language_preferred_languages;
+  language_preferred_languages.Init(prefs::kLanguagePreferredLanguages, prefs);
+  language_preferred_languages.SetValue(JoinString(language_codes, ','));
+}
+
+#if defined(ENABLE_RLZ)
+// Flag file that disables RLZ tracking, when present.
+const base::FilePath::CharType kRLZDisabledFlagName[] =
+    FILE_PATH_LITERAL(".rlz_disabled");
+
+base::FilePath GetRlzDisabledFlagPath() {
+  base::FilePath homedir;
+  PathService::Get(base::DIR_HOME, &homedir);
+  return homedir.Append(kRLZDisabledFlagName);
+}
+#endif
+
+}  // namespace
+
+// static
+SessionManager* SessionManager::GetInstance() {
+  return Singleton<SessionManager,
+      DefaultSingletonTraits<SessionManager> >::get();
+}
+
+// static
+void SessionManager::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterStringPref(prefs::kRLZBrand, std::string());
+  registry->RegisterBooleanPref(prefs::kRLZDisabled, false);
+}
+
+SessionManager::SessionManager()
+    : delegate_(NULL),
+      has_web_auth_cookies_(false),
+      exit_after_session_restore_(false),
+      session_restore_strategy_(
+          OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN) {
+  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+}
+
+SessionManager::~SessionManager() {
+  net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
+}
+
+void SessionManager::OnSessionRestoreStateChanged(
+    Profile* user_profile,
+    OAuth2LoginManager::SessionRestoreState state) {
+  User::OAuthTokenStatus user_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
+  OAuth2LoginManager* login_manager =
+      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
+
+  bool connection_error = false;
+  switch (state) {
+    case OAuth2LoginManager::SESSION_RESTORE_DONE:
+      user_status = User::OAUTH2_TOKEN_STATUS_VALID;
+      break;
+    case OAuth2LoginManager::SESSION_RESTORE_FAILED:
+      user_status = User::OAUTH2_TOKEN_STATUS_INVALID;
+      break;
+    case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED:
+      connection_error = true;
+      break;
+    case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
+    case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
+    case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
+      return;
+  }
+
+  // We should not be clearing existing token state if that was a connection
+  // error. http://crbug.com/295245
+  if (!connection_error) {
+    // We are in one of "done" states here.
+    UserManager::Get()->SaveUserOAuthStatus(
+        UserManager::Get()->GetLoggedInUser()->email(),
+        user_status);
+  }
+
+  login_manager->RemoveObserver(this);
+}
+
+void SessionManager::OnNewRefreshTokenAvaiable(Profile* user_profile) {
+  // Check if we were waiting to restart chrome.
+  if (!exit_after_session_restore_)
+    return;
+
+  OAuth2LoginManager* login_manager =
+      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
+  login_manager->RemoveObserver(this);
+
+  // Mark user auth token status as valid.
+  UserManager::Get()->SaveUserOAuthStatus(
+      UserManager::Get()->GetLoggedInUser()->email(),
+      User::OAUTH2_TOKEN_STATUS_VALID);
+
+  LOG(WARNING) << "Exiting after new refresh token fetched";
+
+  // We need to restart cleanly in this case to make sure OAuth2 RT is actually
+  // saved.
+  chrome::AttemptRestart();
+}
+
+void SessionManager::OnConnectionTypeChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  UserManager* user_manager = UserManager::Get();
+  if (type == net::NetworkChangeNotifier::CONNECTION_NONE ||
+      user_manager->IsLoggedInAsGuest() || !user_manager->IsUserLoggedIn()) {
+    return;
+  }
+
+  // Need to iterate over all users and their OAuth2 session state.
+  const UserList& users = user_manager->GetLoggedInUsers();
+  for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
+    Profile* user_profile = user_manager->GetProfileByUser(*it);
+    bool should_restore_session =
+        pending_restore_sessions_.find((*it)->email()) !=
+            pending_restore_sessions_.end();
+    OAuth2LoginManager* login_manager =
+        OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
+    if (login_manager->state() ==
+            OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS) {
+      // If we come online for the first time after successful offline login,
+      // we need to kick off OAuth token verification process again.
+      login_manager->ContinueSessionRestore();
+    } else if (should_restore_session) {
+      pending_restore_sessions_.erase((*it)->email());
+      RestoreAuthSessionImpl(user_profile, has_web_auth_cookies_);
+    }
+  }
+}
+
+void SessionManager::StartSession(const UserContext& user_context,
+                                  scoped_refptr<Authenticator> authenticator,
+                                  bool has_cookies,
+                                  bool has_active_session,
+                                  Delegate* delegate) {
+  authenticator_ = authenticator;
+  delegate_ = delegate;
+
+  VLOG(1) << "Starting session for " << user_context.GetUserID();
+
+  PreStartSession();
+  CreateUserSession(user_context, has_cookies);
+
+  if (!has_active_session)
+    StartCrosSession();
+
+  // TODO(nkostylev): Notify UserLoggedIn() after profile is actually
+  // ready to be used (http://crbug.com/361528).
+  NotifyUserLoggedIn();
+  PrepareProfile();
+}
+
+void SessionManager::RestoreAuthenticationSession(Profile* user_profile) {
+  UserManager* user_manager = UserManager::Get();
+  // We don't need to restore session for demo/guest/stub/public account users.
+  if (!user_manager->IsUserLoggedIn() ||
+      user_manager->IsLoggedInAsGuest() ||
+      user_manager->IsLoggedInAsPublicAccount() ||
+      user_manager->IsLoggedInAsDemoUser() ||
+      user_manager->IsLoggedInAsStub()) {
+    return;
+  }
+
+  User* user = user_manager->GetUserByProfile(user_profile);
+  DCHECK(user);
+  if (!net::NetworkChangeNotifier::IsOffline()) {
+    pending_restore_sessions_.erase(user->email());
+    RestoreAuthSessionImpl(user_profile, false);
+  } else {
+    // Even if we're online we should wait till initial
+    // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
+    // end up canceling all request when initial network connection type is
+    // processed. See http://crbug.com/121643.
+    pending_restore_sessions_.insert(user->email());
+  }
+}
+
+void SessionManager::InitRlz(Profile* profile) {
+#if defined(ENABLE_RLZ)
+  if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand)) {
+    // Read brand code asynchronously from an OEM data and repost ourselves.
+    google_brand::chromeos::InitBrand(
+        base::Bind(&SessionManager::InitRlz, AsWeakPtr(), profile));
+    return;
+  }
+  base::PostTaskAndReplyWithResult(
+      base::WorkerPool::GetTaskRunner(false),
+      FROM_HERE,
+      base::Bind(&base::PathExists, GetRlzDisabledFlagPath()),
+      base::Bind(&SessionManager::InitRlzImpl, AsWeakPtr(), profile));
+#endif
+}
+
+OAuth2LoginManager::SessionRestoreStrategy
+SessionManager::GetSigninSessionRestoreStrategy() {
+  return session_restore_strategy_;
+}
+
+// static
+void SessionManager::SetFirstLoginPrefs(PrefService* prefs) {
+  VLOG(1) << "Setting first login prefs";
+  InitLocaleAndInputMethodsForNewUser(prefs);
+}
+
+void SessionManager::CreateUserSession(const UserContext& user_context,
+                                       bool has_cookies) {
+  user_context_ = user_context;
+  has_web_auth_cookies_ = has_cookies;
+  InitSessionRestoreStrategy();
+}
+
+void SessionManager::PreStartSession() {
+  // Switch log file as soon as possible.
+  if (base::SysInfo::IsRunningOnChromeOS())
+    logging::RedirectChromeLogging(*(CommandLine::ForCurrentProcess()));
+}
+
+void SessionManager::StartCrosSession() {
+  BootTimesLoader* btl = BootTimesLoader::Get();
+  btl->AddLoginTimeMarker("StartSession-Start", false);
+  DBusThreadManager::Get()->GetSessionManagerClient()->
+      StartSession(user_context_.GetUserID());
+  btl->AddLoginTimeMarker("StartSession-End", false);
+}
+
+void SessionManager:: NotifyUserLoggedIn() {
+  BootTimesLoader* btl = BootTimesLoader::Get();
+  btl->AddLoginTimeMarker("UserLoggedIn-Start", false);
+  UserManager* user_manager = UserManager::Get();
+  user_manager->UserLoggedIn(user_context_.GetUserID(),
+                             user_context_.GetUserIDHash(),
+                             false);
+  btl->AddLoginTimeMarker("UserLoggedIn-End", false);
+}
+
+void SessionManager::PrepareProfile() {
+  UserManager* user_manager = UserManager::Get();
+  bool is_demo_session =
+      DemoAppLauncher::IsDemoAppSession(user_context_.GetUserID());
+
+  // TODO(nkostylev): Figure out whether demo session is using the right profile
+  // path or not. See https://codereview.chromium.org/171423009
+  g_browser_process->profile_manager()->CreateProfileAsync(
+      user_manager->GetUserProfileDir(user_context_.GetUserID()),
+      base::Bind(&SessionManager::OnProfileCreated, AsWeakPtr(),
+                 user_context_.GetUserID(), is_demo_session),
+      base::string16(), base::string16(), std::string());
+}
+
+void SessionManager::OnProfileCreated(const std::string& user_id,
+                                      bool is_incognito_profile,
+                                      Profile* profile,
+                                      Profile::CreateStatus status) {
+  CHECK(profile);
+
+  switch (status) {
+    case Profile::CREATE_STATUS_CREATED:
+      // Profile created but before initializing extensions and promo resources.
+      InitProfilePreferences(profile, user_id);
+      break;
+    case Profile::CREATE_STATUS_INITIALIZED:
+      // Profile is created, extensions and promo resources are initialized.
+      // At this point all other Chrome OS services will be notified that it is
+      // safe to use this profile.
+      UserProfileInitialized(profile, is_incognito_profile);
+      break;
+    case Profile::CREATE_STATUS_LOCAL_FAIL:
+    case Profile::CREATE_STATUS_REMOTE_FAIL:
+    case Profile::CREATE_STATUS_CANCELED:
+    case Profile::MAX_CREATE_STATUS:
+      NOTREACHED();
+      break;
+  }
+}
+
+void SessionManager::InitProfilePreferences(Profile* profile,
+                                            const std::string& user_id) {
+  if (UserManager::Get()->IsCurrentUserNew())
+    SetFirstLoginPrefs(profile->GetPrefs());
+
+  if (UserManager::Get()->IsLoggedInAsLocallyManagedUser()) {
+    User* active_user = UserManager::Get()->GetActiveUser();
+    std::string managed_user_sync_id =
+        UserManager::Get()->GetSupervisedUserManager()->
+            GetUserSyncId(active_user->email());
+    profile->GetPrefs()->SetString(prefs::kSupervisedUserId,
+                                   managed_user_sync_id);
+  } else if (UserManager::Get()->IsLoggedInAsRegularUser()) {
+    // Make sure that the google service username is properly set (we do this
+    // on every sign in, not just the first login, to deal with existing
+    // profiles that might not have it set yet).
+    SigninManagerBase* signin_manager =
+        SigninManagerFactory::GetForProfile(profile);
+    signin_manager->SetAuthenticatedUsername(user_id);
+  }
+}
+
+void SessionManager::UserProfileInitialized(Profile* profile,
+                                            bool is_incognito_profile) {
+  if (is_incognito_profile) {
+    profile->OnLogin();
+    // Send the notification before creating the browser so additional objects
+    // that need the profile (e.g. the launcher) can be created first.
+    content::NotificationService::current()->Notify(
+        chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
+        content::NotificationService::AllSources(),
+        content::Details<Profile>(profile));
+
+    if (delegate_)
+      delegate_->OnProfilePrepared(profile);
+
+    return;
+  }
+
+  BootTimesLoader* btl = BootTimesLoader::Get();
+  btl->AddLoginTimeMarker("UserProfileGotten", false);
+
+  if (user_context_.IsUsingOAuth()) {
+    // Transfer proxy authentication cache, cookies (optionally) and server
+    // bound certs from the profile that was used for authentication.  This
+    // profile contains cookies that auth extension should have already put in
+    // place that will ensure that the newly created session is authenticated
+    // for the websites that work with the used authentication schema.
+    ProfileAuthData::Transfer(
+        authenticator_->authentication_profile(),
+        profile,
+        has_web_auth_cookies_,  // transfer_cookies
+        base::Bind(&SessionManager::CompleteProfileCreateAfterAuthTransfer,
+                   AsWeakPtr(),
+                   profile));
+    return;
+  }
+
+  FinalizePrepareProfile(profile);
+}
+
+void SessionManager::CompleteProfileCreateAfterAuthTransfer(Profile* profile) {
+  RestoreAuthSessionImpl(profile, has_web_auth_cookies_);
+  FinalizePrepareProfile(profile);
+}
+
+void SessionManager::FinalizePrepareProfile(Profile* profile) {
+  BootTimesLoader* btl = BootTimesLoader::Get();
+
+  // Own TPM device if, for any reason, it has not been done in EULA screen.
+  CryptohomeClient* client = DBusThreadManager::Get()->GetCryptohomeClient();
+  btl->AddLoginTimeMarker("TPMOwn-Start", false);
+  if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) {
+    if (cryptohome_util::TpmIsOwned()) {
+      client->CallTpmClearStoredPasswordAndBlock();
+    } else {
+      client->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback());
+    }
+  }
+  btl->AddLoginTimeMarker("TPMOwn-End", false);
+
+  UserManager* user_manager = UserManager::Get();
+  if (user_manager->IsLoggedInAsRegularUser()) {
+    SAMLOfflineSigninLimiter* saml_offline_signin_limiter =
+        SAMLOfflineSigninLimiterFactory::GetForProfile(profile);
+    if (saml_offline_signin_limiter)
+      saml_offline_signin_limiter->SignedIn(user_context_.GetAuthFlow());
+  }
+
+  profile->OnLogin();
+
+  // Send the notification before creating the browser so additional objects
+  // that need the profile (e.g. the launcher) can be created first.
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
+      content::NotificationService::AllSources(),
+      content::Details<Profile>(profile));
+
+  // Initialize RLZ only for primary user.
+  if (user_manager->GetPrimaryUser() ==
+      user_manager->GetUserByProfile(profile)) {
+    InitRlz(profile);
+  }
+
+  // TODO(altimofeev): This pointer should probably never be NULL, but it looks
+  // like LoginUtilsImpl::OnProfileCreated() may be getting called before
+  // SessionManager::PrepareProfile() has set |delegate_| when Chrome is killed
+  // during shutdown in tests -- see http://crosbug.com/18269.  Replace this
+  // 'if' statement with a CHECK(delegate_) once the underlying issue is
+  // resolved.
+  if (delegate_)
+    delegate_->OnProfilePrepared(profile);
+}
+
+void SessionManager::InitSessionRestoreStrategy() {
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  bool in_app_mode = chrome::IsRunningInForcedAppMode();
+
+  // Are we in kiosk app mode?
+  if (in_app_mode) {
+    if (command_line->HasSwitch(::switches::kAppModeOAuth2Token)) {
+      oauth2_refresh_token_ = command_line->GetSwitchValueASCII(
+          ::switches::kAppModeOAuth2Token);
+    }
+
+    if (command_line->HasSwitch(::switches::kAppModeAuthCode)) {
+      user_context_.SetAuthCode(command_line->GetSwitchValueASCII(
+          ::switches::kAppModeAuthCode));
+    }
+
+    DCHECK(!has_web_auth_cookies_);
+    if (!user_context_.GetAuthCode().empty()) {
+      session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
+    } else if (!oauth2_refresh_token_.empty()) {
+      session_restore_strategy_ =
+          OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN;
+    } else {
+      session_restore_strategy_ =
+          OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
+    }
+    return;
+  }
+
+  if (has_web_auth_cookies_) {
+    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR;
+  } else if (!user_context_.GetAuthCode().empty()) {
+    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
+  } else {
+    session_restore_strategy_ =
+        OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
+  }
+}
+
+void SessionManager::RestoreAuthSessionImpl(Profile* profile,
+                                            bool restore_from_auth_cookies) {
+  CHECK((authenticator_.get() && authenticator_->authentication_profile()) ||
+        !restore_from_auth_cookies);
+
+  if (chrome::IsRunningInForcedAppMode() ||
+      CommandLine::ForCurrentProcess()->HasSwitch(
+          chromeos::switches::kOobeSkipPostLogin)) {
+    return;
+  }
+
+  exit_after_session_restore_ = false;
+
+  // Remove legacy OAuth1 token if we have one. If it's valid, we should already
+  // have OAuth2 refresh token in OAuth2TokenService that could be used to
+  // retrieve all other tokens and user_context.
+  OAuth2LoginManager* login_manager =
+      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile);
+  login_manager->AddObserver(this);
+  login_manager->RestoreSession(
+      authenticator_.get() && authenticator_->authentication_profile()
+          ? authenticator_->authentication_profile()->GetRequestContext()
+          : NULL,
+      session_restore_strategy_,
+      oauth2_refresh_token_,
+      user_context_.GetAuthCode());
+}
+
+void SessionManager::InitRlzImpl(Profile* profile, bool disabled) {
+#if defined(ENABLE_RLZ)
+  PrefService* local_state = g_browser_process->local_state();
+  if (disabled) {
+    // Empty brand code means an organic install (no RLZ pings are sent).
+    google_brand::chromeos::ClearBrandForCurrentSession();
+  }
+  if (disabled != local_state->GetBoolean(prefs::kRLZDisabled)) {
+    // When switching to RLZ enabled/disabled state, clear all recorded events.
+    RLZTracker::ClearRlzState();
+    local_state->SetBoolean(prefs::kRLZDisabled, disabled);
+  }
+  // Init the RLZ library.
+  int ping_delay = profile->GetPrefs()->GetInteger(
+      first_run::GetPingDelayPrefName().c_str());
+  // Negative ping delay means to send ping immediately after a first search is
+  // recorded.
+  RLZTracker::InitRlzFromProfileDelayed(
+      profile, UserManager::Get()->IsCurrentUserNew(),
+      ping_delay < 0, base::TimeDelta::FromMilliseconds(abs(ping_delay)));
+  if (delegate_)
+    delegate_->OnRlzInitialized();
+#endif
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/session/session_manager.h b/chrome/browser/chromeos/login/session/session_manager.h
new file mode 100644
index 0000000..8e5a55dd
--- /dev/null
+++ b/chrome/browser/chromeos/login/session/session_manager.h
@@ -0,0 +1,169 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_SESSION_MANAGER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_SESSION_MANAGER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/login/auth/authenticator.h"
+#include "chrome/browser/chromeos/login/auth/user_context.h"
+#include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
+#include "net/base/network_change_notifier.h"
+
+class PrefRegistrySimple;
+class PrefService;
+class Profile;
+
+namespace chromeos {
+
+// SessionManager is responsible for starting user session which includes:
+// load and initialize Profile (including custom Profile preferences),
+// mark user as logged in and notify observers,
+// initialize OAuth2 authentication session,
+// initialize and launch user session based on the user type.
+class SessionManager :
+    public OAuth2LoginManager::Observer,
+    public net::NetworkChangeNotifier::ConnectionTypeObserver,
+    public base::SupportsWeakPtr<SessionManager> {
+ public:
+  class Delegate {
+   public:
+    // Called after profile is loaded and prepared for the session.
+    virtual void OnProfilePrepared(Profile* profile) = 0;
+
+#if defined(ENABLE_RLZ)
+    // Called after post-profile RLZ initialization.
+    virtual void OnRlzInitialized() {}
+#endif
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  // Returns SessionManager instance.
+  static SessionManager* GetInstance();
+
+  // Registers session related preferences.
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+  // OAuth2LoginManager::Observer overrides:
+  virtual void OnSessionRestoreStateChanged(
+      Profile* user_profile,
+      OAuth2LoginManager::SessionRestoreState state) OVERRIDE;
+  virtual void OnNewRefreshTokenAvaiable(Profile* user_profile) OVERRIDE;
+
+  // net::NetworkChangeNotifier::ConnectionTypeObserver overrides:
+  virtual void OnConnectionTypeChanged(
+      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
+
+  // Start user session given |user_context| and |authenticator| which holds
+  // authentication context (profile).
+  void StartSession(const UserContext& user_context,
+                    scoped_refptr<Authenticator> authenticator,
+                    bool has_cookies,
+                    bool has_active_session,
+                    Delegate* delegate);
+
+  // Restores authentication session after crash.
+  void RestoreAuthenticationSession(Profile* profile);
+
+  // Initialize RLZ.
+  void InitRlz(Profile* profile);
+
+  // TODO(nkostylev): Drop these methods once LoginUtilsImpl::AttemptRestart()
+  // is migrated.
+  OAuth2LoginManager::SessionRestoreStrategy GetSigninSessionRestoreStrategy();
+  bool exit_after_session_restore() { return exit_after_session_restore_; }
+  void set_exit_after_session_restore(bool value) {
+    exit_after_session_restore_ = value;
+  }
+
+  // Invoked when the user is logging in for the first time, or is logging in as
+  // a guest user.
+  static void SetFirstLoginPrefs(PrefService* prefs);
+
+ private:
+  friend struct DefaultSingletonTraits<SessionManager>;
+
+  typedef std::set<std::string> SessionRestoreStateSet;
+
+  SessionManager();
+  virtual ~SessionManager();
+
+  void CreateUserSession(const UserContext& user_context,
+                         bool has_cookies);
+  void PreStartSession();
+  void StartCrosSession();
+  void NotifyUserLoggedIn();
+  void PrepareProfile();
+
+  // Callback for asynchronous profile creation.
+  void OnProfileCreated(const std::string& user_id,
+                        bool is_incognito_profile,
+                        Profile* profile,
+                        Profile::CreateStatus status);
+
+  // Callback for Profile::CREATE_STATUS_CREATED profile state.
+  // Initializes basic preferences for newly created profile. Any other
+  // early profile initialization that needs to happen before
+  // ProfileManager::DoFinalInit() gets called is done here.
+  void InitProfilePreferences(Profile* profile,
+                              const std::string& email);
+
+  // Callback for Profile::CREATE_STATUS_INITIALIZED profile state.
+  // Profile is created, extensions and promo resources are initialized.
+  void UserProfileInitialized(Profile* profile, bool is_incognito_profile);
+
+  // Callback to resume profile creation after transferring auth data from
+  // the authentication profile.
+  void CompleteProfileCreateAfterAuthTransfer(Profile* profile);
+
+  // Finalized profile preparation.
+  void FinalizePrepareProfile(Profile* profile);
+
+  // Initializes member variables needed for session restore process via
+  // OAuthLoginManager.
+  void InitSessionRestoreStrategy();
+
+  // Restores GAIA auth cookies for the created user profile from OAuth2 token.
+  void RestoreAuthSessionImpl(Profile* profile,
+                              bool restore_from_auth_cookies);
+
+  // Initializes RLZ. If |disabled| is true, RLZ pings are disabled.
+  void InitRlzImpl(Profile* profile, bool disabled);
+
+  Delegate* delegate_;
+
+  // Authentication/user context.
+  UserContext user_context_;
+  scoped_refptr<Authenticator> authenticator_;
+
+  // True if the authentication context cookie jar should contain
+  // authentication cookies from the authentication extension log in flow.
+  bool has_web_auth_cookies_;
+
+  // OAuth2 session related members.
+
+  // True if we should restart chrome right after session restore.
+  bool exit_after_session_restore_;
+
+  // Sesion restore strategy.
+  OAuth2LoginManager::SessionRestoreStrategy session_restore_strategy_;
+
+  // OAuth2 refresh token for session restore.
+  std::string oauth2_refresh_token_;
+
+  // Set of user_id for those users that we should restore authentication
+  // session when notified about online state change.
+  SessionRestoreStateSet pending_restore_sessions_;
+
+  DISALLOW_COPY_AND_ASSIGN(SessionManager);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_SESSION_MANAGER_H_
diff --git a/chrome/browser/chromeos/login/test_login_utils.cc b/chrome/browser/chromeos/login/test_login_utils.cc
index b673acac..55ecf07 100644
--- a/chrome/browser/chromeos/login/test_login_utils.cc
+++ b/chrome/browser/chromeos/login/test_login_utils.cc
@@ -18,7 +18,6 @@
 
 void TestLoginUtils::PrepareProfile(
     const UserContext& user_context,
-    const std::string& display_email,
     bool has_cookies,
     bool has_active_session,
     Delegate* delegate) {
@@ -36,7 +35,4 @@
   return new MockAuthenticator(consumer, expected_user_context_);
 }
 
-void TestLoginUtils::InitRlzDelayed(Profile* user_profile) {
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test_login_utils.h b/chrome/browser/chromeos/login/test_login_utils.h
index dc1dc12..ba88f81 100644
--- a/chrome/browser/chromeos/login/test_login_utils.h
+++ b/chrome/browser/chromeos/login/test_login_utils.h
@@ -27,17 +27,13 @@
   virtual void DoBrowserLaunch(Profile* profile,
                                LoginDisplayHost* login_host) OVERRIDE {}
   virtual void PrepareProfile(const UserContext& user_context,
-                              const std::string& display_email,
                               bool has_cookies,
                               bool has_active_session,
                               Delegate* delegate) OVERRIDE;
   virtual void DelegateDeleted(Delegate* delegate) OVERRIDE;
   virtual void CompleteOffTheRecordLogin(const GURL& start_url) OVERRIDE {}
-  virtual void SetFirstLoginPrefs(PrefService* prefs) OVERRIDE {}
   virtual scoped_refptr<Authenticator> CreateAuthenticator(
       LoginStatusConsumer* consumer) OVERRIDE;
-  virtual void RestoreAuthenticationSession(Profile* profile) OVERRIDE {}
-  virtual void InitRlzDelayed(Profile* user_profile) OVERRIDE;
 
  private:
   UserContext expected_user_context_;
diff --git a/chrome/browser/chromeos/login/users/user_manager_impl.cc b/chrome/browser/chromeos/login/users/user_manager_impl.cc
index ed8bbdd..a776a12 100644
--- a/chrome/browser/chromeos/login/users/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/user_manager_impl.cc
@@ -35,6 +35,7 @@
 #include "chrome/browser/chromeos/login/auth/user_context.h"
 #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/login/session/session_manager.h"
 #include "chrome/browser/chromeos/login/signin/auth_sync_observer.h"
 #include "chrome/browser/chromeos/login/signin/auth_sync_observer_factory.h"
 #include "chrome/browser/chromeos/login/ui/login_display.h"
@@ -1200,7 +1201,7 @@
     // users once it is fully multi-profile aware. http://crbug.com/238987
     // For now if we have other user pending sessions they'll override OAuth
     // session restore for previous users.
-    LoginUtils::Get()->RestoreAuthenticationSession(profile);
+    SessionManager::GetInstance()->RestoreAuthenticationSession(profile);
   }
 
   // Restore other user sessions if any.
@@ -2038,7 +2039,6 @@
     user_context.SetIsUsingOAuth(false);
     // Will call OnProfilePrepared() once profile has been loaded.
     LoginUtils::Get()->PrepareProfile(user_context,
-                                      std::string(),  // display_email
                                       false,          // has_cookies
                                       true,           // has_active_session
                                       this);
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 4237c879..97e0f97 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -24,7 +24,7 @@
 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/login/session/session_manager.h"
 #include "chrome/browser/chromeos/login/users/user.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
 #include "chrome/browser/download/download_prefs.h"
@@ -362,10 +362,10 @@
   ApplyPreferences(REASON_INITIALIZATION, "");
 
   // If a guest is logged in, initialize the prefs as if this is the first
-  // login.
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) {
-    LoginUtils::Get()->SetFirstLoginPrefs(prefs);
-  }
+  // login. For a regular user this is done in
+  // SessionManager::InitProfilePreferences().
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession))
+    SessionManager::SetFirstLoginPrefs(prefs);
 }
 
 void Preferences::InitUserPrefsForTesting(PrefServiceSyncable* prefs,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 9a241528..a2e5a62 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -144,8 +144,8 @@
 #include "chrome/browser/chromeos/file_system_provider/service.h"
 #include "chrome/browser/chromeos/first_run/first_run.h"
 #include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
-#include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
+#include "chrome/browser/chromeos/login/session/session_manager.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
 #include "chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h"
@@ -170,6 +170,7 @@
 #include "chrome/browser/ui/webui/chromeos/charger_replacement_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/network_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #else
 #include "chrome/browser/extensions/default_apps.h"
@@ -296,14 +297,15 @@
   chromeos::default_pinned_apps_field_trial::RegisterPrefs(registry);
   chromeos::language_prefs::RegisterPrefs(registry);
   chromeos::KioskAppManager::RegisterPrefs(registry);
-  chromeos::LoginUtils::RegisterPrefs(registry);
   chromeos::MultiProfileUserController::RegisterPrefs(registry);
   chromeos::HIDDetectionScreenHandler::RegisterPrefs(registry);
   chromeos::NetworkScreenHandler::RegisterPrefs(registry);
   chromeos::Preferences::RegisterPrefs(registry);
   chromeos::proxy_config::RegisterPrefs(registry);
   chromeos::RegisterDisplayLocalStatePrefs(registry);
+  chromeos::ResetScreenHandler::RegisterPrefs(registry);
   chromeos::ServicesCustomizationDocument::RegisterPrefs(registry);
+  chromeos::SessionManager::RegisterPrefs(registry);
   chromeos::SigninScreenHandler::RegisterPrefs(registry);
   chromeos::system::AutomaticRebootManager::RegisterPrefs(registry);
   chromeos::UserImageManager::RegisterPrefs(registry);
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
index 5d89932..da3063a 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
@@ -14,6 +14,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/histogram.h"
+#include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -223,6 +224,12 @@
   ShowWithParams();
 }
 
+// static
+void ResetScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
+  registry->RegisterBooleanPref(prefs::kRollbackRequested, false);
+}
+
 void ResetScreenHandler::Initialize() {
   if (!page_is_ready() || !delegate_)
     return;
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
index 3a69333..67fb01e 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
@@ -14,6 +14,8 @@
 #include "chromeos/dbus/update_engine_client.h"
 #include "content/public/browser/web_ui.h"
 
+class PrefRegistrySimple;
+
 namespace chromeos {
 
 // WebUI implementation of ResetScreenActor.
@@ -43,6 +45,9 @@
 
   void OnRollbackCheck(bool can_rollback);
 
+  // Registers Local State preferences.
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
  private:
   // JS messages handlers.
   void HandleOnCancel();
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 3e1d59d..b0ecfcc 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -634,6 +634,8 @@
         'browser/chromeos/login/screens/wrong_hwid_screen.cc',
         'browser/chromeos/login/screens/wrong_hwid_screen.h',
         'browser/chromeos/login/screens/wrong_hwid_screen_actor.h',
+        'browser/chromeos/login/session/session_manager.cc',
+        'browser/chromeos/login/session/session_manager.h',
         'browser/chromeos/login/signin/auth_sync_observer.cc',
         'browser/chromeos/login/signin/auth_sync_observer.h',
         'browser/chromeos/login/signin/auth_sync_observer_factory.cc',