2626#import " FirebaseDatabase/Sources/Realtime/FWebSocketConnection.h"
2727#import " FirebaseDatabase/Sources/Utilities/FStringUtilities.h"
2828
29- #if TARGET_OS_IOS || TARGET_OS_TV || \
30- (defined (TARGET_OS_VISION) && TARGET_OS_VISION)
29+ #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
3130#import < UIKit/UIKit.h>
32- #endif // TARGET_OS_IOS || TARGET_OS_TV || (defined(TARGET_OS_VISION) &&
33- // TARGET_OS_VISION)
3431
35- #if TARGET_OS_WATCH
36- #import < Network/Network.h>
32+ #elif TARGET_OS_WATCH
3733#import < WatchKit/WatchKit.h>
38- #endif // TARGET_OS_WATCH
34+
35+ #elif TARGET_OS_OSX
36+ #import < AppKit/NSApplication.h>
37+ #endif
38+
39+ #import < Network/Network.h>
3940
4041static NSString *const kAppCheckTokenHeader = @" X-Firebase-AppCheck" ;
4142static NSString *const kUserAgentHeader = @" User-Agent" ;
@@ -52,9 +53,10 @@ - (void)shutdown;
5253- (void )onClosed ;
5354- (void )closeIfNeverConnected ;
5455
55- #if TARGET_OS_WATCH
56- @property (nonatomic , strong ) NSURLSessionWebSocketTask *webSocketTask;
57- #else
56+ @property (nonatomic , strong )
57+ NSURLSessionWebSocketTask *webSocketTask API_AVAILABLE (
58+ macos (10.15 ), ios(13.0 ), watchos(6.0 ), tvos(13.0 ));
59+ #if !TARGET_OS_WATCH
5860@property(nonatomic, strong) FSRWebSocket *webSocket;
5961#endif // TARGET_OS_WATCH
6062@property(nonatomic, strong) NSNumber *connectionId;
@@ -100,40 +102,56 @@ - (instancetype)initWith:(FRepoInfo *)repoInfo
100102 userAgent: userAgent
101103 googleAppID: googleAppID
102104 appCheckToken: appCheckToken];
103- #if TARGET_OS_WATCH
104- // Regular NSURLSession websocket.
105- NSOperationQueue *opQueue = [[NSOperationQueue alloc ] init ];
106- opQueue.underlyingQueue = queue;
107- NSURLSession *session = [NSURLSession
108- sessionWithConfiguration: [NSURLSessionConfiguration
109- defaultSessionConfiguration ]
110- delegate: self
111- delegateQueue: opQueue];
112- NSURLSessionWebSocketTask *task =
113- [session webSocketTaskWithRequest: req];
114- self.webSocketTask = task;
115-
116- if (@available (watchOS 7.0 , *)) {
117- [[NSNotificationCenter defaultCenter ]
118- addObserverForName: WKApplicationWillResignActiveNotification
119- object: nil
120- queue: opQueue
121- usingBlock: ^(NSNotification *_Nonnull note) {
122- FFLog (@" I-RDB083015" ,
123- @" Received watchOS background notification, "
124- @" closing web socket." );
125- [self onClosed ];
126- }];
105+
106+ if (@available (iOS 13.0 , macOS 10.15 , macCatalyst 13.1 , tvOS 13.0 ,
107+ watchOS 6.0 , *)) {
108+ // Regular NSURLSession websocket.
109+ NSOperationQueue *opQueue = [[NSOperationQueue alloc ] init ];
110+ opQueue.underlyingQueue = queue;
111+ NSURLSession *session = [NSURLSession
112+ sessionWithConfiguration: [NSURLSessionConfiguration
113+ defaultSessionConfiguration ]
114+ delegate: self
115+ delegateQueue: opQueue];
116+ NSURLSessionWebSocketTask *task =
117+ [session webSocketTaskWithRequest: req];
118+ self.webSocketTask = task;
119+
120+ #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION || TARGET_OS_MACCATALYST
121+ NSString *resignName = UIApplicationWillResignActiveNotification;
122+ #elif TARGET_OS_OSX
123+ NSString *resignName = NSApplicationWillResignActiveNotification ;
124+ #elif TARGET_OS_WATCH
125+ NSString *resignName = WKApplicationWillResignActiveNotification;
126+ #elif
127+ #error ("missing platform")
128+ #endif
129+ if (@available (watchOS 7.0 , *)) {
130+ [[NSNotificationCenter defaultCenter ]
131+ addObserverForName: resignName
132+ object: nil
133+ queue: opQueue
134+ usingBlock: ^(NSNotification *_Nonnull note) {
135+ FFLog (@" I-RDB083015" ,
136+ @" Received notification that application "
137+ @" will resign, "
138+ @" closing web socket." );
139+ [self onClosed ];
140+ }];
141+ }
142+ }
143+ #if !TARGET_OS_WATCH
144+ else {
145+ // TODO(mmaksym): Remove googleAppID and userAgent from FSRWebSocket
146+ // as they are passed via NSURLRequest.
147+ self.webSocket =
148+ [[FSRWebSocket alloc ] initWithURLRequest: req
149+ queue: queue
150+ googleAppID: googleAppID
151+ andUserAgent: userAgent];
152+ [self .webSocket setDelegateDispatchQueue: queue];
153+ self.webSocket .delegate = self;
127154 }
128- #else
129- // TODO(mmaksym): Remove googleAppID and userAgent from FSRWebSocket as
130- // they are passed via NSURLRequest.
131- self.webSocket = [[FSRWebSocket alloc ] initWithURLRequest: req
132- queue: queue
133- googleAppID: googleAppID
134- andUserAgent: userAgent];
135- [self .webSocket setDelegateDispatchQueue: queue];
136- self.webSocket .delegate = self;
137155#endif // TARGET_OS_WATCH
138156 }
139157 return self;
@@ -195,13 +213,17 @@ - (void)open {
195213 assert (delegate);
196214 everConnected = NO ;
197215 // TODO Assert url
198- #if TARGET_OS_WATCH
199- [self .webSocketTask resume ];
200- // We need to request data from the web socket in order for it to start
201- // sending data.
202- [self receiveWebSocketData ];
203- #else
204- [self .webSocket open ];
216+ if (@available (iOS 13.0 , macOS 10.15 , macCatalyst 13.1 , tvOS 13.0 ,
217+ watchOS 6.0 , *)) {
218+ [self .webSocketTask resume ];
219+ // We need to request data from the web socket in order for it to start
220+ // sending data.
221+ [self receiveWebSocketData ];
222+ }
223+ #if !TARGET_OS_WATCH
224+ else {
225+ [self .webSocket open ];
226+ }
205227#endif // TARGET_OS_WATCH
206228 dispatch_time_t when = dispatch_time (
207229 DISPATCH_TIME_NOW, kWebsocketConnectTimeout * NSEC_PER_SEC);
@@ -214,12 +236,16 @@ - (void)close {
214236 FFLog (@" I-RDB083003" , @" (wsc:%@ ) FWebSocketConnection is being closed." ,
215237 self.connectionId );
216238 isClosed = YES ;
217- #if TARGET_OS_WATCH
218- [self .webSocketTask
219- cancelWithCloseCode: NSURLSessionWebSocketCloseCodeNormalClosure
220- reason: nil ];
221- #else
222- [self .webSocket close ];
239+ if (@available (iOS 13.0 , macOS 10.15 , macCatalyst 13.1 , tvOS 13.0 ,
240+ watchOS 6.0 , *)) {
241+ [self .webSocketTask
242+ cancelWithCloseCode: NSURLSessionWebSocketCloseCodeNormalClosure
243+ reason: nil ];
244+ }
245+ #if !TARGET_OS_WATCH
246+ else {
247+ [self .webSocket close ];
248+ }
223249#endif // TARGET_OS_WATCH
224250}
225251
@@ -322,25 +348,27 @@ - (void)handleIncomingFrame:(NSString *)message {
322348}
323349
324350#pragma mark -
325- #pragma mark URLSessionWebSocketDelegate watchOS implementation
326- #if TARGET_OS_WATCH
351+ #pragma mark URLSessionWebSocketDelegate implementation
327352
328353- (void )URLSession : (NSURLSession *)session
329354 webSocketTask : (NSURLSessionWebSocketTask *)webSocketTask
330- didOpenWithProtocol : (NSString *)protocol {
355+ didOpenWithProtocol : (NSString *)protocol
356+ API_AVAILABLE(macos(10.15 ), ios(13.0 ), watchos(6.0 ), tvos(13.0 )) {
331357 [self webSocketDidOpen ];
332358}
333359
334360- (void )URLSession : (NSURLSession *)session
335361 webSocketTask : (NSURLSessionWebSocketTask *)webSocketTask
336362 didCloseWithCode : (NSURLSessionWebSocketCloseCode )closeCode
337- reason : (NSData *)reason {
363+ reason : (NSData *)reason
364+ API_AVAILABLE(macos(10.15 ), ios(13.0 ), watchos(6.0 ), tvos(13.0 )) {
338365 FFLog (@" I-RDB083011" , @" (wsc:%@ ) didCloseWithCode: %ld %@ " ,
339366 self.connectionId , (long )closeCode, reason);
340367 [self onClosed ];
341368}
342369
343- - (void )receiveWebSocketData {
370+ - (void )receiveWebSocketData API_AVAILABLE(macos(10.15 ), ios(13.0 ),
371+ watchos (6.0 ), tvos(13.0 )) {
344372 __weak __auto_type weakSelf = self;
345373 [self .webSocketTask receiveMessageWithCompletionHandler: ^(
346374 NSURLSessionWebSocketMessage *_Nullable message,
@@ -364,7 +392,7 @@ - (void)receiveWebSocketData {
364392 }];
365393}
366394
367- #else
395+ #if !TARGET_OS_WATCH
368396
369397#pragma mark SRWebSocketDelegate implementation
370398
@@ -387,7 +415,7 @@ - (void)webSocket:(FSRWebSocket *)webSocket
387415 [self onClosed ];
388416}
389417
390- #endif // TARGET_OS_WATCH
418+ #endif // ! TARGET_OS_WATCH
391419
392420// Common to both SRWebSocketDelegate and URLSessionWebSocketDelegate.
393421
@@ -413,21 +441,26 @@ - (void)webSocketDidOpen {
413441
414442/* * Sends a string through the open web socket. */
415443- (void )sendStringToWebSocket : (NSString *)string {
416- #if TARGET_OS_WATCH
417- // Use built-in URLSessionWebSocket functionality.
418- [self .webSocketTask sendMessage: [[NSURLSessionWebSocketMessage alloc ]
419- initWithString: string]
420- completionHandler: ^(NSError *_Nullable error) {
421- if (error) {
422- FFWarn (@" I-RDB083016" ,
423- @" Error sending web socket data: %@ ." , error);
424- return ;
425- }
426- }];
427- #else
428- // Use existing SocketRocket implementation.
429- [self .webSocket send: string];
430- #endif // TARGET_OS_WATCH
444+ if (@available (iOS 13.0 , macOS 10.15 , macCatalyst 13.1 , tvOS 13.0 ,
445+ watchOS 6.0 , *)) {
446+ // Use built-in URLSessionWebSocket functionality.
447+ [self .webSocketTask
448+ sendMessage: [[NSURLSessionWebSocketMessage alloc ]
449+ initWithString: string]
450+ completionHandler: ^(NSError *_Nullable error) {
451+ if (error) {
452+ FFWarn (@" I-RDB083016" , @" Error sending web socket data: %@ ." ,
453+ error);
454+ return ;
455+ }
456+ }];
457+ }
458+ #if !TARGET_OS_WATCH
459+ else {
460+ // Use existing SocketRocket implementation.
461+ [self .webSocket send: string];
462+ }
463+ #endif // !TARGET_OS_WATCH
431464}
432465
433466/* *
@@ -446,12 +479,17 @@ - (void)closeIfNeverConnected {
446479 if (!everConnected) {
447480 FFLog (@" I-RDB083012" , @" (wsc:%@ ) Websocket timed out on connect" ,
448481 self.connectionId );
449- #if TARGET_OS_WATCH
450- [self .webSocketTask
451- cancelWithCloseCode: NSURLSessionWebSocketCloseCodeNoStatusReceived
452- reason: nil ];
453- #else
454- [self .webSocket close ];
482+ if (@available (iOS 13.0 , macOS 10.15 , macCatalyst 13.1 , tvOS 13.0 ,
483+ watchOS 6.0 , *)) {
484+ [self .webSocketTask
485+ cancelWithCloseCode:
486+ NSURLSessionWebSocketCloseCodeNoStatusReceived
487+ reason: nil ];
488+ }
489+ #if !TARGET_OS_WATCH
490+ else {
491+ [self .webSocket close ];
492+ }
455493#endif // TARGET_OS_WATCH
456494 }
457495}
@@ -468,9 +506,11 @@ - (void)onClosed {
468506 FFLog (@" I-RDB083013" , @" Websocket is closing itself" );
469507 [self shutdown ];
470508 }
471- #if TARGET_OS_WATCH
472- self.webSocketTask = nil ;
473- #else
509+ if (@available (iOS 13.0 , macOS 10.15 , macCatalyst 13.1 , tvOS 13.0 ,
510+ watchOS 6.0 , *)) {
511+ self.webSocketTask = nil ;
512+ }
513+ #if !TARGET_OS_WATCH
474514 self.webSocket = nil ;
475515#endif // TARGET_OS_WATCH
476516 if (keepAlive.isValid ) {
0 commit comments