Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / signin / signin_manager.cc
index 2279e46..7af881b 100644 (file)
@@ -7,8 +7,6 @@
 #include <string>
 #include <vector>
 
-#include "base/command_line.h"
-#include "base/memory/ref_counted.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile_io_data.h"
-#include "chrome/browser/signin/about_signin_internals.h"
-#include "chrome/browser/signin/about_signin_internals_factory.h"
-#include "chrome/browser/signin/local_auth.h"
-#include "chrome/browser/signin/signin_global_error.h"
-#include "chrome/browser/signin/signin_internals_util.h"
-#include "chrome/browser/signin/signin_manager_cookie_helper.h"
-#include "chrome/browser/signin/signin_manager_delegate.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/signin/token_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/ui/global_error/global_error_service.h"
-#include "chrome/browser/ui/global_error/global_error_service_factory.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_account_id_helper.h"
 #include "chrome/common/pref_names.h"
-#include "content/public/browser/browser_thread.h"
+#include "chrome/common/profile_management_switches.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/core/browser/signin_internals_util.h"
+#include "components/signin/core/browser/signin_manager_cookie_helper.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_process_host.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/escape.h"
-#include "net/url_request/url_request_context.h"
 #include "third_party/icu/source/i18n/unicode/regex.h"
 
 using namespace signin_internals_util;
 
-using content::BrowserThread;
-
 namespace {
 
-const char kGetInfoDisplayEmailKey[] = "displayEmail";
-const char kGetInfoEmailKey[] = "email";
-
-const int kInvalidProcessId = -1;
-
 const char kChromiumSyncService[] = "service=chromiumsync";
 
 }  // namespace
 
 // Under the covers, we use a dummy chrome-extension ID to serve the purposes
 // outlined in the .h file comment for this string.
-const char* SigninManager::kChromeSigninEffectiveSite =
+const char SigninManager::kChromeSigninEffectiveSite[] =
     "chrome-extension://acfccoigjajmmgbhpfbjnpckhjjegnih";
 
 // static
@@ -81,49 +61,35 @@ bool SigninManager::IsWebBasedSigninFlowURL(const GURL& url) {
           .find(kChromiumSyncService) != std::string::npos;
 }
 
-SigninManager::SigninManager(scoped_ptr<SigninManagerDelegate> delegate)
-    : prohibit_signout_(false),
-      had_two_factor_error_(false),
+SigninManager::SigninManager(SigninClient* client)
+    : SigninManagerBase(client),
+      profile_(NULL),
+      prohibit_signout_(false),
       type_(SIGNIN_TYPE_NONE),
       weak_pointer_factory_(this),
-      signin_process_id_(kInvalidProcessId),
-      delegate_(delegate.Pass()) {
-}
-
-void SigninManager::SetSigninProcess(int process_id) {
-  if (process_id == signin_process_id_)
-    return;
-  DLOG_IF(WARNING, signin_process_id_ != kInvalidProcessId) <<
-      "Replacing in-use signin process.";
-  signin_process_id_ = process_id;
-  const content::RenderProcessHost* process =
-      content::RenderProcessHost::FromID(process_id);
-  DCHECK(process);
-  registrar_.Add(this,
-                 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
-                 content::Source<content::RenderProcessHost>(process));
-}
-
-void SigninManager::ClearSigninProcess() {
-  signin_process_id_ = kInvalidProcessId;
-}
+      client_(client) {}
 
