Commit 3dffd189 authored by Chris Lu's avatar Chris Lu Committed by Commit Bot

[ios] Add First Run Location Permissions Modal

This change adds logic to show a modal detailing Chromium's
use of location data after First Run and showing the prompt if the
user taps on the primary action button. This is hidden behind the
kLocationFirstRunModal flag.

Bug: 1138603
Change-Id: I5ba49231b547edaeaef1ee025744a344f9135998
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2485748
Commit-Queue: Chris Lu <thegreenfrog@chromium.org>
Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822029}
parent dc84da4d
...@@ -214,6 +214,9 @@ locale. The strings in this file are specific to iOS. ...@@ -214,6 +214,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_LOCATION_AUTHORIZATION_ALERT" desc="Specifies the reason for sending the user's location to Google [Length: unlimited] [iOS only]."> <message name="IDS_IOS_LOCATION_AUTHORIZATION_ALERT" desc="Specifies the reason for sending the user's location to Google [Length: unlimited] [iOS only].">
Get a better Google experience in Chromium based on your location. Get a better Google experience in Chromium based on your location.
</message> </message>
<message name="IDS_IOS_LOCATION_MODAL_DESCRIPTION" desc="The description of the location permissions modal [Length: unlimited] [iOS only].">
When you allow use of your location, Chromium sends it to your default search engine and sites where you give permission. Sites usually use your location for local information, like news or nearby shops.
</message>
<message name="IDS_IOS_LOCATION_WHEN_IN_USE_USAGE_DESCRIPTION" desc="Specifies the reason for accessing the user's location information while the app is in use [Length: unlimited] [iOS only]."> <message name="IDS_IOS_LOCATION_WHEN_IN_USE_USAGE_DESCRIPTION" desc="Specifies the reason for accessing the user's location information while the app is in use [Length: unlimited] [iOS only].">
Get a better experience in Chromium based on your location. Get a better experience in Chromium based on your location.
</message> </message>
......
5e76f676db2a77a2f1256f9273f2ba876bc5cd88
\ No newline at end of file
...@@ -214,6 +214,9 @@ locale. The strings in this file are specific to iOS. ...@@ -214,6 +214,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_LOCATION_AUTHORIZATION_ALERT" desc="Specifies the reason for sending the user's location to Google [Length: unlimited] [iOS only]."> <message name="IDS_IOS_LOCATION_AUTHORIZATION_ALERT" desc="Specifies the reason for sending the user's location to Google [Length: unlimited] [iOS only].">
Get a better Google experience in Chrome based on your location. Get a better Google experience in Chrome based on your location.
</message> </message>
<message name="IDS_IOS_LOCATION_MODAL_DESCRIPTION" desc="The description of the location permissions modal [Length: unlimited] [iOS only].">
When you allow use of your location, Chrome sends it to your default search engine and sites where you give permission. Sites usually use your location for local information, like news or nearby shops.
</message>
<message name="IDS_IOS_LOCATION_WHEN_IN_USE_USAGE_DESCRIPTION" desc="Specifies the reason for accessing the user's location information while the app is in use [Length: unlimited] [iOS only]."> <message name="IDS_IOS_LOCATION_WHEN_IN_USE_USAGE_DESCRIPTION" desc="Specifies the reason for accessing the user's location information while the app is in use [Length: unlimited] [iOS only].">
Get a better experience in Chrome based on your location. Get a better experience in Chrome based on your location.
</message> </message>
......
5e76f676db2a77a2f1256f9273f2ba876bc5cd88
\ No newline at end of file
...@@ -1027,6 +1027,12 @@ Because your account is managed by <ph name="HOSTED_DOMAIN">$1<ex>google.com</ex ...@@ -1027,6 +1027,12 @@ Because your account is managed by <ph name="HOSTED_DOMAIN">$1<ex>google.com</ex
<message name="IDS_IOS_KEYBOARD_PREVIOUS_TAB" desc="Title of the keyboard shortcut to switch to the previous tab in the tab strip. [Length: 20 em] [iOS only]"> <message name="IDS_IOS_KEYBOARD_PREVIOUS_TAB" desc="Title of the keyboard shortcut to switch to the previous tab in the tab strip. [Length: 20 em] [iOS only]">
Previous Tab Previous Tab
</message> </message>
<message name="IDS_IOS_LOCATION_MODAL_TITLE" desc="The title of the locaton permissions modal [Length: unlimited] [iOS only].">
Use Your Current Location.
</message>
<message name="IDS_IOS_LOCATION_MODAL_PRIMARY_BUTTON" desc="The primary button of the locaton permissions modal [Length: unlimited] [iOS only].">
Allow Location...
</message>
<message name="IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_TEXT" desc="Text for the LongPress Toolbar Tip in-product help promotion, explaining that the user can long press on the toolbar's button to display more options. [iOS only]"> <message name="IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_TEXT" desc="Text for the LongPress Toolbar Tip in-product help promotion, explaining that the user can long press on the toolbar's button to display more options. [iOS only]">
Touch &amp; hold for more tab options Touch &amp; hold for more tab options
</message> </message>
......
5e76f676db2a77a2f1256f9273f2ba876bc5cd88
\ No newline at end of file
5e76f676db2a77a2f1256f9273f2ba876bc5cd88
\ No newline at end of file
...@@ -79,6 +79,9 @@ enum class KeyRetrievalTriggerForUMA; ...@@ -79,6 +79,9 @@ enum class KeyRetrievalTriggerForUMA;
- (void)showAdvancedSigninSettingsFromViewController: - (void)showAdvancedSigninSettingsFromViewController:
(UIViewController*)baseViewController; (UIViewController*)baseViewController;
- (void)showLocationPermissionsFromViewController:
(UIViewController*)baseViewController;
// Presents the Trusted Vault reauth dialog. // Presents the Trusted Vault reauth dialog.
// |baseViewController| presents the sign-in. // |baseViewController| presents the sign-in.
// |retrievalTrigger| UI elements where the trusted vault reauth has been // |retrievalTrigger| UI elements where the trusted vault reauth has been
......
...@@ -7,6 +7,11 @@ source_set("first_run") { ...@@ -7,6 +7,11 @@ source_set("first_run") {
sources = [ sources = [
"first_run_util.h", "first_run_util.h",
"first_run_util.mm", "first_run_util.mm",
"location_permissions_commands.h",
"location_permissions_coordinator.h",
"location_permissions_coordinator.mm",
"location_permissions_view_controller.h",
"location_permissions_view_controller.mm",
"orientation_limiting_navigation_controller.h", "orientation_limiting_navigation_controller.h",
"orientation_limiting_navigation_controller.mm", "orientation_limiting_navigation_controller.mm",
"static_file_view_controller.h", "static_file_view_controller.h",
...@@ -20,6 +25,7 @@ source_set("first_run") { ...@@ -20,6 +25,7 @@ source_set("first_run") {
":constants", ":constants",
"resources:checkbox", "resources:checkbox",
"resources:checkbox_checked", "resources:checkbox_checked",
"resources:first_run_location_permissions",
"//base", "//base",
"//base:i18n", "//base:i18n",
"//components/metrics", "//components/metrics",
...@@ -31,6 +37,7 @@ source_set("first_run") { ...@@ -31,6 +37,7 @@ source_set("first_run") {
"//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state",
"//ios/chrome/browser/crash_report", "//ios/chrome/browser/crash_report",
"//ios/chrome/browser/first_run", "//ios/chrome/browser/first_run",
"//ios/chrome/browser/geolocation:geolocation_internal",
"//ios/chrome/browser/main", "//ios/chrome/browser/main",
"//ios/chrome/browser/signin", "//ios/chrome/browser/signin",
"//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui:feature_flags",
...@@ -48,6 +55,7 @@ source_set("first_run") { ...@@ -48,6 +55,7 @@ source_set("first_run") {
"//ios/chrome/browser/web_state_list", "//ios/chrome/browser/web_state_list",
"//ios/chrome/common", "//ios/chrome/common",
"//ios/chrome/common/ui/colors", "//ios/chrome/common/ui/colors",
"//ios/chrome/common/ui/confirmation_alert",
"//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser",
"//ios/public/provider/chrome/browser/signin", "//ios/public/provider/chrome/browser/signin",
"//ios/third_party/material_components_ios", "//ios/third_party/material_components_ios",
......
// Copyright 2020 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_FIRST_RUN_LOCATION_PERMISSIONS_COMMANDS_H_
#define IOS_CHROME_BROWSER_UI_FIRST_RUN_LOCATION_PERMISSIONS_COMMANDS_H_
// Command to signal to receiver to handle location permissions modal actions.
@protocol LocationPermissionsCommands <NSObject>
// Command the modal to be hidden.
- (void)dismissLocationPermissionsExplanationModal;
@end
#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_LOCATION_PERMISSIONS_COMMANDS_H_
// Copyright 2020 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_FIRST_RUN_LOCATION_PERMISSIONS_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_FIRST_RUN_LOCATION_PERMISSIONS_COORDINATOR_H_
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
#import "ios/chrome/browser/ui/first_run/location_permissions_commands.h"
// Coordinator that manages a LocationPermissionsViewController.
@interface LocationPermissionsCoordinator : ChromeCoordinator
// Handler for all actions of this coordinator.
@property(nonatomic, weak) id<LocationPermissionsCommands> handler;
@end
#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_LOCATION_PERMISSIONS_COORDINATOR_H_
// Copyright 2020 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/first_run/location_permissions_coordinator.h"
#import "ios/chrome/browser/geolocation/omnibox_geolocation_controller.h"
#import "ios/chrome/browser/ui/first_run/location_permissions_view_controller.h"
#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface LocationPermissionsCoordinator () <ConfirmationAlertActionHandler>
// The fullscreen confirmation modal promo view controller this coordiantor
// manages.
@property(nonatomic, strong)
LocationPermissionsViewController* locationPermissionsViewController;
@end
@implementation LocationPermissionsCoordinator
#pragma mark - Public Methods.
- (void)start {
[super start];
self.locationPermissionsViewController =
[[LocationPermissionsViewController alloc] init];
self.locationPermissionsViewController.actionHandler = self;
self.locationPermissionsViewController.modalPresentationStyle =
UIModalPresentationFormSheet;
[self.baseViewController
presentViewController:self.locationPermissionsViewController
animated:YES
completion:nil];
}
- (void)stop {
[self.locationPermissionsViewController.presentingViewController
dismissViewControllerAnimated:YES
completion:nil];
self.locationPermissionsViewController = nil;
[super stop];
}
#pragma mark - ConfirmationAlertActionHandler
- (void)confirmationAlertPrimaryAction {
[self.handler dismissLocationPermissionsExplanationModal];
[[OmniboxGeolocationController sharedInstance]
triggerSystemPromptForNewUser:YES];
}
- (void)confirmationAlertSecondaryAction {
[self.handler dismissLocationPermissionsExplanationModal];
}
- (void)confirmationAlertDismissAction {
// No-op.
}
- (void)confirmationAlertLearnMoreAction {
// No-op.
}
@end
// Copyright 2020 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_FIRST_RUN_LOCATION_PERMISSIONS_VIEW_CONTROLLER_H_
#define IOS_CHROME_BROWSER_UI_FIRST_RUN_LOCATION_PERMISSIONS_VIEW_CONTROLLER_H_
#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h"
// Presents a fullscreen modal that explains location data usage. Accepting the
// main action will trigger a native location permissions prompt.
@interface LocationPermissionsViewController : ConfirmationAlertViewController
@end
#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_LOCATION_PERMISSIONS_VIEW_CONTROLLER_H_
// Copyright 2020 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/first_run/location_permissions_view_controller.h"
#include "ios/chrome/grit/ios_google_chrome_strings.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@implementation LocationPermissionsViewController
#pragma mark - Public
- (void)loadView {
self.image = [UIImage imageNamed:@"first_run_location_permissions"];
self.customSpacingAfterImage = 30;
self.primaryActionAvailable = YES;
self.secondaryActionAvailable = YES;
self.showDismissBarButton = NO;
self.titleString = l10n_util::GetNSString(IDS_IOS_LOCATION_MODAL_TITLE);
self.subtitleString =
l10n_util::GetNSString(IDS_IOS_LOCATION_MODAL_DESCRIPTION);
self.primaryActionString =
l10n_util::GetNSString(IDS_IOS_LOCATION_MODAL_PRIMARY_BUTTON);
self.secondaryActionString =
l10n_util::GetNSString(IDS_IOS_DEFAULT_BROWSER_SECONDARY_BUTTON_TEXT);
self.dismissBarButtonSystemItem = UIBarButtonSystemItemCancel;
#if defined(__IPHONE_13_4)
if (@available(iOS 13.4, *)) {
self.pointerInteractionEnabled = YES;
}
#endif // defined(__IPHONE_13_4)
[super loadView];
}
@end
...@@ -25,3 +25,13 @@ imageset("checkbox_checked") { ...@@ -25,3 +25,13 @@ imageset("checkbox_checked") {
"checkbox_checked.imageset/checkbox_checked~ipad.png", "checkbox_checked.imageset/checkbox_checked~ipad.png",
] ]
} }
imageset("first_run_location_permissions") {
sources = [
"first_run_location_permissions.imageset/Contents.json",
"first_run_location_permissions.imageset/first_run_location_permissions_dark@2x.png",
"first_run_location_permissions.imageset/first_run_location_permissions_dark@3x.png",
"first_run_location_permissions.imageset/first_run_location_permissions_light@2x.png",
"first_run_location_permissions.imageset/first_run_location_permissions_light@3x.png",
]
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "first_run_location_permissions_light@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "first_run_location_permissions_dark@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "first_run_location_permissions_light@3x.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "first_run_location_permissions_dark@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -249,6 +249,11 @@ const BOOL kDefaultStatsCheckboxValue = YES; ...@@ -249,6 +249,11 @@ const BOOL kDefaultStatsCheckboxValue = YES;
[self.dispatcher [self.dispatcher
showAdvancedSigninSettingsFromViewController: showAdvancedSigninSettingsFromViewController:
presentingViewController]; presentingViewController];
} else if (base::FeatureList::IsEnabled(
kLocationFirstRunModal)) {
[self.dispatcher
showLocationPermissionsFromViewController:
presentingViewController];
} }
}]; }];
} }
......
...@@ -85,6 +85,7 @@ source_set("scene") { ...@@ -85,6 +85,7 @@ source_set("scene") {
"//ios/chrome/browser/crash_report/breadcrumbs", "//ios/chrome/browser/crash_report/breadcrumbs",
"//ios/chrome/browser/crash_report/breadcrumbs:feature_flags", "//ios/chrome/browser/crash_report/breadcrumbs:feature_flags",
"//ios/chrome/browser/first_run", "//ios/chrome/browser/first_run",
"//ios/chrome/browser/geolocation:geolocation_internal",
"//ios/chrome/browser/main", "//ios/chrome/browser/main",
"//ios/chrome/browser/ntp:features", "//ios/chrome/browser/ntp:features",
"//ios/chrome/browser/screenshot", "//ios/chrome/browser/screenshot",
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "ios/chrome/browser/crash_report/crash_report_helper.h" #include "ios/chrome/browser/crash_report/crash_report_helper.h"
#import "ios/chrome/browser/crash_report/crash_restore_helper.h" #import "ios/chrome/browser/crash_report/crash_restore_helper.h"
#import "ios/chrome/browser/first_run/first_run.h" #import "ios/chrome/browser/first_run/first_run.h"
#import "ios/chrome/browser/geolocation/omnibox_geolocation_controller.h"
#import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/main/browser_list.h" #import "ios/chrome/browser/main/browser_list.h"
#import "ios/chrome/browser/main/browser_list_factory.h" #import "ios/chrome/browser/main/browser_list_factory.h"
...@@ -59,6 +60,8 @@ ...@@ -59,6 +60,8 @@
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/commands/show_signin_command.h" #import "ios/chrome/browser/ui/commands/show_signin_command.h"
#import "ios/chrome/browser/ui/first_run/first_run_util.h" #import "ios/chrome/browser/ui/first_run/first_run_util.h"
#import "ios/chrome/browser/ui/first_run/location_permissions_commands.h"
#import "ios/chrome/browser/ui/first_run/location_permissions_coordinator.h"
#import "ios/chrome/browser/ui/first_run/orientation_limiting_navigation_controller.h" #import "ios/chrome/browser/ui/first_run/orientation_limiting_navigation_controller.h"
#import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h" #import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h"
#include "ios/chrome/browser/ui/history/history_coordinator.h" #include "ios/chrome/browser/ui/history/history_coordinator.h"
...@@ -141,7 +144,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -141,7 +144,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
SettingsNavigationControllerDelegate, SettingsNavigationControllerDelegate,
SceneURLLoadingServiceDelegate, SceneURLLoadingServiceDelegate,
TabGridCoordinatorDelegate, TabGridCoordinatorDelegate,
WebStateListObserving> { WebStateListObserving,
LocationPermissionsCommands> {
std::unique_ptr<WebStateListObserverBridge> _webStateListForwardingObserver; std::unique_ptr<WebStateListObserverBridge> _webStateListForwardingObserver;
} }
...@@ -205,6 +209,9 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -205,6 +209,9 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
// time it is accessed. // time it is accessed.
@property(nonatomic, strong) SigninCoordinator* signinCoordinator; @property(nonatomic, strong) SigninCoordinator* signinCoordinator;
@property(nonatomic, strong)
LocationPermissionsCoordinator* locationPermissionsCoordinator;
// Additional product specific data used by UserFeedbackDataSource. // Additional product specific data used by UserFeedbackDataSource.
// TODO(crbug.com/1117041): Move this into a UserFeedback config object. // TODO(crbug.com/1117041): Move this into a UserFeedback config object.
@property(nonatomic, strong) @property(nonatomic, strong)
...@@ -1078,7 +1085,25 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -1078,7 +1085,25 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
self.signinCoordinator = [SigninCoordinator self.signinCoordinator = [SigninCoordinator
advancedSettingsSigninCoordinatorWithBaseViewController:baseViewController advancedSettingsSigninCoordinatorWithBaseViewController:baseViewController
browser:mainBrowser]; browser:mainBrowser];
[self startSigninCoordinatorWithCompletion:nil]; [self startSigninCoordinatorWithCompletion:^(BOOL success) {
if (base::FeatureList::IsEnabled(kLocationFirstRunModal)) {
[self showLocationPermissionsFromViewController:baseViewController];
}
}];
}
- (void)showLocationPermissionsFromViewController:
(UIViewController*)baseViewController {
self.locationPermissionsCoordinator = [[LocationPermissionsCoordinator alloc]
initWithBaseViewController:baseViewController
browser:self.mainInterface.browser];
self.locationPermissionsCoordinator.handler = self;
[self.locationPermissionsCoordinator start];
}
- (void)dismissLocationPermissionsExplanationModal {
[self.locationPermissionsCoordinator stop];
self.locationPermissionsCoordinator = nil;
} }
- (void) - (void)
......
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