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