1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/metrics/histogram.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h"
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_account_id_helper.h"
18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/signin_client.h"
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/signin_internals_util.h"
20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/signin_manager_cookie_helper.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/signin/core/browser/signin_metrics.h"
22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/common/signin_pref_names.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/escape.h"
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "third_party/icu/source/i18n/unicode/regex.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace signin_internals_util;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kChromiumSyncService[] = "service=chromiumsync";
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Under the covers, we use a dummy chrome-extension ID to serve the purposes
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// outlined in the .h file comment for this string.
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char SigninManager::kChromeSigninEffectiveSite[] =
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "chrome-extension://acfccoigjajmmgbhpfbjnpckhjjegnih";
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SigninManager::IsWebBasedSigninFlowURL(const GURL& url) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL effective(kChromeSigninEffectiveSite);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (url.SchemeIs(effective.scheme().c_str()) &&
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url.host() == effective.host()) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL service_login(GaiaUrls::GetInstance()->service_login_url());
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (url.GetOrigin() != service_login.GetOrigin())
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Any login UI URLs with signin=chromiumsync should be considered a web
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // URL (relies on GAIA keeping the "service=chromiumsync" query string
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // fragment present even when embedding inside a "continue" parameter).
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return net::UnescapeURLComponent(url.query(),
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   net::UnescapeRule::URL_SPECIAL_CHARS)
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             .find(kChromiumSyncService) != std::string::npos;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochSigninManager::SigninManager(SigninClient* client,
62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                             ProfileOAuth2TokenService* token_service)
63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : SigninManagerBase(client),
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      prohibit_signout_(false),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type_(SIGNIN_TYPE_NONE),
66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      client_(client),
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      token_service_(token_service),
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_pointer_factory_(this) {}
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninManager::AddMergeSessionObserver(
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MergeSessionHelper::Observer* observer) {
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (merge_session_helper_)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    merge_session_helper_->AddObserver(observer);
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninManager::RemoveMergeSessionObserver(
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MergeSessionHelper::Observer* observer) {
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (merge_session_helper_)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    merge_session_helper_->RemoveObserver(observer);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochSigninManager::~SigninManager() {}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SigninManager::InitTokenService() {
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string& account_id = GetAuthenticatedUsername();
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (token_service_ && !account_id.empty())
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    token_service_->LoadCredentials(account_id);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochstd::string SigninManager::SigninTypeToString(SigninManager::SigninType type) {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SIGNIN_TYPE_NONE:
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "No Signin";
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case SIGNIN_TYPE_WITH_REFRESH_TOKEN:
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "Signin with refresh token";
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SigninManager::PrepareForSignin(SigninType type,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::string& username,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::string& password) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(possibly_invalid_username_.empty() ||
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         possibly_invalid_username_ == username);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!username.empty());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsAllowedUsername(username)) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Account is not allowed by admin policy.
111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    HandleAuthError(
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This attempt is either 1) the user trying to establish initial sync, or
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2) trying to refresh credentials for an existing username.  If it is 2, we
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to try again, but take care to leave state around tracking that the
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // user has successfully signed in once before with this username, so that on
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // restart we don't think sync setup has never completed.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearTransientSigninData();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = type;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  possibly_invalid_username_.assign(username);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  password_.assign(password);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SigninManager::StartSignInWithRefreshToken(
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& refresh_token,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& username,
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& password,
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const OAuthTokenFetchedCallback& callback) {
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!IsAuthenticated() ||
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         gaia::AreEmailsSame(username, GetAuthenticatedUsername()));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!PrepareForSignin(SIGNIN_TYPE_WITH_REFRESH_TOKEN, username, password))
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Store our callback and token.
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  temp_refresh_token_ = refresh_token;
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  possibly_invalid_username_ = username;
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NotifyDiagnosticsObservers(GET_USER_INFO_STATUS, "Successful");
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!callback.is_null() && !temp_refresh_token_.empty()) {
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    callback.Run(temp_refresh_token_);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // No oauth token or callback, so just complete our pending signin.
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CompletePendingSignin();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SigninManager::CopyCredentialsFrom(const SigninManager& source) {
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_NE(this, &source);
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  possibly_invalid_username_ = source.possibly_invalid_username_;
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  temp_refresh_token_ = source.temp_refresh_token_;
158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  password_ = source.password_;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SigninManager::ClearTransientSigninData() {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsInitialized());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  possibly_invalid_username_.clear();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  password_.clear();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = SIGNIN_TYPE_NONE;
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  temp_refresh_token_.clear();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SigninManager::HandleAuthError(const GoogleServiceAuthError& error) {
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ClearTransientSigninData();
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSigninFailed(error));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SigninManager::SignOut(
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    signin_metrics::ProfileSignout signout_source_metric) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsInitialized());
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  signin_metrics::LogSignout(signout_source_metric);
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!IsAuthenticated()) {
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (AuthInProgress()) {
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // If the user is in the process of signing in, then treat a call to
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // SignOut as a cancellation request.
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      HandleAuthError(error);
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Clean up our transient data and exit if we aren't signed in.
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // This avoids a perf regression from clearing out the TokenDB if
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // SignOut() is invoked on startup to clean up any incomplete previous
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // signin attempts.
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ClearTransientSigninData();
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (prohibit_signout_) {
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DVLOG(1) << "Ignoring attempt to sign out while signout is prohibited";
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearTransientSigninData();
203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const std::string account_id = GetAuthenticatedAccountId();
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const std::string username = GetAuthenticatedUsername();
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const base::Time signin_time =
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Time::FromInternalValue(
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          client_->GetPrefs()->GetInt64(prefs::kSignedInTime));
209a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  clear_authenticated_username();
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  client_->GetPrefs()->ClearPref(prefs::kSignedInTime);
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  client_->ClearSigninScopedDeviceId();
213a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
214a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Erase (now) stale information from AboutSigninInternals.
215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NotifyDiagnosticsObservers(USERNAME, "");
216a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Determine the duration the user was logged in and log that to UMA.
2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!signin_time.is_null()) {
2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::TimeDelta signed_in_duration = base::Time::Now() - signin_time;
2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("Signin.SignedInDurationBeforeSignout",
2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         signed_in_duration.InMinutes());
2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Revoke all tokens before sending signed_out notification, because there
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // may be components that don't listen for token service events when the
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // profile is not connected to an account.
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  LOG(WARNING) << "Revoking refresh token on server. Reason: sign out, "
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               << "IsSigninAllowed: " << IsSigninAllowed();
229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  token_service_->RevokeAllCredentials();
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FOR_EACH_OBSERVER(Observer,
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    observer_list_,
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    GoogleSignedOut(account_id, username));
234a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
235a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
236e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid SigninManager::Initialize(PrefService* local_state) {
237e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  SigninManagerBase::Initialize(local_state);
238a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
239a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // local_state can be null during unit tests.
240a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (local_state) {
241a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    local_state_pref_registrar_.Init(local_state);
242a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    local_state_pref_registrar_.Add(
243a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        prefs::kGoogleServicesUsernamePattern,
244a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        base::Bind(&SigninManager::OnGoogleServicesUsernamePatternChanged,
245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                   weak_pointer_factory_.GetWeakPtr()));
246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  signin_allowed_.Init(prefs::kSigninAllowed,
248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       client_->GetPrefs(),
249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       base::Bind(&SigninManager::OnSigninAllowedPrefChanged,
250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                  base::Unretained(this)));
251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::string user =
253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      client_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
254a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if ((!user.empty() && !IsAllowedUsername(user)) || !IsSigninAllowed()) {
255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // User is signed in, but the username is invalid - the administrator must
256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // have changed the policy since the last signin, so sign out the user.
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SignOut(signin_metrics::SIGNIN_PREF_CHANGED_DURING_SIGNIN);
258a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  InitTokenService();
261effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  account_id_helper_.reset(
262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new SigninAccountIdHelper(client_, token_service_, this));
263a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
264a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
26558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid SigninManager::Shutdown() {
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (merge_session_helper_)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    merge_session_helper_->CancelAll();
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
26958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  local_state_pref_registrar_.RemoveAll();
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  account_id_helper_.reset();
27158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  SigninManagerBase::Shutdown();
27258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}
27358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
274a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SigninManager::OnGoogleServicesUsernamePatternChanged() {
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (IsAuthenticated() &&
276a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      !IsAllowedUsername(GetAuthenticatedUsername())) {
277a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Signed in user is invalid according to the current policy so sign
278a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // the user out.
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SignOut(signin_metrics::GOOGLE_SERVICE_NAME_PATTERN_CHANGED);
280a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
282a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
283a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool SigninManager::IsSigninAllowed() const {
284a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return signin_allowed_.GetValue();
285a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
286a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
287a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SigninManager::OnSigninAllowedPrefChanged() {
288a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!IsSigninAllowed())
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SignOut(signin_metrics::SIGNOUT_PREF_CHANGED);
290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
291a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// static
293a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool SigninManager::IsUsernameAllowedByPolicy(const std::string& username,
294a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                              const std::string& policy) {
295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (policy.empty())
296a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return true;
297a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
298a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Patterns like "*@foo.com" are not accepted by our regex engine (since they
299a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // are not valid regular expressions - they should instead be ".*@foo.com").
300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // For convenience, detect these patterns and insert a "." character at the
301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // front.
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 pattern = base::UTF8ToUTF16(policy);
303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (pattern[0] == L'*')
304a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    pattern.insert(pattern.begin(), L'.');
305a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // See if the username matches the policy-provided pattern.
307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UErrorCode status = U_ZERO_ERROR;
308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  icu::RegexMatcher matcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status);
310a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!U_SUCCESS(status)) {
311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    LOG(ERROR) << "Invalid login regex: " << pattern << ", status: " << status;
312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // If an invalid pattern is provided, then prohibit *all* logins (better to
313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // break signin than to quietly allow users to sign in).
314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
315a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 username16 = base::UTF8ToUTF16(username);
317a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  icu::UnicodeString icu_input(username16.data(), username16.length());
318a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  matcher.reset(icu_input);
319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  status = U_ZERO_ERROR;
320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UBool match = matcher.matches(status);
321a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(U_SUCCESS(status));
322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return !!match;  // !! == convert from UBool to bool.
323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool SigninManager::IsAllowedUsername(const std::string& username) const {
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const PrefService* local_state = local_state_pref_registrar_.prefs();
327a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!local_state)
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;  // In a unit test with no local state - all names are allowed.
329a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
330e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  std::string pattern =
331e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      local_state->GetString(prefs::kGoogleServicesUsernamePattern);
332a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return IsUsernameAllowedByPolicy(username, pattern);
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SigninManager::AuthInProgress() const {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !possibly_invalid_username_.empty();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& SigninManager::GetUsernameForAuthInProgress() const {
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return possibly_invalid_username_;
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid SigninManager::DisableOneClickSignIn(PrefService* prefs) {
344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  prefs->SetBoolean(prefs::kReverseAutologinEnabled, false);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SigninManager::CompletePendingSignin() {
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!possibly_invalid_username_.empty());
3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  OnSignedIn(possibly_invalid_username_);
3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
351e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (client_->ShouldMergeSigninCredentialsIntoCookieJar()) {
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    merge_session_helper_.reset(new MergeSessionHelper(
353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        token_service_, client_->GetURLRequestContext(), NULL));
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!temp_refresh_token_.empty());
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(IsAuthenticated());
358effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  token_service_->UpdateCredentials(GetAuthenticatedUsername(),
359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                    temp_refresh_token_);
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  temp_refresh_token_.clear();
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
362e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (client_->ShouldMergeSigninCredentialsIntoCookieJar())
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    merge_session_helper_->LogIn(GetAuthenticatedUsername());
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SigninManager::OnExternalSigninCompleted(const std::string& username) {
3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  OnSignedIn(username);
3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SigninManager::OnSignedIn(const std::string& username) {
3716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  client_->GetPrefs()->SetInt64(prefs::kSignedInTime,
3726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                base::Time::Now().ToInternalValue());
3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SetAuthenticatedUsername(username);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  possibly_invalid_username_.clear();
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
376e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  FOR_EACH_OBSERVER(
377e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      Observer,
378e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      observer_list_,
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GoogleSigninSucceeded(GetAuthenticatedAccountId(),
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            GetAuthenticatedUsername(),
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            password_));
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  client_->GoogleSigninSucceeded(GetAuthenticatedAccountId(),
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 GetAuthenticatedUsername(),
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 password_);
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
38703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  signin_metrics::LogSigninProfile(client_->IsFirstRun(),
38803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                   client_->GetInstallDate());
38903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
390e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  password_.clear();                           // Don't need it anymore.
391effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DisableOneClickSignIn(client_->GetPrefs());  // Don't ever offer again.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SigninManager::ProhibitSignout(bool prohibit_signout) {
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  prohibit_signout_ = prohibit_signout;
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
398e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool SigninManager::IsSignoutProhibited() const { return prohibit_signout_; }
399