| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "base/ios/ios_util.h" |
| #import "ios/chrome/browser/metrics/model/metrics_app_interface.h" |
| #import "ios/chrome/browser/signin/model/fake_system_identity.h" |
| #import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" |
| #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.h" |
| #import "ios/chrome/test/earl_grey/chrome_actions.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/testing/earl_grey/earl_grey_test.h" |
| |
| using chrome_test_util::GoogleServicesSettingsButton; |
| using chrome_test_util::SettingsDoneButton; |
| |
| @interface UKMTestCase : ChromeTestCase |
| |
| @end |
| |
| @implementation UKMTestCase |
| |
| + (void)setUpForTestCase { |
| [super setUpForTestCase]; |
| [self setUpHelper]; |
| } |
| |
| + (void)setUpHelper { |
| if (![ChromeEarlGrey isUKMEnabled]) { |
| // ukm::kUkmFeature feature is not enabled. You need to pass |
| // --enable-features=Ukm command line argument in order to run this test. |
| DCHECK(false); |
| } |
| } |
| |
| - (void)setUp { |
| [super setUp]; |
| |
| // These tests enable history sync through Recent Tabs. If there are too many |
| // tabs in the list, the button at the bottom of the view is offscreen and its |
| // animation causes tests to hang for the same reasons as crbug.com/640977. |
| // Clear browsing history to ensure that there are no recent tabs. |
| [ChromeEarlGrey clearBrowsingHistory]; |
| |
| [ChromeEarlGrey |
| waitForSyncEngineInitialized:NO |
| syncTimeout:syncher::kSyncUKMOperationsTimeout]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| // Sign in to Chrome and enable history sync. |
| // |
| // Note: URL-keyed anonymized data collection is turned on as part of the |
| // flow to Sign in to Chrome and enable history sync. This matches the main |
| // user flow that enables UKM. |
| [SigninEarlGreyUI signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1] |
| enableHistorySync:YES]; |
| [ChromeEarlGrey |
| waitForSyncEngineInitialized:YES |
| syncTimeout:syncher::kSyncUKMOperationsTimeout]; |
| |
| // Grant metrics consent and update MetricsServicesManager. |
| [MetricsAppInterface overrideMetricsAndCrashReportingForTesting]; |
| |
| GREYAssert(![MetricsAppInterface setMetricsAndCrashReportingForTesting:YES], |
| @"Unpaired set/reset of user consent."); |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| } |
| |
| - (void)tearDown { |
| [ChromeEarlGrey |
| waitForSyncEngineInitialized:YES |
| syncTimeout:syncher::kSyncUKMOperationsTimeout]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| |
| // Revoke metrics consent and update MetricsServicesManager. |
| GREYAssert([MetricsAppInterface setMetricsAndCrashReportingForTesting:NO], |
| @"Unpaired set/reset of user consent."); |
| [MetricsAppInterface stopOverridingMetricsAndCrashReportingForTesting]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // Sign out of Chrome. |
| // |
| // Note: URL-keyed anonymized data collection is turned off as part of the |
| // flow to Sign out of Chrome. This matches the main user flow that disables |
| // UKM. |
| [SigninEarlGrey signOut]; |
| |
| [ChromeEarlGrey |
| waitForSyncEngineInitialized:NO |
| syncTimeout:syncher::kSyncUKMOperationsTimeout]; |
| [ChromeEarlGrey clearFakeSyncServerData]; |
| |
| [super tearDown]; |
| } |
| |
| #pragma mark - Helpers |
| |
| // Waits for a new incognito tab to be opened. |
| - (void)openNewIncognitoTab { |
| const NSUInteger incognitoTabCount = [ChromeEarlGrey incognitoTabCount]; |
| [ChromeEarlGrey openNewIncognitoTab]; |
| [ChromeEarlGrey waitForIncognitoTabCount:(incognitoTabCount + 1)]; |
| GREYAssert([ChromeEarlGrey isIncognitoMode], |
| @"Failed to switch to incognito mode."); |
| } |
| |
| // Waits for the current incognito tab to be closed. |
| - (void)closeCurrentIncognitoTab { |
| const NSUInteger incognitoTabCount = [ChromeEarlGrey incognitoTabCount]; |
| [ChromeEarlGrey closeCurrentTab]; |
| [ChromeEarlGrey waitForIncognitoTabCount:(incognitoTabCount - 1)]; |
| } |
| |
| // Waits for all incognito tabs to be closed. |
| - (void)closeAllIncognitoTabs { |
| [ChromeEarlGrey closeAllIncognitoTabs]; |
| [ChromeEarlGrey waitForIncognitoTabCount:0]; |
| |
| // The user is dropped into the tab grid after closing the last incognito tab. |
| // Therefore this test must manually switch back to showing the normal tabs. |
| [[EarlGrey |
| selectElementWithMatcher:chrome_test_util::TabGridOpenTabsPanelButton()] |
| performAction:grey_tap()]; |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridDoneButton()] |
| performAction:grey_tap()]; |
| GREYAssert(![ChromeEarlGrey isIncognitoMode], |
| @"Failed to switch to normal mode."); |
| } |
| |
| // Waits for a new tab to be opened. |
| - (void)openNewRegularTab { |
| const NSUInteger tabCount = [ChromeEarlGrey mainTabCount]; |
| [ChromeEarlGrey openNewTab]; |
| [ChromeEarlGrey waitForMainTabCount:(tabCount + 1)]; |
| } |
| |
| #pragma mark - Tests |
| |
| // The tests in this file should correspond to the tests in //chrome/browser/ |
| // metrics/ukm_browsertest.cc. |
| |
| // Make sure that UKM is disabled while an incognito tab is open. |
| // |
| // Corresponds to RegularPlusIncognitoCheck in //chrome/browser/metrics/ |
| // ukm_browsertest.cc. |
| - (void)testRegularPlusIncognito { |
| // Note: Tests begin with an open regular tab. This tab is opened in setUp. |
| const uint64_t originalClientID = [MetricsAppInterface UKMClientID]; |
| |
| [self openNewIncognitoTab]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // Opening another regular tab mustn't enable UKM. |
| [self openNewRegularTab]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // Opening and closing an incognito tab mustn't enable UKM. |
| [self openNewIncognitoTab]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| [self closeCurrentIncognitoTab]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // Open a new regular tab to switch from incognito mode to normal mode. Then, |
| // close this newly-opened regular tab plus the regular tab that was opened |
| // after the first incognito tab was opened. |
| // |
| // TODO(crbug.com/41271925): Due to continuous animations, it is not feasible |
| // (i) to use the tab switcher to switch between modes or (ii) to omit the |
| // below code block and simply call [ChromeEarlGrey closeAllIncognitoTabs]; |
| // from incognito mode. |
| [self openNewRegularTab]; |
| [ChromeEarlGrey closeCurrentTab]; |
| [ChromeEarlGrey closeCurrentTab]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // At this point, there is one open regular tab and one open incognito tab. |
| [ChromeEarlGrey closeAllIncognitoTabs]; |
| |
| // All incognito tabs have been closed, so UKM should be enabled. |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| |
| // Client ID should not have been reset. |
| GREYAssertEqual(originalClientID, [MetricsAppInterface UKMClientID], |
| @"Client ID was reset."); |
| } |
| |
| // Make sure opening a real tab after Incognito doesn't enable UKM. |
| // |
| // Corresponds to IncognitoPlusRegularCheck in //chrome/browser/metrics/ |
| // ukm_browsertest.cc. |
| - (void)testIncognitoPlusRegular { |
| // Note: Tests begin with an open regular tab. This tab is opened in setUp. |
| const uint64_t originalClientID = [MetricsAppInterface UKMClientID]; |
| |
| // TODO(crbug.com/41271925): Due to continuous animations, it is not feasible |
| // to close the regular tab that is already open. The functions closeAllTabs, |
| // closeCurrentTab, and closeAllTabsInCurrentMode close the tab and then hang. |
| // |
| // As a workaround, we open an incognito tab and then close the regular tab to |
| // get to a state in which a single incognito tab is open. |
| [self openNewIncognitoTab]; |
| [ChromeEarlGrey closeAllNormalTabs]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // Opening another regular tab mustn't enable UKM. |
| [self openNewRegularTab]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| [ChromeEarlGrey closeAllIncognitoTabs]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| |
| // Client ID should not have been reset. |
| GREYAssertEqual(originalClientID, [MetricsAppInterface UKMClientID], |
| @"Client ID was reset."); |
| } |
| |
| // testRegularPlusGuest is unnecessary since there can't be multiple profiles. |
| |
| // testOpenNonSync is unnecessary since there can't be multiple profiles. |
| |
| // Make sure that UKM is disabled when metrics consent is revoked. |
| // |
| // Corresponds to MetricsConsentCheck in //chrome/browser/metrics/ |
| // ukm_browsertest.cc. |
| - (void)testMetricsConsent { |
| const uint64_t originalClientID = [MetricsAppInterface UKMClientID]; |
| |
| [MetricsAppInterface setMetricsAndCrashReportingForTesting:NO]; |
| |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| [MetricsAppInterface setMetricsAndCrashReportingForTesting:YES]; |
| |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| // Client ID should have been reset. |
| GREYAssertNotEqual(originalClientID, [MetricsAppInterface UKMClientID], |
| @"Client ID was not reset."); |
| } |
| |
| // The tests corresponding to AddSyncedUserBirthYearAndGenderToProtoData in |
| // //chrome/browser/metrics/ukm_browsertest.cc. are in demographics_egtest.mm. |
| |
| // Make sure that providing metrics consent doesn't enable UKM when the user |
| // is signed-in but history sync is disabled. |
| - (void)testConsentAddedButNoHistorySync { |
| [SigninEarlGrey signOut]; |
| [MetricsAppInterface setMetricsAndCrashReportingForTesting:NO]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| [MetricsAppInterface setMetricsAndCrashReportingForTesting:YES]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // Once history sync is enabled, UKM is too. |
| [SigninEarlGreyUI signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1] |
| enableHistorySync:YES]; |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| } |
| |
| // Make sure that UKM is disabled when "Make searches and browsing better" is |
| // disabled. |
| // |
| // Corresponds to ClientIdResetWhenConsentRemoved in //chrome/browser/metrics/ |
| // ukm_browsertest.cc. |
| - (void)testClientIdResetWhenConsentRemoved { |
| const uint64_t originalClientID = [MetricsAppInterface UKMClientID]; |
| |
| [ChromeEarlGreyUI openSettingsMenu]; |
| // Open Google services settings. |
| [ChromeEarlGreyUI tapSettingsMenuButton:GoogleServicesSettingsButton()]; |
| // Toggle "Make searches and browsing better" switch off. |
| |
| [[[EarlGrey |
| selectElementWithMatcher:chrome_test_util::TableViewSwitchCell( |
| @"betterSearchAndBrowsingItem_switch", YES)] |
| usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200) |
| onElementWithMatcher:chrome_test_util::GoogleServicesSettingsView()] |
| performAction:chrome_test_util::TurnTableViewSwitchOn(NO)]; |
| |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| |
| // Toggle "Make searches and browsing better" switch on. |
| [[EarlGrey |
| selectElementWithMatcher:chrome_test_util::TableViewSwitchCell( |
| @"betterSearchAndBrowsingItem_switch", NO)] |
| performAction:chrome_test_util::TurnTableViewSwitchOn(YES)]; |
| |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| // Client ID should have been reset. |
| GREYAssertNotEqual(originalClientID, [MetricsAppInterface UKMClientID], |
| @"Client ID was not reset."); |
| |
| [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] |
| performAction:grey_tap()]; |
| } |
| |
| // Make sure that UKM is disabled when the user is signed out. |
| - (void)testSingleSignout { |
| const uint64_t clientID1 = [MetricsAppInterface UKMClientID]; |
| |
| [SigninEarlGrey signOut]; |
| |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], |
| @"Failed to assert that UKM was not enabled."); |
| // Client ID should have been reset by signout. |
| GREYAssertNotEqual(clientID1, [MetricsAppInterface UKMClientID], |
| @"Client ID was not reset."); |
| |
| // UKM requires enabling history sync. |
| const uint64_t clientID2 = [MetricsAppInterface UKMClientID]; |
| [SigninEarlGreyUI signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1] |
| enableHistorySync:YES]; |
| |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| // Client ID should not have been reset. |
| GREYAssertEqual(clientID2, [MetricsAppInterface UKMClientID], |
| @"Client ID was reset."); |
| } |
| |
| // testMultiSyncSignout is unnecessary since there can't be multiple profiles. |
| |
| // testMetricsReporting is unnecessary since iOS doesn't use sampling. |
| |
| // Tests that pending data is deleted when the user deletes their history. |
| // |
| // Corresponds to HistoryDeleteCheck in //chrome/browser/metrics/ |
| // ukm_browsertest.cc. |
| - (void)testHistoryDelete { |
| const uint64_t originalClientID = [MetricsAppInterface UKMClientID]; |
| |
| const uint64_t kDummySourceId = 0x54321; |
| [MetricsAppInterface UKMRecordDummySource:kDummySourceId]; |
| GREYAssert([MetricsAppInterface UKMHasDummySource:kDummySourceId], |
| @"Dummy source failed to record."); |
| |
| [ChromeEarlGrey clearBrowsingHistory]; |
| GREYAssertEqual([ChromeEarlGrey browsingHistoryEntryCount], 0, |
| @"History was unexpectedly non-empty"); |
| |
| // Other sources may have already been recorded since the data was cleared, |
| // but the dummy source should be gone. |
| GREYAssert(![MetricsAppInterface UKMHasDummySource:kDummySourceId], |
| @"Dummy source was not purged."); |
| GREYAssertEqual(originalClientID, [MetricsAppInterface UKMClientID], |
| @"Client ID was reset."); |
| GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], |
| @"Failed to assert that UKM was enabled."); |
| } |
| |
| @end |