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/base/text/text_elider.h" 20 #include "ui/gfx/font.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 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 string16 elided_username = ui::ElideEmail(UTF8ToUTF16(username), 79 gfx::Font(), 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 string16* status_label, 94 string16* link_label) { 95 string16 username = UTF8ToUTF16(signin_manager.GetAuthenticatedUsername()); 96 string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 97 if (link_label) 98 link_label->assign(l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL)); 99 100 const GoogleServiceAuthError::State state = 101 SigninGlobalError::GetForProfile(profile)->GetLastAuthError().state(); 102 switch (state) { 103 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 104 case GoogleServiceAuthError::ACCOUNT_DELETED: 105 case GoogleServiceAuthError::ACCOUNT_DISABLED: 106 // If the user name is empty then the first login failed, otherwise the 107 // credentials are out-of-date. 108 if (username.empty()) { 109 if (status_label) { 110 status_label->assign( 111 l10n_util::GetStringUTF16(IDS_SYNC_INVALID_USER_CREDENTIALS)); 112 } 113 } else { 114 if (status_label) { 115 status_label->assign( 116 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_INFO_OUT_OF_DATE)); 117 } 118 } 119 break; 120 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: 121 if (status_label) { 122 status_label->assign( 123 l10n_util::GetStringUTF16(IDS_SYNC_SERVICE_UNAVAILABLE)); 124 } 125 if (link_label) 126 link_label->clear(); 127 break; 128 case GoogleServiceAuthError::CONNECTION_FAILED: 129 if (status_label) { 130 status_label->assign( 131 l10n_util::GetStringFUTF16(IDS_SYNC_SERVER_IS_UNREACHABLE, 132 product_name)); 133 } 134 // Note that there is little the user can do if the server is not 135 // reachable. Since attempting to re-connect is done automatically by 136 // the Syncer, we do not show the (re)login link. 137 if (link_label) 138 link_label->clear(); 139 break; 140 default: 141 if (status_label) { 142 status_label->assign(l10n_util::GetStringUTF16( 143 IDS_SYNC_ERROR_SIGNING_IN)); 144 } 145 break; 146 } 147 } 148 149 } // namespace signin_ui_util 150