// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "base/ios/ios_util.h"
#import "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#import "components/content_settings/core/browser/content_settings_uma_util.h"
#import "components/content_settings/core/common/content_settings_types.h"
#import "components/feature_engagement/public/feature_constants.h"
#import "components/optimization_guide/core/optimization_guide_switches.h"
#import "components/page_info/core/page_info_action.h"
#import "components/strings/grit/components_branded_strings.h"
#import "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/metrics/model/metrics_app_interface.h"
#import "ios/chrome/browser/overlays/model/public/web_content_area/alert_constants.h"
#import "ios/chrome/browser/permissions/ui_bundled/permissions_app_interface.h"
#import "ios/chrome/browser/permissions/ui_bundled/permissions_constants.h"
#import "ios/chrome/browser/ui/page_info/features.h"
#import "ios/chrome/browser/ui/page_info/page_info_app_interface.h"
#import "ios/chrome/browser/ui/page_info/page_info_constants.h"
#import "ios/chrome/grit/ios_branded_strings.h"
#import "ios/chrome/grit/ios_strings.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"
#import "ios/web/public/permissions/permissions.h"
#import "net/test/embedded_test_server/embedded_test_server.h"
#import "ui/base/l10n/l10n_util.h"
namespace {
using ::base::test::ios::kWaitForUIElementTimeout;
using ::base::test::ios::WaitUntilConditionOrTimeout;
// Matcher infobar modal camera permissions switch.
id<GREYMatcher> CameraPermissionsSwitch(BOOL isOn) {
return chrome_test_util::TableViewSwitchCell(
kPageInfoCameraSwitchAccessibilityIdentifier, isOn);
}
// Matcher infobar modal microphone permissions switch.
id<GREYMatcher> MicrophonePermissionsSwitch(BOOL isOn) {
return chrome_test_util::TableViewSwitchCell(
kPageInfoMicrophoneSwitchAccessibilityIdentifier, isOn);
}
// Matcher for Security help center link in footer.
id<GREYMatcher> SecurityHelpCenterLink() {
return grey_allOf(
// The link is within the security footer with ID
// `kPageInfoSecurityFooterAccessibilityIdentifier`.
grey_ancestor(
grey_accessibilityID(kPageInfoSecurityFooterAccessibilityIdentifier)),
// UIKit instantiates a `UIAccessibilityLinkSubelement` for the link
// element in the label with attributed string.
grey_kindOfClassName(@"UIAccessibilityLinkSubelement"),
grey_accessibilityTrait(UIAccessibilityTraitLink), nil);
}
void AddAboutThisSiteHint(GURL url) {
[PageInfoAppInterface
addAboutThisSiteHintForURL:
[NSString stringWithCString:url.spec().c_str()
encoding:[NSString defaultCStringEncoding]]
description:
@"A domain used in illustrative examples in documents"
aboutThisSiteURL:@"https://diner.com"];
}
void ExpectPageInfoActionHistograms(page_info::PageInfoAction action) {
GREYAssertNil(
[MetricsAppInterface
expectCount:1
forBucket:action
forHistogram:base::SysUTF8ToNSString(
page_info::kWebsiteSettingsActionHistogram)],
@"WebsiteSettings.Action histogram not logged.");
}
void ExpectPermissionChangedHistograms(ContentSettingsType type) {
int bucket =
content_settings_uma_util::ContentSettingTypeToHistogramValue(type);
GREYAssertNil([MetricsAppInterface
expectCount:1
forBucket:bucket
forHistogram:base::SysUTF8ToNSString(
kOriginInfoPermissionChangedHistogram)],
@"PermissionChanged histogram not logged.");
GREYAssertNil(
[MetricsAppInterface
expectCount:1
forBucket:bucket
forHistogram:base::SysUTF8ToNSString(
kOriginInfoPermissionChangedBlockedHistogram)],
@"PermissionChanged.Blocked histogram not logged.");
ExpectPageInfoActionHistograms(page_info::PAGE_INFO_CHANGED_PERMISSION);
}
} // namespace
@interface PageInfoTestCase : ChromeTestCase
@end
@implementation PageInfoTestCase
- (AppLaunchConfiguration)appConfigurationForTestCase {
AppLaunchConfiguration config;
config.relaunch_policy = NoForceRelaunchAndResetState;
config.features_enabled.push_back(
feature_engagement::kIPHiOSInlineEnhancedSafeBrowsingPromoFeature);
if ([self isRunningTest:@selector(testLegacySecuritySection)]) {
config.features_disabled.push_back(kRevampPageInfoIos);
} else {
config.features_enabled.push_back(kRevampPageInfoIos);
}
config.features_enabled.push_back(kPageInfoLastVisitedIOS);
config.additional_args.push_back(
std::string("-") +
optimization_guide::switches::kDisableCheckingUserPermissionsForTesting);
return config;
}
- (void)setUp {
[super setUp];
[ChromeEarlGrey clearBrowsingHistory];
GREYAssertNil([MetricsAppInterface setupHistogramTester],
@"Failed to set up histogram tester.");
}
- (void)tearDown {
[super tearDown];
GREYAssertNil([MetricsAppInterface releaseHistogramTester],
@"Cannot reset histogram tester.");
}
// Checks that if the alert for site permissions pops up, and allow it.
- (void)checkAndAllowPermissionAlerts {
// Allow system permission if shown.
NSError* systemAlertFoundError = nil;
[[EarlGrey selectElementWithMatcher:grey_systemAlertViewShown()]
assertWithMatcher:grey_nil()
error:&systemAlertFoundError];
if (systemAlertFoundError) {
NSError* acceptAlertError = nil;
[self grey_acceptSystemDialogWithError:&acceptAlertError];
GREYAssertNil(acceptAlertError, @"Error accepting system alert.\n%@",
acceptAlertError);
}
// Allow site permission.
id<GREYMatcher> dialogMatcher =
grey_accessibilityID(kPermissionsDialogAccessibilityIdentifier);
ConditionBlock condition = ^{
NSError* error = nil;
[[EarlGrey selectElementWithMatcher:dialogMatcher]
assertWithMatcher:grey_sufficientlyVisible()
error:&error];
return !error;
};
GREYAssert(WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition),
@"Permissions dialog was not shown.");
NSString* allowButtonText = l10n_util::GetNSString(
IDS_IOS_PERMISSIONS_ALERT_DIALOG_BUTTON_TEXT_GRANT);
id<GREYMatcher> allowButtonMatcher = allowButtonMatcher = grey_allOf(
grey_ancestor(dialogMatcher), grey_accessibilityLabel(allowButtonText),
grey_accessibilityTrait(UIAccessibilityTraitStaticText), nil);
[[[EarlGrey selectElementWithMatcher:allowButtonMatcher]
assertWithMatcher:grey_sufficientlyVisible()] performAction:grey_tap()];
}
// Checks `expectedStatesForPermissions` matches the actual states for
// permissions of the active web state; checks will fail if there is no active
// web state.
- (void)checkStatesForPermissions:
(NSDictionary<NSNumber*, NSNumber*>*)expectedStatesForPermissions {
NSDictionary<NSNumber*, NSNumber*>* actualStatesForPermissions =
[PermissionsAppInterface statesForAllPermissions];
GREYAssertEqualObjects(
expectedStatesForPermissions[@(web::PermissionCamera)],
actualStatesForPermissions[@(web::PermissionCamera)],
@"Camera state: %@ does not match expected: %@.",
actualStatesForPermissions[@(web::PermissionCamera)],
expectedStatesForPermissions[@(web::PermissionCamera)]);
GREYAssertEqualObjects(
expectedStatesForPermissions[@(web::PermissionMicrophone)],
actualStatesForPermissions[@(web::PermissionMicrophone)],
@"Microphone state: %@ does not match expected: %@.",
actualStatesForPermissions[@(web::PermissionMicrophone)],
expectedStatesForPermissions[@(web::PermissionMicrophone)]);
}
// Tests that rotating the device will don't dismiss the page info view.
- (void)testShowPageInfoRotation {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGreyUI openPageInfo];
ExpectPageInfoActionHistograms(page_info::PAGE_INFO_OPENED);
// Checks that the page info view has appeared.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
// Rotates the device and checks that the page info view is still presented.
[EarlGrey rotateDeviceToOrientation:UIDeviceOrientationLandscapeRight
error:nil];
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
// Closes the page info using the 'Done' button.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::NavigationBarDoneButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
assertWithMatcher:grey_nil()];
}
// Tests that opening the page info on a Chromium page displays the correct
// information.
- (void)testShowPageInfoChromePage {
[ChromeEarlGrey loadURL:GURL("chrome://version")];
[ChromeEarlGreyUI openPageInfo];
// Checks that the page info view has appeared.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
// Checks that “You’re viewing a secure Chrome page.” is displayed.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_PAGE_INFO_INTERNAL_PAGE))]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that the Permissions section is not displayed, as there isn't any
// accessible permissions.
- (void)testShowPageInfoWithNoAccessiblePermission {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGreyUI openPageInfo];
// Checks that no permissions are not visible.
[[EarlGrey
selectElementWithMatcher:grey_anyOf(CameraPermissionsSwitch(YES),
CameraPermissionsSwitch(NO), nil)]
assertWithMatcher:grey_notVisible()];
[[EarlGrey
selectElementWithMatcher:grey_anyOf(MicrophonePermissionsSwitch(YES),
MicrophonePermissionsSwitch(NO), nil)]
assertWithMatcher:grey_notVisible()];
}
// Tests that single accessible permission is shown in Permissions section with
// toggle.
- (void)testShowOneAccessiblePermissionInPageInfo {
// Open a page that requests microphone permissions.
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey
loadURL:self.testServer->GetURL("/permissions/microphone_only.html")];
[self checkAndAllowPermissionAlerts];
// Check that camera permission item is hidden, and in accordance with the
// web state permission states.
[ChromeEarlGreyUI openPageInfo];
[self checkStatesForPermissions:@{
@(web::PermissionCamera) : @(web::PermissionStateNotAccessible),
@(web::PermissionMicrophone) : @(web::PermissionStateAllowed)
}];
[[EarlGrey
selectElementWithMatcher:grey_anyOf(CameraPermissionsSwitch(YES),
CameraPermissionsSwitch(NO), nil)]
assertWithMatcher:grey_notVisible()];
// Check that microphone permission item is visible, and turn it off.
[[EarlGrey selectElementWithMatcher:MicrophonePermissionsSwitch(YES)]
performAction:chrome_test_util::TurnTableViewSwitchOn(NO)];
[[EarlGrey // Dismiss view.
selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
performAction:grey_swipeFastInDirection(kGREYDirectionDown)];
[self checkStatesForPermissions:@{
@(web::PermissionCamera) : @(web::PermissionStateNotAccessible),
@(web::PermissionMicrophone) : @(web::PermissionStateBlocked)
}];
// Check that the correct histograms are logged when a camera permission is
// changed via Page Info.
ExpectPermissionChangedHistograms(ContentSettingsType::MEDIASTREAM_MIC);
}
// Tests that two accessible permissions are shown in Permissions section with
// toggle.
- (void)testShowTwoAccessiblePermissionsInPageInfo {
// TODO(crbug.com/342245057): Camera access is broken in the simulator on iOS
// 17.5.
if (@available(iOS 17.5, *)) {
EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 17.5.");
}
// Open a page that requests microphone permissions.
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey loadURL:self.testServer->GetURL(
"/permissions/camera_and_microphone.html")];
[self checkAndAllowPermissionAlerts];
// Check that switchs for both permissions are visible.
[ChromeEarlGreyUI openPageInfo];
[self checkStatesForPermissions:@{
@(web::PermissionCamera) : @(web::PermissionStateAllowed),
@(web::PermissionMicrophone) : @(web::PermissionStateAllowed)
}];
// Check that both permission item is visible, and turn off camera
// permission.
[[EarlGrey selectElementWithMatcher:MicrophonePermissionsSwitch(YES)]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:CameraPermissionsSwitch(YES)]
performAction:chrome_test_util::TurnTableViewSwitchOn(NO)];
[[EarlGrey // Dismiss view.
selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
performAction:grey_swipeFastInDirection(kGREYDirectionDown)];
[self checkStatesForPermissions:@{
@(web::PermissionCamera) : @(web::PermissionStateBlocked),
@(web::PermissionMicrophone) : @(web::PermissionStateAllowed)
}];
// Check that the correct histograms are logged when a camera permission is
// changed via Page Info.
ExpectPermissionChangedHistograms(ContentSettingsType::MEDIASTREAM_CAMERA);
}
// Tests that rotating the device will not dismiss the navigation bar.
- (void)testShowPageInfoTitleRotation {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGreyUI openPageInfo];
// Check that the navigation bar is visible.
[[EarlGrey selectElementWithMatcher:
grey_accessibilityID(
kPageInfoViewNavigationBarAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
// Check that the navigation bar has both the page info's page title and the
// page URL.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_SITE_INFORMATION))]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:
grey_text([NSString
stringWithCString:[ChromeEarlGrey webStateVisibleURL]
.host()
.c_str()
encoding:[NSString defaultCStringEncoding]])]
assertWithMatcher:grey_sufficientlyVisible()];
// Rotate to landscape mode and check the navigation bar is still visible.
[EarlGrey rotateDeviceToOrientation:UIDeviceOrientationLandscapeRight
error:nil];
[[EarlGrey selectElementWithMatcher:
grey_accessibilityID(
kPageInfoViewNavigationBarAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
// Rotate back to portrait mode and check the navigation bar is still visible.
[EarlGrey rotateDeviceToOrientation:UIDeviceOrientationPortrait error:nil];
[[EarlGrey selectElementWithMatcher:
grey_accessibilityID(
kPageInfoViewNavigationBarAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests the legacy security section by checking that the correct site security
// label and that the security footer are displayed.
- (void)testLegacySecuritySection {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGreyUI openPageInfo];
// Check that "Site Security | Not secure” is displayed.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_SITE_SECURITY))]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:
grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_SECURITY_STATUS_NOT_SECURE))]
assertWithMatcher:grey_sufficientlyVisible()];
// Check that the security footer is displayed.
[[EarlGrey
selectElementWithMatcher:
grey_accessibilityID(kPageInfoSecurityFooterAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
// Tap on the Learn more link.
[[EarlGrey selectElementWithMatcher:SecurityHelpCenterLink()]
performAction:grey_tap()];
// Check that the help center article was opened.
GREYAssertEqual(std::string("support.google.com"),
[ChromeEarlGrey webStateVisibleURL].host(),
@"Did not navigate to the help center article.");
ExpectPageInfoActionHistograms(page_info::PAGE_INFO_CONNECTION_HELP_OPENED);
}
// Tests the security section by checking that the correct connection label is
// displayed, that no security footer is displayed and that clicking on the
// security row leads to the security subpage.
- (void)testSecuritySection {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGreyUI openPageInfo];
// Check that “Connection | Not secure” is displayed.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_CONNECTION))]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:
grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_SECURITY_STATUS_NOT_SECURE))]
assertWithMatcher:grey_sufficientlyVisible()];
// Check that the security footer is not displayed.
[[EarlGrey
selectElementWithMatcher:
grey_accessibilityID(kPageInfoSecurityFooterAccessibilityIdentifier)]
assertWithMatcher:grey_notVisible()];
// Check that tapping on the security row leads to the security subpage.
[[EarlGrey selectElementWithMatcher:
grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_SECURITY_STATUS_NOT_SECURE))]
performAction:grey_tap()];
[[EarlGrey
selectElementWithMatcher:
grey_accessibilityID(kPageInfoSecurityViewAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
ExpectPageInfoActionHistograms(page_info::PAGE_INFO_SECURITY_DETAILS_OPENED);
}
// Most of the tests for AboutThisSite section are in chrome-internal
// (chrome/test/external_url/external_url_ssl_app_interface.mm).
// It seems that https pages in egtests always have an invalid certificate,
// NET::ERR_CERT_AUTHORITY_INVALID, which makes the page unsecure. The
// AboutThisSite section should only be available for secure pages. Tests in
// chrome-internal can use real pages and so we are able to test Page Info with
// secure pages.
// Tests that the AboutThisSite section does not appear even if optimization
// guide returns a hint but the connection is HTTP. The AboutThisSite section
// should only appear for secure pages.
- (void)testAboutThisSiteSectionWithHttp {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
GURL url = self.testServer->GetURL("/");
AddAboutThisSiteHint(url);
[ChromeEarlGrey loadURL:url];
[ChromeEarlGreyUI openPageInfo];
// Check that AboutThisSite section is not displayed.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_ABOUT_THIS_PAGE))]
assertWithMatcher:grey_nil()];
}
// Tests that the AboutThisSite section does not appear even if the connection
// is HTTPs and optimization guide returns a hint but the certificate is not
// valid. The AboutThisSite section should only appear for secure pages.
- (void)testAboutThisSiteSectionWithHttpsInvalidCert {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
GREYAssertTrue(https_server.Start(), @"Test server failed to start.");
GURL url = https_server.GetURL("/");
AddAboutThisSiteHint(url);
[ChromeEarlGrey loadURL:url];
[ChromeEarlGreyUI openPageInfo];
// Check that AboutThisSite section is not displayed.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_IOS_PAGE_INFO_ABOUT_THIS_PAGE))]
assertWithMatcher:grey_nil()];
}
// Tests that the Last Visited section is not displayed when there is no
// previous visit to the current website.
- (void)testLastVisitedSectionWithNoPreviousVisit {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
GURL URL("https://www.example.com/");
AddAboutThisSiteHint(URL);
[ChromeEarlGrey loadURL:URL];
[ChromeEarlGreyUI openPageInfo];
// Check that Last Visited section is not displayed.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_PAGE_INFO_HISTORY))]
assertWithMatcher:grey_nil()];
}
// Tests that the Last Visited section is displayed when there exists a previous
// visit, and also, it tests that the correct timestamp of the last visit is
// presented.
- (void)testLastVisitedSectionDisplaysToday {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
GURL URL("https://www.example.com/");
// Create an entry in History which took place one hour ago on `url`.
const base::Time oneHourAgo = base::Time::Now() - base::Hours(1);
[ChromeEarlGrey addHistoryServiceTypedURL:URL visitTimestamp:oneHourAgo];
// Visit `url` and open Page Info.
AddAboutThisSiteHint(URL);
[ChromeEarlGrey loadURL:URL];
[ChromeEarlGreyUI openPageInfo];
// Check that the Last Visited row is displayed.
[[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_PAGE_INFO_HISTORY))]
assertWithMatcher:grey_sufficientlyVisible()];
// Check that the Last Visited summary displays "Today".
[[EarlGrey
selectElementWithMatcher:grey_text(l10n_util::GetNSString(
IDS_PAGE_INFO_HISTORY_LAST_VISIT_TODAY))]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that we don't crash when showing the page info twice (prevent
// regression from (crbug.com/1486309).
- (void)testShowingPageInfoTwice {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGreyUI openPageInfo];
// Check that the page info view has appeared.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
performAction:grey_swipeFastInDirection(kGREYDirectionDown)];
// Check that the page info view has disappeared.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
assertWithMatcher:grey_not(grey_sufficientlyVisible())];
// Reopen the page.
[ChromeEarlGreyUI openPageInfo];
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPageInfoViewAccessibilityIdentifier)]
assertWithMatcher:grey_sufficientlyVisible()];
}
@end