blob: 4c2ae69966630b275256dae0d141db14b4761a94 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/ui/cocoa/password_reuse_warning_view_controller.h"
#import "base/mac/scoped_nsobject.h"
#include "chrome/app/vector_icons/vector_icons.h"
#import "chrome/browser/ui/cocoa/chrome_style.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h"
#include "chrome/browser/ui/cocoa/key_equivalent_constants.h"
#include "chrome/browser/ui/cocoa/l10n_util.h"
#import "chrome/browser/ui/cocoa/password_reuse_warning_dialog_cocoa.h"
#include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h"
#import "ui/base/cocoa/controls/imageview_utils.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/image/image_skia_util_mac.h"
#include "ui/gfx/paint_vector_icon.h"
namespace {
// Size of the security icon.
constexpr CGFloat kIconSize = 20;
constexpr CGFloat kWindowMinWidth = 500;
constexpr CGFloat kButtonGap = 8;
constexpr CGFloat kIconGap = 18;
constexpr CGFloat kBaselineAdjust = 1;
} // namespace
@interface PasswordReuseWarningViewController () {
PasswordReuseWarningDialogCocoa* owner_; // weak.
// UI elements.
base::scoped_nsobject<NSBox> box_;
base::scoped_nsobject<NSTextField> titleField_;
base::scoped_nsobject<NSImageView> iconView_;
base::scoped_nsobject<NSTextField> messageField_;
base::scoped_nsobject<ConstrainedWindowButton> ignoreButton_;
base::scoped_nsobject<ConstrainedWindowButton> changePasswordButton_;
}
@end
@implementation PasswordReuseWarningViewController
- (instancetype)initWithOwner:(PasswordReuseWarningDialogCocoa*)owner {
if ((self = [super init])) {
DCHECK(owner);
owner_ = owner;
}
return self;
}
- (void)loadView {
self.view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease];
box_.reset([[NSBox alloc] initWithFrame:NSZeroRect]);
[[self view] addSubview:box_];
CGFloat dialogHeight = chrome_style::kClientBottomPadding;
changePasswordButton_.reset(
[[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
constrained_window::AddButton([self view], changePasswordButton_,
IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON, self,
@selector(changePassword:), true);
[changePasswordButton_ setKeyEquivalent:kKeyEquivalentReturn];
ignoreButton_.reset(
[[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
constrained_window::AddButton([self view], ignoreButton_,
IDS_PAGE_INFO_IGNORE_PASSWORD_WARNING_BUTTON,
self, @selector(ignore:), true);
dialogHeight += NSHeight([ignoreButton_ frame]) + chrome_style::kRowPadding;
// Compute the dialog width using the title and buttons.
const CGFloat buttonsWidth = NSWidth([changePasswordButton_ frame]) +
kButtonGap + NSWidth([ignoreButton_ frame]);
const CGFloat titleIconWidth =
NSWidth([titleField_ frame]) + kIconSize + kIconGap;
// Dialog minimum width must include the padding.
const CGFloat minWidth =
kWindowMinWidth - 2 * chrome_style::kHorizontalPadding;
const CGFloat width =
std::max(minWidth, std::max(buttonsWidth, titleIconWidth));
const CGFloat dialogWidth = width + 2 * chrome_style::kHorizontalPadding;
CGFloat textLeftPadding =
chrome_style::kHorizontalPadding + kIconSize + kIconGap;
CGFloat textWidth = width - kIconSize - kIconGap;
messageField_.reset([constrained_window::AddTextField(
[self view], owner_->GetWarningDetailText(), chrome_style::kTextFontStyle)
retain]);
[messageField_
setFrame:constrained_window::ComputeFrame(
[messageField_ attributedStringValue], textWidth, 0.0)];
[messageField_ setFrameOrigin:NSMakePoint(textLeftPadding, dialogHeight)];
dialogHeight += NSHeight([messageField_ frame]) + chrome_style::kRowPadding;
BOOL isSoftWarning =
safe_browsing::PasswordProtectionService::ShouldShowSofterWarning();
int titleTextId = isSoftWarning ? IDS_PAGE_INFO_CHANGE_PASSWORD_SUMMARY_SOFTER
: IDS_PAGE_INFO_CHANGE_PASSWORD_SUMMARY;
// Add the title label.
titleField_.reset([constrained_window::AddTextField(
[self view], l10n_util::GetStringUTF16(titleTextId),
chrome_style::kTitleFontStyle) retain]);
[titleField_ setFrame:constrained_window::ComputeFrame(
[titleField_ attributedStringValue], 0.0, 0.0)];
[titleField_ setFrameOrigin:NSMakePoint(textLeftPadding, dialogHeight)];
dialogHeight += NSHeight([titleField_ frame]);
SkColor iconColor = isSoftWarning ? gfx::kChromeIconGrey : gfx::kGoogleRed700;
const gfx::VectorIcon& icon =
isSoftWarning ? kSecurityIcon : vector_icons::kWarningIcon;
iconView_.reset([ImageViewUtils
imageViewWithImage:NSImageFromImageSkia(gfx::CreateVectorIcon(
icon, kIconSize, iconColor))]);
// Align the icon with the title's baseline.
const NSFont* titleFont = ui::ResourceBundle::GetSharedInstance()
.GetFont(chrome_style::kTitleFontStyle)
.GetNativeFont();
const CGFloat iconViewY =
NSMinY([titleField_ frame]) - titleFont.descender - kBaselineAdjust;
[iconView_ setFrame:NSMakeRect(chrome_style::kHorizontalPadding, iconViewY,
kIconSize, kIconSize)];
[self.view addSubview:iconView_.get()];
dialogHeight += chrome_style::kTitleTopPadding;
[box_ setBorderColor:[NSColor whiteColor]];
[box_ setFillColor:[NSColor whiteColor]];
[box_ setBoxType:NSBoxCustom];
[box_ setTitlePosition:NSNoTitle];
[box_ setFrame:NSMakeRect(0, 0, dialogWidth, dialogHeight)];
// Layout the buttons and box based on the calculated width & height.
CGFloat buttonX = dialogWidth - chrome_style::kHorizontalPadding -
NSWidth([changePasswordButton_ frame]);
[changePasswordButton_
setFrameOrigin:NSMakePoint(buttonX, chrome_style::kRowPadding)];
buttonX -= kButtonGap;
buttonX -= NSWidth([ignoreButton_ frame]);
[ignoreButton_
setFrameOrigin:NSMakePoint(buttonX, chrome_style::kRowPadding)];
// Update the dialog frame with the computed dimensions.
[[self view] setFrame:NSMakeRect(0, 0, dialogWidth, dialogHeight)];
cocoa_l10n_util::FlipAllSubviewsIfNecessary([self view]);
}
- (void)changePassword:(id)sender {
owner_->OnChangePassword();
}
- (void)ignore:(id)sender {
owner_->OnIgnore();
}
- (void)cancelOperation:(id)sender {
DCHECK(owner_);
owner_->Close();
}
@end