Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm

Issue 929293005: Autofill: Add contents of CVC unmask prompt dialog on OSX. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cup_01_initial_add
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 #include "base/strings/sys_string_conversions.h"
5 #include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" 6 #include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h"
6 #include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h" 7 #include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h"
8 #import "chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h"
9 #import "chrome/browser/ui/cocoa/autofill/autofill_textfield.h"
7 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" 10 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
8 #include "chrome/browser/ui/chrome_style.h" 11 #include "chrome/browser/ui/chrome_style.h"
12 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_u tils.h"
9 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sh eet.h" 13 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sh eet.h"
10 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_wi ndow.h" 14 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_wi ndow.h"
11 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h" 15 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
12 #include "grit/generated_resources.h" 16 #include "grit/generated_resources.h"
13 #include "ui/base/cocoa/window_size_constants.h" 17 #include "ui/base/cocoa/window_size_constants.h"
14 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/base/l10n/l10n_util.h"
15 19
16 namespace { 20 namespace {
21
17 const CGFloat kButtonGap = 6.0f; 22 const CGFloat kButtonGap = 6.0f;
23 const CGFloat kDialogMinWidth = 250.0f;
24 const CGFloat kCvcInputWidth = 64.0f;
25
26 AutofillPopUpButton* CreateDatePopup(ui::ComboboxModel& model) {
groby-ooo-7-16 2015/02/18 19:01:19 FWIW, we usually have those builder functions as c
bondd 2015/02/26 01:25:08 Done.
27 AutofillPopUpButton* popup =
groby-ooo-7-16 2015/02/18 19:01:19 why not use menuFromModel:?
bondd 2015/02/26 01:25:08 Views implementation uses autofill::MonthComboboxM
groby-ooo-7-16 2015/02/28 00:49:17 No, you don't. I naively assumed we had a menuFrom
28 [[AutofillPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO];
29
30 for (int i = 0; i < model.GetItemCount(); ++i) {
31 [popup addItemWithTitle:base::SysUTF16ToNSString(model.GetItemAt(i))];
32 }
33 [popup setDefaultValue:base::SysUTF16ToNSString(
34 model.GetItemAt(model.GetDefaultIndex()))];
35 [popup sizeToFit];
36 return popup;
37 }
38
18 } // namespace 39 } // namespace
19 40
20 namespace autofill { 41 namespace autofill {
21 42
22 // static 43 // static
23 CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow( 44 CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow(
24 CardUnmaskPromptController* controller) { 45 CardUnmaskPromptController* controller) {
25 return new CardUnmaskPromptViewBridge(controller); 46 return new CardUnmaskPromptViewBridge(controller);
26 } 47 }
27 48
28 #pragma mark CardUnmaskPromptViewBridge 49 #pragma mark CardUnmaskPromptViewBridge
29 50
30 CardUnmaskPromptViewBridge::CardUnmaskPromptViewBridge( 51 CardUnmaskPromptViewBridge::CardUnmaskPromptViewBridge(
31 CardUnmaskPromptController* controller) 52 CardUnmaskPromptController* controller)
32 : controller_(controller) { 53 : controller_(controller) {
33 sheet_controller_.reset([[CardUnmaskPromptViewCocoa alloc] 54 view_controller_.reset([[CardUnmaskPromptViewCocoa alloc]
34 initWithWebContents:controller_->GetWebContents() 55 initWithWebContents:controller_->GetWebContents()
35 bridge:this]); 56 bridge:this]);
57
58 // Setup the constrained window that will show the view.
59 base::scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
60 initWithContentRect:[[view_controller_ view] bounds]]);
61 [[window contentView] addSubview:[view_controller_ view]];
groby-ooo-7-16 2015/02/18 19:01:19 Are you sure you don't just want to replace the co
bondd 2015/02/26 01:25:08 Done.
36 base::scoped_nsobject<CustomConstrainedWindowSheet> sheet( 62 base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
37 [[CustomConstrainedWindowSheet alloc] 63 [[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window]);
38 initWithCustomWindow:[sheet_controller_ window]]);
39 constrained_window_.reset( 64 constrained_window_.reset(
40 new ConstrainedWindowMac(this, controller_->GetWebContents(), sheet)); 65 new ConstrainedWindowMac(this, controller_->GetWebContents(), sheet));
41 } 66 }
42 67
43 CardUnmaskPromptViewBridge::~CardUnmaskPromptViewBridge() { 68 CardUnmaskPromptViewBridge::~CardUnmaskPromptViewBridge() {
44 } 69 }
45 70
46 void CardUnmaskPromptViewBridge::ControllerGone() { 71 void CardUnmaskPromptViewBridge::ControllerGone() {
72 controller_ = nullptr;
73 PerformClose();
47 } 74 }
48 75
49 void CardUnmaskPromptViewBridge::DisableAndWaitForVerification() { 76 void CardUnmaskPromptViewBridge::DisableAndWaitForVerification() {
50 } 77 }
51 78
52 void CardUnmaskPromptViewBridge::GotVerificationResult(bool success) { 79 void CardUnmaskPromptViewBridge::GotVerificationResult(bool success) {
53 } 80 }
54 81
55 void CardUnmaskPromptViewBridge::OnConstrainedWindowClosed( 82 void CardUnmaskPromptViewBridge::OnConstrainedWindowClosed(
56 ConstrainedWindowMac* window) { 83 ConstrainedWindowMac* window) {
57 constrained_window_.reset(); 84 constrained_window_.reset();
58 controller_->OnUnmaskDialogClosed(); 85 controller_->OnUnmaskDialogClosed();
59 } 86 }
60 87
88 CardUnmaskPromptController* CardUnmaskPromptViewBridge::GetController() {
89 return controller_;
90 }
91
61 void CardUnmaskPromptViewBridge::PerformClose() { 92 void CardUnmaskPromptViewBridge::PerformClose() {
62 constrained_window_->CloseWebContentsModalDialog(); 93 constrained_window_->CloseWebContentsModalDialog();
63 } 94 }
64 95
65 } // autofill 96 } // autofill
66 97
67 #pragma mark CardUnmaskPromptViewCocoa 98 #pragma mark CardUnmaskPromptViewCocoa
68 99
69 @implementation CardUnmaskPromptViewCocoa 100 @implementation CardUnmaskPromptViewCocoa
70 101
71 - (id)initWithWebContents:(content::WebContents*)webContents 102 - (id)initWithWebContents:(content::WebContents*)webContents
72 bridge:(autofill::CardUnmaskPromptViewBridge*)bridge { 103 bridge:(autofill::CardUnmaskPromptViewBridge*)bridge {
73 DCHECK(webContents); 104 DCHECK(webContents);
74 DCHECK(bridge); 105 DCHECK(bridge);
75 106
76 NSRect frame = NSMakeRect(0, 0, 550, 600); 107 if ((self = [super initWithNibName:nil bundle:nil])) {
77 base::scoped_nsobject<ConstrainedWindowCustomWindow> window(
78 [[ConstrainedWindowCustomWindow alloc] initWithContentRect:frame]);
79 if ((self = [super initWithWindow:window])) {
80 webContents_ = webContents; 108 webContents_ = webContents;
81 bridge_ = bridge; 109 bridge_ = bridge;
82
83 [self buildWindowButtons];
84 } 110 }
85 return self; 111 return self;
86 } 112 }
87 113
88 - (IBAction)closeSheet:(id)sender { 114 - (IBAction)closeSheet:(id)sender {
89 bridge_->PerformClose(); 115 bridge_->PerformClose();
90 } 116 }
91 117
92 - (void)buildWindowButtons { 118 - (void)loadView {
93 base::scoped_nsobject<NSView> buttonContainer( 119 self.view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease];
groby-ooo-7-16 2015/02/18 19:01:19 Ideally, loadView does not reference [self view] -
bondd 2015/02/26 01:25:08 Done.
94 [[NSView alloc] initWithFrame:NSZeroRect]);
95 120
96 base::scoped_nsobject<NSButton> button( 121 autofill::CardUnmaskPromptController* controller = bridge_->GetController();
122 if (!controller)
123 return;
bondd 2015/02/18 02:49:28 Is this okay? Should I expose WeakPtr from CardUnm
groby-ooo-7-16 2015/02/18 19:01:19 I can't see any benefit from exposing the WeakPtr
bondd 2015/02/26 01:25:08 Okay, assuming all of this code is run on the same
124
125 // Title label.
126 NSTextField* title = constrained_window::CreateLabel();
127 [title setAttributedStringValue:constrained_window::GetAttributedLabelString(
groby-ooo-7-16 2015/02/18 19:01:19 Is that clang-format? Because it looks horrible :)
bondd 2015/02/26 01:25:09 Added an intermediate variable to make the formatt
128 SysUTF16ToNSString(
129 controller->GetWindowTitle()),
130 chrome_style::kTitleFontStyle,
131 NSNaturalTextAlignment,
132 NSLineBreakByWordWrapping)];
133 [title sizeToFit];
134 [[self view] addSubview:title];
135
136 // Instructions label.
137 NSTextField* instructions = constrained_window::CreateLabel();
138 [instructions
139 setAttributedStringValue:constrained_window::GetAttributedLabelString(
140 SysUTF16ToNSString(
141 controller->GetInstructionsMessage()),
142 chrome_style::kTextFontStyle,
143 NSNaturalTextAlignment,
144 NSLineBreakByWordWrapping)];
145 // No need to call sizeToFit here. Size is calculated later.
146 [[self view] addSubview:instructions];
147
148 base::scoped_nsobject<AutofillPopUpButton> monthPopup;
groby-ooo-7-16 2015/02/18 19:01:19 Do you ever parent these popups to a view?
bondd 2015/02/26 01:25:08 -addSubview is sent 5 lines below this comment. Or
149 base::scoped_nsobject<AutofillPopUpButton> yearPopup;
150 if (controller->ShouldRequestExpirationDate()) {
groby-ooo-7-16 2015/02/18 19:01:19 There are 3 different places that special-case Sho
bondd 2015/02/26 01:25:08 I've reduced it to two places: once for creation a
151 // Month.
152 monthPopup.reset(CreateDatePopup(month_combobox_model_));
153 [[self view] addSubview:monthPopup];
154
155 // Year.
156 yearPopup.reset(CreateDatePopup(year_combobox_model_));
157 [[self view] addSubview:yearPopup];
158 }
159
160 // CVC text input.
161 base::scoped_nsobject<AutofillTextField> cvcInput(
groby-ooo-7-16 2015/02/18 19:01:19 Does this need to be an AutofillTextField?
bondd 2015/02/26 01:25:09 Done.
162 [[AutofillTextField alloc] init]);
groby-ooo-7-16 2015/02/18 19:01:19 You should prefer initWithFrame: over init - init
bondd 2015/02/26 01:25:08 Done.
163 [[cvcInput cell]
164 setPlaceholderString:l10n_util::GetNSString(
165 IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC)];
166 [[cvcInput cell] setScrollable:YES];
167 [cvcInput sizeToFit];
168 [cvcInput
169 setFrameSize:NSMakeSize(kCvcInputWidth, NSHeight([cvcInput frame]))];
170 [[self view] addSubview:cvcInput];
171
172 // CVC image.
173 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
174 NSImage* image =
175 rb.GetNativeImageNamed(controller->GetCvcImageRid()).ToNSImage();
176
177 base::scoped_nsobject<NSImageView> cvcImage([[NSImageView alloc] init]);
178 [cvcImage setImage:image];
179
180 const CGFloat inputRowHeight = NSHeight([cvcInput frame]);
bondd 2015/02/18 02:49:28 This assumes that cvcInput is the tallest element
groby-ooo-7-16 2015/02/18 19:01:19 I have no idea what the guarantees are :) In gener
bondd 2015/02/26 01:25:08 Changed it to make no assumptions about element he
181 [cvcImage setFrameSize:NSMakeSize([image size].width, inputRowHeight)];
182 [[self view] addSubview:cvcImage];
183
184 // Cancel button.
185 base::scoped_nsobject<NSButton> cancelButton(
97 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); 186 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
98 [button setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)]; 187 [cancelButton setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)];
99 [button setKeyEquivalent:kKeyEquivalentEscape]; 188 [cancelButton setKeyEquivalent:kKeyEquivalentEscape];
100 [button setTarget:self]; 189 [cancelButton setTarget:self];
101 [button setAction:@selector(closeSheet:)]; 190 [cancelButton setAction:@selector(closeSheet:)];
102 [button sizeToFit]; 191 [cancelButton sizeToFit];
103 [buttonContainer addSubview:button]; 192 [[self view] addSubview:cancelButton];
104 193
105 CGFloat nextX = NSMaxX([button frame]) + kButtonGap; 194 // Verify button.
106 button.reset([[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); 195 base::scoped_nsobject<NSButton> verifyButton(
107 [button setFrameOrigin:NSMakePoint(nextX, 0)]; 196 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
108 [button setTitle:l10n_util::GetNSStringWithFixup( 197 // TODO(bondd): use l10n string.
109 IDS_AUTOFILL_DIALOG_SUBMIT_BUTTON)]; 198 [verifyButton setTitle:@"Verify"];
110 [button setKeyEquivalent:kKeyEquivalentReturn]; 199 [verifyButton setKeyEquivalent:kKeyEquivalentReturn];
111 [button setTarget:self]; 200 [verifyButton setTarget:self];
112 [button setAction:@selector(closeSheet:)]; 201 [verifyButton setAction:@selector(closeSheet:)];
113 [button sizeToFit]; 202 [verifyButton sizeToFit];
114 [buttonContainer addSubview:button]; 203 [[self view] addSubview:verifyButton];
115 204
116 const CGFloat dialogOffset = NSWidth([[self window] frame]) - 205 // Calculate dialog width.
117 chrome_style::kHorizontalPadding - 206 CGFloat inputRowWidth =
118 NSMaxX([button frame]); 207 NSWidth([cvcInput frame]) + kButtonGap + NSWidth([cvcImage frame]);
119 [buttonContainer 208 if (controller->ShouldRequestExpirationDate()) {
120 setFrame:NSMakeRect(dialogOffset, chrome_style::kClientBottomPadding, 209 inputRowWidth += NSWidth([monthPopup frame]) + NSWidth([yearPopup frame]) +
121 NSMaxX([button frame]), NSMaxY([button frame]))]; 210 kButtonGap * 2;
211 }
212 CGFloat dialogWidth = std::max(NSWidth([title frame]), inputRowWidth) +
213 chrome_style::kHorizontalPadding * 2;
214 dialogWidth = std::max(dialogWidth, kDialogMinWidth);
122 215
123 [[[self window] contentView] addSubview:buttonContainer]; 216 // Layout the elements, starting at the bottom and moving up.
bondd 2015/02/18 02:49:28 Doing creation and layout in the same message, per
groby-ooo-7-16 2015/02/18 19:01:19 Perfectly fine, unless you'll need to re-layout. Y
217
218 CGFloat curX = dialogWidth - chrome_style::kHorizontalPadding;
219 CGFloat curY = chrome_style::kClientBottomPadding;
220
221 // Verify and Cancel buttons.
222 curX -= NSWidth([verifyButton frame]);
223 [verifyButton setFrameOrigin:NSMakePoint(curX, curY)];
224 curX -= kButtonGap + NSWidth([cancelButton frame]);
225 [cancelButton setFrameOrigin:NSMakePoint(curX, curY)];
226 curY += NSHeight([cancelButton frame]);
227
228 // Input row.
229 curX = chrome_style::kHorizontalPadding;
230 curY += chrome_style::kRowPadding;
231
232 if (controller->ShouldRequestExpirationDate()) {
233 [monthPopup setFrameOrigin:NSMakePoint(curX, curY)];
234 curX += NSWidth([monthPopup frame]) + kButtonGap;
235 [yearPopup setFrameOrigin:NSMakePoint(curX, curY)];
236 curX += NSWidth([yearPopup frame]) + kButtonGap;
237 }
238
239 [cvcInput setFrameOrigin:NSMakePoint(curX, curY)];
240 curX += NSWidth([cvcInput frame]) + kButtonGap;
241 [cvcImage setFrameOrigin:NSMakePoint(curX, curY)];
242 curX += NSWidth([cvcImage frame]);
243
244 // Instruction label.
245 curX = chrome_style::kHorizontalPadding;
246 curY += inputRowHeight + chrome_style::kRowPadding;
247 [instructions setFrameOrigin:NSMakePoint(curX, curY)];
248 CGFloat maxTextWidth = dialogWidth - chrome_style::kHorizontalPadding * 2;
249 NSSize instructionsSize = [[instructions cell]
groby-ooo-7-16 2015/02/18 19:01:19 Why use cellsize? This ignores any chrome around t
bondd 2015/02/26 01:25:08 Instructions text needs to wrap onto multiple line
groby-ooo-7-16 2015/02/28 00:49:17 Acknowledged.
250 cellSizeForBounds:NSMakeRect(0.0, 0.0, maxTextWidth, CGFLOAT_MAX)];
251 [instructions setFrameSize:instructionsSize];
252
253 // Title label.
254 curY += instructionsSize.height + chrome_style::kRowPadding;
255 [title setFrameOrigin:NSMakePoint(curX, curY)];
256
257 // Dialog size.
258 CGFloat dialogHeight =
259 curY + NSHeight([title frame]) + chrome_style::kTitleTopPadding;
260
261 [[self view] setFrame:NSMakeRect(0, 0, dialogWidth, dialogHeight)];
124 } 262 }
125 263
126 @end 264 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698