Commit f598b314 authored by Nohemi Fernandez's avatar Nohemi Fernandez Committed by Commit Bot

[iOS] Add a new option to non-managed account Sign-Out.

Re-enables the 'ClearSyncData' feature reverted in change 2020323.
Fixes the DCHECK errors due to incomplete URLs in tests and uses
the ScopedFeatureList to enable the experimental flag that is
compatible with both EarlGrey 1 and 2.

Bug: 1005509
Change-Id: Ib300eb8d89e125e9bfa26045b41f59209228ac85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2019362Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Commit-Queue: Nohemi Fernandez <fernandex@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735382}
parent 09878ba9
......@@ -662,6 +662,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE" desc="The title of the continue button on the disconnect dialog [Length: 20em].">
Sign Out
</message>
<message name="IDS_IOS_DISCONNECT_DIALOG_CONTINUE_AND_CLEAR_MOBILE" desc="The title of the continue and clear browsing data button on the disconnect dialog [iOS only].">
Sign Out and Clear Synced Data
</message>
<message name="IDS_IOS_DISCONNECT_DIALOG_INFO_MOBILE" desc="The information text on the disconnect dialog [Length: 400em].">
Changes to your bookmarks, history, passwords, and other settings will no longer be synced to your Google Account. However, your existing data will remain stored in your Google Account.
</message>
......
......@@ -11,6 +11,12 @@
@class FakeChromeIdentity;
typedef NS_ENUM(NSInteger, SignOutConfirmation) {
SignOutConfirmationManagedUser,
SignOutConfirmationNonManagedUser,
SignOutConfirmationNonManagedUserWithClearedData,
};
// Methods used for the EarlGrey tests, related to UI.
@interface SigninEarlGreyUI : NSObject
......@@ -57,9 +63,9 @@
// Checks that the sign-in promo view is not visible.
+ (void)checkSigninPromoNotVisible;
// Signs out from the current identity. if |isManagedAccount| is true, the
// confirmed managed dialog is confirmed while signing out.
+ (void)signOutWithManagedAccount:(BOOL)isManagedAccount;
// Taps the appropriate action label on the sign-out dialog for the given
// |signOutConfirmation| profile and signs out from the current identity.
+ (void)signOutWithSignOutConfirmation:(SignOutConfirmation)signOutConfirmation;
@end
......
......@@ -189,16 +189,31 @@ using chrome_test_util::UnifiedConsentAddAccountButton;
assertWithMatcher:grey_nil()];
}
+ (void)signOutWithManagedAccount:(BOOL)isManagedAccount {
+ (void)signOutWithSignOutConfirmation:
(SignOutConfirmation)signOutConfirmation {
[ChromeEarlGreyUI openSettingsMenu];
[ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
[ChromeEarlGreyUI tapAccountsMenuButton:SignOutAccountsButton()];
int confirmationLabelID = 0;
if (isManagedAccount) {
confirmationLabelID = IDS_IOS_MANAGED_DISCONNECT_DIALOG_ACCEPT_UNITY;
} else {
confirmationLabelID = IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE;
switch (signOutConfirmation) {
case SignOutConfirmationManagedUser: {
confirmationLabelID = IDS_IOS_MANAGED_DISCONNECT_DIALOG_ACCEPT_UNITY;
break;
}
case SignOutConfirmationNonManagedUser: {
confirmationLabelID = IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE;
break;
}
case SignOutConfirmationNonManagedUserWithClearedData: {
confirmationLabelID = IDS_IOS_DISCONNECT_DIALOG_CONTINUE_AND_CLEAR_MOBILE;
break;
}
default: {
NOTREACHED();
break;
}
}
id<GREYMatcher> confirmationButtonMatcher = [ChromeMatchersAppInterface
buttonWithAccessibilityLabelID:confirmationLabelID];
[[EarlGrey selectElementWithMatcher:confirmationButtonMatcher]
......
......@@ -109,9 +109,12 @@ source_set("eg_tests") {
deps = [
":constants",
":test_support",
"//base/test:test_support",
"//ios/chrome/app/strings",
"//ios/chrome/browser/tabs",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/authentication:eg_test_support",
"//ios/chrome/browser/ui/bookmarks:eg_test_support",
"//ios/chrome/test/app:test_support",
"//ios/chrome/test/earl_grey:test_support",
"//ios/public/provider/chrome/browser/signin:fake_chrome_identity",
......@@ -179,8 +182,11 @@ source_set("eg2_tests") {
deps = [
":eg_test_support+eg2",
"//base",
"//base/test:test_support",
"//ios/chrome/app/strings",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/authentication:eg_test_support+eg2",
"//ios/chrome/browser/ui/bookmarks:eg_test_support+eg2",
"//ios/chrome/browser/ui/settings/google_services:constants",
"//ios/chrome/test/earl_grey:eg_test_support+eg2",
"//ios/public/provider/chrome/browser/signin:fake_chrome_identity",
......
......@@ -2,13 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "base/test/scoped_feature_list.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h"
#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h"
#import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h"
#import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_ui.h"
#import "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
#import "ios/testing/earl_grey/app_launch_manager.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -22,18 +31,48 @@ using chrome_test_util::PrimarySignInButton;
namespace {
// Constant for timeout while waiting for asynchronous sync operations.
const NSTimeInterval kSyncOperationTimeout = 10.0;
// Returns a matcher for a button that matches the userEmail in the given
// |fakeIdentity|.
id<GREYMatcher> ButtonWithFakeIdentity(FakeChromeIdentity* fakeIdentity) {
return ButtonWithAccessibilityLabel(fakeIdentity.userEmail);
}
id<GREYMatcher> NoBookmarksLabel() {
return grey_text(l10n_util::GetNSString(IDS_IOS_BOOKMARK_NO_BOOKMARKS_LABEL));
}
}
// Integration tests using the Account Settings screen.
@interface AccountCollectionsTestCase : ChromeTestCase
@end
@implementation AccountCollectionsTestCase
@implementation AccountCollectionsTestCase {
base::test::ScopedFeatureList _featureList;
}
- (void)tearDown {
[ChromeEarlGrey waitForBookmarksToFinishLoading];
[ChromeEarlGrey clearBookmarks];
[BookmarkEarlGrey clearBookmarksPositionCache];
[ChromeEarlGrey clearSyncServerData];
[super tearDown];
}
- (void)setUp {
_featureList.InitAndEnableFeature(kClearSyncedData);
[super setUp];
[ChromeEarlGrey waitForBookmarksToFinishLoading];
[ChromeEarlGrey clearBookmarks];
GREYAssertEqual(
[ChromeEarlGrey numberOfSyncEntitiesWithType:syncer::BOOKMARKS], 0,
@"No bookmarks should exist before tests start.");
}
// Tests that the Sync and Account Settings screen are correctly popped if the
// signed in account is removed.
......@@ -138,6 +177,58 @@ id<GREYMatcher> ButtonWithFakeIdentity(FakeChromeIdentity* fakeIdentity) {
performAction:grey_tap()];
}
// Tests that selecting sign-out from a non-managed account keeps the user's
// synced data.
- (void)testSignOutFromNonManagedAccountKeepsData {
FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1];
// Sign In |fakeIdentity|.
[SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity];
// Add a bookmark after sync is initialized.
[ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout];
[ChromeEarlGrey waitForBookmarksToFinishLoading];
[SigninEarlGreyUtilsAppInterface addBookmark:@"http://youtube.com"
withTitle:@"cats"];
[SigninEarlGreyUI
signOutWithSignOutConfirmation:SignOutConfirmationNonManagedUser];
// Open the Bookmarks screen on the Tools menu.
[BookmarkEarlGreyUI openBookmarks];
[BookmarkEarlGreyUI openMobileBookmarks];
// Assert that the 'cats' bookmark is displayed.
[[EarlGrey selectElementWithMatcher:grey_text(@"cats")]
assertWithMatcher:grey_notNil()];
}
// Tests that selecting sign-out and clear data from a non-managed user account
// clears the user's synced data.
- (void)testSignOutAndClearDataFromNonManagedAccountClearsData {
FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1];
// Sign In |fakeIdentity|.
[SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity];
// Add a bookmark after sync is initialized.
[ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout];
[ChromeEarlGrey waitForBookmarksToFinishLoading];
[SigninEarlGreyUtilsAppInterface addBookmark:@"http://youtube.com"
withTitle:@"cats"];
[SigninEarlGreyUI signOutWithSignOutConfirmation:
SignOutConfirmationNonManagedUserWithClearedData];
// Open the Bookmarks screen on the Tools menu.
[BookmarkEarlGreyUI openBookmarks];
[BookmarkEarlGreyUI openMobileBookmarks];
// Assert that there are no bookmarks.
[[EarlGrey selectElementWithMatcher:NoBookmarksLabel()]
assertWithMatcher:grey_notNil()];
}
// Tests that the user isn't signed out and the UI is correct when the
// disconnect is cancelled in the Account Settings screen.
- (void)testSignInDisconnectCancelled {
......
......@@ -5,6 +5,7 @@
#import "ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.h"
#import "base/mac/foundation_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
......@@ -347,11 +348,11 @@ typedef NS_ENUM(NSInteger, ItemType) {
return;
}
NSString* title = l10n_util::GetNSString(IDS_IOS_DISCONNECT_DIALOG_TITLE);
NSString* message =
l10n_util::GetNSString(IDS_IOS_DISCONNECT_DIALOG_INFO_MOBILE);
NSString* continueButtonTitle =
l10n_util::GetNSString(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE);
NSString* title = nil;
NSString* message = nil;
NSString* continueButtonTitle = nil;
NSString* clearDataButtonTitle = nil;
if ([self authService] -> IsAuthenticatedIdentityManaged()) {
signin::IdentityManager* identityManager =
IdentityManagerFactory::GetForBrowserState(_browser->GetBrowserState());
......@@ -361,6 +362,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
std::string hosted_domain = accountInfo.has_value()
? accountInfo.value().hosted_domain
: std::string();
title =
l10n_util::GetNSString(IDS_IOS_MANAGED_DISCONNECT_DIALOG_TITLE_UNITY);
message =
......@@ -374,7 +376,10 @@ typedef NS_ENUM(NSInteger, ItemType) {
l10n_util::GetNSString(IDS_IOS_DISCONNECT_DIALOG_INFO_MOBILE_UNITY);
continueButtonTitle = l10n_util::GetNSString(
IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE);
clearDataButtonTitle = l10n_util::GetNSString(
IDS_IOS_DISCONNECT_DIALOG_CONTINUE_AND_CLEAR_MOBILE);
}
_alertCoordinator =
[[AlertCoordinator alloc] initWithBaseViewController:self
title:title
......@@ -384,28 +389,41 @@ typedef NS_ENUM(NSInteger, ItemType) {
action:nil
style:UIAlertActionStyleCancel];
__weak AccountsTableViewController* weakSelf = self;
[_alertCoordinator addItemWithTitle:continueButtonTitle
action:^{
[weakSelf handleDisconnect];
}
style:UIAlertActionStyleDefault];
[_alertCoordinator
addItemWithTitle:continueButtonTitle
action:^{
[weakSelf handleDisconnectWithForceClearSyncData:NO];
}
style:UIAlertActionStyleDefault];
if (base::FeatureList::IsEnabled(kClearSyncedData)) {
[_alertCoordinator
addItemWithTitle:clearDataButtonTitle
action:^{
[weakSelf handleDisconnectWithForceClearSyncData:YES];
}
style:UIAlertActionStyleDestructive];
}
[_alertCoordinator start];
}
- (void)handleDisconnect {
- (void)handleDisconnectWithForceClearSyncData:(BOOL)forceClearSyncData {
AuthenticationService* authService = [self authService];
if (authService->IsAuthenticated()) {
_authenticationOperationInProgress = YES;
[self preventUserInteraction];
authService->SignOut(
signin_metrics::USER_CLICKED_SIGNOUT_SETTINGS,
/*force_clear_browsing_data=*/false, ^{
signin_metrics::USER_CLICKED_SIGNOUT_SETTINGS, forceClearSyncData, ^{
[self allowUserInteraction];
_authenticationOperationInProgress = NO;
[base::mac::ObjCCastStrict<SettingsNavigationController>(
self.navigationController)
popViewControllerOrCloseSettingsAnimated:YES];
});
if (base::FeatureList::IsEnabled(kClearSyncedData)) {
UMA_HISTOGRAM_BOOLEAN("Signin.UserRequestedWipeDataOnSignout",
forceClearSyncData);
}
}
}
......
......@@ -96,7 +96,8 @@ void ChooseImportOrKeepDataSepareteDialog(id<GREYMatcher> choiceButtonMatcher) {
// Sign in to |fakeIdentity1|.
[SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity1];
[SigninEarlGreyUI signOutWithManagedAccount:NO];
[SigninEarlGreyUI
signOutWithSignOutConfirmation:SignOutConfirmationNonManagedUser];
// Sign in with |fakeIdentity2|.
[ChromeEarlGreyUI openSettingsMenu];
......@@ -178,7 +179,8 @@ void ChooseImportOrKeepDataSepareteDialog(id<GREYMatcher> choiceButtonMatcher) {
[SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity];
// Sign out.
[SigninEarlGreyUI signOutWithManagedAccount:NO];
[SigninEarlGreyUI
signOutWithSignOutConfirmation:SignOutConfirmationNonManagedUser];
}
// Tests that signing out of a managed account from the Settings works
......@@ -190,7 +192,8 @@ void ChooseImportOrKeepDataSepareteDialog(id<GREYMatcher> choiceButtonMatcher) {
[SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity isManagedAccount:YES];
// Sign out.
[SigninEarlGreyUI signOutWithManagedAccount:YES];
[SigninEarlGreyUI
signOutWithSignOutConfirmation:SignOutConfirmationManagedUser];
// Check that there is no signed in user.
[SigninEarlGreyUtils checkSignedOut];
......@@ -270,8 +273,8 @@ void ChooseImportOrKeepDataSepareteDialog(id<GREYMatcher> choiceButtonMatcher) {
[SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity2];
// Sign out.
[SigninEarlGreyUI signOutWithManagedAccount:NO];
[SigninEarlGreyUI
signOutWithSignOutConfirmation:SignOutConfirmationNonManagedUser];
// Sign in with |fakeIdentity1|.
[ChromeEarlGreyUI openSettingsMenu];
[[EarlGrey selectElementWithMatcher:SecondarySignInButton()]
......
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