1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "components/signin/core/browser/signin_error_controller.h" 6 7namespace { 8 9typedef std::set<const SigninErrorController::AuthStatusProvider*> 10 AuthStatusProviderSet; 11 12} // namespace 13 14SigninErrorController::AuthStatusProvider::AuthStatusProvider() { 15} 16 17SigninErrorController::AuthStatusProvider::~AuthStatusProvider() { 18} 19 20SigninErrorController::SigninErrorController() 21 : auth_error_(GoogleServiceAuthError::AuthErrorNone()) { 22} 23 24SigninErrorController::~SigninErrorController() { 25 DCHECK(provider_set_.empty()) 26 << "All AuthStatusProviders should be unregistered before" 27 << " SigninErrorController::Shutdown() is called"; 28} 29 30void SigninErrorController::AddProvider(const AuthStatusProvider* provider) { 31 DCHECK(provider_set_.find(provider) == provider_set_.end()) 32 << "Adding same AuthStatusProvider multiple times"; 33 provider_set_.insert(provider); 34 AuthStatusChanged(); 35} 36 37void SigninErrorController::RemoveProvider(const AuthStatusProvider* provider) { 38 AuthStatusProviderSet::iterator iter = provider_set_.find(provider); 39 DCHECK(iter != provider_set_.end()) 40 << "Removing provider that was never added"; 41 provider_set_.erase(iter); 42 AuthStatusChanged(); 43} 44 45void SigninErrorController::AuthStatusChanged() { 46 GoogleServiceAuthError::State prev_state = auth_error_.state(); 47 std::string prev_account_id = error_account_id_; 48 bool error_changed = false; 49 50 // Find an error among the status providers. If |auth_error_| has an 51 // actionable error state and some provider exposes a similar error and 52 // account id, use that error. Otherwise, just take the first actionable 53 // error we find. 54 for (AuthStatusProviderSet::const_iterator it = provider_set_.begin(); 55 it != provider_set_.end(); ++it) { 56 GoogleServiceAuthError error = (*it)->GetAuthStatus(); 57 58 // Ignore the states we don't want to elevate to the user. 59 if (error.state() == GoogleServiceAuthError::NONE || 60 error.state() == GoogleServiceAuthError::CONNECTION_FAILED) { 61 continue; 62 } 63 64 std::string account_id = (*it)->GetAccountId(); 65 std::string username = (*it)->GetUsername(); 66 67 // Prioritize this error if it matches the previous |auth_error_|. 68 if (error.state() == prev_state && account_id == prev_account_id) { 69 auth_error_ = error; 70 error_account_id_ = account_id; 71 error_username_ = username; 72 error_changed = true; 73 break; 74 } 75 76 // Use this error if we haven't found one already, but keep looking for the 77 // previous |auth_error_| in case there's a match elsewhere in the set. 78 if (!error_changed) { 79 auth_error_ = error; 80 error_account_id_ = account_id; 81 error_username_ = username; 82 error_changed = true; 83 } 84 } 85 86 if (!error_changed && prev_state != GoogleServiceAuthError::NONE) { 87 // No provider reported an error, so clear the error we have now. 88 auth_error_ = GoogleServiceAuthError::AuthErrorNone(); 89 error_account_id_.clear(); 90 error_username_.clear(); 91 error_changed = true; 92 } 93 94 if (error_changed) { 95 FOR_EACH_OBSERVER(Observer, observer_list_, OnErrorChanged()); 96 } 97} 98 99bool SigninErrorController::HasError() const { 100 return auth_error_.state() != GoogleServiceAuthError::NONE && 101 auth_error_.state() != GoogleServiceAuthError::CONNECTION_FAILED; 102} 103 104void SigninErrorController::AddObserver(Observer* observer) { 105 observer_list_.AddObserver(observer); 106} 107 108void SigninErrorController::RemoveObserver(Observer* observer) { 109 observer_list_.RemoveObserver(observer); 110} 111