microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
f521686613075eb4a9cebc89a01cbcf289ec258f

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/cdp-proxy/reactNativeCDPProxy.ts

185lines · 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 { ICDPMessageHandler } from "./CDPMessageHandlers/ICDPMessageHandler";
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: ICDPMessageHandler;
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: ICDPMessageHandler,
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 // dequeue any messages we got in the meantime
121 this.debuggerTarget.unpause();
122 }
123
124 private handleDebuggerTargetCommand(event: IProtocolCommand) {
125 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.DEBUGGER_COMMAND, JSON.stringify(event, null , 2), this.logLevel);
126 const processedMessage = this.CDPMessageHandler.processDebuggerCDPMessage(event);
127
128 if (processedMessage.sendBack) {
129 this.debuggerTarget?.send(processedMessage.event);
130 } else {
131 this.applicationTarget?.send(processedMessage.event);
132 }
133 }
134
135 private handleApplicationTargetCommand(event: IProtocolCommand) {
136 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.APPLICATION_COMMAND, JSON.stringify(event, null , 2), this.logLevel);
137 const processedMessage = this.CDPMessageHandler.processApplicationCDPMessage(event);
138
139 if (processedMessage.sendBack) {
140 this.applicationTarget?.send(processedMessage.event);
141 } else {
142 this.debuggerTarget?.send(processedMessage.event);
143 }
144 }
145
146 private handleDebuggerTargetReply(event: IProtocolError | IProtocolSuccess) {
147 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.DEBUGGER_REPLY, JSON.stringify(event, null , 2), this.logLevel);
148 const processedMessage = this.CDPMessageHandler.processDebuggerCDPMessage(event);
149
150 if (processedMessage.sendBack) {
151 this.debuggerTarget?.send(processedMessage.event);
152 } else {
153 this.applicationTarget?.send(processedMessage.event);
154 }
155 }
156
157 private handleApplicationTargetReply(event: IProtocolError | IProtocolSuccess) {
158 this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.APPLICATION_REPLY, JSON.stringify(event, null , 2), this.logLevel);
159 const processedMessage = this.CDPMessageHandler.processApplicationCDPMessage(event);
160
161 if (processedMessage.sendBack) {
162 this.applicationTarget?.send(processedMessage.event);
163 } else {
164 this.debuggerTarget?.send(processedMessage.event);
165 }
166 }
167
168 private onDebuggerTargetError(err: Error) {
169 this.logger.error("Error on debugger transport", err);
170 }
171
172 private onApplicationTargetError(err: Error) {
173 this.logger.error("Error on application transport", err);
174 }
175
176 private async onApplicationTargetClosed() {
177 this.applicationTarget = null;
178 }
179
180 private async onDebuggerTargetClosed() {
181 this.browserInspectUri = "";
182 this.CDPMessageHandler.processDebuggerCDPMessage({method: "close"});
183 this.debuggerTarget = null;
184 }
185}