| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.h" | 5 #import "chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #include "chrome/browser/profiles/profile.h" | |
| 11 #import "chrome/browser/ui/cocoa/bubble_combobox.h" | |
| 12 #import "chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h" | 10 #import "chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h" |
| 13 #import "chrome/browser/ui/cocoa/passwords/passwords_bubble_utils.h" | 11 #import "chrome/browser/ui/cocoa/passwords/passwords_bubble_utils.h" |
| 14 #include "chrome/browser/ui/passwords/account_chooser_more_combobox_model.h" | 12 #include "chrome/browser/ui/passwords/password_dialog_controller.h" |
| 15 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" | |
| 16 #include "chrome/grit/generated_resources.h" | 13 #include "chrome/grit/generated_resources.h" |
| 17 #include "components/password_manager/core/common/credential_manager_types.h" | 14 #include "components/password_manager/core/common/credential_manager_types.h" |
| 15 #include "ui/base/cocoa/controls/hyperlink_text_view.h" |
| 18 #include "ui/base/l10n/l10n_util.h" | 16 #include "ui/base/l10n/l10n_util.h" |
| 19 | 17 |
| 20 @implementation CredentialItemCell { | 18 @implementation CredentialItemCell { |
| 21 base::scoped_nsobject<CredentialItemView> view_; | 19 base::scoped_nsobject<CredentialItemView> view_; |
| 22 } | 20 } |
| 23 - (id)initWithView:(CredentialItemView*)view { | 21 - (id)initWithView:(CredentialItemView*)view { |
| 24 if ((self = [super init])) | 22 if ((self = [super init])) |
| 25 view_.reset([view retain]); | 23 view_.reset([view retain]); |
| 26 return self; | 24 return self; |
| 27 } | 25 } |
| 28 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { | 26 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
| 29 [controlView addSubview:view_]; | 27 [controlView addSubview:view_]; |
| 30 [view_ setFrame:cellFrame]; | 28 [view_ setFrame:cellFrame]; |
| 31 } | 29 } |
| 32 - (id)copyWithZone:(NSZone*)zone { | 30 - (id)copyWithZone:(NSZone*)zone { |
| 33 return [[CredentialItemCell alloc] initWithView:view_]; | 31 return [[CredentialItemCell alloc] initWithView:view_]; |
| 34 } | 32 } |
| 35 - (CredentialItemView*)view { | 33 - (CredentialItemView*)view { |
| 36 return view_.get(); | 34 return view_.get(); |
| 37 } | 35 } |
| 38 @end | 36 @end |
| 39 | 37 |
| 40 @interface ManagePasswordsBubbleAccountChooserViewController() | 38 @interface AccountChooserViewController() |
| 41 - (id)initWithModel:(ManagePasswordsBubbleModel*)model | |
| 42 avatarManager:(AccountAvatarFetcherManager*)avatarManager | |
| 43 delegate:(id<ManagePasswordsBubbleContentViewDelegate>)delegate; | |
| 44 - (void)onCancelClicked:(id)sender; | 39 - (void)onCancelClicked:(id)sender; |
| 45 - (void)onLearnMoreClicked:(id)sender; | 40 + (NSArray*)credentialItemsFromBridge:(AccountChooserBridge*)bridge |
| 46 - (void)onSettingsClicked:(id)sender; | 41 delegate:(id<CredentialItemDelegate>)delegate; |
| 47 + (NSArray*)credentialItemsForModel:(ManagePasswordsBubbleModel*)model | |
| 48 delegate:(id<CredentialItemDelegate>)delegate; | |
| 49 @property(nonatomic, readonly) NSButton* cancelButton; | |
| 50 @property(nonatomic, readonly) BubbleCombobox* moreButton; | |
| 51 @property(nonatomic, readonly) NSTableView* credentialsView; | |
| 52 @end | 42 @end |
| 53 | 43 |
| 54 @implementation ManagePasswordsBubbleAccountChooserViewController | 44 @implementation AccountChooserViewController |
| 55 | 45 |
| 56 @synthesize cancelButton = cancelButton_; | 46 - (id)initWithBridge:(AccountChooserBridge*)bridge { |
| 57 @synthesize moreButton = moreButton_; | |
| 58 @synthesize credentialsView = credentialsView_; | |
| 59 | |
| 60 - (id)initWithModel:(ManagePasswordsBubbleModel*)model | |
| 61 avatarManager:(AccountAvatarFetcherManager*)avatarManager | |
| 62 delegate:(id<ManagePasswordsBubbleContentViewDelegate>)delegate { | |
| 63 DCHECK(model); | |
| 64 if (([super initWithDelegate:delegate])) { | |
| 65 model_ = model; | |
| 66 avatarManager_.reset([avatarManager retain]); | |
| 67 } | |
| 68 return self; | |
| 69 } | |
| 70 | |
| 71 - (id)initWithModel:(ManagePasswordsBubbleModel*)model | |
| 72 delegate:(id<ManagePasswordsBubbleContentViewDelegate>)delegate { | |
| 73 base::scoped_nsobject<AccountAvatarFetcherManager> avatarManager( | 47 base::scoped_nsobject<AccountAvatarFetcherManager> avatarManager( |
| 74 [[AccountAvatarFetcherManager alloc] | 48 [[AccountAvatarFetcherManager alloc] |
| 75 initWithRequestContext:model->GetProfile()->GetRequestContext()]); | 49 initWithRequestContext:bridge->GetRequestContext()]); |
| 76 return | 50 return [self initWithBridge:bridge avatarManager:avatarManager]; |
| 77 [self initWithModel:model avatarManager:avatarManager delegate:delegate]; | |
| 78 } | 51 } |
| 79 | 52 |
| 80 - (void)dealloc { | 53 - (void)dealloc { |
| 81 [credentialsView_ setDelegate:nil]; | 54 [credentialsView_ setDelegate:nil]; |
| 82 [credentialsView_ setDataSource:nil]; | 55 [credentialsView_ setDataSource:nil]; |
| 83 [super dealloc]; | 56 [super dealloc]; |
| 84 } | 57 } |
| 85 | 58 |
| 86 - (void)loadView { | 59 - (void)loadView { |
| 87 base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]); | 60 base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]); |
| 88 | 61 |
| 89 // ------------------------------------ | 62 // ------------------------------------ |
| 90 // | | | 63 // | | |
| 91 // | Choose an account etc etc | | 64 // | Choose an account etc etc | |
| 92 // | | | 65 // | | |
| 93 // | ---- | | 66 // | ---- | |
| 94 // | | | credential view | | 67 // | | | credential view | |
| 95 // | ---- | | 68 // | ---- | |
| 96 // | | | credential view | | 69 // | | | credential view | |
| 97 // | ---- | | 70 // | ---- | |
| 98 // | | | 71 // | | |
| 99 // | [ More v] [ Cancel ] | | 72 // | [ Cancel ] | |
| 100 // ------------------------------------ | 73 // ------------------------------------ |
| 101 | 74 |
| 102 // Create the views. | 75 // Create the views. |
| 103 // Title. | 76 // Title. |
| 104 NSTextField* title = | 77 std::pair<base::string16, gfx::Range> title_text = |
| 105 [self addTitleLabel:base::SysUTF16ToNSString(model_->title()) | 78 bridge_->GetDialogController()->GetAccoutChooserTitle(); |
| 106 toView:view]; | 79 titleView_ = TitleLabelWithLink(title_text.first, title_text.second, self); |
| 107 [title setAlignment:base::i18n::IsRTL() ? NSRightTextAlignment | 80 // Force the text to wrap to fit in the bubble size. |
| 108 : NSLeftTextAlignment]; | 81 [titleView_ setVerticallyResizable:YES]; |
| 82 const CGFloat width = kDesiredBubbleWidth - 2*kFramePadding; |
| 83 [titleView_ setFrameSize:NSMakeSize(width, MAXFLOAT)]; |
| 84 [titleView_ sizeToFit]; |
| 85 [view addSubview:titleView_]; |
| 109 | 86 |
| 110 // Credentials list. | 87 // Credentials list. |
| 111 credentialItems_.reset( | 88 credentialItems_.reset( |
| 112 [[[self class] credentialItemsForModel:model_ delegate:self] retain]); | 89 [[[self class] credentialItemsFromBridge:bridge_ delegate:self] retain]); |
| 113 base::scoped_nsobject<NSTableView> credentialsView( | 90 base::scoped_nsobject<NSTableView> credentialsView( |
| 114 [[NSTableView alloc] initWithFrame:NSZeroRect]); | 91 [[NSTableView alloc] initWithFrame:NSZeroRect]); |
| 115 [credentialsView | 92 [credentialsView |
| 116 setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone]; | 93 setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone]; |
| 117 NSTableColumn* column = | 94 NSTableColumn* column = |
| 118 [[[NSTableColumn alloc] initWithIdentifier:@""] autorelease]; | 95 [[[NSTableColumn alloc] initWithIdentifier:@""] autorelease]; |
| 119 [credentialsView addTableColumn:column]; | 96 [credentialsView addTableColumn:column]; |
| 120 [credentialsView setDelegate:self]; | 97 [credentialsView setDelegate:self]; |
| 121 [credentialsView setDataSource:self]; | 98 [credentialsView setDataSource:self]; |
| 122 [credentialsView setFocusRingType:NSFocusRingTypeNone]; | 99 [credentialsView setFocusRingType:NSFocusRingTypeNone]; |
| 123 credentialsView_ = credentialsView; | 100 credentialsView_ = credentialsView; |
| 124 [view addSubview:credentialsView_]; | 101 [view addSubview:credentialsView_]; |
| 125 | 102 |
| 126 // "Cancel" button. | 103 // "Cancel" button. |
| 127 cancelButton_ = | 104 cancelButton_ = DialogButton(l10n_util::GetNSString( |
| 128 [self addButton:l10n_util::GetNSString( | 105 IDS_CREDENTIAL_MANAGEMENT_ACCOUNT_CHOOSER_NO_THANKS)); |
| 129 IDS_CREDENTIAL_MANAGEMENT_ACCOUNT_CHOOSER_NO_THANKS) | 106 [cancelButton_ setTarget:self]; |
| 130 toView:view | 107 [cancelButton_ setAction:@selector(onCancelClicked:)]; |
| 131 target:self | 108 [view addSubview:cancelButton_]; |
| 132 action:@selector(onCancelClicked:)]; | |
| 133 | |
| 134 // "More" button. | |
| 135 AccountChooserMoreComboboxModel comboboxModel; | |
| 136 moreButton_ = [[BubbleCombobox alloc] initWithFrame:NSZeroRect | |
| 137 pullsDown:YES | |
| 138 model:&comboboxModel]; | |
| 139 [moreButton_ sizeToFit]; | |
| 140 NSMenuItem* learnMoreItem = [moreButton_ | |
| 141 itemAtIndex:AccountChooserMoreComboboxModel::INDEX_LEARN_MORE]; | |
| 142 [learnMoreItem setTarget:self]; | |
| 143 [learnMoreItem setAction:@selector(onLearnMoreClicked:)]; | |
| 144 NSMenuItem* settingsItem = | |
| 145 [moreButton_ itemAtIndex:AccountChooserMoreComboboxModel::INDEX_SETTINGS]; | |
| 146 [settingsItem setTarget:self]; | |
| 147 [settingsItem setAction:@selector(onSettingsClicked:)]; | |
| 148 [view addSubview:moreButton_]; | |
| 149 | 109 |
| 150 // Lay out the views. | 110 // Lay out the views. |
| 151 const CGFloat width = | 111 [cancelButton_ setFrameOrigin:NSMakePoint( |
| 152 std::max(NSWidth([title frame]), NSWidth([credentialsView_ frame])); | 112 kFramePadding + width - NSWidth([cancelButton_ frame]), |
| 153 [cancelButton_ | 113 kFramePadding)]; |
| 154 setFrameOrigin:NSMakePoint(base::i18n::IsRTL() | |
| 155 ? kFramePadding | |
| 156 : kFramePadding + width - | |
| 157 NSWidth([cancelButton_ frame]), | |
| 158 kFramePadding)]; | |
| 159 [moreButton_ | |
| 160 setFrameOrigin:NSMakePoint(base::i18n::IsRTL() | |
| 161 ? NSMaxX([cancelButton_ frame]) + | |
| 162 kRelatedControlHorizontalPadding | |
| 163 : NSMinX([cancelButton_ frame]) - | |
| 164 kRelatedControlHorizontalPadding - | |
| 165 NSWidth([moreButton_ frame]), | |
| 166 std::ceil(kFramePadding + | |
| 167 (NSHeight([cancelButton_ frame]) - | |
| 168 NSHeight([moreButton_ frame])) / | |
| 169 2.0f))]; | |
| 170 | 114 |
| 171 // The credentials TableView expands to fill available space. | 115 // The credentials TableView expands to fill available space. |
| 172 [column setMaxWidth:width]; | 116 [column setMaxWidth:width]; |
| 173 [credentialsView | 117 [credentialsView |
| 174 setFrameSize:NSMakeSize(width, NSHeight([credentialsView_ frame]))]; | 118 setFrameSize:NSMakeSize(width, NSHeight([credentialsView_ frame]))]; |
| 175 [credentialsView_ | 119 [credentialsView_ |
| 176 setFrameOrigin:NSMakePoint(kFramePadding, | 120 setFrameOrigin:NSMakePoint(kFramePadding, |
| 177 NSMaxY([cancelButton_ frame]) + | 121 NSMaxY([cancelButton_ frame]) + |
| 178 kUnrelatedControlVerticalPadding)]; | 122 kUnrelatedControlVerticalPadding)]; |
| 179 | 123 |
| 180 [title setFrameOrigin:NSMakePoint( | 124 [titleView_ setFrameOrigin:NSMakePoint( |
| 181 base::i18n::IsRTL() | 125 kFramePadding, |
| 182 ? kFramePadding + width - NSWidth([title frame]) | 126 NSMaxY([credentialsView_ frame]) + kUnrelatedControlVerticalPadding)]; |
| 183 : kFramePadding, | |
| 184 NSMaxY([credentialsView_ frame]) + | |
| 185 kUnrelatedControlVerticalPadding)]; | |
| 186 | 127 |
| 187 // Compute the frame to hold all the views. | 128 const CGFloat frameHeight = NSMaxY([titleView_ frame]) + kFramePadding; |
| 188 const CGFloat frameWidth = width + 2 * kFramePadding; | 129 [view setFrame:NSMakeRect(0, 0, kDesiredBubbleWidth, frameHeight)]; |
| 189 const CGFloat frameHeight = NSMaxY([title frame]) + kFramePadding; | |
| 190 [view setFrame:NSMakeRect(0, 0, frameWidth, frameHeight)]; | |
| 191 | 130 |
| 192 [self setView:view]; | 131 [self setView:view]; |
| 193 } | 132 } |
| 194 | 133 |
| 195 - (void)onCancelClicked:(id)sender { | 134 - (BOOL)textView:(NSTextView*)textView |
| 196 model_->OnCancelClicked(); | 135 clickedOnLink:(id)link |
| 197 [delegate_ viewShouldDismiss]; | 136 atIndex:(NSUInteger)charIndex { |
| 137 bridge_->GetDialogController()->OnSmartLockLinkClicked(); |
| 138 return YES; |
| 198 } | 139 } |
| 199 | 140 |
| 200 - (void)onLearnMoreClicked:(id)sender { | 141 - (void)onCancelClicked:(id)sender { |
| 201 // TODO(dconnelly): Open some help center article that's not written yet. | 142 bridge_->PerformClose(); |
| 202 [delegate_ viewShouldDismiss]; | |
| 203 } | |
| 204 | |
| 205 - (void)onSettingsClicked:(id)sender { | |
| 206 model_->OnManageLinkClicked(); | |
| 207 [delegate_ viewShouldDismiss]; | |
| 208 } | 143 } |
| 209 | 144 |
| 210 - (void)fetchAvatar:(const GURL&)avatarURL forView:(CredentialItemView*)view { | 145 - (void)fetchAvatar:(const GURL&)avatarURL forView:(CredentialItemView*)view { |
| 211 [avatarManager_ fetchAvatar:avatarURL forView:view]; | 146 [avatarManager_ fetchAvatar:avatarURL forView:view]; |
| 212 } | 147 } |
| 213 | 148 |
| 214 + (NSArray*)credentialItemsForModel:(ManagePasswordsBubbleModel*)model | 149 + (NSArray*)credentialItemsFromBridge:(AccountChooserBridge*)bridge |
| 215 delegate:(id<CredentialItemDelegate>)delegate { | 150 delegate:(id<CredentialItemDelegate>)delegate { |
| 216 base::scoped_nsobject<NSMutableArray> items([[NSMutableArray alloc] init]); | 151 base::scoped_nsobject<NSMutableArray> items([[NSMutableArray alloc] init]); |
| 217 for (auto form : model->local_credentials()) { | 152 PasswordDialogController* controller = bridge->GetDialogController(); |
| 153 for (const auto& form : controller->GetLocalForms()) { |
| 218 base::scoped_nsobject<CredentialItemView> item([[CredentialItemView alloc] | 154 base::scoped_nsobject<CredentialItemView> item([[CredentialItemView alloc] |
| 219 initWithPasswordForm:*form | 155 initWithPasswordForm:*form |
| 220 credentialType:password_manager::CredentialType:: | 156 credentialType:password_manager::CredentialType:: |
| 221 CREDENTIAL_TYPE_PASSWORD | 157 CREDENTIAL_TYPE_PASSWORD |
| 222 style:password_manager_mac::CredentialItemStyle:: | 158 style:password_manager_mac::CredentialItemStyle:: |
| 223 ACCOUNT_CHOOSER | 159 ACCOUNT_CHOOSER |
| 224 delegate:delegate]); | 160 delegate:delegate]); |
| 225 [item setAutoresizingMask:NSViewWidthSizable]; | 161 [item setAutoresizingMask:NSViewWidthSizable]; |
| 226 [items addObject:item]; | 162 [items addObject:item]; |
| 227 } | 163 } |
| 228 for (auto form : model->federated_credentials()) { | 164 for (const auto& form : controller->GetFederationsForms()) { |
| 229 base::scoped_nsobject<CredentialItemView> item([[CredentialItemView alloc] | 165 base::scoped_nsobject<CredentialItemView> item([[CredentialItemView alloc] |
| 230 initWithPasswordForm:*form | 166 initWithPasswordForm:*form |
| 231 credentialType:password_manager::CredentialType:: | 167 credentialType:password_manager::CredentialType:: |
| 232 CREDENTIAL_TYPE_FEDERATED | 168 CREDENTIAL_TYPE_FEDERATED |
| 233 style:password_manager_mac::CredentialItemStyle:: | 169 style:password_manager_mac::CredentialItemStyle:: |
| 234 ACCOUNT_CHOOSER | 170 ACCOUNT_CHOOSER |
| 235 delegate:delegate]); | 171 delegate:delegate]); |
| 236 [item setAutoresizingMask:NSViewWidthSizable]; | 172 [item setAutoresizingMask:NSViewWidthSizable]; |
| 237 [items addObject:item]; | 173 [items addObject:item]; |
| 238 } | 174 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 254 - (NSCell*)tableView:(NSTableView*)tableView | 190 - (NSCell*)tableView:(NSTableView*)tableView |
| 255 dataCellForTableColumn:(NSTableColumn*)tableColumn | 191 dataCellForTableColumn:(NSTableColumn*)tableColumn |
| 256 row:(NSInteger)row { | 192 row:(NSInteger)row { |
| 257 return [[[CredentialItemCell alloc] | 193 return [[[CredentialItemCell alloc] |
| 258 initWithView:[credentialItems_.get() objectAtIndex:row]] autorelease]; | 194 initWithView:[credentialItems_.get() objectAtIndex:row]] autorelease]; |
| 259 } | 195 } |
| 260 | 196 |
| 261 - (void)tableViewSelectionDidChange:(NSNotification *)notification { | 197 - (void)tableViewSelectionDidChange:(NSNotification *)notification { |
| 262 CredentialItemView* item = | 198 CredentialItemView* item = |
| 263 [credentialItems_.get() objectAtIndex:[credentialsView_ selectedRow]]; | 199 [credentialItems_.get() objectAtIndex:[credentialsView_ selectedRow]]; |
| 264 model_->OnChooseCredentials(item.passwordForm, item.credentialType); | 200 bridge_->GetDialogController()->OnChooseCredentials(item.passwordForm, |
| 265 [delegate_ viewShouldDismiss]; | 201 item.credentialType); |
| 266 } | 202 } |
| 267 | 203 |
| 268 @end | 204 @end |
| 205 |
| 206 @implementation AccountChooserViewController(Testing) |
| 207 |
| 208 - (id)initWithBridge:(AccountChooserBridge*)bridge |
| 209 avatarManager:(AccountAvatarFetcherManager*)avatarManager { |
| 210 DCHECK(bridge); |
| 211 if (self = [super initWithNibName:nil bundle:nil]) { |
| 212 bridge_ = bridge; |
| 213 avatarManager_.reset([avatarManager retain]); |
| 214 } |
| 215 return self; |
| 216 } |
| 217 |
| 218 - (NSButton*)cancelButton { |
| 219 return cancelButton_; |
| 220 } |
| 221 |
| 222 - (NSTableView*)credentialsView { |
| 223 return credentialsView_; |
| 224 } |
| 225 |
| 226 - (NSTextView*)titleView { |
| 227 return titleView_; |
| 228 } |
| 229 |
| 230 @end |
| OLD | NEW |