signin_ui_util.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
1// Copyright (c) 2013 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 "chrome/browser/signin/signin_ui_util.h"
6
7#include "base/strings/sys_string_conversions.h"
8#include "base/strings/utf_string_conversions.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
11#include "chrome/browser/signin/signin_global_error.h"
12#include "chrome/browser/signin/signin_global_error_factory.h"
13#include "chrome/browser/signin/signin_manager_factory.h"
14#include "chrome/browser/sync/profile_sync_service.h"
15#include "chrome/browser/sync/profile_sync_service_factory.h"
16#include "chrome/browser/sync/sync_global_error.h"
17#include "chrome/browser/sync/sync_global_error_factory.h"
18#include "components/signin/core/browser/profile_oauth2_token_service.h"
19#include "components/signin/core/browser/signin_manager.h"
20#include "grit/chromium_strings.h"
21#include "grit/generated_resources.h"
22#include "ui/base/l10n/l10n_util.h"
23#include "ui/gfx/font_list.h"
24#include "ui/gfx/text_elider.h"
25
26namespace {
27// Maximum width of a username - we trim emails that are wider than this so
28// the wrench menu doesn't get ridiculously wide.
29const int kUsernameMaxWidth = 200;
30}  // namespace
31
32namespace signin_ui_util {
33
34GlobalError* GetSignedInServiceError(Profile* profile) {
35  std::vector<GlobalError*> errors = GetSignedInServiceErrors(profile);
36  if (errors.empty())
37    return NULL;
38  return errors[0];
39}
40
41std::vector<GlobalError*> GetSignedInServiceErrors(Profile* profile) {
42  std::vector<GlobalError*> errors;
43  // Chrome OS doesn't use SigninGlobalError or SyncGlobalError. Other platforms
44  // may use these services to show auth and sync errors in the toolbar menu.
45#if !defined(OS_CHROMEOS)
46  // Auth errors have the highest priority - after that, individual service
47  // errors.
48  SigninGlobalError* signin_error =
49      SigninGlobalErrorFactory::GetForProfile(profile);
50  if (signin_error && signin_error->HasMenuItem())
51    errors.push_back(signin_error);
52
53  // No auth error - now try other services. Currently the list is just hard-
54  // coded but in the future if we add more we can create some kind of
55  // registration framework.
56  if (profile->IsSyncAccessible()) {
57    SyncGlobalError* error = SyncGlobalErrorFactory::GetForProfile(profile);
58    if (error && error->HasMenuItem())
59      errors.push_back(error);
60  }
61#endif
62
63  return errors;
64}
65
66base::string16 GetSigninMenuLabel(Profile* profile) {
67  GlobalError* error = signin_ui_util::GetSignedInServiceError(profile);
68  if (error)
69    return error->MenuItemLabel();
70
71  // No errors, so just display the signed in user, if any.
72  ProfileSyncService* service = profile->IsSyncAccessible() ?
73      ProfileSyncServiceFactory::GetForProfile(profile) : NULL;
74
75  // Even if the user is signed in, don't display the "signed in as..."
76  // label if we're still setting up sync.
77  if (!service || !service->FirstSetupInProgress()) {
78    std::string username;
79    SigninManagerBase* signin_manager =
80        SigninManagerFactory::GetForProfileIfExists(profile);
81    if (signin_manager)
82      username = signin_manager->GetAuthenticatedUsername();
83    if (!username.empty() && !signin_manager->AuthInProgress()) {
84      base::string16 elided_username = gfx::ElideEmail(
85          base::UTF8ToUTF16(username), gfx::FontList(), kUsernameMaxWidth);
86      return l10n_util::GetStringFUTF16(IDS_SYNC_MENU_SYNCED_LABEL,
87                                        elided_username);
88    }
89  }
90  return l10n_util::GetStringFUTF16(IDS_SYNC_MENU_PRE_SYNCED_LABEL,
91      l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
92}
93
94// Given an authentication state this helper function returns various labels
95// that can be used to display information about the state.
96void GetStatusLabelsForAuthError(Profile* profile,
97                                 const SigninManagerBase& signin_manager,
98                                 base::string16* status_label,
99                                 base::string16* link_label) {
100  base::string16 username =
101      base::UTF8ToUTF16(signin_manager.GetAuthenticatedUsername());
102  base::string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
103  if (link_label)
104    link_label->assign(l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL));
105
106  const GoogleServiceAuthError::State state =
107      ProfileOAuth2TokenServiceFactory::GetForProfile(profile)->
108          signin_error_controller()->auth_error().state();
109  switch (state) {
110    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
111    case GoogleServiceAuthError::SERVICE_ERROR:
112    case GoogleServiceAuthError::ACCOUNT_DELETED:
113    case GoogleServiceAuthError::ACCOUNT_DISABLED:
114      // If the user name is empty then the first login failed, otherwise the
115      // credentials are out-of-date.
116      if (username.empty()) {
117        if (status_label) {
118          status_label->assign(
119              l10n_util::GetStringUTF16(IDS_SYNC_INVALID_USER_CREDENTIALS));
120        }
121      } else {
122        if (status_label) {
123          status_label->assign(
124              l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_INFO_OUT_OF_DATE));
125        }
126      }
127      break;
128    case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
129      if (status_label) {
130        status_label->assign(
131            l10n_util::GetStringUTF16(IDS_SYNC_SERVICE_UNAVAILABLE));
132      }
133      if (link_label)
134        link_label->clear();
135      break;
136    case GoogleServiceAuthError::CONNECTION_FAILED:
137      if (status_label) {
138        status_label->assign(
139            l10n_util::GetStringFUTF16(IDS_SYNC_SERVER_IS_UNREACHABLE,
140                                       product_name));
141      }
142      // Note that there is little the user can do if the server is not
143      // reachable. Since attempting to re-connect is done automatically by
144      // the Syncer, we do not show the (re)login link.
145      if (link_label)
146        link_label->clear();
147      break;
148    default:
149      if (status_label) {
150        status_label->assign(l10n_util::GetStringUTF16(
151            IDS_SYNC_ERROR_SIGNING_IN));
152      }
153      break;
154  }
155}
156
157}  // namespace signin_ui_util
158