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

Unified 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: Fix failing browser test by calling test::SetCreditCardInfo. Created 5 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
diff --git a/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm b/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
index cc8897d4e7692583d115c363dd61d96f79105a6e..542441543c31948a3d4a532c86957d4ec2d8d132 100644
--- a/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
+++ b/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
@@ -2,10 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/strings/sys_string_conversions.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_models.h"
#include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h"
#include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h"
+#import "chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
#include "chrome/browser/ui/chrome_style.h"
+#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
#import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
@@ -14,7 +18,11 @@
#include "ui/base/l10n/l10n_util.h"
namespace {
+
const CGFloat kButtonGap = 6.0f;
+const CGFloat kDialogContentMinWidth = 210.0f;
+const CGFloat kCvcInputWidth = 64.0f;
+
} // namespace
namespace autofill {
@@ -30,12 +38,16 @@ CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow(
CardUnmaskPromptViewBridge::CardUnmaskPromptViewBridge(
CardUnmaskPromptController* controller)
: controller_(controller) {
- sheet_controller_.reset([[CardUnmaskPromptViewCocoa alloc]
+ view_controller_.reset([[CardUnmaskPromptViewCocoa alloc]
initWithWebContents:controller_->GetWebContents()
bridge:this]);
+
+ // Setup the constrained window that will show the view.
+ base::scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
+ initWithContentRect:[[view_controller_ view] bounds]]);
+ [window setContentView:[view_controller_ view]];
base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
- [[CustomConstrainedWindowSheet alloc]
- initWithCustomWindow:[sheet_controller_ window]]);
+ [[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window]);
constrained_window_.reset(
new ConstrainedWindowMac(this, controller_->GetWebContents(), sheet));
}
@@ -44,6 +56,8 @@ CardUnmaskPromptViewBridge::~CardUnmaskPromptViewBridge() {
}
void CardUnmaskPromptViewBridge::ControllerGone() {
+ controller_ = nullptr;
+ PerformClose();
}
void CardUnmaskPromptViewBridge::DisableAndWaitForVerification() {
@@ -55,7 +69,12 @@ void CardUnmaskPromptViewBridge::GotVerificationResult(bool success) {
void CardUnmaskPromptViewBridge::OnConstrainedWindowClosed(
ConstrainedWindowMac* window) {
constrained_window_.reset();
- controller_->OnUnmaskDialogClosed();
+ if (controller_)
+ controller_->OnUnmaskDialogClosed();
+}
+
+CardUnmaskPromptController* CardUnmaskPromptViewBridge::GetController() {
+ return controller_;
}
void CardUnmaskPromptViewBridge::PerformClose() {
@@ -68,19 +87,46 @@ void CardUnmaskPromptViewBridge::PerformClose() {
@implementation CardUnmaskPromptViewCocoa
++ (AutofillPopUpButton*)buildDatePopupWithModel:(ui::ComboboxModel&)model {
+ AutofillPopUpButton* popup =
+ [[AutofillPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO];
+
+ for (int i = 0; i < model.GetItemCount(); ++i) {
+ [popup addItemWithTitle:base::SysUTF16ToNSString(model.GetItemAt(i))];
+ }
+ [popup setDefaultValue:base::SysUTF16ToNSString(
+ model.GetItemAt(model.GetDefaultIndex()))];
+ [popup sizeToFit];
+ return popup;
+}
+
+// Set |view|'s frame to the minimum dimensions required to contain all of its
+// subviews.
++ (void)sizeToFitView:(NSView*)view {
+ NSRect frame = NSZeroRect;
+ for (NSView* child in [view subviews]) {
+ frame = NSUnionRect(frame, [child frame]);
+ }
+ [view setFrame:frame];
+}
+
++ (void)verticallyCenterSubviewsInView:(NSView*)view {
+ CGFloat height = NSHeight([view frame]);
+ for (NSView* child in [view subviews]) {
+ [child setFrameOrigin:NSMakePoint(
+ NSMinX([child frame]),
+ ceil((height - NSHeight([child frame])) * 0.5))];
+ }
+}
+
- (id)initWithWebContents:(content::WebContents*)webContents
bridge:(autofill::CardUnmaskPromptViewBridge*)bridge {
DCHECK(webContents);
DCHECK(bridge);
- NSRect frame = NSMakeRect(0, 0, 550, 600);
- base::scoped_nsobject<ConstrainedWindowCustomWindow> window(
- [[ConstrainedWindowCustomWindow alloc] initWithContentRect:frame]);
- if ((self = [super initWithWindow:window])) {
+ if ((self = [super initWithNibName:nil bundle:nil])) {
webContents_ = webContents;
bridge_ = bridge;
-
- [self buildWindowButtons];
}
return self;
}
@@ -89,38 +135,157 @@ void CardUnmaskPromptViewBridge::PerformClose() {
bridge_->PerformClose();
}
-- (void)buildWindowButtons {
- base::scoped_nsobject<NSView> buttonContainer(
+- (void)loadView {
+ autofill::CardUnmaskPromptController* controller = bridge_->GetController();
+ DCHECK(controller);
+
+ base::scoped_nsobject<NSBox> mainView(
+ [[NSBox alloc] initWithFrame:NSZeroRect]);
+ [mainView setBoxType:NSBoxCustom];
+ [mainView setBorderType:NSNoBorder];
+ [mainView setTitlePosition:NSNoTitle];
+ [mainView
+ setContentViewMargins:NSMakeSize(chrome_style::kHorizontalPadding, 0)];
+
+ base::scoped_nsobject<NSView> inputRowView(
[[NSView alloc] initWithFrame:NSZeroRect]);
+ [mainView addSubview:inputRowView];
+
+ // Title label.
+ NSTextField* title = constrained_window::CreateLabel();
+ NSAttributedString* titleString =
+ constrained_window::GetAttributedLabelString(
+ SysUTF16ToNSString(controller->GetWindowTitle()),
+ chrome_style::kTitleFontStyle, NSNaturalTextAlignment,
+ NSLineBreakByWordWrapping);
+ [title setAttributedStringValue:titleString];
+ [title sizeToFit];
+ [mainView addSubview:title];
+
+ // Instructions label.
+ NSTextField* instructions = constrained_window::CreateLabel();
+ NSAttributedString* instructionsString =
+ constrained_window::GetAttributedLabelString(
+ SysUTF16ToNSString(controller->GetInstructionsMessage()),
+ chrome_style::kTextFontStyle, NSNaturalTextAlignment,
+ NSLineBreakByWordWrapping);
+ [instructions setAttributedStringValue:instructionsString];
+ [mainView addSubview:instructions];
- base::scoped_nsobject<NSButton> button(
+ // Expiration date.
+ base::scoped_nsobject<NSView> expirationView;
+ if (controller->ShouldRequestExpirationDate()) {
+ expirationView.reset([[NSView alloc] initWithFrame:NSZeroRect]);
+
+ // Month.
+ autofill::MonthComboboxModel monthModel;
+ base::scoped_nsobject<AutofillPopUpButton> monthPopup(
+ [CardUnmaskPromptViewCocoa buildDatePopupWithModel:monthModel]);
+ [expirationView addSubview:monthPopup];
+
+ // Year.
+ autofill::YearComboboxModel yearModel;
+ base::scoped_nsobject<AutofillPopUpButton> yearPopup(
+ [CardUnmaskPromptViewCocoa buildDatePopupWithModel:yearModel]);
+ [expirationView addSubview:yearPopup];
+
+ // Layout month and year within expirationView.
+ [yearPopup
+ setFrameOrigin:NSMakePoint(NSMaxX([monthPopup frame]) + kButtonGap, 0)];
+ NSRect expirationFrame = NSUnionRect([monthPopup frame], [yearPopup frame]);
+ expirationFrame.size.width += kButtonGap;
+ [expirationView setFrame:expirationFrame];
+ [inputRowView addSubview:expirationView];
+ }
+
+ // CVC text input.
+ base::scoped_nsobject<NSTextField> cvcInput(
+ [[NSTextField alloc] initWithFrame:NSZeroRect]);
+ [[cvcInput cell]
+ setPlaceholderString:l10n_util::GetNSString(
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC)];
+ [[cvcInput cell] setScrollable:YES];
+ [cvcInput sizeToFit];
+ [cvcInput setFrame:NSMakeRect(NSMaxX([expirationView frame]), 0,
+ kCvcInputWidth, NSHeight([cvcInput frame]))];
+ [inputRowView addSubview:cvcInput];
+
+ // CVC image.
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ NSImage* cvcImage =
+ rb.GetNativeImageNamed(controller->GetCvcImageRid()).ToNSImage();
+ base::scoped_nsobject<NSImageView> cvcImageView(
+ [[NSImageView alloc] initWithFrame:NSZeroRect]);
+ [cvcImageView setImage:cvcImage];
+ [cvcImageView setFrameSize:[cvcImage size]];
+ [cvcImageView
+ setFrameOrigin:NSMakePoint(NSMaxX([cvcInput frame]) + kButtonGap, 0)];
+ [inputRowView addSubview:cvcImageView];
+
+ // Cancel button.
+ base::scoped_nsobject<NSButton> cancelButton(
[[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
- [button setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)];
- [button setKeyEquivalent:kKeyEquivalentEscape];
- [button setTarget:self];
- [button setAction:@selector(closeSheet:)];
- [button sizeToFit];
- [buttonContainer addSubview:button];
-
- CGFloat nextX = NSMaxX([button frame]) + kButtonGap;
- button.reset([[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
- [button setFrameOrigin:NSMakePoint(nextX, 0)];
- [button setTitle:l10n_util::GetNSStringWithFixup(
- IDS_AUTOFILL_DIALOG_SUBMIT_BUTTON)];
- [button setKeyEquivalent:kKeyEquivalentReturn];
- [button setTarget:self];
- [button setAction:@selector(closeSheet:)];
- [button sizeToFit];
- [buttonContainer addSubview:button];
-
- const CGFloat dialogOffset = NSWidth([[self window] frame]) -
- chrome_style::kHorizontalPadding -
- NSMaxX([button frame]);
- [buttonContainer
- setFrame:NSMakeRect(dialogOffset, chrome_style::kClientBottomPadding,
- NSMaxX([button frame]), NSMaxY([button frame]))];
-
- [[[self window] contentView] addSubview:buttonContainer];
+ [cancelButton setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)];
+ [cancelButton setKeyEquivalent:kKeyEquivalentEscape];
+ [cancelButton setTarget:self];
+ [cancelButton setAction:@selector(closeSheet:)];
+ [cancelButton sizeToFit];
+ [mainView addSubview:cancelButton];
+
+ // Verify button.
+ base::scoped_nsobject<NSButton> verifyButton(
+ [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
+ // TODO(bondd): use l10n string.
+ [verifyButton setTitle:@"Verify"];
+ [verifyButton setKeyEquivalent:kKeyEquivalentReturn];
+ [verifyButton setTarget:self];
+ [verifyButton setAction:@selector(closeSheet:)];
+ [verifyButton sizeToFit];
+ [mainView addSubview:verifyButton];
+
+ // Layout inputRowView.
+ [CardUnmaskPromptViewCocoa sizeToFitView:inputRowView];
+ [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:inputRowView];
+
+ // Calculate dialog content width.
+ CGFloat contentWidth =
+ std::max(NSWidth([title frame]), NSWidth([inputRowView frame]));
+ contentWidth = std::max(contentWidth, kDialogContentMinWidth);
+
+ // Layout mainView contents, starting at the bottom and moving up.
+
+ // Verify and Cancel buttons.
+ [verifyButton
+ setFrameOrigin:NSMakePoint(contentWidth - NSWidth([verifyButton frame]),
+ chrome_style::kClientBottomPadding)];
+
+ [cancelButton
+ setFrameOrigin:NSMakePoint(NSMinX([verifyButton frame]) - kButtonGap -
+ NSWidth([cancelButton frame]),
+ NSMinY([verifyButton frame]))];
+
+ // Input row.
+ [inputRowView setFrameOrigin:NSMakePoint(0, NSMaxY([cancelButton frame]) +
+ chrome_style::kRowPadding)];
+
+ // Instruction label.
+ [instructions setFrameOrigin:NSMakePoint(0, NSMaxY([inputRowView frame]) +
+ chrome_style::kRowPadding)];
+ NSSize instructionsSize = [[instructions cell]
+ cellSizeForBounds:NSMakeRect(0, 0, contentWidth, CGFLOAT_MAX)];
+ [instructions setFrameSize:instructionsSize];
+
+ // Title label.
+ [title setFrameOrigin:NSMakePoint(0, NSMaxY([instructions frame]) +
+ chrome_style::kRowPadding)];
+
+ // Dialog size.
+ [mainView
+ setFrameSize:NSMakeSize(
+ contentWidth + [mainView contentViewMargins].width * 2.0,
+ NSMaxY([title frame]) + chrome_style::kTitleTopPadding)];
+
+ [self setView:mainView];
}
@end

Powered by Google App Engine
This is Rietveld 408576698