appium-webdriveragent 16.5.1 → 16.7.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/WebDriverAgent.xcodeproj/project.pbxproj +48 -300
  3. package/WebDriverAgentLib/Info.plist +2 -2
  4. package/WebDriverAgentLib/Routing/{WatchOS/FBWatchHTTPServer.h → FBHTTPServer.h} +11 -7
  5. package/WebDriverAgentLib/Routing/{WatchOS/FBWatchHTTPServer.m → FBHTTPServer.m} +26 -13
  6. package/WebDriverAgentLib/Routing/FBTCPSocket.h +17 -45
  7. package/WebDriverAgentLib/Routing/FBTCPSocket.m +16 -95
  8. package/WebDriverAgentLib/Routing/FBWebServer.h +1 -1
  9. package/WebDriverAgentLib/Routing/FBWebServer.m +5 -55
  10. package/WebDriverAgentLib/Routing/{WatchOS/RouteRequest.h → RouteRequest.h} +2 -4
  11. package/WebDriverAgentLib/Routing/{WatchOS/RouteResponse.h → RouteResponse.h} +2 -2
  12. package/WebDriverAgentLib/Utilities/FBMjpegServer.h +7 -0
  13. package/WebDriverAgentLib/Utilities/FBMjpegServer.m +15 -16
  14. package/WebDriverAgentTests/IntegrationTests_watchOS/IntegrationTests_watchOS-Bridging-Header.h +2 -0
  15. package/WebDriverAgentTests/IntegrationTests_watchOS/WDAMjpegStreamingIntegrationTests.swift +81 -0
  16. package/package.json +1 -1
  17. package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +0 -1220
  18. package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +0 -8786
  19. package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.h +0 -1036
  20. package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.m +0 -5868
  21. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.h +0 -12
  22. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.m +0 -88
  23. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.h +0 -56
  24. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.m +0 -100
  25. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.h +0 -109
  26. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.m +0 -2281
  27. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPLogging.h +0 -122
  28. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.h +0 -53
  29. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.m +0 -357
  30. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPResponse.h +0 -149
  31. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.h +0 -126
  32. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.m +0 -372
  33. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/LICENSE +0 -18
  34. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.h +0 -13
  35. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.m +0 -83
  36. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.h +0 -9
  37. package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.m +0 -38
  38. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.h +0 -13
  39. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.m +0 -84
  40. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/LICENSE +0 -19
  41. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.h +0 -18
  42. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.m +0 -11
  43. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.h +0 -16
  44. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.m +0 -50
  45. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.h +0 -20
  46. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.m +0 -66
  47. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.h +0 -5
  48. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.m +0 -142
  49. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.h +0 -55
  50. package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.m +0 -303
  51. /package/WebDriverAgentLib/Routing/{WatchOS/RouteRequest.m → RouteRequest.m} +0 -0
  52. /package/WebDriverAgentLib/Routing/{WatchOS/RouteResponse.m → RouteResponse.m} +0 -0
@@ -11,7 +11,8 @@
11
11
  #import <mach/mach_time.h>
12
12
  @import UniformTypeIdentifiers;
13
13
 
14
- #import "GCDAsyncSocket.h"
14
+ // Textual import, not `@import Network;` - see the comment in FBTCPSocket.h.
15
+ #import <Network/Network.h>
15
16
  #import "FBConfiguration.h"
16
17
  #import "FBLogger.h"
17
18
  #import "FBScreenshot.h"
@@ -36,7 +37,7 @@ static NSUInteger FBNormalizedMjpegFramerate(NSUInteger framerate)
36
37
  @interface FBMjpegServer()
37
38
 
38
39
  @property (nonatomic, readonly) dispatch_queue_t backgroundQueue;
39
- @property (nonatomic, readonly) NSMutableArray<GCDAsyncSocket *> *listeningClients;
40
+ @property (nonatomic, readonly) NSMutableArray<nw_connection_t> *listeningClients;
40
41
  @property (nonatomic, readonly) FBImageProcessor *imageProcessor;
