appium-webdriveragent 5.3.1 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## [5.4.0](https://github.com/appium/WebDriverAgent/compare/v5.3.3...v5.4.0) (2023-06-09)
2
+
3
+
4
+ ### Features
5
+
6
+ * Drop older screenshoting APIs ([#721](https://github.com/appium/WebDriverAgent/issues/721)) ([4a08d7a](https://github.com/appium/WebDriverAgent/commit/4a08d7a843af6b93b378b4e3dc10f123d2e56359))
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Streamline errors handling for async block calls ([#725](https://github.com/appium/WebDriverAgent/issues/725)) ([364b779](https://github.com/appium/WebDriverAgent/commit/364b7791393ffae9c048c5cac023e3e7d1813a14))
12
+
13
+ ## [5.3.3](https://github.com/appium/WebDriverAgent/compare/v5.3.2...v5.3.3) (2023-06-08)
14
+
15
+
16
+ ### Miscellaneous Chores
17
+
18
+ * Disable automatic screen recording by default ([#726](https://github.com/appium/WebDriverAgent/issues/726)) ([a070223](https://github.com/appium/WebDriverAgent/commit/a070223e0ef43be8dd54d16ee3e3b96603ad5f3a))
19
+
20
+ ## [5.3.2](https://github.com/appium/WebDriverAgent/compare/v5.3.1...v5.3.2) (2023-06-07)
21
+
22
+
23
+ ### Miscellaneous Chores
24
+
25
+ * **deps-dev:** bump conventional-changelog-conventionalcommits ([#723](https://github.com/appium/WebDriverAgent/issues/723)) ([b22f61e](https://github.com/appium/WebDriverAgent/commit/b22f61eda142ee6ec1db8c74a4788e0270ac7740))
26
+
1
27
  ## [5.3.1](https://github.com/appium/WebDriverAgent/compare/v5.3.0...v5.3.1) (2023-06-06)
2
28
 
3
29
 
@@ -49,10 +49,14 @@ extern NSString *const FBSnapshotMaxDepthKey;
49
49
 
50
50
  /*! Disables XCTest automated screenshots taking */
51
51
  + (void)disableScreenshots;
52
-
53
52
  /*! Enables XCTest automated screenshots taking */
54
53
  + (void)enableScreenshots;
55
54
 
55
+ /*! Disables XCTest automated videos taking (iOS 17+) */
56
+ + (void)disableScreenRecordings;
57
+ /*! Enables XCTest automated videos taking (iOS 17+) */
58
+ + (void)enableScreenRecordings;
59
+
56
60
  /* The maximum typing frequency for all typing activities */
57
61
  + (void)setMaxTypingFrequency:(NSUInteger)value;
58
62
  + (NSUInteger)maxTypingFrequency;
@@ -89,9 +93,9 @@ extern NSString *const FBSnapshotMaxDepthKey;
89
93
  + (void)setMjpegServerFramerate:(NSUInteger)framerate;
90
94
 
91
95
  /**
92
- The quality of phone display screenshots. The higher quality you set is the bigger screenshot size is.
93
- The highest quality value is 0 (lossless PNG). The lowest quality is 2 (highly compressed JPEG).
94
- The default quality value is 1 (high quality JPEG).
96
+ The quality of display screenshots. The higher quality you set is the bigger screenshot size is.
97
+ The highest quality value is 0 (lossless PNG) or 3 (lossless HEIC). The lowest quality is 2 (highly compressed JPEG).
98
+ The default quality value is 3 (lossless HEIC).
95
99
  See https://developer.apple.com/documentation/xctest/xctimagequality?language=objc
96
100
  */
97
101
  + (NSUInteger)screenshotQuality;
@@ -94,6 +94,16 @@ static UIInterfaceOrientation FBScreenshotOrientation;
94
94
  [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"DisableScreenshots"];
95
95
  }
96
96
 
97
+ + (void)disableScreenRecordings
98
+ {
99
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DisableDiagnosticScreenRecordings"];
100
+ }
101
+
102
+ + (void)enableScreenRecordings
103
+ {
104
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"DisableDiagnosticScreenRecordings"];
105
+ }
106
+
97
107
  + (NSRange)bindingPortRange
98
108
  {
99
109
  // 'WebDriverAgent --port 8080' can be passed via the arguments to the process
@@ -443,7 +453,7 @@ static UIInterfaceOrientation FBScreenshotOrientation;
443
453
  FBShouldUseCompactResponses = YES;
444
454
  FBElementResponseAttributes = @"type,label";
445
455
  FBMaxTypingFrequency = 60;
446
- FBScreenshotQuality = 1;
456
+ FBScreenshotQuality = 3;
447
457
  FBCustomSnapshotTimeout = 15.;
448
458
  FBShouldUseFirstMatch = NO;
449
459
  FBShouldBoundElementsByIndex = NO;
@@ -10,6 +10,8 @@
10
10
  #import <Foundation/Foundation.h>
11
11
  #import <CoreGraphics/CoreGraphics.h>
12
12
 
13
+ @class UTType;
14
+
13
15
  NS_ASSUME_NONNULL_BEGIN
14
16
 
15
17
  // Those values define the allowed ranges for the scaling factor and compression quality settings
@@ -25,14 +27,12 @@ extern const CGFloat FBMaxCompressionQuality;
25
27
  queue it will be replaced with the new one
26
28
 
27
29
  @param image The image to scale down
28
- @param uti Either kUTTypePNG or kUTTypeJPEG
29
30
  @param completionHandler called after successfully scaling down an image
30
31
  @param scalingFactor the scaling factor in range 0.01..1.0. A value of 1.0 won't perform scaling at all
31
32
  @param compressionQuality the compression quality in range 0.0..1.0 (0.0 for max. compression and 1.0 for lossless compression)
32
- Only applicable for kUTTypeJPEG
33
+ Only applicable for UTTypeJPEG
33
34
  */
34
35
  - (void)submitImage:(NSData *)image
35
- uti:(NSString *)uti
36
36
  scalingFactor:(CGFloat)scalingFactor
37
37
  compressionQuality:(CGFloat)compressionQuality
38
38
  completionHandler:(void (^)(NSData *))completionHandler;
@@ -41,7 +41,7 @@ extern const CGFloat FBMaxCompressionQuality;
41
41
  Scales and crops the source image
42
42
 
43
43
  @param image The source image data
44
- @param uti Either kUTTypePNG or kUTTypeJPEG
44
+ @param uti Either UTTypePNG or UTTypeJPEG
45
45
  @param rect The cropping rectange for the screenshot. The value is expected to be non-scaled one
46
46
  since it happens after scaling/orientation change.
47
47
  CGRectNull could be used to take a screenshot of the full screen.
@@ -52,7 +52,7 @@ extern const CGFloat FBMaxCompressionQuality;
52
52
  @returns Processed image data compressed according to the given UTI or nil in case of a failure
53
53
  */
54
54
  - (nullable NSData *)scaledImageWithImage:(NSData *)image
55
- uti:(NSString *)uti
55
+ uti:(UTType *)uti
56
56
  rect:(CGRect)rect
57
57
  scalingFactor:(CGFloat)scalingFactor
58
58
  compressionQuality:(CGFloat)compressionQuality
@@ -11,7 +11,7 @@
11
11
 
12
12
  #import <ImageIO/ImageIO.h>
13
13
  #import <UIKit/UIKit.h>
14
- #import <MobileCoreServices/MobileCoreServices.h>
14
+ @import UniformTypeIdentifiers;
15
15
 
16
16
  #import "FBConfiguration.h"
17
17
  #import "FBErrorBuilder.h"
@@ -43,7 +43,6 @@ const CGFloat FBMaxCompressionQuality = 1.0f;
43
43
  }
44
44
 
45
45
  - (void)submitImage:(NSData *)image
46
- uti:(NSString *)uti
47
46
  scalingFactor:(CGFloat)scalingFactor
48
47
  compressionQuality:(CGFloat)compressionQuality
49
48
  completionHandler:(void (^)(NSData *))completionHandler
@@ -118,7 +117,7 @@ const CGFloat FBMaxCompressionQuality = 1.0f;
118
117
  }
119
118
 
120
119
  - (nullable NSData *)scaledImageWithImage:(NSData *)image
121
- uti:(NSString *)uti
120
+ uti:(UTType *)uti
122
121
  rect:(CGRect)rect
123
122
  scalingFactor:(CGFloat)scalingFactor
124
123
  compressionQuality:(CGFloat)compressionQuality
@@ -154,7 +153,7 @@ const CGFloat FBMaxCompressionQuality = 1.0f;
154
153
  UIGraphicsEndImageContext();
155
154
  }
156
155
 
157
- return [uti isEqualToString:(__bridge id)kUTTypePNG]
156
+ return [uti conformsToType:UTTypePNG]
158
157
  ? UIImagePNGRepresentation(resultImage)
159
158
  : UIImageJPEGRepresentation(resultImage, compressionQuality);
160
159
  }
@@ -163,7 +162,11 @@ const CGFloat FBMaxCompressionQuality = 1.0f;
163
162
  compressionQuality:(CGFloat)compressionQuality
164
163
  {
165
164
  NSMutableData *newImageData = [NSMutableData data];
166
- CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((CFMutableDataRef)newImageData, kUTTypeJPEG, 1, NULL);
165
+ CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData(
166
+ (__bridge CFMutableDataRef) newImageData,
167
+ (__bridge CFStringRef) UTTypeJPEG.identifier,
168
+ 1,
169
+ NULL);
167
170
  CFDictionaryRef compressionOptions = (__bridge CFDictionaryRef)@{
168
171
  (const NSString *)kCGImageDestinationLossyCompressionQuality: @(compressionQuality)
169
172
  };
@@ -10,7 +10,7 @@
10
10
  #import "FBMjpegServer.h"
11
11
 
12
12
  #import <mach/mach_time.h>
13
- #import <MobileCoreServices/MobileCoreServices.h>
13
+ @import UniformTypeIdentifiers;
14
14
 
15
15
  #import "GCDAsyncSocket.h"
16
16
  #import "FBApplication.h"
@@ -72,11 +72,6 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
72
72
 
73
73
  - (void)streamScreenshot
74
74
  {
75
- if (![self.class canStreamScreenshots]) {
76
- [FBLogger log:@"MJPEG server cannot start because the current iOS version is not supported"];
77
- return;
78
- }
79
-
80
75
  NSUInteger framerate = FBConfiguration.mjpegServerFramerate;
81
76
  uint64_t timerInterval = (uint64_t)(1.0 / ((0 == framerate || framerate > MAX_FPS) ? MAX_FPS : framerate) * NSEC_PER_SEC);
82
77
  uint64_t timeStarted = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW);
@@ -96,7 +91,7 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
96
91
  NSError *error;
97
92
  NSData *screenshotData = [FBScreenshot takeInOriginalResolutionWithScreenID:self.mainScreenID
98
93
  compressionQuality:screenshotCompressionQuality
99
- uti:(__bridge id)kUTTypeJPEG
94
+ uti:UTTypeJPEG
100
95
  timeout:FRAME_TIMEOUT
101
96
  error:&error];
102
97
  if (nil == screenshotData) {
@@ -107,7 +102,6 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
107
102
 
108
103
  if (usesScaling) {
109
104
  [self.imageScaler submitImage:screenshotData
110
- uti:(__bridge id)kUTTypeJPEG
111
105
  scalingFactor:scalingFactor
112
106
  compressionQuality:compressionQuality
113
107
  completionHandler:^(NSData * _Nonnull scaled) {
@@ -132,11 +126,6 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
132
126
  }
133
127
  }
134
128
 
135
- + (BOOL)canStreamScreenshots
136
- {
137
- return [FBScreenshot isNewScreenshotAPISupported];
138
- }
139
-
140
129
  - (void)didClientConnect:(GCDAsyncSocket *)newClient
141
130
  {
142
131
  [FBLogger logFmt:@"Got screenshots broadcast client connection at %@:%d", newClient.connectedHost, newClient.connectedPort];
@@ -8,22 +8,18 @@
8
8
  */
9
9
 
10
10
  #import <XCTest/XCTest.h>
11
+ @class UTType;
11
12
 
12
13
  NS_ASSUME_NONNULL_BEGIN
13
14
 
14
15
  @interface FBScreenshot : NSObject
15
16
 
16
- /**
17
- Returns YES if the current OS SDK supports advanced screenshoting APIs (added since Xcode SDK 10)
18
- */
19
- + (BOOL)isNewScreenshotAPISupported;
20
-
21
17
  /**
22
18
  Retrieves non-scaled screenshot of the whole screen
23
19
 
24
- @param quality The number in range 0-2, where 2 (JPG) is the lowest and 0 (PNG) is the highest quality.
20
+ @param quality The number in range 0-3, where 0 is PNG (lossless), 3 is HEIC (lossless), 1- low quality JPEG and 2 - high quality JPEG
25
21
  @param error If there is an error, upon return contains an NSError object that describes the problem.
26
- @return Device screenshot as PNG- or JPG-encoded data or nil in case of failure
22
+ @return Device screenshot as PNG-encoded data or nil in case of failure
27
23
  */
28
24
  + (nullable NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality
29
25
  error:(NSError **)error;
@@ -31,11 +27,11 @@ NS_ASSUME_NONNULL_BEGIN
31
27
  /**
32
28
  Retrieves non-scaled screenshot of the particular screen rectangle
33
29
 
34
- @param quality The number in range 0-2, where 2 (JPG) is the lowest and 0 (PNG) is the highest quality.
30
+ @param quality The number in range 0-3, where 0 is PNG (lossless), 3 is HEIC (lossless), 1- low quality JPEG and 2 - high quality JPEG
35
31
  @param rect The bounding rectange for the screenshot. The value is expected be non-scaled one.
36
32
  CGRectNull could be used to take a screenshot of the full screen.
37
33
  @param error If there is an error, upon return contains an NSError object that describes the problem.
38
- @return Device screenshot as PNG- or JPG-encoded data or nil in case of failure
34
+ @return Device screenshot as PNG-encoded data or nil in case of failure
39
35
  */
40
36
  + (nullable NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality
41
37
  rect:(CGRect)rect
@@ -46,14 +42,14 @@ NS_ASSUME_NONNULL_BEGIN
46
42
 
47
43
  @param screenID The screen identifier to take the screenshot from
48
44
  @param compressionQuality Normalized screenshot quality value in range 0..1, where 1 is the best quality
49
- @param uti kUTType... constant, which defines the type of the returned screenshot image
45
+ @param uti UTType... constant, which defines the type of the returned screenshot image
50
46
  @param timeout how much time to allow for the screenshot to be taken
51
47
  @param error If there is an error, upon return contains an NSError object that describes the problem.
52
- @return Device screenshot as PNG- or JPG-encoded data or nil in case of failure
48
+ @return Device screenshot as PNG-, HEIC- or JPG-encoded data or nil in case of failure
53
49
  */
54
50
  + (nullable NSData *)takeInOriginalResolutionWithScreenID:(long long)screenID
55
51
  compressionQuality:(CGFloat)compressionQuality
56
- uti:(NSString *)uti
52
+ uti:(UTType *)uti
57
53
  timeout:(NSTimeInterval)timeout
58
54
  error:(NSError **)error;
59
55
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  #import "FBScreenshot.h"
11
11
 
12
- #import <MobileCoreServices/MobileCoreServices.h>
12
+ @import UniformTypeIdentifiers;
13
13
 
14
14
  #import "FBConfiguration.h"
15
15
  #import "FBErrorBuilder.h"
@@ -33,16 +33,6 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
33
33
 
34
34
  @implementation FBScreenshot
35
35
 
36
- + (BOOL)isNewScreenshotAPISupported
37
- {
38
- static dispatch_once_t newScreenshotAPISupported;
39
- static BOOL result;
40
- dispatch_once(&newScreenshotAPISupported, ^{
41
- result = [(NSObject *)[FBXCTestDaemonsProxy testRunnerProxy] respondsToSelector:@selector(_XCT_requestScreenshotOfScreenWithID:withRect:uti:compressionQuality:withReply:)];
42
- });
43
- return result;
44
- }
45
-
46
36
  + (CGFloat)compressionQualityWithQuality:(NSUInteger)quality
47
37
  {
48
38
  switch (quality) {
@@ -55,14 +45,16 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
55
45
  }
56
46
  }
57
47
 
58
- + (NSString *)imageUtiWithQuality:(NSUInteger)quality
48
+ + (UTType *)imageUtiWithQuality:(NSUInteger)quality
59
49
  {
60
50
  switch (quality) {
61
51
  case 1:
62
52
  case 2:
63
- return (__bridge id)kUTTypeJPEG;
53
+ return UTTypeJPEG;
54
+ case 3:
55
+ return UTTypeHEIC;
64
56
  default:
65
- return (__bridge id)kUTTypePNG;
57
+ return UTTypePNG;
66
58
  }
67
59
  }
68
60
 
@@ -70,64 +62,28 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
70
62
  rect:(CGRect)rect
71
63
  error:(NSError **)error
72
64
  {
73
- if ([self.class isNewScreenshotAPISupported]) {
74
- XCUIScreen *mainScreen = XCUIScreen.mainScreen;
75
- return [self.class takeWithScreenID:mainScreen.displayID
76
- scale:SCREENSHOT_SCALE
77
- compressionQuality:[self.class compressionQualityWithQuality:FBConfiguration.screenshotQuality]
78
- rect:rect
79
- sourceUTI:[self.class imageUtiWithQuality:FBConfiguration.screenshotQuality]
80
- error:error];
81
- }
82
-
83
- [[[FBErrorBuilder builder]
84
- withDescription:@"Screenshots of limited areas are only available for newer OS versions"]
85
- buildError:error];
86
- return nil;
65
+ XCUIScreen *mainScreen = XCUIScreen.mainScreen;
66
+ return [self.class takeWithScreenID:mainScreen.displayID
67
+ scale:SCREENSHOT_SCALE
68
+ compressionQuality:[self.class compressionQualityWithQuality:quality]
69
+ rect:rect
70
+ sourceUTI:[self.class imageUtiWithQuality:quality]
71
+ error:error];
87
72
  }
88
73
 
89
74
  + (NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality
90
75
  error:(NSError **)error
91
76
  {
92
- if ([self.class isNewScreenshotAPISupported]) {
93
- XCUIScreen *mainScreen = XCUIScreen.mainScreen;
94
- return [self.class takeWithScreenID:mainScreen.displayID
95
- scale:SCREENSHOT_SCALE
96
- compressionQuality:[self.class compressionQualityWithQuality:FBConfiguration.screenshotQuality]
97
- rect:CGRectNull
98
- sourceUTI:[self.class imageUtiWithQuality:FBConfiguration.screenshotQuality]
99
- error:error];
100
- }
101
-
102
- id<XCTestManager_ManagerInterface> proxy = [FBXCTestDaemonsProxy testRunnerProxy];
103
- __block NSData *screenshotData = nil;
104
- __block NSError *innerError = nil;
105
- dispatch_semaphore_t sem = dispatch_semaphore_create(0);
106
- [proxy _XCT_requestScreenshotWithReply:^(NSData *data, NSError *screenshotError) {
107
- if (nil == screenshotError) {
108
- screenshotData = data;
109
- } else {
110
- innerError = screenshotError;
111
- }
112
- dispatch_semaphore_signal(sem);
113
- }];
114
- if (nil != innerError && error) {
115
- *error = innerError;
116
- }
117
- int64_t timeoutNs = (int64_t)(SCREENSHOT_TIMEOUT * NSEC_PER_SEC);
118
- if (0 != dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, timeoutNs))) {
119
- [[[FBErrorBuilder builder]
120
- withDescription:[NSString stringWithFormat:@"Cannot take a screenshot within %@ timeout", formatTimeInterval(SCREENSHOT_TIMEOUT)]]
121
- buildError:error];
122
- };
123
- return screenshotData;
77
+ return [self.class takeInOriginalResolutionWithQuality:quality
78
+ rect:CGRectNull
79
+ error:error];
124
80
  }
125
81
 
126
82
  + (NSData *)takeWithScreenID:(long long)screenID
127
83
  scale:(CGFloat)scale
128
84
  compressionQuality:(CGFloat)compressionQuality
129
85
  rect:(CGRect)rect
130
- sourceUTI:(NSString *)uti
86
+ sourceUTI:(UTType *)uti
131
87
  error:(NSError **)error
132
88
  {
133
89
  NSData *screenshotData = [self.class takeInOriginalResolutionWithScreenID:screenID
@@ -139,7 +95,7 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
139
95
  return nil;
140
96
  }
141
97
  return [[[FBImageIOScaler alloc] init] scaledImageWithImage:screenshotData
142
- uti:(__bridge id)kUTTypePNG
98
+ uti:UTTypePNG
143
99
  rect:rect
144
100
  scalingFactor:1.0 / scale
145
101
  compressionQuality:FBMaxCompressionQuality
@@ -148,7 +104,7 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
148
104
 
149
105
  + (NSData *)takeInOriginalResolutionWithScreenID:(long long)screenID
150
106
  compressionQuality:(CGFloat)compressionQuality
151
- uti:(NSString *)uti
107
+ uti:(UTType *)uti
152
108
  timeout:(NSTimeInterval)timeout
153
109
  error:(NSError **)error
154
110
  {
@@ -156,38 +112,23 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
156
112
  __block NSData *screenshotData = nil;
157
113
  __block NSError *innerError = nil;
158
114
  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
159
- if ([self.class shouldUseScreenshotRequestApiForProxy:(NSObject *)proxy]) {
160
- id screnshotRequest = [self.class screenshotRequestWithScreenID:screenID
161
- rect:CGRectNull
162
- uti:uti
163
- compressionQuality:compressionQuality
164
- error:error];
165
- if (nil == screnshotRequest) {
166
- return nil;
167
- }
168
- [proxy _XCT_requestScreenshot:screnshotRequest
169
- withReply:^(id image, NSError *err) {
170
- if (nil != err) {
171
- innerError = err;
172
- } else {
173
- screenshotData = [image data];
174
- }
175
- dispatch_semaphore_signal(sem);
176
- }];
177
- } else {
178
- [proxy _XCT_requestScreenshotOfScreenWithID:screenID
179
- withRect:CGRectNull
180
- uti:uti
181
- compressionQuality:compressionQuality
182
- withReply:^(NSData *data, NSError *err) {
183
- if (nil != err) {
184
- innerError = err;
185
- } else {
186
- screenshotData = data;
187
- }
188
- dispatch_semaphore_signal(sem);
189
- }];
115
+ id screnshotRequest = [self.class screenshotRequestWithScreenID:screenID
116
+ rect:CGRectNull
117
+ uti:uti
118
+ compressionQuality:compressionQuality
119
+ error:error];
120
+ if (nil == screnshotRequest) {
121
+ return nil;
190
122
  }
123
+ [proxy _XCT_requestScreenshot:screnshotRequest
124
+ withReply:^(id image, NSError *err) {
125
+ if (nil != err) {
126
+ innerError = err;
127
+ } else {
128
+ screenshotData = [image data];
129
+ }
130
+ dispatch_semaphore_signal(sem);
131
+ }];
191
132
  int64_t timeoutNs = (int64_t)(timeout * NSEC_PER_SEC);
192
133
  if (0 != dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, timeoutNs))) {
193
134
  NSString *timeoutMsg = [NSString stringWithFormat:@"Cannot take a screenshot within %@ timeout", formatTimeInterval(SCREENSHOT_TIMEOUT)];
@@ -205,26 +146,7 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
205
146
  return screenshotData;
206
147
  }
207
148
 
208
- + (BOOL)shouldUseScreenshotRequestApiForProxy:(NSObject *)proxy
209
- {
210
- static dispatch_once_t shouldUseSRApi;
211
- static BOOL result;
212
- dispatch_once(&shouldUseSRApi, ^{
213
- if ([proxy respondsToSelector:@selector(_XCT_requestScreenshot:withReply:)]) {
214
- #if TARGET_OS_SIMULATOR
215
- // Required to support simulators running iOS 14.4 and below with Xcode 12.5 and above due to unsupported API on the simulator side.
216
- result = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"14.5");
217
- #else
218
- result = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0");
219
- #endif
220
- } else {
221
- result = NO;
222
- }
223
- });
224
- return result;
225
- }
226
-
227
- + (nullable id)imageEncodingWithUniformTypeIdentifier:(NSString *)uti
149
+ + (nullable id)imageEncodingWithUniformTypeIdentifier:(UTType *)uti
228
150
  compressionQuality:(CGFloat)compressionQuality
229
151
  error:(NSError **)error
230
152
  {
@@ -235,6 +157,26 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
235
157
  buildError:error];
236
158
  return nil;
237
159
  }
160
+
161
+ if ([uti conformsToType:UTTypeHEIC]) {
162
+ static BOOL isHeicSuppported = NO;
163
+ static dispatch_once_t onceToken;
164
+ dispatch_once(&onceToken, ^{
165
+ SEL selector = NSSelectorFromString(@"supportsHEICImageEncoding");
166
+ NSMethodSignature *signature = [imageEncodingClass methodSignatureForSelector:selector];
167
+ if (nil != signature) {
168
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
169
+ [invocation setSelector:selector];
170
+ [invocation invokeWithTarget:imageEncodingClass];
171
+ [invocation getReturnValue:&isHeicSuppported];
172
+ }
173
+ });
174
+ if (!isHeicSuppported) {
175
+ [FBLogger logFmt:@"The device under test does not support HEIC image encoding. Falling back to PNG"];
176
+ uti = UTTypePNG;
177
+ }
178
+ }
179
+
238
180
  id imageEncodingAllocated = [imageEncodingClass alloc];
239
181
  SEL imageEncodingConstructorSelector = NSSelectorFromString(@"initWithUniformTypeIdentifier:compressionQuality:");
240
182
  if (![imageEncodingAllocated respondsToSelector:imageEncodingConstructorSelector]) {
@@ -246,7 +188,8 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
246
188
  NSMethodSignature *imageEncodingContructorSignature = [imageEncodingAllocated methodSignatureForSelector:imageEncodingConstructorSelector];
247
189
  NSInvocation *imageEncodingInitInvocation = [NSInvocation invocationWithMethodSignature:imageEncodingContructorSignature];
248
190
  [imageEncodingInitInvocation setSelector:imageEncodingConstructorSelector];
249
- [imageEncodingInitInvocation setArgument:&uti atIndex:2];
191
+ NSString *utiIdentifier = uti.identifier;
192
+ [imageEncodingInitInvocation setArgument:&utiIdentifier atIndex:2];
250
193
  [imageEncodingInitInvocation setArgument:&compressionQuality atIndex:3];
251
194
  [imageEncodingInitInvocation invokeWithTarget:imageEncodingAllocated];
252
195
  id __unsafe_unretained imageEncoding;
@@ -256,11 +199,10 @@ NSString *formatTimeInterval(NSTimeInterval interval) {
256
199
 
257
200
  + (nullable id)screenshotRequestWithScreenID:(long long)screenID
258
201
  rect:(struct CGRect)rect
259
- uti:(NSString *)uti
202
+ uti:(UTType *)uti
260
203
  compressionQuality:(CGFloat)compressionQuality
261
204
  error:(NSError **)error
262
205
  {
263
- // TODO: Use native accessors after we drop the support of Xcode 12.4 and below
264
206
  id imageEncoding = [self.class imageEncodingWithUniformTypeIdentifier:uti
265
207
  compressionQuality:compressionQuality
266
208
  error:error];
@@ -8,6 +8,9 @@
8
8
  */
9
9
 
10
10
  #import "FBUnattachedAppLauncher.h"
11
+
12
+ #import <MobileCoreServices/MobileCoreServices.h>
13
+
11
14
  #import "LSApplicationWorkspace.h"
12
15
 
13
16
  @implementation FBUnattachedAppLauncher
@@ -100,13 +100,12 @@ static void swizzledLaunchApp(id self, SEL _cmd, NSString *path, NSString *bundl
100
100
 
101
101
  + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSError *__autoreleasing*)error
102
102
  {
103
- __block BOOL didSucceed = NO;
103
+ __block NSError *innerError = nil;
104
104
  [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){
105
105
  void (^errorHandler)(NSError *) = ^(NSError *invokeError) {
106
- if (error) {
107
- *error = invokeError;
106
+ if (nil != invokeError) {
107
+ innerError = invokeError;
108
108
  }
109
- didSucceed = (invokeError == nil);
110
109
  completion();
111
110
  };
112
111
 
@@ -117,31 +116,40 @@ static void swizzledLaunchApp(id self, SEL _cmd, NSString *path, NSString *bundl
117
116
  handlerBlock(record, invokeError);
118
117
  }];
119
118
  }];
120
- return didSucceed;
119
+ if (nil != innerError) {
120
+ if (error) {
121
+ *error = innerError;
122
+ }
123
+ return NO;
124
+ }
125
+ return YES;
121
126
  }
122
127
 
123
128
  + (BOOL)openURL:(NSURL *)url usingApplication:(NSString *)bundleId error:(NSError *__autoreleasing*)error
124
129
  {
125
130
  XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession];
126
131
  if (![session respondsToSelector:@selector(openURL:usingApplication:completion:)]) {
127
- if (error) {
128
- [[[FBErrorBuilder builder]
129
- withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs with given application"]
130
- buildError:error];
131
- }
132
+ [[[FBErrorBuilder builder]
133
+ withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs with given application"]
134
+ buildError:error];
132
135
  return NO;
133
136
  }
134
137
 
138
+ __block NSError *innerError = nil;
135
139
  __block BOOL didSucceed = NO;
136
140
  [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){
137
141
  [session openURL:url usingApplication:bundleId completion:^(bool result, NSError *invokeError) {
138
- if (error) {
139
- *error = invokeError;
142
+ if (nil != invokeError) {
143
+ innerError = invokeError;
144
+ } else {
145
+ didSucceed = result;
140
146
  }
141
- didSucceed = invokeError == nil && result;
142
147
  completion();
143
148
  }];
144
149
  }];
150
+ if (nil != innerError && error) {
151
+ *error = innerError;
152
+ }
145
153
  return didSucceed;
146
154
  }
147
155
 
@@ -149,24 +157,27 @@ static void swizzledLaunchApp(id self, SEL _cmd, NSString *path, NSString *bundl
149
157
  {
150
158
  XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession];
151
159
  if (![session respondsToSelector:@selector(openDefaultApplicationForURL:completion:)]) {
152
- if (error) {
153
- [[[FBErrorBuilder builder]
154
- withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs. Consider upgrading to Xcode 14.3+/iOS 16.4+"]
155
- buildError:error];
156
- }
160
+ [[[FBErrorBuilder builder]
161
+ withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs. Consider upgrading to Xcode 14.3+/iOS 16.4+"]
162
+ buildError:error];
157
163
  return NO;
158
164
  }
159
165
 
166
+ __block NSError *innerError = nil;
160
167
  __block BOOL didSucceed = NO;
161
168
  [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){
162
169
  [session openDefaultApplicationForURL:url completion:^(bool result, NSError *invokeError) {
163
- if (error) {
164
- *error = invokeError;
170
+ if (nil != invokeError) {
171
+ innerError = invokeError;
172
+ } else {
173
+ didSucceed = result;
165
174
  }
166
- didSucceed = invokeError == nil && result;
167
175
  completion();
168
176
  }];
169
177
  }];
178
+ if (nil != innerError && error) {
179
+ *error = innerError;
180
+ }
170
181
  return didSucceed;
171
182
  }
172
183
 
@@ -175,32 +186,33 @@ static void swizzledLaunchApp(id self, SEL _cmd, NSString *path, NSString *bundl
175
186
  {
176
187
  XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession];
177
188
  if (![session respondsToSelector:@selector(setSimulatedLocation:completion:)]) {
178
- if (error) {
179
- [[[FBErrorBuilder builder]
180
- withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"]
181
- buildError:error];
182
- }
189
+ [[[FBErrorBuilder builder]
190
+ withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"]
191
+ buildError:error];
183
192
  return NO;
184
193
  }
185
194
  if (![session supportsLocationSimulation]) {
186
- if (error) {
187
- [[[FBErrorBuilder builder]
188
- withDescriptionFormat:@"Your device does not support location simulation"]
189
- buildError:error];
190
- }
195
+ [[[FBErrorBuilder builder]
196
+ withDescriptionFormat:@"Your device does not support location simulation"]
197
+ buildError:error];
191
198
  return NO;
192
199
  }
193
200
 
201
+ __block NSError *innerError = nil;
194
202
  __block BOOL didSucceed = NO;
195
203
  [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){
196
204
  [session setSimulatedLocation:location completion:^(bool result, NSError *invokeError) {
197
- if (error) {
198
- *error = invokeError;
205
+ if (nil != invokeError) {
206
+ innerError = invokeError;
207
+ } else {
208
+ didSucceed = result;
199
209
  }
200
- didSucceed = invokeError == nil && result;
201
210
  completion();
202
211
  }];
203
212
  }];
213
+ if (nil != innerError && error) {
214
+ *error = innerError;
215
+ }
204
216
  return didSucceed;
205
217
  }
206
218
 
@@ -208,34 +220,33 @@ static void swizzledLaunchApp(id self, SEL _cmd, NSString *path, NSString *bundl
208
220
  {
209
221
  XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession];
210
222
  if (![session respondsToSelector:@selector(getSimulatedLocationWithReply:)]) {
211
- if (error) {
212
- [[[FBErrorBuilder builder]
213
- withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"]
214
- buildError:error];
215
- }
223
+ [[[FBErrorBuilder builder]
224
+ withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"]
225
+ buildError:error];
216
226
  return nil;
217
227
  }
218
228
  if (![session supportsLocationSimulation]) {
219
- if (error) {
220
- [[[FBErrorBuilder builder]
221
- withDescriptionFormat:@"Your device does not support location simulation"]
222
- buildError:error];
223
- }
229
+ [[[FBErrorBuilder builder]
230
+ withDescriptionFormat:@"Your device does not support location simulation"]
231
+ buildError:error];
224
232
  return nil;
225
233
  }
226
234
 
235
+ __block NSError *innerError = nil;
227
236
  __block CLLocation *location = nil;
228
237
  [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){
229
238
  [session getSimulatedLocationWithReply:^(CLLocation *reply, NSError *invokeError) {
230
- if (error) {
231
- *error = invokeError;
232
- }
233
- if (nil == invokeError) {
239
+ if (nil != invokeError) {
240
+ innerError = invokeError;
241
+ } else {
234
242
  location = reply;
235
243
  }
236
244
  completion();
237
245
  }];
238
246
  }];
247
+ if (nil != innerError && error) {
248
+ *error = innerError;
249
+ }
239
250
  return location;
240
251
  }
241
252
 
@@ -259,16 +270,21 @@ static void swizzledLaunchApp(id self, SEL _cmd, NSString *path, NSString *bundl
259
270
  return NO;
260
271
  }
261
272
 
273
+ __block NSError *innerError = nil;
262
274
  __block BOOL didSucceed = NO;
263
275
  [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){
264
276
  [session clearSimulatedLocationWithReply:^(bool result, NSError *invokeError) {
265
- if (error) {
266
- *error = invokeError;
277
+ if (nil != invokeError) {
278
+ innerError = invokeError;
279
+ } else {
280
+ didSucceed = result;
267
281
  }
268
- didSucceed = invokeError == nil && result;
269
282
  completion();
270
283
  }];
271
284
  }];
285
+ if (nil != innerError && error) {
286
+ *error = innerError;
287
+ }
272
288
  return didSucceed;
273
289
  }
274
290
  #endif
@@ -26,6 +26,11 @@
26
26
  [FBConfiguration disableRemoteQueryEvaluation];
27
27
  [FBConfiguration configureDefaultKeyboardPreferences];
28
28
  [FBConfiguration disableApplicationUIInterruptionsHandling];
29
+ if (NSProcessInfo.processInfo.environment[@"ENABLE_AUTOMATIC_SCREEN_RECORDINGS"]) {
30
+ [FBConfiguration enableScreenRecordings];
31
+ } else {
32
+ [FBConfiguration disableScreenRecordings];
33
+ }
29
34
  if (NSProcessInfo.processInfo.environment[@"ENABLE_AUTOMATIC_SCREENSHOTS"]) {
30
35
  [FBConfiguration enableScreenshots];
31
36
  } else {
@@ -8,7 +8,6 @@
8
8
  */
9
9
 
10
10
  #import <XCTest/XCTest.h>
11
- #import <MobileCoreServices/MobileCoreServices.h>
12
11
 
13
12
  #import "FBImageIOScaler.h"
14
13
  #import "FBIntegrationTestCase.h"
@@ -55,7 +54,6 @@
55
54
  id expScaled = [self expectationWithDescription:@"Receive scaled image"];
56
55
 
57
56
  [scaler submitImage:self.originalImage
58
- uti:(__bridge id)kUTTypeJPEG
59
57
  scalingFactor:scalingFactor
60
58
  compressionQuality:1.0
61
59
  completionHandler:^(NSData *scaled) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "5.3.1",
3
+ "version": "5.4.0",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {
@@ -68,7 +68,7 @@
68
68
  "appium-xcode": "^5.0.0",
69
69
  "chai": "^4.2.0",
70
70
  "chai-as-promised": "^7.1.1",
71
- "conventional-changelog-conventionalcommits": "^5.0.0",
71
+ "conventional-changelog-conventionalcommits": "^6.0.0",
72
72
  "eslint": "^7.32.0",
73
73
  "eslint-config-prettier": "^8.5.0",
74
74
  "glob": "^8.0.1",