blob: eb680105d10cb8a2674404d1a71b543ac518a3aa [file] [log] [blame]
// 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 "components/signin/core/browser/signin_error_controller.h"
namespace {
typedef std::set<const SigninErrorController::AuthStatusProvider*>
AuthStatusProviderSet;
} // namespace
SigninErrorController::AuthStatusProvider::AuthStatusProvider() {
}
SigninErrorController::AuthStatusProvider::~AuthStatusProvider() {
}
SigninErrorController::SigninErrorController()
: auth_error_(GoogleServiceAuthError::AuthErrorNone()) {
}
SigninErrorController::~SigninErrorController() {
DCHECK(provider_set_.empty())
<< "All AuthStatusProviders should be unregistered before"
<< " SigninErrorController::Shutdown() is called";
}
void SigninErrorController::AddProvider(const AuthStatusProvider* provider) {
DCHECK(provider_set_.find(provider) == provider_set_.end())
<< "Adding same AuthStatusProvider multiple times";
provider_set_.insert(provider);
AuthStatusChanged();
}
void SigninErrorController::RemoveProvider(const AuthStatusProvider* provider) {
AuthStatusProviderSet::iterator iter = provider_set_.find(provider);
DCHECK(iter != provider_set_.end())
<< "Removing provider that was never added";
provider_set_.erase(iter);
AuthStatusChanged();
}
void SigninErrorController::AuthStatusChanged() {
GoogleServiceAuthError::State prev_state = auth_error_.state();
std::string prev_account_id = error_account_id_;
bool error_changed = false;
// Find an error among the status providers. If |auth_error_| has an
// actionable error state and some provider exposes a similar error and
// account id, use that error. Otherwise, just take the first actionable
// error we find.
for (AuthStatusProviderSet::const_iterator it = provider_set_.begin();
it != provider_set_.end(); ++it) {
GoogleServiceAuthError error = (*it)->GetAuthStatus();
// Ignore the states we don't want to elevate to the user.
if (error.state() == GoogleServiceAuthError::NONE ||
error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
continue;
}
std::string account_id = (*it)->GetAccountId();
std::string username = (*it)->GetUsername();
// Prioritize this error if it matches the previous |auth_error_|.
if (error.state() == prev_state && account_id == prev_account_id) {
auth_error_ = error;
error_account_id_ = account_id;
error_username_ = username;
error_changed = true;
break;
}
// Use this error if we haven't found one already, but keep looking for the
// previous |auth_error_| in case there's a match elsewhere in the set.
if (!error_changed) {
auth_error_ = error;
error_account_id_ = account_id;
error_username_ = username;
error_changed = true;
}
}
if (!error_changed && prev_state != GoogleServiceAuthError::NONE) {
// No provider reported an error, so clear the error we have now.
auth_error_ = GoogleServiceAuthError::AuthErrorNone();
error_account_id_.clear();
error_username_.clear();
error_changed = true;
}
if (error_changed) {
FOR_EACH_OBSERVER(Observer, observer_list_, OnErrorChanged());
}
}
bool SigninErrorController::HasError() const {
return auth_error_.state() != GoogleServiceAuthError::NONE &&
auth_error_.state() != GoogleServiceAuthError::CONNECTION_FAILED;
}
void SigninErrorController::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void SigninErrorController::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}