初始化提交
This commit is contained in:
677
WebDriverAgentLib/Utilities/FBConfiguration.m
Normal file
677
WebDriverAgentLib/Utilities/FBConfiguration.m
Normal file
@@ -0,0 +1,677 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "FBConfiguration.h"
|
||||
|
||||
#import "AXSettings.h"
|
||||
#import "UIKeyboardImpl.h"
|
||||
#import "TIPreferencesController.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include "TargetConditionals.h"
|
||||
#import "FBXCodeCompatibility.h"
|
||||
#import "XCAXClient_iOS+FBSnapshotReqParams.h"
|
||||
#import "XCTestPrivateSymbols.h"
|
||||
#import "XCTestConfiguration.h"
|
||||
#import "XCUIApplication+FBUIInterruptions.h"
|
||||
|
||||
static NSUInteger const DefaultStartingPort = 8567;
|
||||
static NSUInteger const DefaultMjpegServerPort = 9567;
|
||||
static NSUInteger const DefaultPortRange = 100;
|
||||
|
||||
static char const *const controllerPrefBundlePath = "/System/Library/PrivateFrameworks/TextInput.framework/TextInput";
|
||||
static NSString *const controllerClassName = @"TIPreferencesController";
|
||||
static NSString *const FBKeyboardAutocorrectionKey = @"KeyboardAutocorrection";
|
||||
static NSString *const FBKeyboardPredictionKey = @"KeyboardPrediction";
|
||||
static NSString *const axSettingsClassName = @"AXSettings";
|
||||
|
||||
static BOOL FBShouldUseTestManagerForVisibilityDetection = NO;
|
||||
static BOOL FBShouldUseSingletonTestManager = YES;
|
||||
static BOOL FBShouldRespectSystemAlerts = NO;
|
||||
|
||||
static CGFloat FBMjpegScalingFactor = 100.0;
|
||||
static BOOL FBMjpegShouldFixOrientation = NO;
|
||||
static NSUInteger FBMjpegServerScreenshotQuality = 25;
|
||||
static NSUInteger FBMjpegServerFramerate = 10;
|
||||
|
||||
// Session-specific settings
|
||||
static BOOL FBShouldTerminateApp;
|
||||
static NSNumber* FBMaxTypingFrequency;
|
||||
static NSUInteger FBScreenshotQuality;
|
||||
static BOOL FBShouldUseFirstMatch;
|
||||
static BOOL FBShouldBoundElementsByIndex;
|
||||
static BOOL FBIncludeNonModalElements;
|
||||
static NSString *FBAcceptAlertButtonSelector;
|
||||
static NSString *FBDismissAlertButtonSelector;
|
||||
static NSString *FBAutoClickAlertSelector;
|
||||
static NSTimeInterval FBWaitForIdleTimeout;
|
||||
static NSTimeInterval FBAnimationCoolOffTimeout;
|
||||
static BOOL FBShouldUseCompactResponses;
|
||||
static NSString *FBElementResponseAttributes;
|
||||
static BOOL FBUseClearTextShortcut;
|
||||
static BOOL FBLimitXpathContextScope = YES;
|
||||
#if !TARGET_OS_TV
|
||||
static UIInterfaceOrientation FBScreenshotOrientation;
|
||||
#endif
|
||||
static BOOL FBShouldIncludeHittableInPageSource = NO;
|
||||
static BOOL FBShouldIncludeNativeFrameInPageSource = NO;
|
||||
static BOOL FBShouldIncludeMinMaxValueInPageSource = NO;
|
||||
|
||||
@implementation FBConfiguration
|
||||
|
||||
+ (NSUInteger)defaultTypingFrequency
|
||||
{
|
||||
NSInteger defaultFreq = [[NSUserDefaults standardUserDefaults]
|
||||
integerForKey:@"com.apple.xctest.iOSMaximumTypingFrequency"];
|
||||
return defaultFreq > 0 ? defaultFreq : 60;
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
[FBConfiguration resetSessionSettings];
|
||||
}
|
||||
|
||||
#pragma mark Public
|
||||
|
||||
+ (void)disableRemoteQueryEvaluation
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"XCTDisableRemoteQueryEvaluation"];
|
||||
}
|
||||
|
||||
+ (void)disableApplicationUIInterruptionsHandling
|
||||
{
|
||||
[XCUIApplication fb_disableUIInterruptionsHandling];
|
||||
}
|
||||
|
||||
+ (void)enableXcTestDebugLogs
|
||||
{
|
||||
((XCTestConfiguration *)XCTestConfiguration.activeTestConfiguration).emitOSLogs = YES;
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"XCTEmitOSLogs"];
|
||||
}
|
||||
|
||||
+ (void)disableAttributeKeyPathAnalysis
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"XCTDisableAttributeKeyPathAnalysis"];
|
||||
}
|
||||
|
||||
+ (void)disableScreenshots
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DisableScreenshots"];
|
||||
}
|
||||
|
||||
+ (void)enableScreenshots
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"DisableScreenshots"];
|
||||
}
|
||||
|
||||
+ (void)disableScreenRecordings
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DisableDiagnosticScreenRecordings"];
|
||||
}
|
||||
|
||||
+ (void)enableScreenRecordings
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"DisableDiagnosticScreenRecordings"];
|
||||
}
|
||||
|
||||
+ (NSRange)bindingPortRange
|
||||
{
|
||||
// 'WebDriverAgent --port 8080' can be passed via the arguments to the process
|
||||
if (self.bindingPortRangeFromArguments.location != NSNotFound) {
|
||||
return self.bindingPortRangeFromArguments;
|
||||
}
|
||||
|
||||
// Existence of USE_PORT in the environment implies the port range is managed by the launching process.
|
||||
if (NSProcessInfo.processInfo.environment[@"USE_PORT"] &&
|
||||
[NSProcessInfo.processInfo.environment[@"USE_PORT"] length] > 0) {
|
||||
return NSMakeRange([NSProcessInfo.processInfo.environment[@"USE_PORT"] integerValue] , 1);
|
||||
}
|
||||
|
||||
return NSMakeRange(DefaultStartingPort, DefaultPortRange);
|
||||
}
|
||||
|
||||
+ (NSInteger)mjpegServerPort
|
||||
{
|
||||
if (self.mjpegServerPortFromArguments != NSNotFound) {
|
||||
return self.mjpegServerPortFromArguments;
|
||||
}
|
||||
|
||||
if (NSProcessInfo.processInfo.environment[@"MJPEG_SERVER_PORT"] &&
|
||||
[NSProcessInfo.processInfo.environment[@"MJPEG_SERVER_PORT"] length] > 0) {
|
||||
return [NSProcessInfo.processInfo.environment[@"MJPEG_SERVER_PORT"] integerValue];
|
||||
}
|
||||
|
||||
return DefaultMjpegServerPort;
|
||||
}
|
||||
|
||||
+ (CGFloat)mjpegScalingFactor
|
||||
{
|
||||
return FBMjpegScalingFactor;
|
||||
}
|
||||
|
||||
+ (void)setMjpegScalingFactor:(CGFloat)scalingFactor {
|
||||
FBMjpegScalingFactor = scalingFactor;
|
||||
}
|
||||
|
||||
+ (BOOL)mjpegShouldFixOrientation
|
||||
{
|
||||
return FBMjpegShouldFixOrientation;
|
||||
}
|
||||
|
||||
+ (void)setMjpegShouldFixOrientation:(BOOL)enabled {
|
||||
FBMjpegShouldFixOrientation = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)verboseLoggingEnabled
|
||||
{
|
||||
return [NSProcessInfo.processInfo.environment[@"VERBOSE_LOGGING"] boolValue];
|
||||
}
|
||||
|
||||
+ (void)setShouldUseTestManagerForVisibilityDetection:(BOOL)value
|
||||
{
|
||||
FBShouldUseTestManagerForVisibilityDetection = value;
|
||||
}
|
||||
|
||||
+ (BOOL)shouldUseTestManagerForVisibilityDetection
|
||||
{
|
||||
return FBShouldUseTestManagerForVisibilityDetection;
|
||||
}
|
||||
|
||||
+ (void)setShouldUseCompactResponses:(BOOL)value
|
||||
{
|
||||
FBShouldUseCompactResponses = value;
|
||||
}
|
||||
|
||||
+ (BOOL)shouldUseCompactResponses
|
||||
{
|
||||
return FBShouldUseCompactResponses;
|
||||
}
|
||||
|
||||
+ (void)setShouldTerminateApp:(BOOL)value
|
||||
{
|
||||
FBShouldTerminateApp = value;
|
||||
}
|
||||
|
||||
+ (BOOL)shouldTerminateApp
|
||||
{
|
||||
return FBShouldTerminateApp;
|
||||
}
|
||||
|
||||
+ (void)setElementResponseAttributes:(NSString *)value
|
||||
{
|
||||
FBElementResponseAttributes = value;
|
||||
}
|
||||
|
||||
+ (NSString *)elementResponseAttributes
|
||||
{
|
||||
return FBElementResponseAttributes;
|
||||
}
|
||||
|
||||
+ (void)setMaxTypingFrequency:(NSUInteger)value
|
||||
{
|
||||
FBMaxTypingFrequency = @(value);
|
||||
}
|
||||
|
||||
+ (NSUInteger)maxTypingFrequency
|
||||
{
|
||||
if (nil == FBMaxTypingFrequency) {
|
||||
return [self defaultTypingFrequency];
|
||||
}
|
||||
return FBMaxTypingFrequency.integerValue <= 0
|
||||
? [self defaultTypingFrequency]
|
||||
: FBMaxTypingFrequency.integerValue;
|
||||
}
|
||||
|
||||
+ (void)setShouldUseSingletonTestManager:(BOOL)value
|
||||
{
|
||||
FBShouldUseSingletonTestManager = value;
|
||||
}
|
||||
|
||||
+ (BOOL)shouldUseSingletonTestManager
|
||||
{
|
||||
return FBShouldUseSingletonTestManager;
|
||||
}
|
||||
|
||||
+ (NSUInteger)mjpegServerFramerate
|
||||
{
|
||||
return FBMjpegServerFramerate;
|
||||
}
|
||||
|
||||
+ (void)setMjpegServerFramerate:(NSUInteger)framerate
|
||||
{
|
||||
FBMjpegServerFramerate = framerate;
|
||||
}
|
||||
|
||||
+ (NSUInteger)mjpegServerScreenshotQuality
|
||||
{
|
||||
return FBMjpegServerScreenshotQuality;
|
||||
}
|
||||
|
||||
+ (void)setMjpegServerScreenshotQuality:(NSUInteger)quality
|
||||
{
|
||||
FBMjpegServerScreenshotQuality = quality;
|
||||
}
|
||||
|
||||
+ (NSUInteger)screenshotQuality
|
||||
{
|
||||
return FBScreenshotQuality;
|
||||
}
|
||||
|
||||
+ (void)setScreenshotQuality:(NSUInteger)quality
|
||||
{
|
||||
FBScreenshotQuality = quality;
|
||||
}
|
||||
|
||||
+ (NSTimeInterval)waitForIdleTimeout
|
||||
{
|
||||
return FBWaitForIdleTimeout;
|
||||
}
|
||||
|
||||
+ (void)setWaitForIdleTimeout:(NSTimeInterval)timeout
|
||||
{
|
||||
FBWaitForIdleTimeout = timeout;
|
||||
}
|
||||
|
||||
+ (NSTimeInterval)animationCoolOffTimeout
|
||||
{
|
||||
return FBAnimationCoolOffTimeout;
|
||||
}
|
||||
|
||||
+ (void)setAnimationCoolOffTimeout:(NSTimeInterval)timeout
|
||||
{
|
||||
FBAnimationCoolOffTimeout = timeout;
|
||||
}
|
||||
|
||||
// Works for Simulator and Real devices
|
||||
+ (void)configureDefaultKeyboardPreferences
|
||||
{
|
||||
void *handle = dlopen(controllerPrefBundlePath, RTLD_LAZY);
|
||||
|
||||
Class controllerClass = NSClassFromString(controllerClassName);
|
||||
|
||||
TIPreferencesController *controller = [controllerClass sharedPreferencesController];
|
||||
// Auto-Correction in Keyboards
|
||||
// 'setAutocorrectionEnabled' Was in TextInput.framework/TIKeyboardState.h over iOS 10.3
|
||||
if ([controller respondsToSelector:@selector(setAutocorrectionEnabled:)]) {
|
||||
// Under iOS 10.2
|
||||
controller.autocorrectionEnabled = NO;
|
||||
} else if ([controller respondsToSelector:@selector(setValue:forPreferenceKey:)]) {
|
||||
// Over iOS 10.3
|
||||
[controller setValue:@NO forPreferenceKey:FBKeyboardAutocorrectionKey];
|
||||
}
|
||||
|
||||
// Predictive in Keyboards
|
||||
if ([controller respondsToSelector:@selector(setPredictionEnabled:)]) {
|
||||
controller.predictionEnabled = NO;
|
||||
} else if ([controller respondsToSelector:@selector(setValue:forPreferenceKey:)]) {
|
||||
[controller setValue:@NO forPreferenceKey:FBKeyboardPredictionKey];
|
||||
}
|
||||
|
||||
// To dismiss keyboard tutorial on iOS 11+ (iPad)
|
||||
if ([controller respondsToSelector:@selector(setValue:forPreferenceKey:)]) {
|
||||
[controller setValue:@YES forPreferenceKey:@"DidShowGestureKeyboardIntroduction"];
|
||||
if (isSDKVersionGreaterThanOrEqualTo(@"13.0")) {
|
||||
[controller setValue:@YES forPreferenceKey:@"DidShowContinuousPathIntroduction"];
|
||||
}
|
||||
[controller synchronizePreferences];
|
||||
}
|
||||
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
+ (void)forceSimulatorSoftwareKeyboardPresence
|
||||
{
|
||||
#if TARGET_OS_SIMULATOR
|
||||
// Force toggle software keyboard on.
|
||||
// This can avoid 'Keyboard is not present' error which can happen
|
||||
// when send_keys are called by client
|
||||
[[UIKeyboardImpl sharedInstance] setAutomaticMinimizationEnabled:NO];
|
||||
|
||||
if ([(NSObject *)[UIKeyboardImpl sharedInstance]
|
||||
respondsToSelector:@selector(setSoftwareKeyboardShownByTouch:)]) {
|
||||
// Xcode 13 no longer has this method
|
||||
[[UIKeyboardImpl sharedInstance] setSoftwareKeyboardShownByTouch:YES];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (FBConfigurationKeyboardPreference)keyboardAutocorrection
|
||||
{
|
||||
return [self keyboardsPreference:FBKeyboardAutocorrectionKey];
|
||||
}
|
||||
|
||||
+ (void)setKeyboardAutocorrection:(BOOL)isEnabled
|
||||
{
|
||||
[self configureKeyboardsPreference:isEnabled forPreferenceKey:FBKeyboardAutocorrectionKey];
|
||||
}
|
||||
|
||||
+ (FBConfigurationKeyboardPreference)keyboardPrediction
|
||||
{
|
||||
return [self keyboardsPreference:FBKeyboardPredictionKey];
|
||||
}
|
||||
|
||||
+ (void)setKeyboardPrediction:(BOOL)isEnabled
|
||||
{
|
||||
[self configureKeyboardsPreference:isEnabled forPreferenceKey:FBKeyboardPredictionKey];
|
||||
}
|
||||
|
||||
+ (void)setSnapshotMaxDepth:(int)maxDepth
|
||||
{
|
||||
FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @(maxDepth));
|
||||
}
|
||||
|
||||
+ (int)snapshotMaxDepth
|
||||
{
|
||||
return [FBGetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey) intValue];
|
||||
}
|
||||
|
||||
+ (void)setShouldRespectSystemAlerts:(BOOL)value
|
||||
{
|
||||
FBShouldRespectSystemAlerts = value;
|
||||
}
|
||||
|
||||
+ (BOOL)shouldRespectSystemAlerts
|
||||
{
|
||||
return FBShouldRespectSystemAlerts;
|
||||
}
|
||||
|
||||
+ (void)setUseFirstMatch:(BOOL)enabled
|
||||
{
|
||||
FBShouldUseFirstMatch = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)useFirstMatch
|
||||
{
|
||||
return FBShouldUseFirstMatch;
|
||||
}
|
||||
|
||||
+ (void)setBoundElementsByIndex:(BOOL)enabled
|
||||
{
|
||||
FBShouldBoundElementsByIndex = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)boundElementsByIndex
|
||||
{
|
||||
return FBShouldBoundElementsByIndex;
|
||||
}
|
||||
|
||||
+ (void)setIncludeNonModalElements:(BOOL)isEnabled
|
||||
{
|
||||
FBIncludeNonModalElements = isEnabled;
|
||||
}
|
||||
|
||||
+ (BOOL)includeNonModalElements
|
||||
{
|
||||
return FBIncludeNonModalElements;
|
||||
}
|
||||
|
||||
+ (void)setAcceptAlertButtonSelector:(NSString *)classChainSelector
|
||||
{
|
||||
FBAcceptAlertButtonSelector = classChainSelector;
|
||||
}
|
||||
|
||||
+ (NSString *)acceptAlertButtonSelector
|
||||
{
|
||||
return FBAcceptAlertButtonSelector;
|
||||
}
|
||||
|
||||
+ (void)setDismissAlertButtonSelector:(NSString *)classChainSelector
|
||||
{
|
||||
FBDismissAlertButtonSelector = classChainSelector;
|
||||
}
|
||||
|
||||
+ (NSString *)dismissAlertButtonSelector
|
||||
{
|
||||
return FBDismissAlertButtonSelector;
|
||||
}
|
||||
|
||||
+ (void)setAutoClickAlertSelector:(NSString *)classChainSelector
|
||||
{
|
||||
FBAutoClickAlertSelector = classChainSelector;
|
||||
}
|
||||
|
||||
+ (NSString *)autoClickAlertSelector
|
||||
{
|
||||
return FBAutoClickAlertSelector;
|
||||
}
|
||||
|
||||
+ (void)setUseClearTextShortcut:(BOOL)enabled
|
||||
{
|
||||
FBUseClearTextShortcut = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)useClearTextShortcut
|
||||
{
|
||||
return FBUseClearTextShortcut;
|
||||
}
|
||||
|
||||
+ (BOOL)limitXpathContextScope
|
||||
{
|
||||
return FBLimitXpathContextScope;
|
||||
}
|
||||
|
||||
+ (void)setLimitXpathContextScope:(BOOL)enabled
|
||||
{
|
||||
FBLimitXpathContextScope = enabled;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
+ (BOOL)setScreenshotOrientation:(NSString *)orientation error:(NSError **)error
|
||||
{
|
||||
// Only UIInterfaceOrientationUnknown is over iOS 8. Others are over iOS 2.
|
||||
// https://developer.apple.com/documentation/uikit/uiinterfaceorientation/uiinterfaceorientationunknown
|
||||
if ([orientation.lowercaseString isEqualToString:@"portrait"]) {
|
||||
FBScreenshotOrientation = UIInterfaceOrientationPortrait;
|
||||
} else if ([orientation.lowercaseString isEqualToString:@"portraitupsidedown"]) {
|
||||
FBScreenshotOrientation = UIInterfaceOrientationPortraitUpsideDown;
|
||||
} else if ([orientation.lowercaseString isEqualToString:@"landscaperight"]) {
|
||||
FBScreenshotOrientation = UIInterfaceOrientationLandscapeRight;
|
||||
} else if ([orientation.lowercaseString isEqualToString:@"landscapeleft"]) {
|
||||
FBScreenshotOrientation = UIInterfaceOrientationLandscapeLeft;
|
||||
} else if ([orientation.lowercaseString isEqualToString:@"auto"]) {
|
||||
FBScreenshotOrientation = UIInterfaceOrientationUnknown;
|
||||
} else {
|
||||
return [[FBErrorBuilder.builder withDescriptionFormat:
|
||||
@"The orientation value '%@' is not known. Only the following orientation values are supported: " \
|
||||
"'auto', 'portrait', 'portraitUpsideDown', 'landscapeRight' and 'landscapeLeft'", orientation]
|
||||
buildError:error];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (NSInteger)screenshotOrientation
|
||||
{
|
||||
return FBScreenshotOrientation;
|
||||
}
|
||||
|
||||
+ (NSString *)humanReadableScreenshotOrientation
|
||||
{
|
||||
switch (FBScreenshotOrientation) {
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return @"portrait";
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return @"portraitUpsideDown";
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return @"landscapeRight";
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return @"landscapeLeft";
|
||||
case UIInterfaceOrientationUnknown:
|
||||
return @"auto";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+ (void)resetSessionSettings
|
||||
{
|
||||
FBShouldTerminateApp = YES;
|
||||
FBShouldUseCompactResponses = YES;
|
||||
FBElementResponseAttributes = @"type,label";
|
||||
FBMaxTypingFrequency = @([self defaultTypingFrequency]);
|
||||
FBScreenshotQuality = 3;
|
||||
FBShouldUseFirstMatch = NO;
|
||||
FBShouldBoundElementsByIndex = NO;
|
||||
// This is diabled by default because enabling it prevents the accessbility snapshot to be taken
|
||||
// (it always errors with kxIllegalArgument error)
|
||||
FBIncludeNonModalElements = NO;
|
||||
FBAcceptAlertButtonSelector = @"";
|
||||
FBDismissAlertButtonSelector = @"";
|
||||
FBAutoClickAlertSelector = @"";
|
||||
FBWaitForIdleTimeout = 10.;
|
||||
FBAnimationCoolOffTimeout = 2.;
|
||||
// 50 should be enough for the majority of the cases. The performance is acceptable for values up to 100.
|
||||
FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @50);
|
||||
FBUseClearTextShortcut = YES;
|
||||
FBLimitXpathContextScope = YES;
|
||||
#if !TARGET_OS_TV
|
||||
FBScreenshotOrientation = UIInterfaceOrientationUnknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark Private
|
||||
|
||||
+ (FBConfigurationKeyboardPreference)keyboardsPreference:(nonnull NSString *)key
|
||||
{
|
||||
Class controllerClass = NSClassFromString(controllerClassName);
|
||||
TIPreferencesController *controller = [controllerClass sharedPreferencesController];
|
||||
if ([key isEqualToString:FBKeyboardAutocorrectionKey]) {
|
||||
if ([controller respondsToSelector:@selector(boolForPreferenceKey:)]) {
|
||||
return [controller boolForPreferenceKey:FBKeyboardAutocorrectionKey]
|
||||
? FBConfigurationKeyboardPreferenceEnabled
|
||||
: FBConfigurationKeyboardPreferenceDisabled;
|
||||
} else {
|
||||
[FBLogger log:@"Updating keyboard autocorrection preference is not supported"];
|
||||
return FBConfigurationKeyboardPreferenceNotSupported;
|
||||
}
|
||||
} else if ([key isEqualToString:FBKeyboardPredictionKey]) {
|
||||
if ([controller respondsToSelector:@selector(boolForPreferenceKey:)]) {
|
||||
return [controller boolForPreferenceKey:FBKeyboardPredictionKey]
|
||||
? FBConfigurationKeyboardPreferenceEnabled
|
||||
: FBConfigurationKeyboardPreferenceDisabled;
|
||||
} else {
|
||||
[FBLogger log:@"Updating keyboard prediction preference is not supported"];
|
||||
return FBConfigurationKeyboardPreferenceNotSupported;
|
||||
}
|
||||
}
|
||||
@throw [[FBErrorBuilder.builder withDescriptionFormat:@"No available keyboardsPreferenceKey: '%@'", key] build];
|
||||
}
|
||||
|
||||
+ (void)configureKeyboardsPreference:(BOOL)enable forPreferenceKey:(nonnull NSString *)key
|
||||
{
|
||||
void *handle = dlopen(controllerPrefBundlePath, RTLD_LAZY);
|
||||
Class controllerClass = NSClassFromString(controllerClassName);
|
||||
|
||||
TIPreferencesController *controller = [controllerClass sharedPreferencesController];
|
||||
|
||||
if ([key isEqualToString:FBKeyboardAutocorrectionKey]) {
|
||||
// Auto-Correction in Keyboards
|
||||
if ([controller respondsToSelector:@selector(setAutocorrectionEnabled:)]) {
|
||||
controller.autocorrectionEnabled = enable;
|
||||
} else {
|
||||
[controller setValue:@(enable) forPreferenceKey:FBKeyboardAutocorrectionKey];
|
||||
}
|
||||
} else if ([key isEqualToString:FBKeyboardPredictionKey]) {
|
||||
// Predictive in Keyboards
|
||||
if ([controller respondsToSelector:@selector(setPredictionEnabled:)]) {
|
||||
controller.predictionEnabled = enable;
|
||||
} else {
|
||||
[controller setValue:@(enable) forPreferenceKey:FBKeyboardPredictionKey];
|
||||
}
|
||||
}
|
||||
|
||||
[controller synchronizePreferences];
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
+ (NSString*)valueFromArguments: (NSArray<NSString *> *)arguments forKey: (NSString*)key
|
||||
{
|
||||
NSUInteger index = [arguments indexOfObject:key];
|
||||
if (index == NSNotFound || index == arguments.count - 1) {
|
||||
return nil;
|
||||
}
|
||||
return arguments[index + 1];
|
||||
}
|
||||
|
||||
+ (NSUInteger)mjpegServerPortFromArguments
|
||||
{
|
||||
NSString *portNumberString = [self valueFromArguments: NSProcessInfo.processInfo.arguments
|
||||
forKey: @"--mjpeg-server-port"];
|
||||
NSUInteger port = (NSUInteger)[portNumberString integerValue];
|
||||
if (port == 0) {
|
||||
return NSNotFound;
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
+ (NSRange)bindingPortRangeFromArguments
|
||||
{
|
||||
NSString *portNumberString = [self valueFromArguments:NSProcessInfo.processInfo.arguments
|
||||
forKey: @"--port"];
|
||||
NSUInteger port = (NSUInteger)[portNumberString integerValue];
|
||||
if (port == 0) {
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
return NSMakeRange(port, 1);
|
||||
}
|
||||
|
||||
+ (void)setReduceMotionEnabled:(BOOL)isEnabled
|
||||
{
|
||||
Class settingsClass = NSClassFromString(axSettingsClassName);
|
||||
AXSettings *settings = [settingsClass sharedInstance];
|
||||
|
||||
// Below does not work on real devices because of iOS security model
|
||||
// (lldb) po settings.reduceMotionEnabled = isEnabled
|
||||
// 2019-08-21 22:58:19.776165+0900 WebDriverAgentRunner-Runner[322:13361] [User Defaults] Couldn't write value for key ReduceMotionEnabled in CFPrefsPlistSource<0x28111a700> (Domain: com.apple.Accessibility, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: No): setting preferences outside an application's container requires user-preference-write or file-write-data sandbox access
|
||||
if ([settings respondsToSelector:@selector(setReduceMotionEnabled:)]) {
|
||||
[settings setReduceMotionEnabled:isEnabled];
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)reduceMotionEnabled
|
||||
{
|
||||
Class settingsClass = NSClassFromString(axSettingsClassName);
|
||||
AXSettings *settings = [settingsClass sharedInstance];
|
||||
|
||||
if ([settings respondsToSelector:@selector(reduceMotionEnabled)]) {
|
||||
return settings.reduceMotionEnabled;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (void)setIncludeHittableInPageSource:(BOOL)enabled
|
||||
{
|
||||
FBShouldIncludeHittableInPageSource = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)includeHittableInPageSource
|
||||
{
|
||||
return FBShouldIncludeHittableInPageSource;
|
||||
}
|
||||
|
||||
+ (void)setIncludeNativeFrameInPageSource:(BOOL)enabled
|
||||
{
|
||||
FBShouldIncludeNativeFrameInPageSource = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)includeNativeFrameInPageSource
|
||||
{
|
||||
return FBShouldIncludeNativeFrameInPageSource;
|
||||
}
|
||||
|
||||
+ (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled
|
||||
{
|
||||
FBShouldIncludeMinMaxValueInPageSource = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)includeMinMaxValueInPageSource
|
||||
{
|
||||
return FBShouldIncludeMinMaxValueInPageSource;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user