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 ea26e90dc3ef73cd94a95cf74770d8392f846bab..61b2771dbafd454d870488cb57921af54b3bd8fd 100644 |
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm |
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm |
@@ -230,6 +230,31 @@ NSView* BuildTitleCard(NSRect frame_rect, |
return container.autorelease(); |
} |
+bool HasAuthError(Profile* profile) { |
msw
2014/06/03 04:15:31
nit: this is used twice, is a helper necessary?
noms (inactive)
2014/06/06 20:33:44
I thought it looked a little nicer, because the th
|
+ const SigninErrorController* error = |
+ profiles::GetSigninErrorController(profile); |
+ return error && error->HasError(); |
+} |
+ |
+std::string GetAuthErrorAccountId(Profile* profile) { |
msw
2014/06/03 04:15:31
nit: this is used once, please inline it.
noms (inactive)
2014/06/06 20:33:44
Done.
|
+ SigninErrorController* error = |
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile)-> |
+ signin_error_controller(); |
+ if (!error) |
msw
2014/06/03 04:15:31
nit: return error ? error->error_account_id() : st
noms (inactive)
2014/06/06 20:33:44
Done.
|
+ return std::string(); |
+ |
+ return error->error_account_id(); |
+} |
+ |
+std::string GetAuthErrorUsername(Profile* profile) { |
msw
2014/06/03 04:15:31
nit: this is used once, please inline it.
noms (inactive)
2014/06/06 20:33:43
Done.
|
+ const SigninErrorController* error = |
+ profiles::GetSigninErrorController(profile); |
+ if (!error) |
msw
2014/06/03 04:15:31
nit: return error ? error->error_username() : std:
noms (inactive)
2014/06/06 20:33:44
Done.
|
+ return std::string(); |
+ |
+ return error->error_username(); |
+} |
+ |
} // namespace |
// Class that listens to changes to the OAuth2Tokens for the active profile, |
@@ -281,7 +306,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]; |
} |
@@ -736,11 +762,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 |
@@ -816,6 +844,11 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
[self initMenuContentsWithView:profiles::BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL]; |
} |
+- (IBAction)showAccountReauthView:(id)sender { |
+ DCHECK(!isGuestSession_); |
+ [self initMenuContentsWithView:profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH]; |
+} |
+ |
- (IBAction)removeAccount:(id)sender { |
DCHECK(!accountIdToRemove_.empty()); |
ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile( |
@@ -903,6 +936,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()]; |
@@ -1481,21 +1521,28 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
std::vector<std::string>accounts = |
profiles::GetSecondaryAccountsForProfile(profile, primaryAccount); |
+ // Get state of authentication error, if any. |
msw
2014/06/03 04:15:31
nit: this comment should be made more helpful or r
noms (inactive)
2014/06/06 20:33:43
Done.
|
+ std::string errorAccountId = GetAuthErrorAccountId(profile); |
+ |
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]]; |
msw
2014/06/03 04:15:31
Couldn't multiple accounts have auth errors at the
noms (inactive)
2014/06/06 20:33:44
They could, but the way it works right now is that
msw
2014/06/09 19:02:38
It's also unclear to me how this retains the autho
noms (inactive)
2014/06/10 15:02:47
A little background: this error controller used to
|
[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]))]; |
@@ -1507,20 +1554,39 @@ 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; |
msw
2014/06/03 04:15:31
nit: initialize this value
noms (inactive)
2014/06/06 20:33:44
Done.
|
+ 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: { |
msw
2014/06/03 04:15:31
nit: you shouldn't need these curly braces.
noms (inactive)
2014/06/06 20:33:44
Without the curly braces, the compiler is unhappy
|
+ DCHECK(HasAuthError(browser_->profile())); |
+ url = signin::GetReauthURL(browser_->profile(), |
+ GetAuthErrorUsername(browser_->profile())); |
+ messageId = IDS_PROFILES_GAIA_REAUTH_TITLE; |
+ break; |
+ } |
+ default: |
+ NOTREACHED() << "Called with invalid mode=" << viewMode_; |
+ return NULL; |
+ } |
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]; |
@@ -1533,9 +1599,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]; |
@@ -1724,29 +1789,45 @@ 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).AsNSImage(); |
+ CGFloat deleteImageWidth = [deleteImage size].width; |
+ |
+ NSImage* reauthImage = nil; |
+ CGFloat reauthImageWidth = 0; |
+ if (reauthRequired) { |
+ reauthImage = rb->GetNativeImageNamed( |
+ IDR_ICON_PROFILES_ACCOUNT_BUTTON_ERROR).AsNSImage(); |
+ reauthImageWidth = [reauthImage size].width; |
msw
2014/06/03 04:15:31
Do you need to add some padding, like kHorizontalS
noms (inactive)
2014/06/06 20:33:44
Done.
|
+ } |
+ |
+ CGFloat availableTextWidth = rect.size.width - kHorizontalSpacing - |
+ deleteImageWidth - reauthImageWidth; |
+ |
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 setTarget:self]; |
+ [button setAction:@selector(showAccountReauthView:)]; |
+ [button setTag:tag]; |
+ } |
// Delete button. |
- rect.origin = NSMakePoint(availableWidth, 0); |
- rect.size.width = kDeleteButtonWidth; |
+ rect.origin = NSMakePoint(availableTextWidth + reauthImageWidth, 0); |
+ rect.size.width = deleteImageWidth; |
base::scoped_nsobject<HoverImageButton> deleteButton( |
[[HoverImageButton alloc] initWithFrame:rect]); |
[deleteButton setBordered:NO]; |
- [deleteButton setDefaultImage:defaultImage]; |
+ [deleteButton setDefaultImage:deleteImage]; |
[deleteButton setHoverImage:rb->GetNativeImageNamed( |
IDR_CLOSE_1_H).ToNSImage()]; |
[deleteButton setPressedImage:rb->GetNativeImageNamed( |
@@ -1756,6 +1837,16 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, |
[deleteButton setTag:tag]; |
[button addSubview:deleteButton]; |
+ |
+ // Warning icon. |
+ if (reauthRequired) { |
+ base::scoped_nsobject<NSImageView> reauthIcon( |
+ [[NSImageView alloc] initWithFrame:NSMakeRect( |
+ availableTextWidth, 0, reauthImageWidth, rect.size.height)]); |
+ [reauthIcon setImage:reauthImage]; |
+ [button addSubview:reauthIcon]; |
+ } |
+ |
return button.autorelease(); |
} |