41
42
  @property (nonatomic, readonly) long long mainScreenID;
42
43
  @property (nonatomic, assign) NSUInteger consecutiveScreenshotFailures;
@@ -148,9 +149,8 @@ static NSUInteger FBNormalizedMjpegFramerate(NSUInteger framerate)
148
149
  return;
149
150
  }
150
151
  NSUInteger clientCount = self.listeningClients.count;
151
- for (GCDAsyncSocket *client in self.listeningClients) {
152
- // Slow clients should fail/close instead of buffering indefinitely.
153
- [client writeData:chunk withTimeout:FRAME_TIMEOUT tag:0];
152
+ for (nw_connection_t client in self.listeningClients) {
153
+ [self.socket writeData:chunk toClient:client];
154
154
  }
155
155
  self.sentFramesCount++;
156
156
  self.sentBytesCount += chunk.length * clientCount;
@@ -164,14 +164,13 @@ static NSUInteger FBNormalizedMjpegFramerate(NSUInteger framerate)
164
164
  }
165
165
  }
166
166
 
167
- - (void)didClientConnect:(GCDAsyncSocket *)newClient
167
+ - (void)didClientConnect:(nw_connection_t)newClient
168
168
  {
169
- [FBLogger logFmt:@"Got screenshots broadcast client connection at %@:%d", newClient.connectedHost, newClient.connectedPort];
170
- // Start broadcast only after there is any data from the client
171
- [newClient readDataWithTimeout:-1 tag:0];
169
+ [FBLogger log:@"Got screenshots broadcast client connection"];
170
+ // FBTCPSocket already schedules the receive that -client:didReceiveData: relies on below.
172
171
  }
173
172
 
