1// Copyright 2015-present 650 Industries. All rights reserved.
2
3#import "EXVersionedNetworkInterceptor.h"
4
5#import <React/RCTHTTPRequestHandler.h>
6#import <React/RCTInspector.h>
7#import <React/RCTInspectorPackagerConnection.h>
8#import <SocketRocket/SRWebSocket.h>
9
10#import "ExpoModulesCore-Swift.h"
11
12#pragma mark - RCTInspectorPackagerConnection category interface
13
14@interface RCTInspectorPackagerConnection(sendWrappedEventToAllPages)
15
16- (BOOL)isReadyToSend;
17- (void)sendWrappedEventToAllPages:(NSString *)event;
18
19@end
20
21#pragma mark -
22
23@interface EXVersionedNetworkInterceptor () <EXRequestCdpInterceptorDelegate>
24
25@property (nonatomic, strong) RCTInspectorPackagerConnection *inspectorPackgerConnection;
26
27@end
28
29@implementation EXVersionedNetworkInterceptor
30
31- (instancetype)initWithRCTInspectorPackagerConnection:(RCTInspectorPackagerConnection *)inspectorPackgerConnection
32{
33  if (self = [super init]) {
34    self.inspectorPackgerConnection = inspectorPackgerConnection;
35    [EXRequestCdpInterceptor.shared setDelegate:self];
36
37    Class requestInterceptorClass = [EXRequestInterceptorProtocol class];
38    RCTSetCustomNSURLSessionConfigurationProvider(^{
39      NSURLSessionConfiguration *urlSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
40      NSMutableArray<Class> *protocolClasses = [urlSessionConfiguration.protocolClasses mutableCopy];
41      if (![protocolClasses containsObject:requestInterceptorClass]) {
42        [protocolClasses insertObject:requestInterceptorClass atIndex:0];
43      }
44      urlSessionConfiguration.protocolClasses = protocolClasses;
45
46      [urlSessionConfiguration setHTTPShouldSetCookies:YES];
47      [urlSessionConfiguration setHTTPCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
48      [urlSessionConfiguration setHTTPCookieStorage:[NSHTTPCookieStorage sharedHTTPCookieStorage]];
49      return urlSessionConfiguration;
50    });
51  }
52  return self;
53}
54
55- (void)dealloc
56{
57  [EXRequestCdpInterceptor.shared setDelegate:nil];
58}
59
60#pragma mark - EXRequestCdpInterceptorDelegate implementations
61
62- (void)dispatch:(NSString * _Nonnull)event {
63  [self.inspectorPackgerConnection sendWrappedEventToAllPages:event];
64}
65
66@end
67
68#pragma mark - RCTInspectorPackagerConnection category
69
70@interface RCTInspectorPackagerConnection(sendWrappedEventToAllPages)
71
72- (BOOL)isReadyToSend;
73- (void)sendWrappedEventToAllPages:(NSString *)event;
74
75@end
76
77#pragma mark - RCTInspectorPackagerConnection category implementation
78
79@implementation RCTInspectorPackagerConnection(sendWrappedEventToAllPages)
80
81- (BOOL)isReadyToSend
82{
83  if ([self isConnected]) {
84    return YES;
85  }
86
87  SRWebSocket *websocket = [self valueForKey:@"_webSocket"];
88  return websocket.readyState == SR_OPEN;
89}
90
91- (void)sendWrappedEventToAllPages:(NSString *)event
92{
93  if (![self isReadyToSend]) {
94    return;
95  }
96
97  SEL selector = NSSelectorFromString(@"sendWrappedEvent:message:");
98  if ([self respondsToSelector:selector]) {
99    IMP sendWrappedEventIMP = [self methodForSelector:selector];
100    void (*functor)(id, SEL, NSString *, NSString *) = (void *)sendWrappedEventIMP;
101    for (RCTInspectorPage* page in RCTInspector.pages) {
102      if (![page.title containsString:@"Reanimated"]) {
103        functor(self, selector, [@(page.id) stringValue], event);
104      }
105    }
106  }
107}
108
109@end
110