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 |