174
- - (void)didClientSendData:(GCDAsyncSocket *)client
173
+ - (void)client:(nw_connection_t)client didReceiveData:(NSData *)data
175
174
  {
176
175
  @synchronized (self.listeningClients) {
177
176
  if ([self.listeningClients containsObject:client]) {
@@ -179,15 +178,15 @@ static NSUInteger FBNormalizedMjpegFramerate(NSUInteger framerate)
179
178
  }
180
179
  }
181
180
 
182
- [FBLogger logFmt:@"Starting screenshots broadcast for the client at %@:%d", client.connectedHost, client.connectedPort];
181
+ [FBLogger log:@"Starting screenshots broadcast for the client"];
183
182
  NSString *streamHeader = [NSString stringWithFormat:@"HTTP/1.0 200 OK\r\nServer: %@\r\nConnection: close\r\nMax-Age: 0\r\nExpires: 0\r\nCache-Control: no-cache, private\r\nPragma: no-cache\r\nContent-Type: multipart/x-mixed-replace; boundary=--BoundaryString\r\n\r\n", SERVER_NAME];
184
- [client writeData:(id)[streamHeader dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
183
+ [self.socket writeData:(id)[streamHeader dataUsingEncoding:NSUTF8StringEncoding] toClient:client];
185
184
  @synchronized (self.listeningClients) {
186
185
  [self.listeningClients addObject:client];
187
186
  }
188
187
  }
189
188
 
190
- - (void)didClientDisconnect:(GCDAsyncSocket *)client
189
+ - (void)didClientDisconnect:(nw_connection_t)client
191
190
  {
192
191
  @synchronized (self.listeningClients) {
193
192
  [self.listeningClients removeObject:client];
@@ -199,10 +198,10 @@ static NSUInteger FBNormalizedMjpegFramerate(NSUInteger framerate)
199
198
  {
200
199
  self.isStreaming = NO;
201
200
  @synchronized (self.listeningClients) {
202
- NSArray<GCDAsyncSocket *> *clients = self.listeningClients.copy;
201
+ NSArray<nw_connection_t> *clients = self.listeningClients.copy;
203
202
  [self.listeningClients removeAllObjects];
204
- for (GCDAsyncSocket *client in clients) {
205
- [client disconnect];
203
+ for (nw_connection_t client in clients) {
204
+ nw_connection_cancel(client);
206
205
  }
207
206
  }
208
207
  }
@@ -19,3 +19,5 @@
19
19
  #import "XCUIDevice+FBHelpers.h"
20
20
  #import "FBAlert.h"
21
21
  #import "FBElement.h"
22
+ #import "FBMjpegServer.h"
23
+ #import "FBTCPSocket.h"
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ import Network
10
+ import XCTest
11
+
12
+ /// Exercises FBMjpegServer+FBTCPSocket the same way FBWebServer wires them together in
13
+ /// -initScreenshotsBroadcaster, but standalone (no full FBWebServer/HTTP command server needed).
14
+ /// A client NWConnection reads the raw wire bytes back to confirm the multipart/x-mixed-replace
15
+ /// stream and its JPEG frames actually arrive, since watchOS has no BSD sockets/GCDAsyncSocket -
16
+ /// the production implementation is Network.framework-backed and worth covering for real.
17
+ final class WDAMjpegStreamingIntegrationTests: WDAWatchInProcessTestCase {
18
+ override class var relaunchForEachTest: Bool { false }
19
+
20
+ private static let jpegMagicBytes: [UInt8] = [0xFF, 0xD8, 0xFF]
21
+
22
+ func testMjpegStreamingProducesJpegFrames() throws {
23
+ // Port 0 asks the system to assign an ephemeral port; -[FBTCPSocket port] then reflects the
24
+ // actual bound port once -start returns, per nw_listener_get_port's documented behavior.
25
+ let socket = FBTCPSocket(port: 0)
26
+ let server = FBMjpegServer()
27
+ server.socket = socket
28
+ socket.delegate = server
29
+ defer {
30
+ server.stopStreaming()
31
+ socket.stop()
32
+ }
33
+ try socket.start()
34
+ let boundPort = socket.port
35
+ XCTAssertNotEqual(boundPort, 0, "FBTCPSocket did not report its bound ephemeral port")
36
+
37
+ let connection = NWConnection(host: "127.0.0.1", port: NWEndpoint.Port(rawValue: boundPort)!, using: .tcp)
38
+ defer { connection.cancel() }
39
+
40
+ let connected = expectation(description: "client connected to the mjpeg broadcaster")
41
+ connection.stateUpdateHandler = { state in
42
+ if case .ready = state {
43
+ connected.fulfill()
44
+ }
45
+ }
46
+ connection.start(queue: .main)
47
+ wait(for: [connected], timeout: 15)
48
+
49
+ // FBMjpegServer only starts broadcasting once it has seen any data from the client - mimic the
50
+ // request line a real HTTP client would send.
51
+ let sent = expectation(description: "sent the request line")
52
+ connection.send(content: Data("GET / HTTP/1.0\r\n\r\n".utf8), completion: .contentProcessed { _ in
53
+ sent.fulfill()
54
+ })
55
+ wait(for: [sent], timeout: 15)
56
+
57
+ var received = Data()
58
+ let jpegMagicData = Data(Self.jpegMagicBytes)
59
+ let sawJpegFrame = expectation(description: "received at least one jpeg frame")
60
+ func receiveMore() {
61
+ connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, _, _, error in
62
+ if let data = data {
63
+ received.append(data)
64
+ if received.range(of: jpegMagicData) != nil {
65
+ sawJpegFrame.fulfill()
66
+ return
67
+ }
68
+ }
69
+ if error == nil {
70
+ receiveMore()
71
+ }
72
+ }
73
+ }
74
+ receiveMore()
75
+ wait(for: [sawJpegFrame], timeout: 15)
76
+
77
+ XCTAssertNotNil(received.range(of: Data("multipart/x-mixed-replace".utf8)), "Response is not a multipart stream")
78
+ XCTAssertNotNil(received.range(of: Data("Content-type: image/jpeg".utf8)), "No JPEG part header found")
79
+ XCTAssertNotNil(received.range(of: jpegMagicData), "No JPEG frame data found")
80
+ }
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "16.5.1",
3
+ "version": "16.7.0",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "keywords": [
6
6
  "Appium",