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_global_error.h" 6 7 #include "base/logging.h" 8 #include "chrome/app/chrome_command_ids.h" 9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/signin/signin_header_helper.h" 11 #include "chrome/browser/signin/signin_manager_factory.h" 12 #include "chrome/browser/signin/signin_promo.h" 13 #include "chrome/browser/ui/browser_commands.h" 14 #include "chrome/browser/ui/browser_window.h" 15 #include "chrome/browser/ui/chrome_pages.h" 16 #include "chrome/browser/ui/global_error/global_error_service.h" 17 #include "chrome/browser/ui/global_error/global_error_service_factory.h" 18 #include "chrome/browser/ui/singleton_tabs.h" 19 #include "chrome/browser/ui/webui/signin/login_ui_service.h" 20 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" 21 #include "chrome/common/url_constants.h" 22 #include "components/signin/core/browser/signin_manager.h" 23 #include "components/signin/core/common/profile_management_switches.h" 24 #include "grit/chromium_strings.h" 25 #include "grit/generated_resources.h" 26 #include "net/base/url_util.h" 27 #include "ui/base/l10n/l10n_util.h" 28 29 SigninGlobalError::SigninGlobalError( 30 SigninErrorController* error_controller, 31 Profile* profile) 32 : profile_(profile), 33 error_controller_(error_controller), 34 is_added_to_global_error_service_(false) { 35 error_controller_->AddObserver(this); 36 is_added_to_global_error_service_ = !switches::IsNewAvatarMenu(); 37 if (is_added_to_global_error_service_) 38 GlobalErrorServiceFactory::GetForProfile(profile_)->AddGlobalError(this); 39 } 40 41 SigninGlobalError::~SigninGlobalError() { 42 DCHECK(!error_controller_) 43 << "SigninGlobalError::Shutdown() was not called"; 44 } 45 46 bool SigninGlobalError::HasError() { 47 return HasMenuItem(); 48 } 49 50 void SigninGlobalError::AttemptToFixError(Browser* browser) { 51 if (!HasError()) 52 return; 53 54 ExecuteMenuItem(browser); 55 } 56 57 void SigninGlobalError::Shutdown() { 58 if (is_added_to_global_error_service_) { 59 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError(this); 60 is_added_to_global_error_service_ = false; 61 } 62 63 error_controller_->RemoveObserver(this); 64 error_controller_ = NULL; 65 } 66 67 bool SigninGlobalError::HasMenuItem() { 68 return error_controller_->HasError(); 69 } 70 71 int SigninGlobalError::MenuItemCommandID() { 72 return IDC_SHOW_SIGNIN_ERROR; 73 } 74 75 base::string16 SigninGlobalError::MenuItemLabel() { 76 // Notify the user if there's an auth error the user should know about. 77 if (error_controller_->HasError()) 78 return l10n_util::GetStringUTF16(IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM); 79 return base::string16(); 80 } 81 82 void SigninGlobalError::ExecuteMenuItem(Browser* browser) { 83 #if defined(OS_CHROMEOS) 84 if (error_controller_->auth_error().state() != 85 GoogleServiceAuthError::NONE) { 86 DVLOG(1) << "Signing out the user to fix a sync error."; 87 // TODO(beng): seems like this could just call chrome::AttemptUserExit(). 88 chrome::ExecuteCommand(browser, IDC_EXIT); 89 return; 90 } 91 #endif 92 93 // Global errors don't show up in the wrench menu on android. 94 #if !defined(OS_ANDROID) 95 LoginUIService* login_ui = LoginUIServiceFactory::GetForProfile(profile_); 96 if (login_ui->current_login_ui()) { 97 login_ui->current_login_ui()->FocusUI(); 98 return; 99 } 100 101 if (switches::IsNewAvatarMenu()) { 102 browser->window()->ShowAvatarBubbleFromAvatarButton( 103 BrowserWindow::AVATAR_BUBBLE_MODE_REAUTH, 104 signin::ManageAccountsParams()); 105 } else { 106 chrome::ShowSingletonTab( 107 browser, 108 signin::GetReauthURL(profile_, error_controller_->error_account_id())); 109 } 110 #endif 111 } 112 113 bool SigninGlobalError::HasBubbleView() { 114 return !GetBubbleViewMessages().empty(); 115 } 116 117 base::string16 SigninGlobalError::GetBubbleViewTitle() { 118 return l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE); 119 } 120 121 std::vector<base::string16> SigninGlobalError::GetBubbleViewMessages() { 122 std::vector<base::string16> messages; 123 124 // If the user isn't signed in, no need to display an error bubble. 125 SigninManagerBase* signin_manager = 126 SigninManagerFactory::GetForProfileIfExists(profile_); 127 if (signin_manager) { 128 std::string username = signin_manager->GetAuthenticatedUsername(); 129 if (username.empty()) 130 return messages; 131 } 132 133 if (!error_controller_->HasError()) 134 return messages; 135 136 switch (error_controller_->auth_error().state()) { 137 // TODO(rogerta): use account id in error messages. 138 139 // User credentials are invalid (bad acct, etc). 140 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 141 case GoogleServiceAuthError::SERVICE_ERROR: 142 case GoogleServiceAuthError::ACCOUNT_DELETED: 143 case GoogleServiceAuthError::ACCOUNT_DISABLED: 144 messages.push_back(l10n_util::GetStringUTF16( 145 IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE)); 146 break; 147 148 // Sync service is not available for this account's domain. 149 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: 150 messages.push_back(l10n_util::GetStringUTF16( 151 IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE)); 152 break; 153 154 // Generic message for "other" errors. 155 default: 156 messages.push_back(l10n_util::GetStringUTF16( 157 IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE)); 158 } 159 return messages; 160 } 161 162 base::string16 SigninGlobalError::GetBubbleViewAcceptButtonLabel() { 163 // If the auth service is unavailable, don't give the user the option to try 164 // signing in again. 165 if (error_controller_->auth_error().state() == 166 GoogleServiceAuthError::SERVICE_UNAVAILABLE) { 167 return l10n_util::GetStringUTF16( 168 IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_ACCEPT); 169 } else { 170 return l10n_util::GetStringUTF16(IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT); 171 } 172 } 173 174 base::string16 SigninGlobalError::GetBubbleViewCancelButtonLabel() { 175 return base::string16(); 176 } 177 178 void SigninGlobalError::OnBubbleViewDidClose(Browser* browser) { 179 } 180 181 void SigninGlobalError::BubbleViewAcceptButtonPressed(Browser* browser) { 182 ExecuteMenuItem(browser); 183 } 184 185 void SigninGlobalError::BubbleViewCancelButtonPressed(Browser* browser) { 186 NOTREACHED(); 187 } 188 189 void SigninGlobalError::OnErrorChanged() { 190 GlobalErrorServiceFactory::GetForProfile(profile_)->NotifyErrorsChanged(this); 191 } 192