microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.0.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/cdp-proxy/reactNativeCDPProxy.ts

188lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import {
5 Connection,
6 Server,
7 WebSocketTransport,
8 IProtocolCommand,
9 IProtocolError,
10 IProtocolSuccess
11} from "vscode-cdp-proxy";
12import { IncomingMessage } from "http";
13import { CancellationToken } from "vscode";
14import { OutputChannelLogger } from "../extension/log/OutputChannelLogger";
15import { LogLevel } from "../extension/log/LogHelper";
16import { DebuggerEndpointHelper } from "./debuggerEndpointHelper";
17import { BaseCDPMessageHandler } from "./CDPMessageHandlers/baseCDPMessageHandler";
18
19export class ReactNativeCDPProxy {
20
21 private readonly PROXY_LOG_TAGS = {
22 DEBUGGER_COMMAND: "Command Debugger To Target",
23 APPLICATION_COMMAND: "Command Target To Debugger",
24 DEBUGGER_REPLY: "Reply From Debugger To Target",
25 APPLICATION_REPLY: "Reply From Target To Debugger",
26 };
27
28 private server: Server | null;
29 private hostAddress: string;
30 private port: number;
31 private debuggerTarget: Connection | null;
32 private applicationTarget: Connection | null;
33 private logger: OutputChannelLogger;
34 private logLevel: LogLevel;
35 private debuggerEndpointHelper: DebuggerEndpointHelper;
36 private CDPMessageHandler: BaseCDPMessageHandler;
37 private applicationTargetPort: number;
38 private browserInspectUri: string;
39 private cancellationToken: CancellationToken | undefined;
40
41 constructor(hostAddress: string, port: number, logLevel: LogLevel = LogLevel.None) {
42 this.port = port;
43 this.hostAddress = hostAddress;
44 this.logger = OutputChannelLogger.getChannel("React Native Chrome Proxy", true, false, true);
45 this.logLevel = logLevel;
46 this.browserInspectUri = "";
47 this.debuggerEndpointHelper = new DebuggerEndpointHelper();
48 }
49
50 public initializeServer(
51 CDPMessageHandler: BaseCDPMessageHandler,
52 logLevel: LogLevel,
53 cancellationToken?: CancellationToken
54 ): Promise<void> {
55 this.logLevel = logLevel;
56 this.CDPMessageHandler = CDPMessageHandler;
57 this.cancellationToken = cancellationToken;
58
59 return Server.create({ port: this.port, host: this.hostAddress })
60 .then((server: Server) => {
61 this.server = server;
62 this.server.onConnection(this.onConnectionHandler.bind(this));
63 });
64 }
65
66 public async stopServer(): Promise<void> {
67 if (this.server) {
68 this.server.dispose();
69 this.server = null;
70 }
71
72 if (this.applicationTarget) {
73 await this.applicationTarget.close();
74 this.applicationTarget = null;
75 }
76
77 this.browserInspectUri = "";
78 this.cancellationToken = undefined;
79 }
80
81 public setBrowserInspectUri(browserInspectUri: string) {
82 this.browserInspectUri = browserInspectUri;
83 }
84
85 public setApplicationTargetPort(applicationTargetPort: number): void {
86 this.applicationTargetPort = applicationTargetPort;
87 }
88
89 private async onConnectionHandler([debuggerTarget, request]: [Connection, IncomingMessage]): Promise<void> {
90 this.debuggerTarget = debuggerTarget;
91
92 this.debuggerTarget.pause(); // don't listen for events until the target is ready
93
94 if (!this.browserInspectUri) {
95 if (this.cancellationToken) {
96 this.browserInspectUri = await this.debuggerEndpointHelper.retryGetWSEndpoint(
97 `http://localhost:${this.applicationTargetPort}`,
98 90,
99 this.cancellationToken
100 );
101 } else {
102 this.browserInspectUri = await this.debuggerEndpointHelper.getWSEndpoint(`http://localhost:${this.applicationTargetPort}`);
103 }
104 }
105
106 this.applicationTarget = new Connection(await WebSocketTransport.create(this.browserInspectUri));
107
108 this.applicationTarget.onError(this.onApplicationTargetError.bind(this));
109 this.debuggerTarget.onError(this.onDebuggerTargetError.bind(this));
110
111 this.applicationTarget.onCommand(this.handleApplicationTargetCommand.bind(this));
112 this.debuggerTarget.onCommand(this.handleDebuggerTargetCommand.bind(this));
113
114 this.applicationTarget.onReply(this.handleApplicationTargetReply.bind(this));
115 this.debuggerTarget.onReply(this.handleDebuggerTargetReply.bind(this));
116
117 this.applicationTarget.onEnd(this.onApplicationTargetClosed.bind(this));
118 this.debuggerTarget.onEnd(this.onDebuggerTargetClosed.bind(this));
119
120 this.CDPMessageHandler?.setApplicationTarget(this.applicationTarget);
121 this.CDPMessageHandler?.setDebuggerTarget(this.debuggerTarget);
122
123 // dequeue any messages we got in the meantime
124 this.debuggerTarget.unpause();
125 }
126
127 private handleDebuggerTargetCommand(event: IProtocolCommand) {
128 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.DEBUGGER_COMMAND, JSON.stringify(event, null , 2), this.logLevel);
129 const processedMessage = this.CDPMessageHandler.processDebuggerCDPMessage(event);
130
131 if (processedMessage.sendBack) {
132 this.debuggerTarget?.send(processedMessage.event);
133 } else {
134 this.applicationTarget?.send(processedMessage.event);
135 }
136 }
137
138 private handleApplicationTargetCommand(event: IProtocolCommand) {
139 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.APPLICATION_COMMAND, JSON.stringify(event, null , 2), this.logLevel);
140 const processedMessage = this.CDPMessageHandler.processApplicationCDPMessage(event);
141
142 if (processedMessage.sendBack) {
143 this.applicationTarget?.send(processedMessage.event);
144 } else {
145 this.debuggerTarget?.send(processedMessage.event);
146 }
147 }
148
149 private handleDebuggerTargetReply(event: IProtocolError | IProtocolSuccess) {
150 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.DEBUGGER_REPLY, JSON.stringify(event, null , 2), this.logLevel);
151 const processedMessage = this.CDPMessageHandler.processDebuggerCDPMessage(event);
152
153 if (processedMessage.sendBack) {
154 this.debuggerTarget?.send(processedMessage.event);
155 } else {
156 this.applicationTarget?.send(processedMessage.event);
157 }
158 }
159
160 private handleApplicationTargetReply(event: IProtocolError | IProtocolSuccess) {
161 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.APPLICATION_REPLY, JSON.stringify(event, null , 2), this.logLevel);
162 const processedMessage = this.CDPMessageHandler.processApplicationCDPMessage(event);
163
164 if (processedMessage.sendBack) {
165 this.applicationTarget?.send(processedMessage.event);
166 } else {
167 this.debuggerTarget?.send(processedMessage.event);
168 }
169 }
170
171 private onDebuggerTargetError(err: Error) {
172 this.logger.error("Error on debugger transport", err);
173 }
174
175 private onApplicationTargetError(err: Error) {
176 this.logger.error("Error on application transport", err);
177 }
178
179 private async onApplicationTargetClosed() {
180 this.applicationTarget = null;
181 }
182
183 private async onDebuggerTargetClosed() {
184 this.browserInspectUri = "";
185 this.CDPMessageHandler.processDebuggerCDPMessage({method: "close"});
186 this.debuggerTarget = null;
187 }
188}
189