Commit 70a4ce30 authored by spqchan's avatar spqchan Committed by Commit Bot

[Mac] Credit Card Autofill Touch Bar Refactor

Move the credit card autofill touch bar logic from
AutofillPopupViewCocoa to AutofillPopupControllerImplMac
so that is can be used on both Toolkit and Cocoa
autofill popups.

Bug: 812658
Change-Id: Ic8d788dddabb909edee46da46899d759447a7c7d
Reviewed-on: https://chromium-review.googlesource.com/915438Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Commit-Queue: Sarah Chan <spqchan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537852}
parent fccdfe27
......@@ -72,6 +72,8 @@ split_static_library("ui") {
"cocoa/autofill/autofill_popup_view_cocoa.mm",
"cocoa/autofill/autofill_tooltip_controller.h",
"cocoa/autofill/autofill_tooltip_controller.mm",
"cocoa/autofill/credit_card_autofill_touch_bar_controller.h",
"cocoa/autofill/credit_card_autofill_touch_bar_controller.mm",
"cocoa/autofill/password_generation_popup_view_bridge.h",
"cocoa/autofill/password_generation_popup_view_bridge.mm",
"cocoa/autofill/password_generation_popup_view_cocoa.h",
......@@ -618,6 +620,8 @@ split_static_library("ui") {
"autofill/autofill_popup_controller.h",
"autofill/autofill_popup_controller_impl.cc",
"autofill/autofill_popup_controller_impl.h",
"autofill/autofill_popup_controller_impl_mac.h",
"autofill/autofill_popup_controller_impl_mac.mm",
"autofill/autofill_popup_layout_model.cc",
"autofill/autofill_popup_layout_model.h",
"autofill/autofill_popup_view.h",
......
......@@ -30,6 +30,7 @@ using base::WeakPtr;
namespace autofill {
#if !defined(OS_MACOSX)
// static
WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetOrCreate(
WeakPtr<AutofillPopupControllerImpl> previous,
......@@ -54,6 +55,7 @@ WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetOrCreate(
text_direction);
return controller->GetWeakPtr();
}
#endif
AutofillPopupControllerImpl::AutofillPopupControllerImpl(
base::WeakPtr<AutofillPopupDelegate> delegate,
......
......@@ -49,11 +49,11 @@ class AutofillPopupControllerImpl : public AutofillPopupController {
base::i18n::TextDirection text_direction);
// Shows the popup, or updates the existing popup with the given values.
void Show(const std::vector<autofill::Suggestion>& suggestions);
virtual void Show(const std::vector<autofill::Suggestion>& suggestions);
// Updates the data list values currently shown with the popup.
void UpdateDataListValues(const std::vector<base::string16>& values,
const std::vector<base::string16>& labels);
virtual void UpdateDataListValues(const std::vector<base::string16>& values,
const std::vector<base::string16>& labels);
// Hides the popup and destroys the controller. This also invalidates
// |delegate_|.
......
// Copyright 2018 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.
#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_MAC_H_
#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_MAC_H_
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
@class WebTextfieldTouchBarController;
namespace autofill {
class AutofillPopupControllerImplMac : public AutofillPopupControllerImpl {
public:
AutofillPopupControllerImplMac(base::WeakPtr<AutofillPopupDelegate> delegate,
content::WebContents* web_contents,
gfx::NativeView container_view,
const gfx::RectF& element_bounds,
base::i18n::TextDirection text_direction);
~AutofillPopupControllerImplMac() override;
// Shows the popup, or updates the existing popup with the given values.
// If the popup contains credit card items, find and set
// |touchBarController_| and show the credit card autofill touch bar.
void Show(const std::vector<autofill::Suggestion>& suggestions) override;
// Updates the data list values currently shown with the popup. Calls
// -invalidateTouchBar from |touchBarController_|.
void UpdateDataListValues(const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) override;
// Hides the popup and destroys the controller. This also invalidates
// |delegate_|.
void Hide() override;
private:
// The controller providing the autofill touch bar.
WebTextfieldTouchBarController* touchBarController_; // weak.
DISALLOW_COPY_AND_ASSIGN(AutofillPopupControllerImplMac);
};
} // namespace autofill
#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_H_
// Copyright 2018 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.
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.h"
#include "base/mac/availability.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
#import "chrome/browser/ui/cocoa/web_textfield_touch_bar_controller.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/popup_item_ids.h"
using base::WeakPtr;
namespace autofill {
// static
WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetOrCreate(
WeakPtr<AutofillPopupControllerImpl> previous,
WeakPtr<AutofillPopupDelegate> delegate,
content::WebContents* web_contents,
gfx::NativeView container_view,
const gfx::RectF& element_bounds,
base::i18n::TextDirection text_direction) {
if (previous.get() && previous->delegate_.get() == delegate.get() &&
previous->container_view() == container_view) {
previous->SetElementBounds(element_bounds);
previous->ClearState();
return previous;
}
if (previous.get())
previous->Hide();
AutofillPopupControllerImpl* controller = new AutofillPopupControllerImplMac(
delegate, web_contents, container_view, element_bounds, text_direction);
return controller->GetWeakPtr();
}
AutofillPopupControllerImplMac::AutofillPopupControllerImplMac(
base::WeakPtr<AutofillPopupDelegate> delegate,
content::WebContents* web_contents,
gfx::NativeView container_view,
const gfx::RectF& element_bounds,
base::i18n::TextDirection text_direction)
: AutofillPopupControllerImpl(delegate,
web_contents,
container_view,
element_bounds,
text_direction),
touchBarController_(nil) {}
AutofillPopupControllerImplMac::~AutofillPopupControllerImplMac() {}
void AutofillPopupControllerImplMac::Show(
const std::vector<autofill::Suggestion>& suggestions) {
AutofillPopupControllerImpl::Show(suggestions);
if (!autofill::IsCreditCardAutofillTouchBarExperimentEnabled())
return;
if (!GetLineCount() || !layout_model().is_credit_card_popup())
return;
if (@available(macOS 10.12.2, *)) {
BrowserWindowController* bwc = [BrowserWindowController
browserWindowControllerForWindow:[container_view() window]];
TabContentsController* tabContentsController =
[[bwc tabStripController] activeTabContentsController];
touchBarController_ =
[tabContentsController webTextfieldTouchBarController];
[touchBarController_ showCreditCardAutofillWithController:this];
}
}
void AutofillPopupControllerImplMac::UpdateDataListValues(
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
AutofillPopupControllerImpl::UpdateDataListValues(values, labels);
if (touchBarController_) {
[touchBarController_ invalidateTouchBar];
}
}
void AutofillPopupControllerImplMac::Hide() {
if (touchBarController_) {
[touchBarController_ hideCreditCardAutofillTouchBar];
touchBarController_ = nil;
}
AutofillPopupControllerImpl::Hide();
}
} // namespace autofill
......@@ -18,8 +18,7 @@ class AutofillPopupViewCocoaDelegate;
} // namespace autofill
// Draws the native Autofill popup view on Mac.
@interface AutofillPopupViewCocoa
: AutofillPopupBaseViewCocoa<NSTouchBarDelegate> {
@interface AutofillPopupViewCocoa : AutofillPopupBaseViewCocoa {
@private
// The cross-platform controller for this view.
autofill::AutofillPopupController* controller_; // weak
......@@ -38,15 +37,6 @@ class AutofillPopupViewCocoaDelegate;
- (void)invalidateRow:(NSInteger)row;
// Creates and returns a touch bar if the popup is for credit cards.
- (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2));
@end
@interface AutofillPopupViewCocoa (ExposedForTesting)
- (void)acceptCreditCard:(id)sender;
@end
#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_VIEW_COCOA_H_
......@@ -8,22 +8,15 @@
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#include "chrome/browser/ui/autofill/autofill_popup_layout_model.h"
#include "chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
#import "chrome/browser/ui/cocoa/web_textfield_touch_bar_controller.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/grit/components_scaled_resources.h"
#include "components/toolbar/vector_icons.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/skia/include/core/SkColor.h"
#import "ui/base/cocoa/touch_bar_util.h"
#include "ui/base/cocoa/window_size_constants.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_palette.h"
......@@ -40,36 +33,6 @@ using autofill::AutofillPopupView;
using autofill::AutofillPopupLayoutModel;
using base::SysUTF16ToNSString;
namespace {
// Touch bar identifier.
NSString* const kCreditCardAutofillTouchBarId = @"credit-card-autofill";
// Touch bar items identifiers.
NSString* const kCreditCardTouchId = @"CREDIT-CARD";
NSString* const kCreditCardItemsTouchId = @"CREDIT-CARD-ITEMS";
// Maximum number of autofill items that can appear on the touch bar.
constexpr int maxTouchBarItems = 3;
// Returns the credit card image.
NSImage* GetCreditCardTouchBarImage(int iconId) {
if (iconId == -1)
return nil;
// If it's a generic card image, use the vector icon instead.
if (iconId == IDR_AUTOFILL_CC_GENERIC) {
return NSImageFromImageSkia(
gfx::CreateVectorIcon(kCreditCardIcon, 16, SK_ColorWHITE));
}
return ui::ResourceBundle::GetSharedInstance()
.GetNativeImageNamed(iconId)
.AsNSImage();
}
} // namespace
@interface AutofillPopupViewCocoa ()
#pragma mark -
......@@ -114,8 +77,6 @@ NSImage* GetCreditCardTouchBarImage(int iconId) {
// none.
- (NSImage*)iconAtIndex:(NSInteger)index;
- (NSColor*)touchBarSubtextColor;
@end
@implementation AutofillPopupViewCocoa
......@@ -178,88 +139,6 @@ NSImage* GetCreditCardTouchBarImage(int iconId) {
}
}
#pragma mark -
#pragma mark NSTouchBarDelegate implementation:
- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
API_AVAILABLE(macos(10.12.2)) {
if (![identifier hasSuffix:kCreditCardItemsTouchId])
return nil;
NSMutableArray* creditCardItems = [NSMutableArray array];
for (int i = 0; i < controller_->GetLineCount() && i < maxTouchBarItems;
i++) {
const autofill::Suggestion& suggestion = controller_->GetSuggestionAt(i);
if (suggestion.frontend_id < autofill::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY)
continue;
NSString* identifier = [NSString
stringWithFormat:@"%@-%i",
ui::GetTouchBarItemId(kCreditCardAutofillTouchBarId,
kCreditCardTouchId),
i];
base::scoped_nsobject<NSCustomTouchBarItem> item(
[[ui::NSCustomTouchBarItem() alloc] initWithIdentifier:identifier]);
NSString* label = SysUTF16ToNSString(controller_->GetElidedValueAt(i));
NSString* subtext = SysUTF16ToNSString(controller_->GetElidedLabelAt(i));
// Create the button title based on the text direction.
NSString* buttonTitle =
[subtext length] ? [NSString stringWithFormat:@"%@ %@", label, subtext]
: label;
// Create the button.
NSImage* cardIconImage = GetCreditCardTouchBarImage(
controller_->layout_model().GetIconResourceID(suggestion.icon));
NSButton* button = nil;
if (cardIconImage) {
button = [NSButton buttonWithTitle:buttonTitle
image:cardIconImage
target:self
action:@selector(acceptCreditCard:)];
button.imageHugsTitle = YES;
button.imagePosition = controller_->IsRTL() ? NSImageLeft : NSImageRight;
} else {
button = [NSButton buttonWithTitle:buttonTitle
target:self
action:@selector(acceptCreditCard:)];
}
// Apply text attributes to the button so that the subtext will appear
// smaller and lighter than the rest of the title.
base::scoped_nsobject<NSMutableAttributedString> attributedString(
[[NSMutableAttributedString alloc]
initWithAttributedString:button.attributedTitle]);
NSFont* subtextFont = [[NSFontManager sharedFontManager]
convertFont:button.font
toSize:button.font.pointSize - 1];
NSRange labelRange = NSMakeRange(0, label.length);
NSRange subtextRange =
NSMakeRange(buttonTitle.length - subtext.length, subtext.length);
[attributedString addAttribute:NSForegroundColorAttributeName
value:[NSColor whiteColor]
range:labelRange];
[attributedString addAttribute:NSForegroundColorAttributeName
value:[self touchBarSubtextColor]
range:subtextRange];
[attributedString addAttribute:NSFontAttributeName
value:subtextFont
range:subtextRange];
button.attributedTitle = attributedString;
// The tag is used to store the suggestion index.
button.tag = i;
[item setView:button];
[creditCardItems addObject:item.autorelease()];
}
return [ui::NSGroupTouchBarItem() groupItemWithIdentifier:identifier
items:creditCardItems];
}
#pragma mark -
#pragma mark Public API:
......@@ -275,38 +154,6 @@ NSImage* GetCreditCardTouchBarImage(int iconId) {
[self setNeedsDisplayInRect:dirty_rect];
}
- (NSTouchBar*)makeTouchBar {
if (!autofill::IsCreditCardAutofillTouchBarExperimentEnabled())
return nil;
if (!controller_->GetLineCount() ||
!controller_->layout_model().is_credit_card_popup()) {
return nil;
}
base::scoped_nsobject<NSTouchBar> touchBar([[ui::NSTouchBar() alloc] init]);
[touchBar setCustomizationIdentifier:ui::GetTouchBarId(
kCreditCardAutofillTouchBarId)];
[touchBar setDelegate:self];
[touchBar setDefaultItemIdentifiers:@[ kCreditCardItemsTouchId ]];
return touchBar.autorelease();
}
- (void)showPopup {
[super showPopup];
// The following code may show/update the touch bar by eventually calling
// into |makeTouchBar|.
BrowserWindowController* bwc = [BrowserWindowController
browserWindowControllerForWindow:[[self window] parentWindow]];
TabContentsController* tabContentsController =
[[bwc tabStripController] activeTabContentsController];
WebTextfieldTouchBarController* touchBarController =
[tabContentsController webTextfieldTouchBarController];
[touchBarController showCreditCardAutofillForPopupView:self];
}
#pragma mark -
#pragma mark Private API:
......@@ -454,16 +301,4 @@ NSImage* GetCreditCardTouchBarImage(int iconId) {
return rb.GetNativeImageNamed(iconId).ToNSImage();
}
- (NSColor*)touchBarSubtextColor {
return [NSColor colorWithCalibratedRed:180.0 / 255.0
green:180.0 / 255.0
blue:180.0 / 255.0
alpha:1.0];
}
- (void)acceptCreditCard:(id)sender {
ui::LogTouchBarUMA(ui::TouchBarAction::CREDIT_CARD_AUTOFILL);
controller_->AcceptSuggestion([sender tag]);
}
@end
// Copyright 2018 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.
#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_CREDIT_CARD_AUTOFILL_TOUCH_BAR_CONTROLLER_H_
#define CHROME_BROWSER_UI_COCOA_AUTOFILL_CREDIT_CARD_AUTOFILL_TOUCH_BAR_CONTROLLER_H_
#import <Cocoa/Cocoa.h>
#import "ui/base/cocoa/touch_bar_forward_declarations.h"
namespace autofill {
class AutofillPopupController;
}
@interface CreditCardAutofillTouchBarController : NSObject<NSTouchBarDelegate> {
autofill::AutofillPopupController* controller_; // weak
}
- (instancetype)initWithController:
(autofill::AutofillPopupController*)controller;
- (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2));
- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
API_AVAILABLE(macos(10.12.2));
@end
@interface CreditCardAutofillTouchBarController (ExposedForTesting)
- (NSButton*)createCreditCardButtonAtRow:(int)row API_AVAILABLE(macos(10.12.2));
- (void)acceptCreditCard:(id)sender;
@end
#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_CREDIT_CARD_AUTOFILL_TOUCH_BAR_CONTROLLER_H_
\ No newline at end of file
// Copyright 2018 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/autofill/credit_card_autofill_touch_bar_controller.h"
#import "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#include "chrome/browser/ui/autofill/autofill_popup_layout_model.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/grit/components_scaled_resources.h"
#import "ui/base/cocoa/touch_bar_forward_declarations.h"
#import "ui/base/cocoa/touch_bar_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia_util_mac.h"
#include "ui/gfx/paint_vector_icon.h"
namespace {
// Touch bar identifier.
NSString* const kCreditCardAutofillTouchBarId = @"credit-card-autofill";
// Touch bar items identifiers.
NSString* const kCreditCardTouchId = @"CREDIT-CARD";
NSString* const kCreditCardItemsTouchId = @"CREDIT-CARD-ITEMS";
// Maximum number of autofill items that can appear on the touch bar.
constexpr int maxTouchBarItems = 3;
// Returns the credit card image.
NSImage* GetCreditCardTouchBarImage(int iconId) {
if (iconId == -1)
return nil;
// If it's a generic card image, use the vector icon instead.
if (iconId == IDR_AUTOFILL_CC_GENERIC) {
return NSImageFromImageSkia(
gfx::CreateVectorIcon(kCreditCardIcon, 16, SK_ColorWHITE));
}
return ui::ResourceBundle::GetSharedInstance()
.GetNativeImageNamed(iconId)
.AsNSImage();
}
} // namespace
@interface CreditCardAutofillTouchBarController ()
- (NSColor*)touchBarSubtextColor;
@end
@implementation CreditCardAutofillTouchBarController
- (instancetype)initWithController:
(autofill::AutofillPopupController*)controller {
if ((self = [super init])) {
controller_ = controller;
}
return self;
}
- (NSTouchBar*)makeTouchBar {
if (!autofill::IsCreditCardAutofillTouchBarExperimentEnabled())
return nil;
if (!controller_->GetLineCount() ||
!controller_->layout_model().is_credit_card_popup()) {
return nil;
}
base::scoped_nsobject<NSTouchBar> touchBar([[ui::NSTouchBar() alloc] init]);
[touchBar setCustomizationIdentifier:ui::GetTouchBarId(
kCreditCardAutofillTouchBarId)];
[touchBar setDelegate:self];
[touchBar setDefaultItemIdentifiers:@[ kCreditCardItemsTouchId ]];
return touchBar.autorelease();
}
- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
API_AVAILABLE(macos(10.12.2)) {
if (![identifier hasSuffix:kCreditCardItemsTouchId])
return nil;
NSMutableArray* creditCardItems = [NSMutableArray array];
for (int i = 0; i < controller_->GetLineCount() && i < maxTouchBarItems;
i++) {
const autofill::Suggestion& suggestion = controller_->GetSuggestionAt(i);
if (suggestion.frontend_id < autofill::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY)
continue;
NSString* cardIdentifier = [NSString
stringWithFormat:@"%@-%i",
ui::GetTouchBarItemId(kCreditCardAutofillTouchBarId,
kCreditCardTouchId),
i];
base::scoped_nsobject<NSCustomTouchBarItem> item(
[[ui::NSCustomTouchBarItem() alloc] initWithIdentifier:cardIdentifier]);
[item setView:[self createCreditCardButtonAtRow:i]];
[creditCardItems addObject:item.autorelease()];
}
return [ui::NSGroupTouchBarItem() groupItemWithIdentifier:identifier
items:creditCardItems];
}
- (NSColor*)touchBarSubtextColor {
return [NSColor colorWithCalibratedRed:180.0 / 255.0
green:180.0 / 255.0
blue:180.0 / 255.0
alpha:1.0];
}
- (NSButton*)createCreditCardButtonAtRow:(int)row {
NSString* label =
base::SysUTF16ToNSString(controller_->GetElidedValueAt(row));
NSString* subtext =
base::SysUTF16ToNSString(controller_->GetElidedLabelAt(row));
// Create the button title based on the text direction.
NSString* buttonTitle =
[subtext length] ? [NSString stringWithFormat:@"%@ %@", label, subtext]
: label;
// Create the button.
const autofill::Suggestion& suggestion = controller_->GetSuggestionAt(row);
NSImage* cardIconImage = GetCreditCardTouchBarImage(
controller_->layout_model().GetIconResourceID(suggestion.icon));
NSButton* button = nil;
if (cardIconImage) {
button = [NSButton buttonWithTitle:buttonTitle
image:cardIconImage
target:self
action:@selector(acceptCreditCard:)];
button.imageHugsTitle = YES;
button.imagePosition = controller_->IsRTL() ? NSImageLeft : NSImageRight;
} else {
button = [NSButton buttonWithTitle:buttonTitle
target:self
action:@selector(acceptCreditCard:)];
}
// Apply text attributes to the button so that the subtext will appear
// smaller and lighter than the rest of the title.
base::scoped_nsobject<NSMutableAttributedString> attributedString(
[[NSMutableAttributedString alloc]
initWithAttributedString:button.attributedTitle]);
NSFont* subtextFont =
[[NSFontManager sharedFontManager] convertFont:button.font
toSize:button.font.pointSize - 1];
NSRange labelRange = NSMakeRange(0, label.length);
NSRange subtextRange =
NSMakeRange(buttonTitle.length - subtext.length, subtext.length);
[attributedString addAttribute:NSForegroundColorAttributeName
value:[NSColor whiteColor]
range:labelRange];
[attributedString addAttribute:NSForegroundColorAttributeName
value:[self touchBarSubtextColor]
range:subtextRange];
[attributedString addAttribute:NSFontAttributeName
value:subtextFont
range:subtextRange];
button.attributedTitle = attributedString;
// The tag is used to store the suggestion index.
button.tag = row;
return button;
}
- (void)acceptCreditCard:(id)sender {
ui::LogTouchBarUMA(ui::TouchBarAction::CREDIT_CARD_AUTOFILL);
controller_->AcceptSuggestion([sender tag]);
}
@end
......@@ -6,12 +6,13 @@
#include "base/mac/mac_util.h"
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#include "chrome/browser/ui/autofill/autofill_popup_layout_model.h"
#import "chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h"
#import "chrome/browser/ui/cocoa/autofill/credit_card_autofill_touch_bar_controller.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/suggestion.h"
......@@ -23,12 +24,23 @@
namespace {
NSString* const kCreditCardAutofillTouchBarId = @"credit-card-autofill";
NSString* const kCreditCardItemsTouchId = @"CREDIT-CARD-ITEMS";
constexpr int testSuggestionsMaxCount = 4;
class MockAutofillPopupController : public autofill::AutofillPopupController {
public:
MockAutofillPopupController() {
gfx::FontList::SetDefaultFontDescription("Arial, Times New Roman, 15px");
layout_model_.reset(new autofill::AutofillPopupLayoutModel(this, false));
suggestions_.push_back(
autofill::Suggestion("bufflehead", "canvasback", "goldeneye", 1));
suggestions_.push_back(
autofill::Suggestion("yellowlegs", "killdeer", "sandpiper", 1));
suggestions_.push_back(
autofill::Suggestion("phoebe", "flycatcher", "tyrant", 1));
suggestions_.push_back(
autofill::Suggestion("scrubjay", "bluejay", "stellersjay", 1));
}
// AutofillPopupViewDelegate
......@@ -42,9 +54,7 @@ class MockAutofillPopupController : public autofill::AutofillPopupController {
MOCK_CONST_METHOD0(element_bounds, const gfx::RectF&());
MOCK_CONST_METHOD0(IsRTL, bool());
const std::vector<autofill::Suggestion> GetSuggestions() override {
std::vector<autofill::Suggestion> suggestions(
GetLineCount(), autofill::Suggestion("", "", "", 0));
return suggestions;
return suggestions_;
}
MOCK_METHOD1(SetTypesetter, void(gfx::Typesetter typesetter));
MOCK_METHOD1(GetElidedValueWidthForRow, int(int row));
......@@ -57,10 +67,17 @@ class MockAutofillPopupController : public autofill::AutofillPopupController {
int GetLineCount() const override { return line_count_; }
const autofill::Suggestion& GetSuggestionAt(int row) const override {
return suggestion_;
return suggestions_.at(row);
}
const base::string16& GetElidedValueAt(int row) const override {
return suggestions_.at(row).value;
}
MOCK_CONST_METHOD1(GetElidedValueAt, const base::string16&(int row));
MOCK_CONST_METHOD1(GetElidedLabelAt, const base::string16&(int row));
const base::string16& GetElidedLabelAt(int row) const override {
return suggestions_.at(row).label;
}
MOCK_METHOD3(GetRemovalConfirmationText,
bool(int index, base::string16* title, base::string16* body));
MOCK_METHOD1(RemoveSuggestion, bool(int index));
......@@ -77,29 +94,25 @@ class MockAutofillPopupController : public autofill::AutofillPopupController {
new autofill::AutofillPopupLayoutModel(this, is_credit_card_field));
}
void set_line_count(int line_count) { line_count_ = line_count; }
void set_line_count(int line_count) {
EXPECT_LE(line_count, testSuggestionsMaxCount);
line_count_ = line_count;
}
private:
int line_count_;
std::vector<autofill::Suggestion> suggestions_;
std::unique_ptr<autofill::AutofillPopupLayoutModel> layout_model_;
autofill::Suggestion suggestion_;
};
class AutofillPopupViewCocoaUnitTest : public CocoaTest {
class CreditCardAutofillTouchBarControllerUnitTest : public CocoaTest {
public:
void SetUp() override {
CocoaTest::SetUp();
feature_list.InitAndEnableFeature(autofill::kCreditCardAutofillTouchBar);
// Ensure the strings in the model are elided with the BROWSER typesetter
// (i.e. CoreText), since this test can only show Cocoa UI.
EXPECT_CALL(autofill_popup_controller_,
SetTypesetter(gfx::Typesetter::BROWSER));
view_.reset([[AutofillPopupViewCocoa alloc]
initWithController:&autofill_popup_controller_
frame:NSZeroRect
delegate:nil]);
touch_bar_controller_.reset([[CreditCardAutofillTouchBarController alloc]
initWithController:&autofill_popup_controller_]);
}
void SetLineCount(int line_count) {
......@@ -109,36 +122,71 @@ class AutofillPopupViewCocoaUnitTest : public CocoaTest {
// Used to enable the the browser window touch bar.
base::test::ScopedFeatureList feature_list;
base::scoped_nsobject<AutofillPopupViewCocoa> view_;
base::scoped_nsobject<CreditCardAutofillTouchBarController>
touch_bar_controller_;
MockAutofillPopupController autofill_popup_controller_;
};
// Tests to check if the touch bar shows up properly.
TEST_F(AutofillPopupViewCocoaUnitTest, CreditCardAutofillTouchBar) {
TEST_F(CreditCardAutofillTouchBarControllerUnitTest, TouchBar) {
if (@available(macOS 10.12.2, *)) {
// Touch bar shouldn't appear if the popup is not for credit cards.
autofill_popup_controller_.SetIsCreditCardField(false);
EXPECT_FALSE([view_ makeTouchBar]);
EXPECT_FALSE([touch_bar_controller_ makeTouchBar]);
// Touch bar shouldn't appear if the popup is empty.
autofill_popup_controller_.SetIsCreditCardField(true);
SetLineCount(0);
EXPECT_FALSE([view_ makeTouchBar]);
EXPECT_FALSE([touch_bar_controller_ makeTouchBar]);
autofill_popup_controller_.SetIsCreditCardField(true);
SetLineCount(3);
NSTouchBar* touch_bar = [view_ makeTouchBar];
SetLineCount(2);
NSTouchBar* touch_bar = [touch_bar_controller_ makeTouchBar];
EXPECT_TRUE(touch_bar);
EXPECT_TRUE([[touch_bar customizationIdentifier]
isEqual:ui::GetTouchBarId(kCreditCardAutofillTouchBarId)]);
EXPECT_EQ(1UL, [[touch_bar itemIdentifiers] count]);
}
}
// Tests to check that the touch bar doesn't show more than 3 items
TEST_F(CreditCardAutofillTouchBarControllerUnitTest, TouchBarCardLimit) {
if (@available(macOS 10.12.2, *)) {
autofill_popup_controller_.SetIsCreditCardField(true);
SetLineCount(4);
NSTouchBar* touch_bar = [touch_bar_controller_ makeTouchBar];
EXPECT_TRUE(touch_bar);
EXPECT_TRUE([[touch_bar customizationIdentifier]
isEqual:ui::GetTouchBarId(kCreditCardAutofillTouchBarId)]);
NSTouchBarItem* item =
[touch_bar_controller_ touchBar:touch_bar
makeItemForIdentifier:ui::GetTouchBarItemId(
kCreditCardAutofillTouchBarId,
kCreditCardItemsTouchId)];
NSGroupTouchBarItem* groupItem = static_cast<NSGroupTouchBarItem*>(item);
EXPECT_EQ(3UL, [[[groupItem groupTouchBar] itemIdentifiers] count]);
}
}
// Tests for for the credit card button.
TEST_F(CreditCardAutofillTouchBarControllerUnitTest, CreditCardButtonCheck) {
if (@available(macOS 10.12.2, *)) {
autofill_popup_controller_.SetIsCreditCardField(true);
SetLineCount(1);
NSButton* button = [touch_bar_controller_ createCreditCardButtonAtRow:0];
EXPECT_TRUE(button);
EXPECT_EQ(0, [button tag]);
EXPECT_EQ("bufflehead canvasback", base::SysNSStringToUTF8([button title]));
}
}
// Tests that the touch bar histogram is logged correctly.
TEST_F(AutofillPopupViewCocoaUnitTest, CreditCardAutofillTouchBarMetric) {
TEST_F(CreditCardAutofillTouchBarControllerUnitTest, TouchBarMetric) {
{
base::HistogramTester histogram_tester;
[view_ acceptCreditCard:nil];
[touch_bar_controller_ acceptCreditCard:nil];
histogram_tester.ExpectBucketCount("TouchBar.Default.Metrics",
ui::TouchBarAction::CREDIT_CARD_AUTOFILL,
1);
......
......@@ -9,24 +9,33 @@
#include <memory>
#import "base/mac/scoped_nsobject.h"
#import "ui/base/cocoa/touch_bar_forward_declarations.h"
@class AutofillPopupViewCocoa;
@class CreditCardAutofillTouchBarController;
@class TabContentsController;
namespace autofill {
class AutofillPopupController;
}
// Provides a touch bar for the textfields in the WebContents. This class
// implements the NSTouchBarDelegate and handles the items in the touch bar.
@interface WebTextfieldTouchBarController : NSObject<NSTouchBarDelegate> {
TabContentsController* owner_; // weak.
AutofillPopupViewCocoa* popupView_; // weak.
NSWindow* window_; // weak.
base::scoped_nsobject<CreditCardAutofillTouchBarController>
autofillTouchBarController_; // weak.
}
// Designated initializer.
- (instancetype)initWithTabContentsController:(TabContentsController*)owner;
// Display the touch bar that is provided by |popupView|.
- (void)showCreditCardAutofillForPopupView:(AutofillPopupViewCocoa*)popupView;
- (void)showCreditCardAutofillWithController:
(autofill::AutofillPopupController*)controller;
- (void)hideCreditCardAutofillTouchBar;
- (void)invalidateTouchBar;
// Creates and returns a touch bar.
- (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2));
......
......@@ -6,7 +6,8 @@
#include "base/mac/scoped_nsobject.h"
#include "base/mac/sdk_forward_declarations.h"
#import "chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#import "chrome/browser/ui/cocoa/autofill/credit_card_autofill_touch_bar_controller.h"
#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
#import "ui/base/cocoa/touch_bar_util.h"
......@@ -25,41 +26,27 @@
[super dealloc];
}
- (void)showCreditCardAutofillForPopupView:(AutofillPopupViewCocoa*)popupView {
DCHECK(popupView);
DCHECK([popupView window]);
window_ = [popupView window];
// Remove any existing notifications before registering for new ones.
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:NSWindowWillCloseNotification object:nil];
[center addObserver:self
selector:@selector(popupWindowWillClose:)
name:NSWindowWillCloseNotification
object:window_];
popupView_ = popupView;
if ([owner_ respondsToSelector:@selector(setTouchBar:)])
[owner_ performSelector:@selector(setTouchBar:) withObject:nil];
- (void)showCreditCardAutofillWithController:
(autofill::AutofillPopupController*)controller {
autofillTouchBarController_.reset(
[[CreditCardAutofillTouchBarController alloc]
initWithController:controller]);
[self invalidateTouchBar];
}
- (void)popupWindowWillClose:(NSNotification*)notif {
popupView_ = nil;
- (void)hideCreditCardAutofillTouchBar {
autofillTouchBarController_.reset();
[self invalidateTouchBar];
}
- (void)invalidateTouchBar {
if ([owner_ respondsToSelector:@selector(setTouchBar:)])
[owner_ performSelector:@selector(setTouchBar:) withObject:nil];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:NSWindowWillCloseNotification
object:window_];
}
- (NSTouchBar*)makeTouchBar {
if (popupView_)
return [popupView_ makeTouchBar];
if (autofillTouchBarController_)
return [autofillTouchBarController_ makeTouchBar];
return nil;
}
......
......@@ -3841,8 +3841,8 @@ test("unit_tests") {
"../browser/ui/cocoa/app_menu/app_menu_controller_unittest.mm",
"../browser/ui/cocoa/app_menu/menu_tracked_root_view_unittest.mm",
"../browser/ui/cocoa/autofill/autofill_bubble_controller_unittest.mm",
"../browser/ui/cocoa/autofill/autofill_popup_view_cocoa_unittest.mm",
"../browser/ui/cocoa/autofill/autofill_tooltip_controller_unittest.mm",
"../browser/ui/cocoa/autofill/credit_card_autofill_touch_bar_controller_unittest.mm",
"../browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm",
"../browser/ui/cocoa/background_gradient_view_unittest.mm",
"../browser/ui/cocoa/base_bubble_controller_unittest.mm",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment