Index: chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm |
diff --git a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm |
index ba08b6d7ec458b5492c0a27e54c474fdee0066dd..9b06c91157113c0f18146a7ee00c3fd22ce511c9 100644 |
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm |
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm |
@@ -228,6 +228,12 @@ NSView* BuildTitleCard(NSRect frame_rect, |
return container.autorelease(); |
} |
+bool HasAuthError(Profile* profile) { |
+ const SigninErrorController* error_controller = |
+ profiles::GetSigninErrorController(profile); |
+ return error_controller && error_controller->HasError(); |
+} |
+ |
} // namespace |
// Class that listens to changes to the OAuth2Tokens for the active profile, |
@@ -279,7 +285,8 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
profiles::BubbleViewMode viewMode = [controller_ viewMode]; |
if (viewMode == profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT || |
viewMode == profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN || |
- viewMode == profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT) { |
+ viewMode == profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT || |
+ viewMode == profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH) { |
[controller_ initMenuContentsWithView: |
profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT]; |
} |
@@ -746,11 +753,13 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
frameOrigin:(NSPoint)frameOrigin |
action:(SEL)action; |
-// Creates an email account button with |title| and a remove icon. |tag| |
+// Creates an email account button with |title| and a remove icon. If |
+// |reauthRequired| is true, the button also displays a warning icon. |tag| |
// indicates which account the button refers to. |
- (NSButton*)accountButtonWithRect:(NSRect)rect |
title:(const std::string&)title |
- tag:(int)tag; |
+ tag:(int)tag |
+ reauthRequired:(BOOL)reauthRequired; |
@end |
@implementation ProfileChooserController |
@@ -827,6 +836,11 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
[self initMenuContentsWithView:profiles::BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL]; |
} |
+- (IBAction)showAccountReauthenticationView:(id)sender { |
+ DCHECK(!isGuestSession_); |
+ [self initMenuContentsWithView:profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH]; |
+} |
+ |
- (IBAction)removeAccount:(id)sender { |
DCHECK(!accountIdToRemove_.empty()); |
ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile( |
@@ -917,6 +931,13 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
// Guest profiles do not have a token service. |
isGuestSession_ = browser_->profile()->IsGuestSession(); |
+ // If view mode is PROFILE_CHOOSER but there is an auth error, force |
+ // ACCOUNT_MANAGEMENT mode. |
+ if (viewMode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER && |
+ HasAuthError(browser_->profile())) { |
+ viewMode_ = profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT; |
+ } |
+ |
[[self bubble] setAlignment:info_bubble::kAlignRightEdgeToAnchorEdge]; |
[[self bubble] setArrowLocation:info_bubble::kNoArrow]; |
[[self bubble] setBackgroundColor:GetDialogBackgroundColor()]; |
@@ -1506,21 +1527,32 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
std::vector<std::string>accounts = |
profiles::GetSecondaryAccountsForProfile(profile, primaryAccount); |
+ // If there is an account with an authentication error, it needs to be |
+ // badged with a warning icon. |
+ const SigninErrorController* errorController = |
+ profiles::GetSigninErrorController(profile); |
+ std::string errorAccountId = |
+ errorController ? errorController->error_account_id() : std::string(); |
+ |
rect.origin.y = 0; |
for (size_t i = 0; i < accounts.size(); ++i) { |
// Save the original email address, as the button text could be elided. |
currentProfileAccounts_[i] = accounts[i]; |
- NSButton* accountButton = [self accountButtonWithRect:rect |
- title:accounts[i] |
- tag:i]; |
+ NSButton* accountButton = |
+ [self accountButtonWithRect:rect |
+ title:accounts[i] |
+ tag:i |
+ reauthRequired:errorAccountId == accounts[i]]; |
[container addSubview:accountButton]; |
rect.origin.y = NSMaxY([accountButton frame]); |
} |
// The primary account should always be listed first. |
- NSButton* accountButton = [self accountButtonWithRect:rect |
- title:primaryAccount |
- tag:kPrimaryProfileTag]; |
+ NSButton* accountButton = |
+ [self accountButtonWithRect:rect |
+ title:primaryAccount |
+ tag:kPrimaryProfileTag |
+ reauthRequired:errorAccountId == primaryAccount]; |
[container addSubview:accountButton]; |
[container setFrameSize:NSMakeSize(NSWidth([container frame]), |
NSMaxY([accountButton frame]))]; |
@@ -1532,20 +1564,41 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
[[NSView alloc] initWithFrame:NSZeroRect]); |
CGFloat yOffset = 0; |
- bool addSecondaryAccount = |
- viewMode_ == profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT; |
- signin::Source source = addSecondaryAccount ? |
- signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT : |
- signin::SOURCE_AVATAR_BUBBLE_SIGN_IN; |
+ GURL url; |
+ int messageId = -1; |
+ SigninErrorController* errorController = NULL; |
+ switch (viewMode_) { |
+ case profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN: |
+ url = signin::GetPromoURL(signin::SOURCE_AVATAR_BUBBLE_SIGN_IN, |
+ false /* auto_close */, |
+ true /* is_constrained */); |
+ messageId = IDS_PROFILES_GAIA_SIGNIN_TITLE; |
+ break; |
+ case profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT: |
+ url = signin::GetPromoURL(signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT, |
+ false /* auto_close */, |
+ true /* is_constrained */); |
+ messageId = IDS_PROFILES_GAIA_ADD_ACCOUNT_TITLE; |
+ break; |
+ case profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH: |
+ DCHECK(HasAuthError(browser_->profile())); |
+ errorController = profiles::GetSigninErrorController(browser_->profile()); |
+ url = signin::GetReauthURL( |
+ browser_->profile(), |
+ errorController ? errorController->error_username() : std::string()); |
+ messageId = IDS_PROFILES_GAIA_REAUTH_TITLE; |
+ break; |
+ default: |
+ NOTREACHED() << "Called with invalid mode=" << viewMode_; |
+ break; |
+ } |
webContents_.reset(content::WebContents::Create( |
content::WebContents::CreateParams(browser_->profile()))); |
- webContents_->GetController().LoadURL( |
- signin::GetPromoURL( |
- source, false /* auto_close */, true /* is_constrained */), |
- content::Referrer(), |
- content::PAGE_TRANSITION_AUTO_TOPLEVEL, |
- std::string()); |
+ webContents_->GetController().LoadURL(url, |
+ content::Referrer(), |
+ content::PAGE_TRANSITION_AUTO_TOPLEVEL, |
+ std::string()); |
NSView* webview = webContents_->GetNativeView(); |
[webview setFrameSize:NSMakeSize(kFixedGaiaViewWidth, kFixedGaiaViewHeight)]; |
[container addSubview:webview]; |
@@ -1558,9 +1611,8 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
yOffset = NSMaxY([separator frame]) + kSmallVerticalSpacing; |
NSView* titleView = BuildTitleCard( |
- NSMakeRect(0, yOffset, kFixedGaiaViewWidth,0), |
- addSecondaryAccount ? IDS_PROFILES_GAIA_ADD_ACCOUNT_TITLE : |
- IDS_PROFILES_GAIA_SIGNIN_TITLE, |
+ NSMakeRect(0, yOffset, kFixedGaiaViewWidth, 0), |
+ messageId, |
self /* backButtonTarget*/, |
@selector(navigateBackFromSigninPage:) /* backButtonAction */); |
[container addSubview:titleView]; |
@@ -1749,29 +1801,47 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
- (NSButton*)accountButtonWithRect:(NSRect)rect |
title:(const std::string&)title |
- tag:(int)tag { |
+ tag:(int)tag |
+ reauthRequired:(BOOL)reauthRequired { |
+ ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
+ NSImage* deleteImage = rb->GetNativeImageNamed(IDR_CLOSE_1).ToNSImage(); |
+ CGFloat deleteImageWidth = [deleteImage size].width; |
+ NSImage* warningImage = reauthRequired ? rb->GetNativeImageNamed( |
+ IDR_ICON_PROFILES_ACCOUNT_BUTTON_ERROR).ToNSImage() : nil; |
+ CGFloat warningImageWidth = [warningImage size].width; |
+ |
+ CGFloat availableTextWidth = rect.size.width - kHorizontalSpacing - |
+ warningImageWidth - deleteImageWidth; |
+ if (warningImage) |
+ availableTextWidth -= kHorizontalSpacing; |
+ |
NSColor* backgroundColor = gfx::SkColorToCalibratedNSColor( |
profiles::kAvatarBubbleAccountsBackgroundColor); |
base::scoped_nsobject<BackgroundColorHoverButton> button( |
[[BackgroundColorHoverButton alloc] initWithFrame:rect |
imageTitleSpacing:0 |
backgroundColor:backgroundColor]); |
- ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
- NSImage* defaultImage = rb->GetNativeImageNamed(IDR_CLOSE_1).AsNSImage(); |
- CGFloat kDeleteButtonWidth = [defaultImage size].width; |
- CGFloat availableWidth = rect.size.width - |
- kDeleteButtonWidth - kHorizontalSpacing; |
- [button setTitle:ElideEmail(title, availableWidth)]; |
+ [button setTitle:ElideEmail(title, availableTextWidth)]; |
[button setAlignment:NSLeftTextAlignment]; |
[button setBordered:NO]; |
+ if (reauthRequired) { |
+ [button setDefaultImage:warningImage]; |
+ [button setImagePosition:NSImageLeft]; |
+ [button setTarget:self]; |
+ [button setAction:@selector(showAccountReauthenticationView:)]; |
+ [button setTag:tag]; |
+ } |
// Delete button. |
- rect.origin = NSMakePoint(availableWidth, 0); |
- rect.size.width = kDeleteButtonWidth; |
+ NSRect buttonRect; |
+ NSDivideRect(rect, &buttonRect, &rect, |
+ deleteImageWidth + kHorizontalSpacing, NSMaxXEdge); |
+ buttonRect.origin.y = 0; |
+ |
base::scoped_nsobject<HoverImageButton> deleteButton( |
- [[HoverImageButton alloc] initWithFrame:rect]); |
+ [[HoverImageButton alloc] initWithFrame:buttonRect]); |
[deleteButton setBordered:NO]; |
- [deleteButton setDefaultImage:defaultImage]; |
+ [deleteButton setDefaultImage:deleteImage]; |
[deleteButton setHoverImage:rb->GetNativeImageNamed( |
IDR_CLOSE_1_H).ToNSImage()]; |
[deleteButton setPressedImage:rb->GetNativeImageNamed( |
@@ -1781,6 +1851,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
[deleteButton setTag:tag]; |
[button addSubview:deleteButton]; |
+ |
return button.autorelease(); |
} |