signin_error_controller.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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
66    // Prioritize this error if it matches the previous |auth_error_|.
67    if (error.state() == prev_state && account_id == prev_account_id) {
68      auth_error_ = error;
69      error_account_id_ = account_id;
70      error_changed = true;
71      break;
72    }
73
74    // Use this error if we haven't found one already, but keep looking for the
75    // previous |auth_error_| in case there's a match elsewhere in the set.
76    if (!error_changed) {
77      auth_error_ = error;
78      error_account_id_ = account_id;
79      error_changed = true;
80    }
81  }
82
83  if (!error_changed && prev_state != GoogleServiceAuthError::NONE) {
84    // No provider reported an error, so clear the error we have now.
85    auth_error_ = GoogleServiceAuthError::AuthErrorNone();
86    error_account_id_.clear();
87    error_changed = true;
88  }
89
90  if (error_changed) {
91    FOR_EACH_OBSERVER(Observer, observer_list_, OnErrorChanged());
92  }
93}
94
95bool SigninErrorController::HasError() const {
96  return auth_error_.state() != GoogleServiceAuthError::NONE &&
97      auth_error_.state() != GoogleServiceAuthError::CONNECTION_FAILED;
98}
99
100void SigninErrorController::AddObserver(Observer* observer) {
101  observer_list_.AddObserver(observer);
102}
103
104void SigninErrorController::RemoveObserver(Observer* observer) {
105  observer_list_.RemoveObserver(observer);
106}
107