Commit 98929d43 authored by Stepan Khapugin's avatar Stepan Khapugin Committed by Commit Bot

Revert "Fix URL clipping on iOS 11."

This reverts commit 2d55caf6.

Reason for revert: fails tests downstream 

Original change's description:
> Fix URL clipping on iOS 11.
> 
> Wraps omnibox textfield into a container that positions the textfield
> inside of itself and clips its bounds so that the optimal clipping is
> used. The clipping logic replicates that of the pre-iOS 11 solution
> with UITextField overrides that are now broken in iOS 11.
> To mask the clipped ends of the omnibox, a ClippingMaskView is used
> as a maskView of the clipping view.
> All of this is behind kClippingTextfield flag that is enabled by
> default.
> 
> Bug: 749788
> Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
> Change-Id: Ia03649618397d19990d39914fe1fb1b152b2760d
> Reviewed-on: https://chromium-review.googlesource.com/779191
> Commit-Queue: Stepan Khapugin <stkhapugin@chromium.org>
> Reviewed-by: Sylvain Defresne <sdefresne@chromium.org>
> Reviewed-by: Justin Cohen <justincohen@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#525322}

TBR=rohitrao@chromium.org,sdefresne@chromium.org,justincohen@chromium.org,stkhapugin@chromium.org

Change-Id: I6b97cd711ef968ded8ff9a45574d6670b7c7f05f
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 749788
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Reviewed-on: https://chromium-review.googlesource.com/837087Reviewed-by: default avatarStepan Khapugin <stkhapugin@chromium.org>
Commit-Queue: Stepan Khapugin <stkhapugin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#525355}
parent e0a06a4c
...@@ -128,7 +128,6 @@ source_set("browser") { ...@@ -128,7 +128,6 @@ source_set("browser") {
"//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen",
"//ios/chrome/browser/ui/history:history_base_feature", "//ios/chrome/browser/ui/history:history_base_feature",
"//ios/chrome/browser/ui/main:feature_flags", "//ios/chrome/browser/ui/main:feature_flags",
"//ios/chrome/browser/ui/omnibox",
"//ios/chrome/browser/ui/toolbar:feature", "//ios/chrome/browser/ui/toolbar:feature",
"//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature", "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature",
"//ios/chrome/common", "//ios/chrome/common",
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #include "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
#import "ios/chrome/browser/ui/history/history_base_feature.h" #import "ios/chrome/browser/ui/history/history_base_feature.h"
#include "ios/chrome/browser/ui/main/main_feature_flags.h" #include "ios/chrome/browser/ui/main/main_feature_flags.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_clipping_feature.h"
#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
#import "ios/chrome/browser/ui/toolbar/toolbar_private_base_feature.h" #import "ios/chrome/browser/ui/toolbar/toolbar_private_base_feature.h"
#include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_strings.h"
...@@ -191,9 +190,6 @@ const flags_ui::FeatureEntry kFeatureEntries[] = { ...@@ -191,9 +190,6 @@ const flags_ui::FeatureEntry kFeatureEntries[] = {
{"clean-toolbar", flag_descriptions::kCleanToolbarName, {"clean-toolbar", flag_descriptions::kCleanToolbarName,
flag_descriptions::kCleanToolbarDescription, flags_ui::kOsIos, flag_descriptions::kCleanToolbarDescription, flags_ui::kOsIos,
FEATURE_VALUE_TYPE(kCleanToolbar)}, FEATURE_VALUE_TYPE(kCleanToolbar)},
{"clipping-textfield", flag_descriptions::kClippingTextfieldName,
flag_descriptions::kClippingTextfieldDescription, flags_ui::kOsIos,
FEATURE_VALUE_TYPE(kClippingTextfield)},
{"bookmark-new-edit-page", flag_descriptions::kBookmarkNewEditPageName, {"bookmark-new-edit-page", flag_descriptions::kBookmarkNewEditPageName,
flag_descriptions::kBookmarkNewEditPageDescription, flags_ui::kOsIos, flag_descriptions::kBookmarkNewEditPageDescription, flags_ui::kOsIos,
FEATURE_VALUE_TYPE(kBookmarkNewEditPage)}, FEATURE_VALUE_TYPE(kBookmarkNewEditPage)},
......
...@@ -35,11 +35,6 @@ const char kCleanToolbarDescription[] = ...@@ -35,11 +35,6 @@ const char kCleanToolbarDescription[] =
"When enabled, the Clean Toolbar will be used instead of " "When enabled, the Clean Toolbar will be used instead of "
"WebToolbarController."; "WebToolbarController.";
const char kClippingTextfieldName[] = "Clipping Textfield";
const char kClippingTextfieldDescription[] =
"When enabled, the new URL clipping implementation compatible with iOS 11 "
"is used.";
const char kContextualSearch[] = "Contextual Search"; const char kContextualSearch[] = "Contextual Search";
const char kContextualSearchDescription[] = const char kContextualSearchDescription[] =
"Whether or not Contextual Search is enabled."; "Whether or not Contextual Search is enabled.";
......
...@@ -29,10 +29,6 @@ extern const char kCaptivePortalDescription[]; ...@@ -29,10 +29,6 @@ extern const char kCaptivePortalDescription[];
extern const char kCleanToolbarName[]; extern const char kCleanToolbarName[];
extern const char kCleanToolbarDescription[]; extern const char kCleanToolbarDescription[];
// Title and description for the flag to enable Omnibox Clipping.
extern const char kClippingTextfieldName[];
extern const char kClippingTextfieldDescription[];
// Title and description for the flag to enable Contextual Search. // Title and description for the flag to enable Contextual Search.
extern const char kContextualSearch[]; extern const char kContextualSearch[];
extern const char kContextualSearchDescription[]; extern const char kContextualSearchDescription[];
......
...@@ -7,8 +7,6 @@ source_set("omnibox") { ...@@ -7,8 +7,6 @@ source_set("omnibox") {
"location_bar_controller.cc", "location_bar_controller.cc",
"location_bar_controller.h", "location_bar_controller.h",
"location_bar_delegate.h", "location_bar_delegate.h",
"omnibox_clipping_feature.h",
"omnibox_clipping_feature.mm",
"web_omnibox_edit_controller.cc", "web_omnibox_edit_controller.cc",
"web_omnibox_edit_controller.h", "web_omnibox_edit_controller.h",
] ]
...@@ -41,12 +39,6 @@ source_set("omnibox_internal") { ...@@ -41,12 +39,6 @@ source_set("omnibox_internal") {
"autocomplete_suggestion.h", "autocomplete_suggestion.h",
"chrome_omnibox_client_ios.h", "chrome_omnibox_client_ios.h",
"chrome_omnibox_client_ios.mm", "chrome_omnibox_client_ios.mm",
"clipping_mask_view.h",
"clipping_mask_view.mm",
"clipping_textfield.h",
"clipping_textfield.mm",
"clipping_textfield_container.h",
"clipping_textfield_container.mm",
"image_retriever.h", "image_retriever.h",
"location_bar_controller_impl.h", "location_bar_controller_impl.h",
"location_bar_controller_impl.mm", "location_bar_controller_impl.mm",
...@@ -138,11 +130,9 @@ source_set("unit_tests") { ...@@ -138,11 +130,9 @@ source_set("unit_tests") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
testonly = true testonly = true
sources = [ sources = [
"clipping_textfield_container_unittest.mm",
"omnibox_text_field_ios_unittest.mm", "omnibox_text_field_ios_unittest.mm",
] ]
deps = [ deps = [
":omnibox",
":omnibox_internal", ":omnibox_internal",
":resources_unit_tests", ":resources_unit_tests",
"//base", "//base",
......
// 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.
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_MASK_VIEW_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_MASK_VIEW_H_
#import <UIKit/UIKit.h>
// The view used as a mask when the omnibox textfield is being clipped.
// Displays an opaque rectangle with left, right, or both edges being
// faded out with transparent gradient.
@interface ClippingMaskView : UIView
// Whether the left edge is faded.
@property(nonatomic, assign) BOOL fadeLeft;
// Whether the right edge is faded.
@property(nonatomic, assign) BOOL fadeRight;
@end
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_MASK_VIEW_H_
// 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 "ios/chrome/browser/ui/omnibox/clipping_mask_view.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
#pragma mark - GradientView
namespace {
enum GradientViewDirection {
GRADIENT_LEFT_TO_RIGHT,
GRADIENT_RIGHT_TO_LEFT,
};
} // namespace
// The gradient view is a view that displays a simple horizontal gradient, from
// black to transparent.
@interface GradientView : UIView
// Sets the gradient's direction. You have to call this at least once to
// configure the gradient.
@property(nonatomic, assign) GradientViewDirection direction;
@end
@implementation GradientView
@synthesize direction = _direction;
+ (Class)layerClass {
return [CAGradientLayer class];
}
- (void)setDirection:(GradientViewDirection)direction {
_direction = direction;
CAGradientLayer* layer = static_cast<CAGradientLayer*>(self.layer);
layer.colors = @[
static_cast<id>([[UIColor clearColor] CGColor]),
static_cast<id>([[UIColor blackColor] CGColor])
];
if (direction == GRADIENT_LEFT_TO_RIGHT) {
layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1);
} else {
layer.transform = CATransform3DMakeRotation(-M_PI_2, 0, 0, 1);
}
[self setNeedsDisplay];
}
@end
#pragma mark - ClippingMaskView
@interface ClippingMaskView ()
// The left gradient view.
@property(nonatomic, strong) GradientView* leftGradientView;
// The right gradient view.
@property(nonatomic, strong) GradientView* rightGradientView;
// The middle view. Used to paint everything not covered by the gradients with
// opaque color.
@property(nonatomic, strong) UIView* middleView;
@end
@implementation ClippingMaskView
@synthesize fadeLeft = _fadeLeft;
@synthesize fadeRight = _fadeRight;
@synthesize middleView = _middleView;
@synthesize leftGradientView = _leftGradientView;
@synthesize rightGradientView = _rightGradientView;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_leftGradientView = [[GradientView alloc] init];
[_leftGradientView setTranslatesAutoresizingMaskIntoConstraints:NO];
_leftGradientView.direction = GRADIENT_RIGHT_TO_LEFT;
_rightGradientView = [[GradientView alloc] init];
[_rightGradientView setTranslatesAutoresizingMaskIntoConstraints:NO];
_rightGradientView.direction = GRADIENT_LEFT_TO_RIGHT;
_middleView = [[UIView alloc] init];
[_middleView setTranslatesAutoresizingMaskIntoConstraints:NO];
_middleView.backgroundColor = [UIColor blackColor];
[self addSubview:_leftGradientView];
[self addSubview:_middleView];
[self addSubview:_rightGradientView];
}
return self;
}
- (void)setFadeLeft:(BOOL)fadeLeft {
_fadeLeft = fadeLeft;
self.leftGradientView.hidden = !fadeLeft;
}
- (void)setFadeRight:(BOOL)fadeRight {
_fadeRight = fadeRight;
self.rightGradientView.hidden = !fadeRight;
}
// Since this view is intended to be used as a maskView of another UIView, and
// maskViews are not in the view hierarchy, autolayout is not supported.
// Luckily, the desired layout is easy:
// |[leftGradientView][middleView][rightGradientView]|,
// where the grad views are sometimes hidden (and then the middle view is
// extended to that side). The gradients' widths are equal to the height of this
// view.
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat height = self.bounds.size.height;
CGFloat gradientWidth = height;
CGFloat xOffset = 0;
if (self.fadeLeft) {
self.leftGradientView.frame = CGRectMake(0, 0, gradientWidth, height);
xOffset += gradientWidth;
}
CGFloat midWidth = self.bounds.size.width - xOffset;
if (self.fadeRight) {
midWidth -= gradientWidth;
}
self.middleView.frame = CGRectMake(xOffset, 0, midWidth, height);
xOffset += midWidth;
if (self.fadeRight) {
self.rightGradientView.frame =
CGRectMake(xOffset, 0, gradientWidth, height);
}
}
@end
// 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.
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_TEXTFIELD_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_TEXTFIELD_H_
#import <UIKit/UIKit.h>
@protocol ClippingTextFieldDelegate;
// This textfield subclass is designed to be paired with
// ClippingTextFieldContainer. It notifies its delegate about changes of text
// and becoming/resigning first responder.
@interface ClippingTextField : UITextField
@property(nonatomic, weak) id<ClippingTextFieldDelegate>
clippingTextfieldDelegate;
@end
@protocol ClippingTextFieldDelegate
// Called when setText: or setAttributedText: was called. Not called when the
// textfield is being typed into.
- (void)textFieldTextChanged:(UITextField*)sender;
- (void)textFieldBecameFirstResponder:(UITextField*)sender;
- (void)textFieldResignedFirstResponder:(UITextField*)sender;
@end
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_TEXTFIELD_H_
// 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 "ios/chrome/browser/ui/omnibox/clipping_textfield.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@implementation ClippingTextField
@synthesize clippingTextfieldDelegate = _clippingTextfieldDelegate;
- (void)setText:(NSString*)setText {
[super setText:setText];
[self.clippingTextfieldDelegate textFieldTextChanged:self];
}
- (void)setAttributedText:(NSAttributedString*)attributedText {
[super setAttributedText:attributedText];
[self.clippingTextfieldDelegate textFieldTextChanged:self];
}
- (BOOL)becomeFirstResponder {
BOOL didBecomeFirstResponder = [super becomeFirstResponder];
[self.clippingTextfieldDelegate textFieldBecameFirstResponder:self];
return didBecomeFirstResponder;
}
- (BOOL)resignFirstResponder {
BOOL didResignFirstResponder = [super resignFirstResponder];
if (didResignFirstResponder) {
[self.clippingTextfieldDelegate textFieldResignedFirstResponder:self];
}
return didResignFirstResponder;
}
@end
// 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.
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_TEXTFIELD_CONTAINER_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_TEXTFIELD_CONTAINER_H_
#import "ios/chrome/browser/ui/omnibox/clipping_textfield.h"
// A container for the textfield that manages clipping it appropriately.
// It will size the textfield to fit precisely when the textfield is first
// responder. Otherwise, it will clip the textfield to its own bounds in the
// best way to fit the most significant part of the URL, like this:
//
// --------------------
// www.somereallyreally|longdomainname.com|/path/gets/clipped
// --------------------
// { clipped prefix } { visible text } { clipped suffix }
//
// The clipped parts will also be masked with a gradient fade effect on the
// clipped ends.
@interface ClippingTextFieldContainer : UIView<ClippingTextFieldDelegate>
// The only available initializer. This will immediately add |textField| as its
// subview and set |self| as textField's clipping delegate.
- (instancetype)initWithClippingTextField:(ClippingTextField*)textField
NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
// Managed textfield.
@property(nonatomic, strong, readonly) ClippingTextField* textField;
@end
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_CLIPPING_TEXTFIELD_CONTAINER_H_
// 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 "ios/chrome/browser/ui/omnibox/clipping_textfield_container.h"
#include "base/strings/sys_string_conversions.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h"
#import "ios/chrome/browser/ui/omnibox/clipping_mask_view.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface ClippingTextFieldContainer ()
@property(nonatomic, strong) NSLayoutConstraint* leftConstraint;
@property(nonatomic, strong) NSLayoutConstraint* rightConstraint;
@property(nonatomic, strong) ClippingMaskView* gradientMaskView;
@property(nonatomic, assign, getter=isClipping) BOOL clipping;
@end
@implementation ClippingTextFieldContainer
@synthesize textField = _textField;
@synthesize leftConstraint = _leftConstraint;
@synthesize rightConstraint = _rightConstraint;
@synthesize gradientMaskView = _gradientMaskView;
@synthesize clipping = _clipping;
- (instancetype)initWithClippingTextField:(ClippingTextField*)textField {
self = [super initWithFrame:CGRectZero];
if (self) {
_textField = textField;
textField.clippingTextfieldDelegate = self;
[self addSubview:textField];
_gradientMaskView = [[ClippingMaskView alloc] init];
self.maskView = _gradientMaskView;
// Configure layout.
// Left and Right are used instead of Leading and Trailing because the
// clipping only ever applies to URLs that are always displayed in LTR.
_leftConstraint =
[self.textField.leftAnchor constraintEqualToAnchor:self.leftAnchor];
_rightConstraint =
[self.textField.rightAnchor constraintEqualToAnchor:self.rightAnchor];
[NSLayoutConstraint activateConstraints:@[
[textField.topAnchor constraintEqualToAnchor:self.topAnchor],
[textField.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
_leftConstraint,
_rightConstraint,
]];
textField.translatesAutoresizingMaskIntoConstraints = NO;
self.clipsToBounds = YES;
_clipping = NO;
}
return self;
}
- (void)layoutSubviews {
if ([self isClipping]) {
[self applyClipping];
}
[super layoutSubviews];
self.gradientMaskView.frame = self.bounds;
}
- (void)startClipping {
self.clipping = YES;
[self applyClipping];
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)applyClipping {
CGFloat suffixWidth = 0;
CGFloat prefixWidth =
-[self leftConstantWithAttributedText:self.textField.attributedText
rightConstant:&suffixWidth];
[self applyGradientsToPrefix:(prefixWidth < 0) suffix:(suffixWidth > 0)];
self.leftConstraint.constant = prefixWidth;
self.rightConstraint.constant = suffixWidth;
}
- (void)stopClipping {
if (![self isClipping]) {
return;
}
self.clipping = NO;
self.leftConstraint.constant = 0;
self.rightConstraint.constant = 0;
[self removeGradient];
}
// Fade the beginning and/or end of the visible string to indicate to the user
// that the URL has been clipped.
- (void)applyGradientsToPrefix:(BOOL)shouldApplyToPrefix
suffix:(BOOL)shouldApplyToSuffix {
self.gradientMaskView.fadeLeft = shouldApplyToPrefix;
self.gradientMaskView.fadeRight = shouldApplyToSuffix;
}
- (void)removeGradient {
[self applyGradientsToPrefix:NO suffix:NO];
}
#pragma mark calculate clipping
// Calculates the length (in pts) of the clipped text on the left and
// right sides of the omnibox in order to show the most significant part of
// the hostname.
- (CGFloat)leftConstantWithAttributedText:(NSAttributedString*)attributedText
rightConstant:(out CGFloat*)right {
// The goal is to always show the most significant part of the hostname
// (i.e. the end of the TLD).
//
// --------------------
// www.somereallyreally|longdomainname.com|/path/gets/clipped
// --------------------
// { clipped prefix } { visible text } { clipped suffix }
// First find how much (if any) of the scheme/host needs to be clipped so that
// the end of the TLD fits in bounds.
CGFloat widthOfClippedPrefix = 0;
url::Component scheme, host;
AutocompleteInput::ParseForEmphasizeComponents(
base::SysNSStringToUTF16(attributedText.string),
AutocompleteSchemeClassifierImpl(), &scheme, &host);
if (host.len < 0) {
return 0;
}
NSRange hostRange = NSMakeRange(0, host.begin + host.len);
NSAttributedString* hostString =
[attributedText attributedSubstringFromRange:hostRange];
CGFloat widthOfHost = ceil(hostString.size.width);
widthOfClippedPrefix = MAX(widthOfHost - self.bounds.size.width, 0);
// Now determine if there is any text that will need to be truncated because
// there's not enough room.
int textWidth = ceil(attributedText.size.width);
CGFloat widthOfClippedSuffix =
MAX(textWidth - self.bounds.size.width - widthOfClippedPrefix, 0);
*right = widthOfClippedSuffix;
return widthOfClippedPrefix;
}
#pragma mark - ClippingTextFieldDelegate
- (void)textFieldTextChanged:(UITextField*)sender {
[self startClipping];
}
- (void)textFieldBecameFirstResponder:(UITextField*)sender {
[self stopClipping];
}
- (void)textFieldResignedFirstResponder:(UITextField*)sender {
[self startClipping];
}
@end
// 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 "ios/chrome/browser/ui/omnibox/clipping_textfield_container.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
class ClippingTextFieldContainerTest : public PlatformTest {
protected:
void SetUp() override {
PlatformTest::SetUp();
textField_ = [[ClippingTextField alloc] init];
container_ = [[ClippingTextFieldContainer alloc]
initWithClippingTextField:textField_];
[[[UIApplication sharedApplication] keyWindow] addSubview:container_];
// Width of 200 is enough to fit "http://www.google.com" and is
// in the same ballpark as iPhone omnibox.
container_.frame = CGRectMake(0, 0, 200, 20);
};
void TearDown() override { [container_ removeFromSuperview]; }
ClippingTextFieldContainer* container_;
ClippingTextField* textField_;
UIView* LeftDecorationView() {
// The decoration container contains the decoration views covering the
// tail and the head.
UIView* decorationContainer = container_.maskView;
CGPoint leftMidPoint = CGPointMake(0, container_.bounds.size.height / 2);
for (UIView* decorationView in decorationContainer.subviews) {
if (CGRectContainsPoint(decorationView.frame, leftMidPoint)) {
return decorationView;
}
}
return nil;
}
UIView* RightDecorationView() {
// The decoration container contains the decoration views covering the
// tail and the head.
UIView* decorationContainer = container_.maskView;
// Substract 0.5pt from x coordinate because CGRectContainsPoint
// returns NO for points on the maximum X edge.
CGPoint rightMidPoint = CGPointMake(container_.bounds.size.width - 0.5,
container_.bounds.size.height / 2);
for (UIView* decorationView in decorationContainer.subviews) {
if (CGRectContainsPoint(decorationView.frame, rightMidPoint)) {
return decorationView;
}
}
return nil;
}
};
TEST_F(ClippingTextFieldContainerTest, DoesntClipWhenEntireURLFits) {
NSString* text = @"http://www.google.com";
[textField_ setText:text];
// The textfield fits in the container.
EXPECT_LE(textField_.frame.size.width, container_.frame.size.width);
}
TEST_F(ClippingTextFieldContainerTest, ClipsLongPrefix) {
NSString* text = @"http://verylongprefixwaymorethan200pts.google.com";
[textField_ setText:text];
// The left edge is clipped, so the textfield is shifted left.
EXPECT_TRUE(textField_.frame.origin.x < 0);
// The amount it's shifted left by is just enough to fit the URL.
EXPECT_EQ(textField_.frame.origin.x + textField_.frame.size.width,
container_.frame.size.width);
}
TEST_F(ClippingTextFieldContainerTest, ClipsLongSuffix) {
NSString* text = @"http://www.google.com/verylongsuffixwaymorethan200pts";
[textField_ setText:text];
// The left edge is not clipped.
EXPECT_EQ(textField_.frame.origin.x, 0);
// The right edge is clipped.
EXPECT_GE(textField_.frame.size.width, container_.frame.size.width);
}
TEST_F(ClippingTextFieldContainerTest, ClipsPrefixAndSuffix) {
NSString* text =
@"http://verylongprefixwaymorethan200pts.google.com/"
@"verylongsuffixwaymorethan200pts";
[textField_ setText:text];
CGSize textSize = [[textField_ attributedText] size];
// The left edge is clipped.
EXPECT_TRUE(textField_.frame.origin.x < 0);
// The right edge is clipped.
EXPECT_GE(textField_.frame.size.width + textField_.frame.origin.x,
container_.frame.size.width);
// The textfield expands to fit the text.
EXPECT_EQ(textField_.frame.size.width, ceil(textSize.width));
}
TEST_F(ClippingTextFieldContainerTest, NoScheme) {
NSString* text = @"www.google.com";
[textField_ setText:text];
// The textfield fits in the container.
EXPECT_LE(textField_.frame.size.width, container_.frame.size.width);
// The left edge is not clipped.
EXPECT_EQ(textField_.frame.origin.x, 0);
// Textfield's size is equal to container size and greater than text.
CGSize textSize = [[textField_ attributedText] size];
textSize.width = ceil(textSize.width);
textSize.height = ceil(textSize.height);
EXPECT_EQ(textField_.frame.size.width, container_.bounds.size.width);
EXPECT_LE(textSize.width, textField_.bounds.size.width);
}
TEST_F(ClippingTextFieldContainerTest, NoHost) {
NSString* text = @"http://";
[textField_ setText:text];
// The textfield fits in the container.
EXPECT_LE(textField_.frame.size.width, container_.frame.size.width);
// The left edge is not clipped.
EXPECT_EQ(textField_.frame.origin.x, 0);
// Textfield's size is equal to container size and greater than text.
CGSize textSize = [[textField_ attributedText] size];
textSize.width = ceil(textSize.width);
textSize.height = ceil(textSize.height);
EXPECT_EQ(textField_.frame.size.width, container_.bounds.size.width);
EXPECT_LE(textSize.width, textField_.bounds.size.width);
}
TEST_F(ClippingTextFieldContainerTest, DoesntClipWhenFocused) {
NSString* text =
@"http://verylongprefixwaymorethan200pts.google.com/"
@"verylongsuffixwaymorethan200pts";
[textField_ setText:text];
// The left edge is clipped.
EXPECT_TRUE(textField_.frame.origin.x < 0);
// The right edge is clipped.
EXPECT_GE(textField_.frame.size.width + textField_.frame.origin.x,
container_.frame.size.width);
[textField_ becomeFirstResponder];
[container_ layoutIfNeeded];
// When focused, the textfield should take the container's space and
// not be clipped.
EXPECT_EQ(textField_.frame.origin.x, 0);
EXPECT_EQ(textField_.frame.size.width, container_.frame.size.width);
[textField_ resignFirstResponder];
[container_ layoutIfNeeded];
// The left edge is clipped.
EXPECT_TRUE(textField_.frame.origin.x < 0);
// The right edge is clipped.
EXPECT_GE(textField_.frame.size.width + textField_.frame.origin.x,
container_.frame.size.width);
}
TEST_F(ClippingTextFieldContainerTest, ShowsDecorationsWhenClipping) {
NSString* text =
@"http://verylongprefixwaymorethan200pts.google.com/"
@"verylongsuffixwaymorethan200pts";
[textField_ setText:text];
// Tail and head are masked when the ends are clipped.
EXPECT_FALSE(LeftDecorationView().hidden);
EXPECT_FALSE(RightDecorationView().hidden);
[textField_ becomeFirstResponder];
[container_ layoutIfNeeded];
// Even for long strings, the masks are disabled while editing.
EXPECT_TRUE(LeftDecorationView().hidden);
EXPECT_TRUE(RightDecorationView().hidden);
[textField_ resignFirstResponder];
[container_ layoutIfNeeded];
// Deselecting textfield with a long string remasks the ends.
EXPECT_FALSE(LeftDecorationView().hidden);
EXPECT_FALSE(RightDecorationView().hidden);
}
} // namespace
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#import "ios/chrome/browser/ui/omnibox/location_bar_view.h" #import "ios/chrome/browser/ui/omnibox/location_bar_view.h"
#import "ios/chrome/browser/ui/animation_util.h" #import "ios/chrome/browser/ui/animation_util.h"
#import "ios/chrome/browser/ui/omnibox/clipping_textfield_container.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_clipping_feature.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h" #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
#import "ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h" #import "ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h"
#include "ios/chrome/browser/ui/ui_util.h" #include "ios/chrome/browser/ui/ui_util.h"
...@@ -62,10 +60,6 @@ const CGFloat kTextFieldLeadingOffsetImage = 6; ...@@ -62,10 +60,6 @@ const CGFloat kTextFieldLeadingOffsetImage = 6;
// When the |leadingButton| is not hidden, this is a constraint that links the // When the |leadingButton| is not hidden, this is a constraint that links the
// leading edge of the button to self leading edge. Used for animations. // leading edge of the button to self leading edge. Used for animations.
@property(nonatomic, strong) NSLayoutConstraint* leadingButtonLeadingConstraint; @property(nonatomic, strong) NSLayoutConstraint* leadingButtonLeadingConstraint;
// The textfield container. The |textField| is contained in it, and its frame
// should not be managed directly, instead the location bar uses this container.
// This is required to achieve desired text clipping of long URLs.
@property(nonatomic, strong) ClippingTextFieldContainer* textFieldContainer;
@end @end
@implementation LocationBarView @implementation LocationBarView
...@@ -74,7 +68,6 @@ const CGFloat kTextFieldLeadingOffsetImage = 6; ...@@ -74,7 +68,6 @@ const CGFloat kTextFieldLeadingOffsetImage = 6;
@synthesize leadingTextfieldConstraint = _leadingTextfieldConstraint; @synthesize leadingTextfieldConstraint = _leadingTextfieldConstraint;
@synthesize incognito = _incognito; @synthesize incognito = _incognito;
@synthesize leadingButtonLeadingConstraint = _leadingButtonLeadingConstraint; @synthesize leadingButtonLeadingConstraint = _leadingButtonLeadingConstraint;
@synthesize textFieldContainer = _textFieldContainer;
#pragma mark - Public properties #pragma mark - Public properties
...@@ -105,55 +98,20 @@ const CGFloat kTextFieldLeadingOffsetImage = 6; ...@@ -105,55 +98,20 @@ const CGFloat kTextFieldLeadingOffsetImage = 6;
font:font font:font
textColor:textColor textColor:textColor
tintColor:tintColor]; tintColor:tintColor];
[self addSubview:_textField];
if (base::FeatureList::IsEnabled(kClippingTextfield)) { _leadingTextfieldConstraint = [_textField.leadingAnchor
// When clipping is enabled, the text field is put into a container. constraintEqualToAnchor:self.leadingAnchor
constant:kTextFieldLeadingOffsetNoImage];
// TODO(crbug.com/789968): remove these insets when the location bar
// background is managed by this view and not toolbar controller. These [NSLayoutConstraint activateConstraints:@[
// insets allow the gradient masking of the omnibox to not extend beyond [_textField.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
// the omnibox background's visible frame. [_textField.topAnchor constraintEqualToAnchor:self.topAnchor],
self.layoutMargins = UIEdgeInsetsMake(3, 3, 3, 3); [_textField.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
_leadingTextfieldConstraint,
_textFieldContainer = [[ClippingTextFieldContainer alloc] ]];
initWithClippingTextField:_textField];
[self addSubview:_textFieldContainer]; _textField.translatesAutoresizingMaskIntoConstraints = NO;
_leadingTextfieldConstraint = [_textFieldContainer.leadingAnchor
constraintEqualToAnchor:self.leadingAnchor
constant:kTextFieldLeadingOffsetNoImage];
[NSLayoutConstraint activateConstraints:@[
[_textFieldContainer.trailingAnchor
constraintEqualToAnchor:self.layoutMarginsGuide.trailingAnchor],
[_textFieldContainer.topAnchor
constraintEqualToAnchor:self.layoutMarginsGuide.topAnchor],
[_textFieldContainer.bottomAnchor
constraintEqualToAnchor:self.layoutMarginsGuide.bottomAnchor],
_leadingTextfieldConstraint,
]];
_textFieldContainer.translatesAutoresizingMaskIntoConstraints = NO;
[_textFieldContainer
setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:
UILayoutConstraintAxisHorizontal];
} else {
// Contain the text field directly, with no clipping container.
[self addSubview:_textField];
_leadingTextfieldConstraint = [_textField.leadingAnchor
constraintEqualToAnchor:self.leadingAnchor
constant:kTextFieldLeadingOffsetNoImage];
[NSLayoutConstraint activateConstraints:@[
[_textField.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
[_textField.topAnchor constraintEqualToAnchor:self.topAnchor],
[_textField.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
_leadingTextfieldConstraint,
]];
_textField.translatesAutoresizingMaskIntoConstraints = NO;
}
} }
return self; return self;
} }
...@@ -169,26 +127,15 @@ const CGFloat kTextFieldLeadingOffsetImage = 6; ...@@ -169,26 +127,15 @@ const CGFloat kTextFieldLeadingOffsetImage = 6;
} else { } else {
[self addSubview:_leadingButton]; [self addSubview:_leadingButton];
self.leadingTextfieldConstraint.active = NO; self.leadingTextfieldConstraint.active = NO;
self.leadingButtonLeadingConstraint = [self.layoutMarginsGuide.leadingAnchor self.leadingButtonLeadingConstraint = [self.leadingAnchor
constraintEqualToAnchor:self.leadingButton.leadingAnchor constraintEqualToAnchor:self.leadingButton.leadingAnchor
constant:-kLeadingButtonEdgeOffset]; constant:-kLeadingButtonEdgeOffset];
NSLayoutConstraint* leadingButtonToTextField = nil;
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
leadingButtonToTextField = [self.leadingButton.trailingAnchor
constraintEqualToAnchor:self.textFieldContainer.leadingAnchor
constant:-kTextFieldLeadingOffsetImage];
} else {
leadingButtonToTextField = [self.leadingButton.trailingAnchor
constraintEqualToAnchor:self.textField.leadingAnchor
constant:-kTextFieldLeadingOffsetImage];
}
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[_leadingButton.centerYAnchor [_leadingButton.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
constraintEqualToAnchor:self.layoutMarginsGuide.centerYAnchor],
self.leadingButtonLeadingConstraint, self.leadingButtonLeadingConstraint,
leadingButtonToTextField, [self.leadingButton.trailingAnchor
constraintEqualToAnchor:self.textField.leadingAnchor
constant:-kTextFieldLeadingOffsetImage],
]]; ]];
} }
} }
......
// 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.
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_CLIPPING_FEATURE_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_CLIPPING_FEATURE_H_
#include "base/feature_list.h"
// Feature to choose whether to use the iOS 11-compatible textfield clipping.
extern const base::Feature kClippingTextfield;
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_CLIPPING_FEATURE_H_
// 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 "ios/chrome/browser/ui/omnibox/omnibox_clipping_feature.h"
const base::Feature kClippingTextfield{"kClippingTextfield",
base::FEATURE_ENABLED_BY_DEFAULT};
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_TEXT_FIELD_IOS_H_ #ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_TEXT_FIELD_IOS_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_TEXT_FIELD_IOS_H_ #define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_TEXT_FIELD_IOS_H_
#import "ios/chrome/browser/ui/omnibox/clipping_textfield.h" #import <UIKit/UIKit.h>
#include "base/strings/string16.h" #include "base/strings/string16.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_text_field_delegate.h" #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_delegate.h"
...@@ -17,7 +17,7 @@ typedef enum { ...@@ -17,7 +17,7 @@ typedef enum {
} OmniboxTextFieldFadeStyle; } OmniboxTextFieldFadeStyle;
// UITextField subclass to allow for adjusting borders. // UITextField subclass to allow for adjusting borders.
@interface OmniboxTextFieldIOS : ClippingTextField @interface OmniboxTextFieldIOS : UITextField
// Initialize the omnibox with the given frame, font, text color, and tint // Initialize the omnibox with the given frame, font, text color, and tint
// color. // color.
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h" #include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h"
#include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/experimental_flags.h"
#import "ios/chrome/browser/ui/animation_util.h" #import "ios/chrome/browser/ui/animation_util.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_clipping_feature.h"
#include "ios/chrome/browser/ui/omnibox/omnibox_util.h" #include "ios/chrome/browser/ui/omnibox/omnibox_util.h"
#import "ios/chrome/browser/ui/reversed_animation.h" #import "ios/chrome/browser/ui/reversed_animation.h"
#include "ios/chrome/browser/ui/rtl_geometry.h" #include "ios/chrome/browser/ui/rtl_geometry.h"
...@@ -534,12 +533,6 @@ NSString* const kOmniboxFadeAnimationKey = @"OmniboxFadeAnimation"; ...@@ -534,12 +533,6 @@ NSString* const kOmniboxFadeAnimationKey = @"OmniboxFadeAnimation";
// Enumerate url components (host, path) and draw each one in different rect. // Enumerate url components (host, path) and draw each one in different rect.
- (void)drawTextInRect:(CGRect)rect { - (void)drawTextInRect:(CGRect)rect {
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
// With the new clipping logic, this override is unnecessary.
[super drawTextInRect:rect];
return;
}
if (base::ios::IsRunningOnOrLater(11, 1, 0)) { if (base::ios::IsRunningOnOrLater(11, 1, 0)) {
// -[UITextField drawTextInRect:] ignores the argument, so we can't do // -[UITextField drawTextInRect:] ignores the argument, so we can't do
// anything on 11.1 and up. // anything on 11.1 and up.
...@@ -846,11 +839,6 @@ NSString* const kOmniboxFadeAnimationKey = @"OmniboxFadeAnimation"; ...@@ -846,11 +839,6 @@ NSString* const kOmniboxFadeAnimationKey = @"OmniboxFadeAnimation";
} }
- (CGRect)rectForDrawTextInRect:(CGRect)rect { - (CGRect)rectForDrawTextInRect:(CGRect)rect {
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
// With the new clipping logic, this override is unnecessary.
return rect;
}
// The goal is to always show the most significant part of the hostname // The goal is to always show the most significant part of the hostname
// (i.e. the end of the TLD). // (i.e. the end of the TLD).
// //
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "ios/chrome/browser/chrome_paths.h" #include "ios/chrome/browser/chrome_paths.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_clipping_feature.h"
#include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_strings.h"
#include "testing/gtest_mac.h" #include "testing/gtest_mac.h"
#include "testing/platform_test.h" #include "testing/platform_test.h"
...@@ -144,12 +143,6 @@ TEST_F(OmniboxTextFieldTest, enterPreEditState_preEditTextAlignment_change) { ...@@ -144,12 +143,6 @@ TEST_F(OmniboxTextFieldTest, enterPreEditState_preEditTextAlignment_change) {
} }
TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_entireURLFits) { TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_entireURLFits) {
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
// This test is expected to not work with new text field clipping because
// the code to implement clipping will be removed.
return;
}
NSString* text = @"http://www.google.com"; NSString* text = @"http://www.google.com";
[textfield_ setText:text]; [textfield_ setText:text];
CGSize textSize = [[textfield_ attributedText] size]; CGSize textSize = [[textfield_ attributedText] size];
...@@ -161,12 +154,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_entireURLFits) { ...@@ -161,12 +154,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_entireURLFits) {
} }
TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedPrefix) { TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedPrefix) {
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
// This test is expected to not work with new text field clipping because
// the code to implement clipping will be removed.
return;
}
NSString* text = @"http://www.google.com"; NSString* text = @"http://www.google.com";
[textfield_ setText:text]; [textfield_ setText:text];
CGSize textSize = [[textfield_ attributedText] size]; CGSize textSize = [[textfield_ attributedText] size];
...@@ -181,12 +168,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedPrefix) { ...@@ -181,12 +168,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedPrefix) {
} }
TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedSuffix) { TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedSuffix) {
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
// This test is expected to not work with new text field clipping because
// the code to implement clipping will be removed.
return;
}
NSString* text = @"http://www.google.com/somelongpath"; NSString* text = @"http://www.google.com/somelongpath";
[textfield_ setText:text]; [textfield_ setText:text];
CGSize textSize = [[textfield_ attributedText] size]; CGSize textSize = [[textfield_ attributedText] size];
...@@ -199,12 +180,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedSuffix) { ...@@ -199,12 +180,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_clippedSuffix) {
} }
TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_noScheme) { TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_noScheme) {
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
// This test is expected to not work with new text field clipping because
// the code to implement clipping will be removed.
return;
}
NSString* text = @"www.google.com"; NSString* text = @"www.google.com";
[textfield_ setText:text]; [textfield_ setText:text];
CGSize textSize = [[textfield_ attributedText] size]; CGSize textSize = [[textfield_ attributedText] size];
...@@ -217,12 +192,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_noScheme) { ...@@ -217,12 +192,6 @@ TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_noScheme) {
// When the text doesn't contain a host the method bails early and returns // When the text doesn't contain a host the method bails early and returns
// the |rect| passed in. // the |rect| passed in.
TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_noHost) { TEST_F(OmniboxTextFieldTest, rectForDrawTextInRect_noHost) {
if (base::FeatureList::IsEnabled(kClippingTextfield)) {
// This test is expected to not work with new text field clipping because
// the code to implement clipping will be removed.
return;
}
NSString* text = @"http://"; NSString* text = @"http://";
[textfield_ setText:text]; [textfield_ setText:text];
CGSize textSize = [[textfield_ attributedText] size]; CGSize textSize = [[textfield_ attributedText] size];
......
...@@ -259,9 +259,6 @@ using ios::material::TimingFunction; ...@@ -259,9 +259,6 @@ using ios::material::TimingFunction;
_keyboardDelegate = [[ToolbarAssistiveKeyboardDelegateImpl alloc] init]; _keyboardDelegate = [[ToolbarAssistiveKeyboardDelegateImpl alloc] init];
_keyboardDelegate.dispatcher = dispatcher; _keyboardDelegate.dispatcher = dispatcher;
_keyboardDelegate.omniboxTextField = _locationBarView.textField; _keyboardDelegate.omniboxTextField = _locationBarView.textField;
[_locationBarView
setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
// Disable default drop interactions on the omnibox. // Disable default drop interactions on the omnibox.
// TODO(crbug.com/739903): Handle drop events once Chrome iOS is built with // TODO(crbug.com/739903): Handle drop events once Chrome iOS is built with
......
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