| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- /**
- * 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. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
- #import "XCUIApplicationProcess+FBQuiescence.h"
- #import <objc/runtime.h>
- #import "FBConfiguration.h"
- #import "FBExceptions.h"
- #import "FBLogger.h"
- #import "FBSettings.h"
- static void (*original_waitForQuiescenceIncludingAnimationsIdle)(id, SEL, BOOL);
- static void (*original_waitForQuiescenceIncludingAnimationsIdlePreEvent)(id, SEL, BOOL, BOOL);
- static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd, BOOL includingAnimations)
- {
- NSString *bundleId = [self bundleID];
- if (![[self fb_shouldWaitForQuiescence] boolValue] || FBConfiguration.waitForIdleTimeout < DBL_EPSILON) {
- [FBLogger logFmt:@"Quiescence checks are disabled for %@ application. Making it to believe it is idling",
- bundleId];
- return;
- }
- NSTimeInterval desiredTimeout = FBConfiguration.waitForIdleTimeout;
- NSTimeInterval previousTimeout = _XCTApplicationStateTimeout();
- _XCTSetApplicationStateTimeout(desiredTimeout);
- [FBLogger logFmt:@"Waiting up to %@s until %@ is in idle state (%@ animations)",
- @(desiredTimeout), bundleId, includingAnimations ? @"including" : @"excluding"];
- @try {
- original_waitForQuiescenceIncludingAnimationsIdle(self, _cmd, includingAnimations);
- } @finally {
- _XCTSetApplicationStateTimeout(previousTimeout);
- }
- }
- static void swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent(id self, SEL _cmd, BOOL includingAnimations, BOOL isPreEvent)
- {
- NSString *bundleId = [self bundleID];
- if (![[self fb_shouldWaitForQuiescence] boolValue] || FBConfiguration.waitForIdleTimeout < DBL_EPSILON) {
- [FBLogger logFmt:@"Quiescence checks are disabled for %@ application. Making it to believe it is idling",
- bundleId];
- return;
- }
- NSTimeInterval desiredTimeout = FBConfiguration.waitForIdleTimeout;
- NSTimeInterval previousTimeout = _XCTApplicationStateTimeout();
- _XCTSetApplicationStateTimeout(desiredTimeout);
- [FBLogger logFmt:@"Waiting up to %@s until %@ is in idle state (%@ animations)",
- @(desiredTimeout), bundleId, includingAnimations ? @"including" : @"excluding"];
- @try {
- original_waitForQuiescenceIncludingAnimationsIdlePreEvent(self, _cmd, includingAnimations, isPreEvent);
- } @finally {
- _XCTSetApplicationStateTimeout(previousTimeout);
- }
- }
- @implementation XCUIApplicationProcess (FBQuiescence)
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wobjc-load-method"
- #pragma clang diagnostic ignored "-Wcast-function-type-strict"
- + (void)load
- {
- Method waitForQuiescenceIncludingAnimationsIdleMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:));
- Method waitForQuiescenceIncludingAnimationsIdlePreEventMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:));
- if (nil != waitForQuiescenceIncludingAnimationsIdleMethod) {
- IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdle;
- original_waitForQuiescenceIncludingAnimationsIdle = (void (*)(id, SEL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdleMethod, swizzledImp);
- } else if (nil != waitForQuiescenceIncludingAnimationsIdlePreEventMethod) {
- IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent;
- original_waitForQuiescenceIncludingAnimationsIdlePreEvent = (void (*)(id, SEL, BOOL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdlePreEventMethod, swizzledImp);
- } else {
- [FBLogger log:@"Could not find method -[XCUIApplicationProcess waitForQuiescenceIncludingAnimationsIdle:]"];
- }
- }
- #pragma clang diagnostic pop
- static char XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE;
- @dynamic fb_shouldWaitForQuiescence;
- - (NSNumber *)fb_shouldWaitForQuiescence
- {
- id result = objc_getAssociatedObject(self, &XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE);
- if (nil == result) {
- return @(YES);
- }
- return (NSNumber *)result;
- }
- - (void)setFb_shouldWaitForQuiescence:(NSNumber *)value
- {
- objc_setAssociatedObject(self, &XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (void)fb_waitForQuiescenceIncludingAnimationsIdle:(bool)waitForAnimations
- {
- if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:)]) {
- [self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations];
- } else if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:)]) {
- [self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations isPreEvent:NO];
- } else {
- @throw [NSException exceptionWithName:FBIncompatibleWdaException
- reason:@"The current WebDriverAgent build is not compatible to your device OS version"
- userInfo:@{}];
- }
- }
- @end
|