Commit a7c84fb2 authored by Guillaume Jenkins's avatar Guillaume Jenkins Committed by Chromium LUCI CQ

[iOS Enterprise] BrowserSignin: FRE changes

Adds a message and an icon to the first run Welcome to Chrome page
when the browser is managed by enterprise. The browser is considered
managed if there is some policy data in the
-com.apple.configuration.managed key of the NSUserDefaults.

Bug: 1155745
Change-Id: Ice85f780c5508376d7ad1cacdddcd7927b8c97fd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2580699Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarJavier Flores <javierrobles@chromium.org>
Commit-Queue: Guillaume Jenkins <gujen@google.com>
Cr-Commit-Position: refs/heads/master@{#837182}
parent 72a96aad
...@@ -828,6 +828,9 @@ Because your account is managed by <ph name="HOSTED_DOMAIN">$1<ex>google.com</ex ...@@ -828,6 +828,9 @@ Because your account is managed by <ph name="HOSTED_DOMAIN">$1<ex>google.com</ex
<message name="IDS_IOS_PHONE_CALL_BUTTON" desc="Text in the confirmation dialog button that will initiate a phone call for the presented number. [Length: 10em] [iOS only]"> <message name="IDS_IOS_PHONE_CALL_BUTTON" desc="Text in the confirmation dialog button that will initiate a phone call for the presented number. [Length: 10em] [iOS only]">
Call Call
</message> </message>
<message name="IDS_IOS_FIRSTRUN_BROWSER_MANAGED" desc="Label explaining that the app is managed by an organization. This is shown on the Welcome screen presented to the user on First Run. Only shown if some enterprise policies are set. [iOS only]">
Your browser is managed by your organization. Some features may be disabled.
</message>
<message name="IDS_IOS_FIRSTRUN_TERMS_TITLE" desc="Title for the Terms of Service page shown to user on First Run. [Length: 20em] [iOS only]"> <message name="IDS_IOS_FIRSTRUN_TERMS_TITLE" desc="Title for the Terms of Service page shown to user on First Run. [Length: 20em] [iOS only]">
Terms of Service Terms of Service
</message> </message>
......
826942b951f0e9ae684c0ad623864df03781b2df
\ No newline at end of file
...@@ -49,6 +49,7 @@ source_set("first_run") { ...@@ -49,6 +49,7 @@ source_set("first_run") {
"//base", "//base",
"//base:i18n", "//base:i18n",
"//components/metrics", "//components/metrics",
"//components/policy/core/common:common_constants",
"//components/prefs", "//components/prefs",
"//components/signin/public/identity_manager", "//components/signin/public/identity_manager",
"//ios/chrome/app:tests_hook", "//ios/chrome/app:tests_hook",
...@@ -68,6 +69,7 @@ source_set("first_run") { ...@@ -68,6 +69,7 @@ source_set("first_run") {
"//ios/chrome/browser/ui/fancy_ui", "//ios/chrome/browser/ui/fancy_ui",
"//ios/chrome/browser/ui/icons", "//ios/chrome/browser/ui/icons",
"//ios/chrome/browser/ui/material_components", "//ios/chrome/browser/ui/material_components",
"//ios/chrome/browser/ui/settings/resources:enterprise_icon",
"//ios/chrome/browser/ui/settings/sync/utils", "//ios/chrome/browser/ui/settings/sync/utils",
"//ios/chrome/browser/ui/settings/utils", "//ios/chrome/browser/ui/settings/utils",
"//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/util",
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/i18n/rtl.h" #include "base/i18n/rtl.h"
#include "base/notreached.h" #include "base/notreached.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#import "components/policy/core/common/policy_loader_ios_constants.h"
#import "ios/chrome/browser/ui/elements/text_view_selection_disabled.h" #import "ios/chrome/browser/ui/elements/text_view_selection_disabled.h"
#include "ios/chrome/browser/ui/fancy_ui/primary_action_button.h" #include "ios/chrome/browser/ui/fancy_ui/primary_action_button.h"
#include "ios/chrome/browser/ui/first_run/first_run_util.h" #include "ios/chrome/browser/ui/first_run/first_run_util.h"
...@@ -67,6 +68,7 @@ const CGFloat kImageTopPadding[SIZE_CLASS_COUNT] = {32.0, 50.0}; ...@@ -67,6 +68,7 @@ const CGFloat kImageTopPadding[SIZE_CLASS_COUNT] = {32.0, 50.0};
const CGFloat kTOSTextViewTopPadding[SIZE_CLASS_COUNT] = {34.0, 40.0}; const CGFloat kTOSTextViewTopPadding[SIZE_CLASS_COUNT] = {34.0, 40.0};
const CGFloat kOptInLabelPadding[SIZE_CLASS_COUNT] = {10.0, 14.0}; const CGFloat kOptInLabelPadding[SIZE_CLASS_COUNT] = {10.0, 14.0};
const CGFloat kCheckBoxPadding[SIZE_CLASS_COUNT] = {10.0, 16.0}; const CGFloat kCheckBoxPadding[SIZE_CLASS_COUNT] = {10.0, 16.0};
const CGFloat kManagedLabelPadding[SIZE_CLASS_COUNT] = {14.0, 20.0};
const CGFloat kOKButtonBottomPadding[SIZE_CLASS_COUNT] = {32.0, 32.0}; const CGFloat kOKButtonBottomPadding[SIZE_CLASS_COUNT] = {32.0, 32.0};
const CGFloat kOKButtonHeight[SIZE_CLASS_COUNT] = {36.0, 54.0}; const CGFloat kOKButtonHeight[SIZE_CLASS_COUNT] = {36.0, 54.0};
// Multiplier matches that used in LaunchScreen.xib to determine size of logo. // Multiplier matches that used in LaunchScreen.xib to determine size of logo.
...@@ -78,6 +80,8 @@ const CGFloat kTOSTOSTextViewFontSize[SIZE_CLASS_COUNT] = {14.0, 21.0}; ...@@ -78,6 +80,8 @@ const CGFloat kTOSTOSTextViewFontSize[SIZE_CLASS_COUNT] = {14.0, 21.0};
const CGFloat kLegacyTOSLabelLineHeight[SIZE_CLASS_COUNT] = {20.0, 32.0}; const CGFloat kLegacyTOSLabelLineHeight[SIZE_CLASS_COUNT] = {20.0, 32.0};
const CGFloat kOptInLabelFontSize[SIZE_CLASS_COUNT] = {13.0, 19.0}; const CGFloat kOptInLabelFontSize[SIZE_CLASS_COUNT] = {13.0, 19.0};
const CGFloat kOptInLabelLineHeight[SIZE_CLASS_COUNT] = {18.0, 26.0}; const CGFloat kOptInLabelLineHeight[SIZE_CLASS_COUNT] = {18.0, 26.0};
const CGFloat kManagedLabelFontSize[SIZE_CLASS_COUNT] = {13.0, 19.0};
const CGFloat kManagedLabelLineHeight[SIZE_CLASS_COUNT] = {18.0, 26.0};
const CGFloat kOKButtonTitleLabelFontSize[SIZE_CLASS_COUNT] = {14.0, 20.0}; const CGFloat kOKButtonTitleLabelFontSize[SIZE_CLASS_COUNT] = {14.0, 20.0};
// Animation constants // Animation constants
...@@ -89,6 +93,7 @@ const CGFloat kAnimationDelay = .5; ...@@ -89,6 +93,7 @@ const CGFloat kAnimationDelay = .5;
NSString* const kAppLogoImageName = @"launchscreen_app_logo"; NSString* const kAppLogoImageName = @"launchscreen_app_logo";
NSString* const kCheckBoxImageName = @"checkbox"; NSString* const kCheckBoxImageName = @"checkbox";
NSString* const kCheckBoxCheckedImageName = @"checkbox_checked"; NSString* const kCheckBoxCheckedImageName = @"checkbox_checked";
NSString* const kEnterpriseIconImageName = @"enterprise_icon";
// Constant for the Terms of Service URL in the first run experience. // Constant for the Terms of Service URL in the first run experience.
const char kTermsOfServiceUrl[] = "internal://terms-of-service"; const char kTermsOfServiceUrl[] = "internal://terms-of-service";
...@@ -101,6 +106,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -101,6 +106,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
UIImageView* _imageView; UIImageView* _imageView;
UIButton* _checkBoxButton; UIButton* _checkBoxButton;
UILabel* _optInLabel; UILabel* _optInLabel;
UILabel* _managedLabel;
UIImageView* _enterpriseIcon;
PrimaryActionButton* _OKButton; PrimaryActionButton* _OKButton;
// Used for iOS 12 compatibility. // Used for iOS 12 compatibility.
...@@ -130,6 +137,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -130,6 +137,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
@property(strong, nonatomic) LabelObserver* optInObserver; @property(strong, nonatomic) LabelObserver* optInObserver;
// The stats reporting opt-in checkbox button. // The stats reporting opt-in checkbox button.
@property(strong, nonatomic, readonly) UIButton* checkBoxButton; @property(strong, nonatomic, readonly) UIButton* checkBoxButton;
// Observer for setting the size of the managedLabel with cr_lineHeight.
@property(strong, nonatomic) LabelObserver* managedObserver;
// The Chrome logo image view.
@property(strong, nonatomic, readonly) UIImageView* enterpriseIcon;
// The "Accept & Continue" button. // The "Accept & Continue" button.
@property(strong, nonatomic, readonly) PrimaryActionButton* OKButton; @property(strong, nonatomic, readonly) PrimaryActionButton* OKButton;
...@@ -140,6 +151,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -140,6 +151,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
- (void)layoutTOSTextView; - (void)layoutTOSTextView;
- (void)layoutOptInLabel; - (void)layoutOptInLabel;
- (void)layoutCheckBoxButton; - (void)layoutCheckBoxButton;
- (void)layoutManagedLabel;
- (void)layoutEnterpriseIcon;
- (void)layoutContainerView; - (void)layoutContainerView;
- (void)layoutOKButton; - (void)layoutOKButton;
...@@ -151,6 +164,7 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -151,6 +164,7 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
- (void)configureImageView; - (void)configureImageView;
- (void)configureTOSTextView; - (void)configureTOSTextView;
- (void)configureOptInLabel; - (void)configureOptInLabel;
- (void)configureManagedLabel;
- (void)configureContainerView; - (void)configureContainerView;
- (void)configureOKButton; - (void)configureOKButton;
...@@ -182,6 +196,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -182,6 +196,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
self.legacyTOSLabel.alpha = 0.0; self.legacyTOSLabel.alpha = 0.0;
self.optInLabel.alpha = 0.0; self.optInLabel.alpha = 0.0;
self.checkBoxButton.alpha = 0.0; self.checkBoxButton.alpha = 0.0;
self.managedLabel.alpha = 0.0;
self.enterpriseIcon.alpha = 0.0;
self.OKButton.alpha = 0.0; self.OKButton.alpha = 0.0;
// Get final location of logo based on result from previously run // Get final location of logo based on result from previously run
...@@ -203,6 +219,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -203,6 +219,8 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
[weakSelf TOSTextView].alpha = 1.0; [weakSelf TOSTextView].alpha = 1.0;
[weakSelf legacyTOSLabel].alpha = 1.0; [weakSelf legacyTOSLabel].alpha = 1.0;
[weakSelf optInLabel].alpha = 1.0; [weakSelf optInLabel].alpha = 1.0;
[weakSelf managedLabel].alpha = 1.0;
[weakSelf enterpriseIcon].alpha = 1.0;
[weakSelf checkBoxButton].alpha = 1.0; [weakSelf checkBoxButton].alpha = 1.0;
[weakSelf OKButton].alpha = 1.0; [weakSelf OKButton].alpha = 1.0;
} }
...@@ -309,6 +327,29 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -309,6 +327,29 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
return _checkBoxButton; return _checkBoxButton;
} }
- (UILabel*)managedLabel {
if (!_managedLabel) {
_managedLabel = [[UILabel alloc] initWithFrame:CGRectZero];
// Add an observer to the label to be able to keep the cr_lineHeight.
self.managedObserver = [LabelObserver observerForLabel:_managedLabel];
[self.managedObserver startObserving];
[_managedLabel setNumberOfLines:0];
[_managedLabel
setText:l10n_util::GetNSString(IDS_IOS_FIRSTRUN_BROWSER_MANAGED)];
[_managedLabel setTextAlignment:NSTextAlignmentNatural];
}
return _managedLabel;
}
- (UIImageView*)enterpriseIcon {
if (!_enterpriseIcon) {
UIImage* image = [UIImage imageNamed:kEnterpriseIconImageName];
_enterpriseIcon = [[UIImageView alloc] initWithImage:image];
}
return _enterpriseIcon;
}
- (PrimaryActionButton*)OKButton { - (PrimaryActionButton*)OKButton {
if (!_OKButton) { if (!_OKButton) {
_OKButton = [[PrimaryActionButton alloc] initWithFrame:CGRectZero]; _OKButton = [[PrimaryActionButton alloc] initWithFrame:CGRectZero];
...@@ -327,6 +368,11 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -327,6 +368,11 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
return _OKButton; return _OKButton;
} }
- (BOOL)isBrowserManaged {
return [[[NSUserDefaults standardUserDefaults]
dictionaryForKey:kPolicyLoaderIOSConfigurationKey] count] > 0;
}
#pragma mark - Layout #pragma mark - Layout
- (void)willMoveToSuperview:(nullable UIView*)newSuperview { - (void)willMoveToSuperview:(nullable UIView*)newSuperview {
...@@ -348,6 +394,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -348,6 +394,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
} }
[self.containerView addSubview:self.optInLabel]; [self.containerView addSubview:self.optInLabel];
[self.containerView addSubview:self.checkBoxButton]; [self.containerView addSubview:self.checkBoxButton];
if ([self isBrowserManaged]) {
[self.containerView addSubview:self.managedLabel];
[self.containerView addSubview:self.enterpriseIcon];
}
[self addSubview:self.OKButton]; [self addSubview:self.OKButton];
[self configureSubviews]; [self configureSubviews];
} }
...@@ -358,6 +408,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -358,6 +408,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
} }
- (void)layoutSubviews { - (void)layoutSubviews {
// TODO(crbug.com/1157934): This page should support dynamic type to respect
// the user's chosen font size. This layout might need to be changed for
// smaller screen sizes and large fonts, as it might not fit a single screen,
// especially with the "managed by organization" enterprise notice.
[super layoutSubviews]; [super layoutSubviews];
[self layoutTitleLabel]; [self layoutTitleLabel];
[self layoutImageView]; [self layoutImageView];
...@@ -368,6 +422,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -368,6 +422,10 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
} }
[self layoutOptInLabel]; [self layoutOptInLabel];
[self layoutCheckBoxButton]; [self layoutCheckBoxButton];
if ([self isBrowserManaged]) {
[self layoutManagedLabel];
[self layoutEnterpriseIcon];
}
[self layoutOKButtonAndContainerView]; [self layoutOKButtonAndContainerView];
} }
...@@ -512,15 +570,62 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -512,15 +570,62 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
base::i18n::IsRTL() ? smallHorizontalInset : largeHorizontalInset); base::i18n::IsRTL() ? smallHorizontalInset : largeHorizontalInset);
} }
- (void)layoutManagedLabel {
// The managed label is laid out to the right (or left in RTL) of the
// enterprise icon and below |optInLabel| as specified by
// kManagedLabelPadding. It is aligned horizontally with |optInLabel|.
CGSize checkBoxSize =
[self.checkBoxButton imageForState:self.checkBoxButton.state].size;
CGFloat checkBoxPadding = kCheckBoxPadding[[self widthSizeClassIdiom]];
CGFloat managedLabelSidePadding = checkBoxSize.width + 2.0 * checkBoxPadding;
CGSize managedLabelSize = [self.managedLabel
sizeThatFits:CGSizeMake(CGRectGetWidth(self.optInLabel.bounds),
CGFLOAT_MAX)];
CGFloat managedLabelTopPadding =
kManagedLabelPadding[[self heightSizeClassIdiom]];
CGFloat managedLabelOriginX =
base::i18n::IsRTL()
? self.optInLabel.bounds.size.width - managedLabelSize.width
: managedLabelSidePadding;
self.managedLabel.frame = AlignRectOriginAndSizeToPixels(CGRectMake(
managedLabelOriginX,
CGRectGetMaxY(self.checkBoxButton.frame) + managedLabelTopPadding,
managedLabelSize.width, managedLabelSize.height));
}
- (void)layoutEnterpriseIcon {
// The enterprise icon is laid out to the left of and is centered vertically
// with |managedLabel|, and is aligned horizontally with the checkbox image
// inside |checkBoxButton|.
CGSize enterpriseIconSize = self.enterpriseIcon.bounds.size;
CGFloat enterpriseIconOriginX =
CGRectGetMidX(self.checkBoxButton.imageView.frame) -
enterpriseIconSize.height / 2.0;
CGFloat enterpriseIconOriginY =
CGRectGetMidY(self.managedLabel.frame) - enterpriseIconSize.height / 2.0;
self.enterpriseIcon.frame = AlignRectOriginAndSizeToPixels(
CGRectMake(enterpriseIconOriginX, enterpriseIconOriginY,
enterpriseIconSize.width, enterpriseIconSize.height));
}
- (void)layoutContainerView { - (void)layoutContainerView {
// The container view is resized according to the final layout of // The container view is resized according to the final layout of its lowest
// |checkBoxButton|, which is its lowest subview. The resized view is then // subview, which is |managedLabel| if the browser is managed and
// centered horizontally and vertically. If necessary, it is shifted up to // |checkBoxButton| if not. The resized view is then centered horizontally and
// allow |kOptInLabelPadding| between |optInLabel| and |OKButton|. // vertically. If necessary, it is shifted up to allow either
// |kmanagedLabelPadding| or |kOptInLabelPadding| (depending if the browser is
// managed) between |optInLabel| and |OKButton|.
CGSize containerViewSize = self.containerView.bounds.size; CGSize containerViewSize = self.containerView.bounds.size;
containerViewSize.height = CGRectGetMaxY(self.checkBoxButton.frame); containerViewSize.height = [self isBrowserManaged]
? CGRectGetMaxY(self.managedLabel.frame)
: CGRectGetMaxY(self.checkBoxButton.frame);
CGFloat padding = [self isBrowserManaged]
? kManagedLabelPadding[[self heightSizeClassIdiom]]
: kOptInLabelPadding[[self heightSizeClassIdiom]];
CGFloat padding = kOptInLabelPadding[[self heightSizeClassIdiom]];
CGFloat originY = fmin( CGFloat originY = fmin(
(CGRectGetHeight(self.bounds) - containerViewSize.height) / 2.0, (CGRectGetHeight(self.bounds) - containerViewSize.height) / 2.0,
CGRectGetMinY(self.OKButton.frame) - padding - containerViewSize.height); CGRectGetMinY(self.OKButton.frame) - padding - containerViewSize.height);
...@@ -560,6 +665,9 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -560,6 +665,9 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
[self configureLegacyTOSLabel]; [self configureLegacyTOSLabel];
} }
[self configureOptInLabel]; [self configureOptInLabel];
if ([self isBrowserManaged]) {
[self configureManagedLabel];
}
[self configureOKButton]; [self configureOKButton];
[self setNeedsLayout]; [self setNeedsLayout];
} }
...@@ -629,6 +737,14 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service"; ...@@ -629,6 +737,14 @@ const char kTermsOfServiceUrl[] = "internal://terms-of-service";
kOptInLabelLineHeight[[self widthSizeClassIdiom]]; kOptInLabelLineHeight[[self widthSizeClassIdiom]];
} }
- (void)configureManagedLabel {
self.managedLabel.font = [[MDCTypography fontLoader]
regularFontOfSize:kManagedLabelFontSize[[self widthSizeClassIdiom]]];
self.managedLabel.cr_lineHeight =
kManagedLabelLineHeight[[self widthSizeClassIdiom]];
self.managedLabel.textColor = [UIColor colorNamed:kTextSecondaryColor];
}
- (void)configureLegacyTOSLabel { - (void)configureLegacyTOSLabel {
self.legacyTOSLabel.font = [[MDCTypography fontLoader] self.legacyTOSLabel.font = [[MDCTypography fontLoader]
regularFontOfSize:kTOSTOSTextViewFontSize[[self widthSizeClassIdiom]]]; regularFontOfSize:kTOSTOSTextViewFontSize[[self widthSizeClassIdiom]]];
......
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