forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRCTInspectorDevServerHelper.mm
More file actions
133 lines (109 loc) · 5.04 KB
/
RCTInspectorDevServerHelper.mm
File metadata and controls
133 lines (109 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
#import "RCTInspectorDevServerHelper.h"
#if RCT_DEV
#import <UIKit/UIKit.h>
#import <React/RCTLog.h>
#import "RCTDefines.h"
#import "RCTInspectorPackagerConnection.h"
static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
static NSString *getServerHost(NSURL *bundleURL, NSNumber *port)
{
NSString *host = [bundleURL host];
if (!host) {
host = @"localhost";
}
// this is consistent with the Android implementation, where http:// is the
// hardcoded implicit scheme for the debug server. Note, packagerURL
// technically looks like it could handle schemes/protocols other than HTTP,
// so rather than force HTTP, leave it be for now, in case someone is relying
// on that ability when developing against iOS.
return [NSString stringWithFormat:@"%@:%@", host, port];
}
static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
{
NSNumber *inspectorProxyPort = @8082;
NSString *escapedDeviceName = [[[UIDevice currentDevice] name] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@",
getServerHost(bundleURL, inspectorProxyPort),
escapedDeviceName,
escapedAppName]];
}
static NSURL *getAttachDeviceUrl(NSURL *bundleURL, NSString *title)
{
NSNumber *metroBundlerPort = @8081;
NSString *escapedDeviceName = [[[UIDevice currentDevice] name] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLHostAllowedCharacterSet];
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLHostAllowedCharacterSet];
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/attach-debugger-nuclide?title=%@&device=%@&app=%@",
getServerHost(bundleURL, metroBundlerPort),
title,
escapedDeviceName,
escapedAppName]];
}
@implementation RCTInspectorDevServerHelper
RCT_NOT_IMPLEMENTED(- (instancetype)init)
static NSMutableDictionary<NSString *, RCTInspectorPackagerConnection *> *socketConnections = nil;
static void sendEventToAllConnections(NSString *event)
{
for (NSString *socketId in socketConnections) {
[socketConnections[socketId] sendEventToAllConnections:event];
}
}
static void displayErrorAlert(UIViewController *view, NSString *message) {
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:nil
message:message
preferredStyle:UIAlertControllerStyleAlert];
[view presentViewController:alert animated:YES completion:nil];
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 2.5),
dispatch_get_main_queue(),
^{
[alert dismissViewControllerAnimated:YES completion:nil];
});
}
+ (void)attachDebugger:(NSString *)owner
withBundleURL:(NSURL *)bundleURL
withView:(UIViewController *)view
{
NSURL *url = getAttachDeviceUrl(bundleURL, owner);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"GET"];
__weak UIViewController *viewCapture = view;
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:
^(NSData *_Nullable data,
NSURLResponse *_Nullable response,
NSError *_Nullable error) {
UIViewController *viewCaptureStrong = viewCapture;
if (error != nullptr && viewCaptureStrong != nullptr) {
displayErrorAlert(viewCaptureStrong, @"The request to attach Nuclide couldn't reach Metro Bundler!");
}
}] resume];
}
+ (void)disableDebugger
{
sendEventToAllConnections(kDebuggerMsgDisable);
}
+ (RCTInspectorPackagerConnection *)connectWithBundleURL:(NSURL *)bundleURL
{
NSURL *inspectorURL = getInspectorDeviceUrl(bundleURL);
// Note, using a static dictionary isn't really the greatest design, but
// the packager connection does the same thing, so it's at least consistent.
// This is a static map that holds different inspector clients per the inspectorURL
if (socketConnections == nil) {
socketConnections = [NSMutableDictionary new];
}
NSString *key = [inspectorURL absoluteString];
RCTInspectorPackagerConnection *connection = socketConnections[key];
if (!connection) {
connection = [[RCTInspectorPackagerConnection alloc] initWithURL:inspectorURL];
socketConnections[key] = connection;
[connection connect];
}
return connection;
}
@end
#endif