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.
5 #include "components/signin/core/browser/signin_error_controller.h"
7 #include "components/signin/core/browser/signin_metrics.h"
11 typedef std::set
<const SigninErrorController::AuthStatusProvider
*>
12 AuthStatusProviderSet
;
16 SigninErrorController::AuthStatusProvider::AuthStatusProvider() {
19 SigninErrorController::AuthStatusProvider::~AuthStatusProvider() {
22 SigninErrorController::SigninErrorController()
23 : auth_error_(GoogleServiceAuthError::AuthErrorNone()) {
26 SigninErrorController::~SigninErrorController() {
27 DCHECK(provider_set_
.empty())
28 << "All AuthStatusProviders should be unregistered before"
29 << " SigninErrorController::Shutdown() is called";
32 void SigninErrorController::AddProvider(const AuthStatusProvider
* provider
) {
33 DCHECK(provider_set_
.find(provider
) == provider_set_
.end())
34 << "Adding same AuthStatusProvider multiple times";
35 provider_set_
.insert(provider
);
39 void SigninErrorController::RemoveProvider(const AuthStatusProvider
* provider
) {
40 AuthStatusProviderSet::iterator iter
= provider_set_
.find(provider
);
41 DCHECK(iter
!= provider_set_
.end())
42 << "Removing provider that was never added";
43 provider_set_
.erase(iter
);
47 void SigninErrorController::AuthStatusChanged() {
48 GoogleServiceAuthError::State prev_state
= auth_error_
.state();
49 std::string prev_account_id
= error_account_id_
;
50 bool error_changed
= false;
52 // Find an error among the status providers. If |auth_error_| has an
53 // actionable error state and some provider exposes a similar error and
54 // account id, use that error. Otherwise, just take the first actionable
56 for (AuthStatusProviderSet::const_iterator it
= provider_set_
.begin();
57 it
!= provider_set_
.end(); ++it
) {
58 GoogleServiceAuthError error
= (*it
)->GetAuthStatus();
60 // Ignore the states we don't want to elevate to the user.
61 if (error
.state() == GoogleServiceAuthError::NONE
||
62 error
.state() == GoogleServiceAuthError::CONNECTION_FAILED
) {
66 std::string account_id
= (*it
)->GetAccountId();
68 // Prioritize this error if it matches the previous |auth_error_|.
69 if (error
.state() == prev_state
&& account_id
== prev_account_id
) {
71 error_account_id_
= account_id
;
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.
80 error_account_id_
= account_id
;
85 if (!error_changed
&& prev_state
!= GoogleServiceAuthError::NONE
) {
86 // No provider reported an error, so clear the error we have now.
87 auth_error_
= GoogleServiceAuthError::AuthErrorNone();
88 error_account_id_
.clear();
93 signin_metrics::LogAuthError(auth_error_
.state());
94 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnErrorChanged());
98 bool SigninErrorController::HasError() const {
99 return auth_error_
.state() != GoogleServiceAuthError::NONE
&&
100 auth_error_
.state() != GoogleServiceAuthError::CONNECTION_FAILED
;
103 void SigninErrorController::AddObserver(Observer
* observer
) {
104 observer_list_
.AddObserver(observer
);
107 void SigninErrorController::RemoveObserver(Observer
* observer
) {
108 observer_list_
.RemoveObserver(observer
);