-bool SigninManager::IsSigninProcess(int process_id) const {
-  return process_id == signin_process_id_;
+void SigninManager::AddMergeSessionObserver(
+    MergeSessionHelper::Observer* observer) {
+  if (merge_session_helper_)
+    merge_session_helper_->AddObserver(observer);
 }
 
-bool SigninManager::HasSigninProcess() const {
-  return signin_process_id_ != kInvalidProcessId;
+void SigninManager::RemoveMergeSessionObserver(
+    MergeSessionHelper::Observer* observer) {
+  if (merge_session_helper_)
+    merge_session_helper_->RemoveObserver(observer);
 }
 
 SigninManager::~SigninManager() {
 }
 
 void SigninManager::InitTokenService() {
-  SigninManagerBase::InitTokenService();
-  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-  if (token_service && !GetAuthenticatedUsername().empty())
-    token_service->LoadTokensFromDB();
+  ProfileOAuth2TokenService* token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
+  const std::string& account_id = GetAuthenticatedUsername();
+  if (token_service && !account_id.empty())
+    token_service->LoadCredentials(account_id);
 }
 
 std::string SigninManager::SigninTypeToString(
@@ -131,10 +97,8 @@ std::string SigninManager::SigninTypeToString(
   switch (type) {
     case SIGNIN_TYPE_NONE:
       return "No Signin";
-    case SIGNIN_TYPE_WITH_CREDENTIALS:
-      return "Signin with credentials";
-    case SIGNIN_TYPE_WITH_OAUTH_CODE:
-      return "Signin with oauth code";
+    case SIGNIN_TYPE_WITH_REFRESH_TOKEN:
+      return "Signin with refresh token";
   }
 
   NOTREACHED();
@@ -151,7 +115,7 @@ bool SigninManager::PrepareForSignin(SigninType type,
   if (!IsAllowedUsername(username)) {
     // Account is not allowed by admin policy.
     HandleAuthError(GoogleServiceAuthError(
-        GoogleServiceAuthError::ACCOUNT_DISABLED), true);
+        GoogleServiceAuthError::ACCOUNT_DISABLED));
     return false;
   }
 
@@ -160,142 +124,66 @@ bool SigninManager::PrepareForSignin(SigninType type,
   // need to try again, but take care to leave state around tracking that the
   // user has successfully signed in once before with this username, so that on
   // restart we don't think sync setup has never completed.
-  RevokeOAuthLoginToken();
   ClearTransientSigninData();
   type_ = type;
   possibly_invalid_username_.assign(username);
   password_.assign(password);
-
-  client_login_.reset(new GaiaAuthFetcher(this,
-                                          GaiaConstants::kChromeSource,
-                                          profile_->GetRequestContext()));
   NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type));
   return true;
 }
 
-void SigninManager::StartSignInWithCredentials(
-    const std::string& session_index,
-    const std::string& username,
-    const std::string& password,
-    const OAuthTokenFetchedCallback& callback) {
-  DCHECK(GetAuthenticatedUsername().empty() ||
-         gaia::AreEmailsSame(username, GetAuthenticatedUsername()));
-
-  if (!PrepareForSignin(SIGNIN_TYPE_WITH_CREDENTIALS, username, password))
-    return;
-
-  // Store our callback.
-  DCHECK(oauth_token_fetched_callback_.is_null());
-  oauth_token_fetched_callback_ = callback;
-
-  if (password.empty()) {
-    // Chrome must verify the GAIA cookies first if auto sign-in is triggered
-    // with no password provided. This is to protect Chrome against forged
-    // GAIA cookies from a super-domain.
-    VerifyGaiaCookiesBeforeSignIn(session_index);
-  } else {
-    // This function starts with the current state of the web session's cookie
-    // jar and mints a new ClientLogin-style SID/LSID pair.  This involves going
-    // through the follow process or requests to GAIA and LSO:
-    //
-    // - call /o/oauth2/programmatic_auth with the returned token to get oauth2
-    //   access and refresh tokens
-    // - call /accounts/OAuthLogin with the oauth2 access token and get SID/LSID
-    //   pair for use by the token service
-    //
-    // The resulting SID/LSID can then be used just as if
-    // client_login_->StartClientLogin() had completed successfully.
-    client_login_->StartCookieForOAuthLoginTokenExchange(session_index);
-  }
-}
-
-void SigninManager::StartSignInWithOAuthCode(
+void SigninManager::StartSignInWithRefreshToken(
+    const std::string& refresh_token,
     const std::string& username,
     const std::string& password,
-    const std::string& oauth_code,
     const OAuthTokenFetchedCallback& callback) {
   DCHECK(GetAuthenticatedUsername().empty() ||
          gaia::AreEmailsSame(username, GetAuthenticatedUsername()));
 
-  if (!PrepareForSignin(SIGNIN_TYPE_WITH_OAUTH_CODE, username, password))
+  if (!PrepareForSignin(SIGNIN_TYPE_WITH_REFRESH_TOKEN, username, password))
     return;
 
-  DCHECK(oauth_token_fetched_callback_.is_null());
-  oauth_token_fetched_callback_ = callback;
-
-  client_login_->StartAuthCodeForOAuth2TokenExchange(oauth_code);
-}
-
-void SigninManager::VerifyGaiaCookiesBeforeSignIn(
-    const std::string& session_index) {
-  scoped_refptr<SigninManagerCookieHelper> cookie_helper(
-      new SigninManagerCookieHelper(profile_->GetRequestContext()));
-  cookie_helper->StartFetchingGaiaCookiesOnUIThread(
-      base::Bind(&SigninManager::OnGaiaCookiesFetched,
-                 weak_pointer_factory_.GetWeakPtr(), session_index));
-}
+  // Store our callback and token.
+  temp_refresh_token_ = refresh_token;
+  possibly_invalid_username_ = username;
 
-void SigninManager::OnGaiaCookiesFetched(
-    const std::string session_index, const net::CookieList& cookie_list) {
-  net::CookieList::const_iterator it;
-  bool success = false;
-  for (it = cookie_list.begin(); it != cookie_list.end(); ++it) {
-    // Make sure the LSID cookie is set on the GAIA host, instead of a super-
-    // domain.
-    if (it->Name() == "LSID") {
-      if (it->IsHostCookie() && it->IsHttpOnly() && it->IsSecure()) {
-        // Found a valid LSID cookie. Continue loop to make sure we don't have
-        // invalid LSID cookies on any super-domain.
-        success = true;
-      } else {
-        success = false;
-        break;
-      }
-    }
-  }
+  NotifyDiagnosticsObservers(GET_USER_INFO_STATUS, "Successful");
 
-  if (success) {
-    client_login_->StartCookieForOAuthLoginTokenExchange(session_index);
+  if (!callback.is_null() && !temp_refresh_token_.empty()) {
+    callback.Run(temp_refresh_token_);
   } else {
-    HandleAuthError(GoogleServiceAuthError(
-        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), true);
+    // No oauth token or callback, so just complete our pending signin.
+    CompletePendingSignin();
   }
 }
 
 void SigninManager::CopyCredentialsFrom(const SigninManager& source) {
   DCHECK_NE(this, &source);
   possibly_invalid_username_ = source.possibly_invalid_username_;
-  last_result_ = source.last_result_;
-  temp_oauth_login_tokens_ = source.temp_oauth_login_tokens_;
+  temp_refresh_token_ = source.temp_refresh_token_;
+  password_ = source.password_;
 }
 
 void SigninManager::ClearTransientSigninData() {
   DCHECK(IsInitialized());
 
-  client_login_.reset();
-  last_result_ = ClientLoginResult();
   possibly_invalid_username_.clear();
   password_.clear();
-  had_two_factor_error_ = false;
   type_ = SIGNIN_TYPE_NONE;
-  temp_oauth_login_tokens_ = ClientOAuthResult();
-  oauth_token_fetched_callback_.Reset();
+  temp_refresh_token_.clear();
 }
 
-void SigninManager::HandleAuthError(const GoogleServiceAuthError& error,
-                                    bool clear_transient_data) {
-  // In some cases, the user should not be signed out.  For example, the failure
-  // may be due to a captcha or OTP challenge.  In these cases, the transient
-  // data must be kept to properly handle the follow up. This routine clears
-  // the data before sending out the notification so the SigninManager is no
-  // longer in the AuthInProgress state when the notification goes out.
-  if (clear_transient_data)
-    ClearTransientSigninData();
+void SigninManager::HandleAuthError(const GoogleServiceAuthError& error) {
+  ClearTransientSigninData();
 
+  // TODO(blundell): Eliminate this notification send once crbug.com/333997 is
+  // fixed.
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
       content::Source<Profile>(profile_),
       content::Details<const GoogleServiceAuthError>(&error));
+
+  FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSigninFailed(error));
 }
 
 void SigninManager::SignOut() {
@@ -306,7 +194,7 @@ void SigninManager::SignOut() {
       // If the user is in the process of signing in, then treat a call to
       // SignOut as a cancellation request.
       GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
-      HandleAuthError(error, true);
+      HandleAuthError(error);
     } else {
       // Clean up our transient data and exit if we aren't signed in.
       // This avoids a perf regression from clearing out the TokenDB if
@@ -323,25 +211,36 @@ void SigninManager::SignOut() {
   }
 
   ClearTransientSigninData();
-  RevokeOAuthLoginToken();
 
-  GoogleServiceSignoutDetails details(GetAuthenticatedUsername());
+  const std::string& username = GetAuthenticatedUsername();
   clear_authenticated_username();
   profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
 
   // Erase (now) stale information from AboutSigninInternals.
   NotifyDiagnosticsObservers(USERNAME, "");
 
+  // Revoke all tokens before sending signed_out notification, because there
+  // may be components that don't listen for token service events when the
+  // profile is not connected to an account.
+  ProfileOAuth2TokenService* token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
+  LOG(WARNING) << "Revoking refresh token on server. Reason: sign out, "
+               << "IsSigninAllowed: " << IsSigninAllowed();
+  token_service->RevokeAllCredentials();
+
+  // TODO(blundell): Eliminate this notification send once crbug.com/333997 is
+  // fixed.
+  GoogleServiceSignoutDetails details(username);
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
       content::Source<Profile>(profile_),
       content::Details<const GoogleServiceSignoutDetails>(&details));
-  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-  token_service->ResetCredentialsInMemory();
-  token_service->EraseTokensFromDB();
+
+  FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSignedOut(username));
 }
 
 void SigninManager::Initialize(Profile* profile, PrefService* local_state) {
+  profile_ = profile;
   SigninManagerBase::Initialize(profile, local_state);
 
   // local_state can be null during unit tests.
@@ -363,10 +262,20 @@ void SigninManager::Initialize(Profile* profile, PrefService* local_state) {
     // have changed the policy since the last signin, so sign out the user.
     SignOut();
   }
+
+  InitTokenService();
+  account_id_helper_.reset(new SigninAccountIdHelper(
+      client_,
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
+      this));
 }
 
 void SigninManager::Shutdown() {
+  if (merge_session_helper_)
+    merge_session_helper_->CancelAll();
+
   local_state_pref_registrar_.RemoveAll();
+  account_id_helper_.reset();
   SigninManagerBase::Shutdown();
 }
 
@@ -383,12 +292,6 @@ bool SigninManager::IsSigninAllowed() const {
   return signin_allowed_.GetValue();
 }
 
-// static
-bool SigninManager::IsSigninAllowedOnIOThread(ProfileIOData* io_data) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  return io_data->signin_allowed()->GetValue();
-}
-
 void SigninManager::OnSigninAllowedPrefChanged() {
   if (!IsSigninAllowed())
     SignOut();
@@ -404,7 +307,7 @@ bool SigninManager::IsUsernameAllowedByPolicy(const std::string& username,
   // are not valid regular expressions - they should instead be ".*@foo.com").
   // For convenience, detect these patterns and insert a "." character at the
   // front.
-  string16 pattern = UTF8ToUTF16(policy);
+  base::string16 pattern = base::UTF8ToUTF16(policy);
   if (pattern[0] == L'*')
     pattern.insert(pattern.begin(), L'.');
 
@@ -418,7 +321,7 @@ bool SigninManager::IsUsernameAllowedByPolicy(const std::string& username,
     // break signin than to quietly allow users to sign in).
     return false;
   }
-  string16 username16 = UTF8ToUTF16(username);
+  base::string16 username16 = base::UTF8ToUTF16(username);
   icu::UnicodeString icu_input(username16.data(), username16.length());
   matcher.reset(icu_input);
   status = U_ZERO_ERROR;
@@ -430,29 +333,13 @@ bool SigninManager::IsUsernameAllowedByPolicy(const std::string& username,
 bool SigninManager::IsAllowedUsername(const std::string& username) const {
   const PrefService* local_state = local_state_pref_registrar_.prefs();
   if (!local_state)
-    return true; // In a unit test with no local state - all names are allowed.
+    return true;  // In a unit test with no local state - all names are allowed.
 
   std::string pattern = local_state->GetString(
       prefs::kGoogleServicesUsernamePattern);
   return IsUsernameAllowedByPolicy(username, pattern);
 }
 
-void SigninManager::RevokeOAuthLoginToken() {
-  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-  if (token_service->HasOAuthLoginToken()) {
-    revoke_token_fetcher_.reset(
-        new GaiaAuthFetcher(this,
-                            GaiaConstants::kChromeSource,
-                            profile_->GetRequestContext()));
-    revoke_token_fetcher_->StartRevokeOAuth2Token(
-        token_service->GetOAuth2LoginRefreshToken());
-  }
-}
-
-void SigninManager::OnOAuth2RevokeTokenCompleted() {
-  revoke_token_fetcher_.reset(NULL);
-}
-
 bool SigninManager::AuthInProgress() const {
   return !possibly_invalid_username_.empty();
 }
@@ -461,129 +348,37 @@ const std::string& SigninManager::GetUsernameForAuthInProgress() const {
   return possibly_invalid_username_;
 }
 
-void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
-  DCHECK(key == kGetInfoDisplayEmailKey || key == kGetInfoEmailKey);
-  LOG(ERROR) << "Account is not associated with a valid email address. "
-             << "Login failed.";
-  OnClientLoginFailure(GoogleServiceAuthError(
-      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-}
-
 void SigninManager::DisableOneClickSignIn(Profile* profile) {
   PrefService* pref_service = profile->GetPrefs();
   pref_service->SetBoolean(prefs::kReverseAutologinEnabled, false);
 }
 
-void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
-  last_result_ = result;
-  // Update signin_internals_
-  NotifyDiagnosticsObservers(CLIENT_LOGIN_STATUS, "Successful");
-  // Make a request for the canonical email address and services.
-  client_login_->StartGetUserInfo(result.lsid);
-}
-
-void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
-  // If we got a bad ASP, prompt for an ASP again by forcing another TWO_FACTOR
-  // error.  This function does not call HandleAuthError() because dealing
-  // with TWO_FACTOR errors needs special handling: we don't want to clear the
-  // transient signin data in such error cases.
-  bool invalid_gaia = error.state() ==
-      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
-
-  GoogleServiceAuthError current_error =
-      (invalid_gaia && had_two_factor_error_) ?
-      GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR) : error;
-
-  if (current_error.state() == GoogleServiceAuthError::TWO_FACTOR)
-    had_two_factor_error_ = true;
-
-  NotifyDiagnosticsObservers(CLIENT_LOGIN_STATUS, error.ToString());
-  HandleAuthError(current_error, !had_two_factor_error_);
-}
-
-void SigninManager::OnClientOAuthSuccess(const ClientOAuthResult& result) {
-  DVLOG(1) << "SigninManager::OnClientOAuthSuccess access_token="
-           << result.access_token;
-
-  NotifyDiagnosticsObservers(OAUTH_LOGIN_STATUS, "Successful");
-
-  switch (type_) {
-    case SIGNIN_TYPE_WITH_CREDENTIALS:
-    case SIGNIN_TYPE_WITH_OAUTH_CODE:
-      temp_oauth_login_tokens_ = result;
-      client_login_->StartOAuthLogin(result.access_token,
-                                     GaiaConstants::kGaiaService);
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-}
+void SigninManager::CompletePendingSignin() {
+  DCHECK(!possibly_invalid_username_.empty());
+  OnSignedIn(possibly_invalid_username_);
 
-void SigninManager::OnClientOAuthFailure(const GoogleServiceAuthError& error) {
-  bool clear_transient_data = true;
-  NotifyDiagnosticsObservers(OAUTH_LOGIN_STATUS, error.ToString());
-  LOG(WARNING) << "SigninManager::OnClientOAuthFailure";
-  HandleAuthError(error, clear_transient_data);
-}
+  ProfileOAuth2TokenService* token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
 
-void SigninManager::OnGetUserInfoSuccess(const UserInfoMap& data) {
-  NotifyDiagnosticsObservers(GET_USER_INFO_STATUS, "Successful");
+  // If inline sign in is enabled, but new profile management is not, perform a
+  // merge session now to push the user's credentials into the cookie jar.
+  bool do_merge_session_in_signin_manager =
+      !switches::IsEnableWebBasedSignin() &&
+      !switches::IsNewProfileManagement();
 
-  UserInfoMap::const_iterator email_iter = data.find(kGetInfoEmailKey);
-  UserInfoMap::const_iterator display_email_iter =
-      data.find(kGetInfoDisplayEmailKey);
-  if (email_iter == data.end()) {
-    OnGetUserInfoKeyNotFound(kGetInfoEmailKey);
-    return;
-  }
-  if (display_email_iter == data.end()) {
-    OnGetUserInfoKeyNotFound(kGetInfoDisplayEmailKey);
-    return;
-  }
-  DCHECK(email_iter->first == kGetInfoEmailKey);
-  DCHECK(display_email_iter->first == kGetInfoDisplayEmailKey);
-
-  // When signing in with credentials, the possibly invalid name is the Gaia
-  // display name. If the name returned by GetUserInfo does not match what is
-  // expected, return an error.
-  if (type_ == SIGNIN_TYPE_WITH_CREDENTIALS &&
-      !gaia::AreEmailsSame(display_email_iter->second,
-                           possibly_invalid_username_)) {
-    OnGetUserInfoKeyNotFound(kGetInfoDisplayEmailKey);
-    return;
+  if (do_merge_session_in_signin_manager) {
+    merge_session_helper_.reset(new MergeSessionHelper(
+        token_service, profile_->GetRequestContext(), NULL));
   }
 
-  possibly_invalid_username_ = email_iter->second;
+  DCHECK(!temp_refresh_token_.empty());
+  DCHECK(!GetAuthenticatedUsername().empty());
+  token_service->UpdateCredentials(GetAuthenticatedUsername(),
+                                   temp_refresh_token_);
+  temp_refresh_token_.clear();
 
-  if (!oauth_token_fetched_callback_.is_null() &&
-      !temp_oauth_login_tokens_.refresh_token.empty()) {
-    oauth_token_fetched_callback_.Run(temp_oauth_login_tokens_.refresh_token);
-  } else {
-    // No oauth token or callback, so just complete our pending signin.
-    CompletePendingSignin();
-  }
-}
-
-void SigninManager::CompletePendingSignin() {
-  DCHECK(!possibly_invalid_username_.empty());
-  OnSignedIn(possibly_invalid_username_);
-
-  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-  token_service->UpdateCredentials(last_result_);
-  DCHECK(token_service->AreCredentialsValid());
-  token_service->StartFetchingTokens();
-
-  // If we have oauth2 tokens, tell token service about them so it does not
-  // need to fetch them again.  Its important that the authenticated name has
-  // already been set before sending the oauth2 token to the token service.
-  // Some token service listeners will query the authenticated name when they
-  // receive the token available notification.
-  if (!temp_oauth_login_tokens_.refresh_token.empty()) {
-    DCHECK(!GetAuthenticatedUsername().empty());
-    token_service->UpdateCredentialsWithOAuth2(temp_oauth_login_tokens_);
-    temp_oauth_login_tokens_ = ClientOAuthResult();
-  }
+  if (do_merge_session_in_signin_manager)
+    merge_session_helper_->LogIn(GetAuthenticatedUsername());
 }
 
 void SigninManager::OnExternalSigninCompleted(const std::string& username) {
@@ -593,9 +388,9 @@ void SigninManager::OnExternalSigninCompleted(const std::string& username) {
 void SigninManager::OnSignedIn(const std::string& username) {
   SetAuthenticatedUsername(username);
   possibly_invalid_username_.clear();
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                  GetAuthenticatedUsername());
 
+  // TODO(blundell): Eliminate this notification send once crbug.com/333997 is
+  // fixed.
   GoogleServiceSigninSuccessDetails details(GetAuthenticatedUsername(),
                                             password_);
   content::NotificationService::current()->Notify(
@@ -603,68 +398,14 @@ void SigninManager::OnSignedIn(const std::string& username) {
       content::Source<Profile>(profile_),
       content::Details<const GoogleServiceSigninSuccessDetails>(&details));
 
-  // Don't store password hash except for users of new profile features.
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kNewProfileManagement)) {
-    std::string auth_username = GetAuthenticatedUsername();
-    chrome::SetLocalAuthCredentials(profile_, auth_username, password_);
-  }
-  password_.clear();  // Don't need it anymore.
-  DisableOneClickSignIn(profile_);  // Don't ever offer again.
+  FOR_EACH_OBSERVER(Observer, observer_list_,
+                    GoogleSigninSucceeded(GetAuthenticatedUsername(),
+                                          password_));
 
-  if (type_ == SIGNIN_TYPE_WITH_OAUTH_CODE &&
-      !temp_oauth_login_tokens_.access_token.empty())
-    // Cookie jar may not be set up properly, need to first get an uber token
-    // and then merge sessions with the token.
-    client_login_->StartTokenFetchForUberAuthExchange(
-        temp_oauth_login_tokens_.access_token);
-}
-
-void SigninManager::OnUberAuthTokenSuccess(const std::string& token) {
-  DVLOG(1) << "SigninManager::OnUberAuthTokenSuccess";
-  NotifyDiagnosticsObservers(UBER_TOKEN_STATUS, "Successful");
-  client_login_->StartMergeSession(token);
-}
+  client_->GoogleSigninSucceeded(GetAuthenticatedUsername(), password_);
 
-void SigninManager::OnMergeSessionSuccess(const std::string& data) {
-  DVLOG(1) << "SigninManager::OnMergeSessionSuccess";
-  NotifyDiagnosticsObservers(MERGE_SESSION_STATUS, "Successful");
-}
-
-void SigninManager::OnMergeSessionFailure(const GoogleServiceAuthError& error) {
-  LOG(ERROR) << "Unable to mereg sessions. Login failed.";
-  NotifyDiagnosticsObservers(MERGE_SESSION_STATUS, error.ToString());
-}
-
-void SigninManager::OnUberAuthTokenFailure(
-    const GoogleServiceAuthError& error) {
-  LOG(ERROR) << "Unable to retreive the uber token. Login failed.";
-  NotifyDiagnosticsObservers(UBER_TOKEN_STATUS, error.ToString());
-}
-
-void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
-  LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
-  NotifyDiagnosticsObservers(GET_USER_INFO_STATUS, error.ToString());
-  // REVIEW: why does this call OnClientLoginFailure?
-  OnClientLoginFailure(error);
-}
-
-void SigninManager::Observe(int type,
-                            const content::NotificationSource& source,
-                            const content::NotificationDetails& details) {
-  DCHECK_EQ(content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, type);
-
-  // It's possible we're listening to a "stale" renderer because it was
-  // replaced with a new process by process-per-site. In either case,
-  // stop listening to it, but only reset signin_process_id_ tracking
-  // if this was from the current signin process.
-  registrar_.Remove(this,
-                    content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
-                    source);
-  if (signin_process_id_ ==
-      content::Source<content::RenderProcessHost>(source)->GetID()) {
-    signin_process_id_ = kInvalidProcessId;
-  }
+  password_.clear();  // Don't need it anymore.
+  DisableOneClickSignIn(profile_);  // Don't ever offer again.
 }
 
 void SigninManager::ProhibitSignout(bool prohibit_signout) {