| // Copyright 2022 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #import "ios/testing/system_alert_handler.h" | 
 |  | 
 | #import <XCTest/XCTest.h> | 
 |  | 
 | #import "base/test/ios/wait_util.h" | 
 |  | 
 | using base::test::ios::kWaitForUIElementTimeout; | 
 |  | 
 | namespace { | 
 |  | 
 | // Returns true if any static text child of `element` (XCUIElement*) contains | 
 | // `text` (NSString*). | 
 | BOOL ElementStaticTextContainsText(XCUIElement* element, NSString* text) { | 
 |   NSPredicate* label_contains_text = | 
 |       [NSPredicate predicateWithFormat:@"%K CONTAINS[c] %@", @"label", text]; | 
 |   return | 
 |       [element.staticTexts containingPredicate:label_contains_text].count > 0; | 
 | } | 
 |  | 
 | // Closes the `alert` (XCUIElement*) if it matches a known text/button pair and | 
 | // returns whether it succeeded or not in closing it. | 
 | BOOL HandleSingleAlert(XCUIElement* alert) { | 
 |   NSDictionary<NSString*, NSArray<NSString*>*>* text_to_buttons = | 
 |       TextToButtonsOfKnownSystemAlerts(); | 
 |   for (NSString* text in text_to_buttons) { | 
 |     if (ElementStaticTextContainsText(alert, text)) { | 
 |       NSLog(@"Found alert containing text: %@", text); | 
 |  | 
 |       for (NSString* button in text_to_buttons[text]) { | 
 |         if (!alert.buttons[button].exists) { | 
 |           NSLog(@"Button %@ doesn't exist. Skip tapping.", button); | 
 |           continue; | 
 |         } | 
 |  | 
 |         NSLog(@"Tapping alert button: %@", button); | 
 |         [alert.buttons[button] tap]; | 
 |         return YES; | 
 |       } | 
 |     } | 
 |   } | 
 |   return NO; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | NSDictionary<NSString*, NSArray<NSString*>*>* TextToButtonsOfKnownSystemAlerts( | 
 |     void) { | 
 |   static NSDictionary<NSString*, NSArray<NSString*>*>* text_to_buttons = nil; | 
 |   static dispatch_once_t once_token; | 
 |   dispatch_once(&once_token, ^{ | 
 |     text_to_buttons = @{ | 
 |       @"Software Update" : @[ @"Later", @"Remind Me Later" ], | 
 |       @"A new iOS update is now available." : @[ @"Close" ], | 
 |       @"Carrier Settings Update" : @[ @"Not Now" ], | 
 |       @"would like to find and connect to devices on your local network" : | 
 |           @[ @"OK", @"Allow" ], | 
 |       @"Unable to activate Touch ID on this iPhone." : @[ @"OK" ], | 
 |       @"Like to Access the Microphone" : @[ @"OK" ], | 
 |       @"Edit Home Screen" : @[ @"Dismiss" ], | 
 |       @"Apple ID Verification" : @[ @"Not Now" ], | 
 |       @"iPhone is not Activated" : @[ @"Dismiss" ], | 
 |       @"Account Verification" : @[ @"Not Now" ], | 
 |       @"to find devices on local networks" : @[ @"Allow" ], | 
 |       @"Not Installed" : @[ @"OK" ], | 
 |       @"No SIM Card Installed" : @[ @"OK" ], | 
 |       @"Set Up Cellular" : @[ @"Not Now" ], | 
 |     }; | 
 |   }); | 
 |   return text_to_buttons; | 
 | } | 
 |  | 
 | BOOL HandleKnownSystemAlertsIfVisible(void) { | 
 |   XCUIApplication* springboard_app = [[XCUIApplication alloc] | 
 |       initWithBundleIdentifier:@"com.apple.springboard"]; | 
 |   XCUIElement* alert = springboard_app.alerts.firstMatch; | 
 |  | 
 |   // Limit attempt times. If attempt limit is exceeded, it means something went | 
 |   // wrong in tapping the buttons. | 
 |   int attempt = 0; | 
 |   while ( | 
 |       attempt < 5 && | 
 |       [alert | 
 |           waitForExistenceWithTimeout:kWaitForUIElementTimeout.InSecondsF()]) { | 
 |     NSLog(@"Alert on screen: %@", alert.label); | 
 |     if (!HandleSingleAlert(alert)) { | 
 |       return NO; | 
 |     } | 
 |     attempt++; | 
 |   } | 
 |   return attempt < 5; | 
 | } |