This source file includes following definitions.
- IsWebBasedSigninFlowURL
- token_service_
- AddMergeSessionObserver
- RemoveMergeSessionObserver
- InitTokenService
- SigninTypeToString
- PrepareForSignin
- StartSignInWithRefreshToken
- CopyCredentialsFrom
- ClearTransientSigninData
- HandleAuthError
- SignOut
- Initialize
- Shutdown
- OnGoogleServicesUsernamePatternChanged
- IsSigninAllowed
- OnSigninAllowedPrefChanged
- IsUsernameAllowedByPolicy
- IsAllowedUsername
- AuthInProgress
- GetUsernameForAuthInProgress
- DisableOneClickSignIn
- CompletePendingSignin
- OnExternalSigninCompleted
- OnSignedIn
- ProhibitSignout
- IsSignoutProhibited
#include "components/signin/core/browser/signin_manager.h"
#include <string>
#include <vector>
#include "base/prefs/pref_service.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_account_id_helper.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 "components/signin/core/common/signin_pref_names.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/escape.h"
#include "third_party/icu/source/i18n/unicode/regex.h"
using namespace signin_internals_util;
namespace {
const char kChromiumSyncService[] = "service=chromiumsync";
}
const char SigninManager::kChromeSigninEffectiveSite[] =
"chrome-extension://acfccoigjajmmgbhpfbjnpckhjjegnih";
bool SigninManager::IsWebBasedSigninFlowURL(const GURL& url) {
GURL effective(kChromeSigninEffectiveSite);
if (url.SchemeIs(effective.scheme().c_str()) &&
url.host() == effective.host()) {
return true;
}
GURL service_login(GaiaUrls::GetInstance()->service_login_url());
if (url.GetOrigin() != service_login.GetOrigin())
return false;
return net::UnescapeURLComponent(url.query(),
net::UnescapeRule::URL_SPECIAL_CHARS)
.find(kChromiumSyncService) != std::string::npos;
}
SigninManager::SigninManager(SigninClient* client,
ProfileOAuth2TokenService* token_service)
: SigninManagerBase(client),
prohibit_signout_(false),
type_(SIGNIN_TYPE_NONE),
weak_pointer_factory_(this),
client_(client),
token_service_(token_service) {}
void SigninManager::AddMergeSessionObserver(
MergeSessionHelper::Observer* observer) {
if (merge_session_helper_)
merge_session_helper_->AddObserver(observer);
}
void SigninManager::RemoveMergeSessionObserver(
MergeSessionHelper::Observer* observer) {
if (merge_session_helper_)
merge_session_helper_->RemoveObserver(observer);
}
SigninManager::~SigninManager() {}
void SigninManager::InitTokenService() {
const std::string& account_id = GetAuthenticatedUsername();
if (token_service_ && !account_id.empty())
token_service_->LoadCredentials(account_id);
}
std::string SigninManager::SigninTypeToString(SigninManager::SigninType type) {
switch (type) {
case SIGNIN_TYPE_NONE:
return "No Signin";
case SIGNIN_TYPE_WITH_REFRESH_TOKEN:
return "Signin with refresh token";
}
NOTREACHED();
return std::string();
}
bool SigninManager::PrepareForSignin(SigninType type,
const std::string& username,
const std::string& password) {
DCHECK(possibly_invalid_username_.empty() ||
possibly_invalid_username_ == username);
DCHECK(!username.empty());
if (!IsAllowedUsername(username)) {
HandleAuthError(
GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
return false;
}
ClearTransientSigninData();
type_ = type;
possibly_invalid_username_.assign(username);
password_.assign(password);
NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type));
return true;
}
void SigninManager::StartSignInWithRefreshToken(
const std::string& refresh_token,
const std::string& username,
const std::string& password,
const OAuthTokenFetchedCallback& callback) {
DCHECK(GetAuthenticatedUsername().empty() ||
gaia::AreEmailsSame(username, GetAuthenticatedUsername()));
if (!PrepareForSignin(SIGNIN_TYPE_WITH_REFRESH_TOKEN, username, password))
return;
temp_refresh_token_ = refresh_token;
possibly_invalid_username_ = username;
NotifyDiagnosticsObservers(GET_USER_INFO_STATUS, "Successful");
if (!callback.is_null() && !temp_refresh_token_.empty()) {
callback.Run(temp_refresh_token_);
} else {
CompletePendingSignin();
}
}
void SigninManager::CopyCredentialsFrom(const SigninManager& source) {
DCHECK_NE(this, &source);
possibly_invalid_username_ = source.possibly_invalid_username_;
temp_refresh_token_ = source.temp_refresh_token_;
password_ = source.password_;
}
void SigninManager::ClearTransientSigninData() {
DCHECK(IsInitialized());
possibly_invalid_username_.clear();
password_.clear();
type_ = SIGNIN_TYPE_NONE;
temp_refresh_token_.clear();
}
void SigninManager::HandleAuthError(const GoogleServiceAuthError& error) {
ClearTransientSigninData();
FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSigninFailed(error));
}
void SigninManager::SignOut() {
DCHECK(IsInitialized());
if (GetAuthenticatedUsername().empty()) {
if (AuthInProgress()) {
GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
HandleAuthError(error);
} else {
ClearTransientSigninData();
}
return;
}
if (prohibit_signout_) {
DVLOG(1) << "Ignoring attempt to sign out while signout is prohibited";
return;
}
ClearTransientSigninData();
const std::string username = GetAuthenticatedUsername();
clear_authenticated_username();
client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
NotifyDiagnosticsObservers(USERNAME, "");
LOG(WARNING) << "Revoking refresh token on server. Reason: sign out, "
<< "IsSigninAllowed: " << IsSigninAllowed();
token_service_->RevokeAllCredentials();
FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSignedOut(username));
}
void SigninManager::Initialize(PrefService* local_state) {
SigninManagerBase::Initialize(local_state);
if (local_state) {
local_state_pref_registrar_.Init(local_state);
local_state_pref_registrar_.Add(
prefs::kGoogleServicesUsernamePattern,
base::Bind(&SigninManager::OnGoogleServicesUsernamePatternChanged,
weak_pointer_factory_.GetWeakPtr()));
}
signin_allowed_.Init(prefs::kSigninAllowed,
client_->GetPrefs(),
base::Bind(&SigninManager::OnSigninAllowedPrefChanged,
base::Unretained(this)));
std::string user =
client_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
if ((!user.empty() && !IsAllowedUsername(user)) || !IsSigninAllowed()) {
SignOut();
}
InitTokenService();
account_id_helper_.reset(
new SigninAccountIdHelper(client_, token_service_, this));
}
void SigninManager::Shutdown() {
if (merge_session_helper_)
merge_session_helper_->CancelAll();
local_state_pref_registrar_.RemoveAll();
account_id_helper_.reset();
SigninManagerBase::Shutdown();
}
void SigninManager::OnGoogleServicesUsernamePatternChanged() {
if (!GetAuthenticatedUsername().empty() &&
!IsAllowedUsername(GetAuthenticatedUsername())) {
SignOut();
}
}
bool SigninManager::IsSigninAllowed() const {
return signin_allowed_.GetValue();
}
void SigninManager::OnSigninAllowedPrefChanged() {
if (!IsSigninAllowed())
SignOut();
}
bool SigninManager::IsUsernameAllowedByPolicy(const std::string& username,
const std::string& policy) {
if (policy.empty())
return true;
base::string16 pattern = base::UTF8ToUTF16(policy);
if (pattern[0] == L'*')
pattern.insert(pattern.begin(), L'.');
UErrorCode status = U_ZERO_ERROR;
const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
icu::RegexMatcher matcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status);
if (!U_SUCCESS(status)) {
LOG(ERROR) << "Invalid login regex: " << pattern << ", status: " << status;
return false;
}
base::string16 username16 = base::UTF8ToUTF16(username);
icu::UnicodeString icu_input(username16.data(), username16.length());
matcher.reset(icu_input);
status = U_ZERO_ERROR;
UBool match = matcher.matches(status);
DCHECK(U_SUCCESS(status));
return !!match;
}
bool SigninManager::IsAllowedUsername(const std::string& username) const {
const PrefService* local_state = local_state_pref_registrar_.prefs();
if (!local_state)
return true;
std::string pattern =
local_state->GetString(prefs::kGoogleServicesUsernamePattern);
return IsUsernameAllowedByPolicy(username, pattern);
}
bool SigninManager::AuthInProgress() const {
return !possibly_invalid_username_.empty();
}
const std::string& SigninManager::GetUsernameForAuthInProgress() const {
return possibly_invalid_username_;
}
void SigninManager::DisableOneClickSignIn(PrefService* prefs) {
prefs->SetBoolean(prefs::kReverseAutologinEnabled, false);
}
void SigninManager::CompletePendingSignin() {
DCHECK(!possibly_invalid_username_.empty());
OnSignedIn(possibly_invalid_username_);
if (client_->ShouldMergeSigninCredentialsIntoCookieJar()) {
merge_session_helper_.reset(new MergeSessionHelper(
token_service_, client_->GetURLRequestContext(), NULL));
}
DCHECK(!temp_refresh_token_.empty());
DCHECK(!GetAuthenticatedUsername().empty());
token_service_->UpdateCredentials(GetAuthenticatedUsername(),
temp_refresh_token_);
temp_refresh_token_.clear();
if (client_->ShouldMergeSigninCredentialsIntoCookieJar())
merge_session_helper_->LogIn(GetAuthenticatedUsername());
}
void SigninManager::OnExternalSigninCompleted(const std::string& username) {
OnSignedIn(username);
}
void SigninManager::OnSignedIn(const std::string& username) {
SetAuthenticatedUsername(username);
possibly_invalid_username_.clear();
FOR_EACH_OBSERVER(
Observer,
observer_list_,
GoogleSigninSucceeded(GetAuthenticatedUsername(), password_));
client_->GoogleSigninSucceeded(GetAuthenticatedUsername(), password_);
password_.clear();
DisableOneClickSignIn(client_->GetPrefs());
}
void SigninManager::ProhibitSignout(bool prohibit_signout) {
prohibit_signout_ = prohibit_signout;
}
bool SigninManager::IsSignoutProhibited() const { return prohibit_signout_; }