microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.11.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/networkInspector/clientDevice.ts

272lines · modeblame

4bb0956eRedMickey5 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
09f6024fHeniker4 years ago4/* eslint-disable */
5/* eslint-enable prettier/prettier*/
6
4bb0956eRedMickey5 years ago7import { ReactiveSocket } from "rsocket-types";
8import { ClientOS } from "./clientUtils";
9import { InspectorView, InspectorViewType } from "./views/inspectorView";
10import { OutputChannelLogger } from "../log/OutputChannelLogger";
11import { InspectorViewFactory } from "./views/inspectorViewFactory";
12
13/**
14* @preserve
15* Start region: the code is borrowed from https://github.com/facebook/flipper/blob/v0.79.1/desktop/app/src/Client.tsx
16*
17* Copyright (c) Facebook, Inc. and its affiliates.
18*
19* This source code is licensed under the MIT license found in the
20* LICENSE file in the root directory of this source tree.
21*
22* @format
23*/
24
25export interface ClientIdConstituents {
26app: string;
27os: ClientOS;
28device: string;
29device_id: string;
30}
31
32export interface UninitializedClient {
33os: ClientOS;
34deviceName: string;
35appName: string;
36}
37
38export interface ClientCsrQuery {
39csr?: string;
40csr_path?: string;
41}
42
43export interface ClientQuery extends ClientIdConstituents {
44sdk_version?: number;
45}
46
47export interface SecureClientQuery extends ClientQuery, ClientCsrQuery {
48medium?: number;
49}
50
51export interface RequestParams {
52api: string;
53method: string;
54params?: Record<string, any>;
55}
56
57type RequestMetadata = { method: string; id: number; params: RequestParams | undefined };
58
59type ErrorType = { message: string; stacktrace: string; name: string };
60
61export class ClientDevice {
62private readonly networkInspectorPluginName: string;
63
64private _id: string;
65private _query: ClientQuery;
66private _connection: ReactiveSocket<any, any> | null | undefined;
67private logger: OutputChannelLogger;
68private messageIdCounter: number;
69private sdkVersion: number;
70private activePlugins: Set<string>;
71private inspectorView: InspectorView;
72
73private requestCallbacks: Map<
74number,
75{
76resolve: (data: any) => void;
77reject: (err: Error) => void;
78metadata: RequestMetadata;
79}
80>;
81
82constructor(
83id: string,
84query: ClientQuery,
85connection: ReactiveSocket<any, any> | null | undefined,
86inspectorViewType: InspectorViewType,
87logger: OutputChannelLogger,
88) {
89this.networkInspectorPluginName = "Network";
90
91this._id = id;
92this._query = query;
93this._connection = connection;
94this.logger = logger;
95this.messageIdCounter = 0;
96this.sdkVersion = query.sdk_version || 0;
97this.activePlugins = new Set();
98this.requestCallbacks = new Map();
99this.inspectorView = InspectorViewFactory.getInspectorView(inspectorViewType);
100}
101
102get id(): string {
103return this._id;
104}
105
106get query(): ClientQuery {
107return this._query;
108}
109
110get connection(): ReactiveSocket<any, any> | null | undefined {
111return this._connection;
112}
113
114public async init(): Promise<void> {
115const plugins = await this.loadPlugins();
116if (plugins.includes(this.networkInspectorPluginName)) {
117this.initNetworkInspectorPlugin();
118}
119await this.inspectorView.init();
120}
121
122public onMessage(msg: string): void {
123if (typeof msg !== "string") {
124return;
125}
126
127let rawData;
128try {
129rawData = JSON.parse(msg);
130} catch (err) {
131this.logger.error(`Invalid JSON: ${msg}`);
132return;
133}
134
135const data: {
136id?: number;
137method?: string;
138params?: RequestParams;
139success?: Record<string, any>;
140error?: ErrorType;
141} = rawData;
142
143if (!data.id) {
144const { error } = data;
145if (error) {
146this.logger.error(
147`Error received from device ${
148data.method ? `when calling ${data.method}` : ""
149}: ${error.message} + \nDevice Stack Trace: ${error.stacktrace}`,
150);
151} else if (data.method === "execute" && data.params) {
152this.inspectorView.handleMessage(data.params);
153}
154return; // method === "execute";
155}
156
157if (this.sdkVersion < 1) {
158const callbacks = this.requestCallbacks.get(data.id);
159if (!callbacks) {
160return;
161}
162this.requestCallbacks.delete(data.id);
163this.onResponse(data, callbacks.resolve, callbacks.reject);
164}
165}
166
167private initNetworkInspectorPlugin(): void {
168this.activePlugins.add(this.networkInspectorPluginName);
169this.rawSend("init", { plugin: this.networkInspectorPluginName });
170}
171
172private async loadPlugins(): Promise<string[]> {
173const plugins = await this.rawCall<{ plugins: string[] }>("getPlugins", false).then(
174data => data.plugins,
175);
176return plugins;
177}
178
179private rawSend(method: string, params?: Record<string, any>): void {
180const data = {
181method,
182params,
183};
184if (this._connection) {
185this._connection.fireAndForget({ data: JSON.stringify(data) });
186}
187}
188
189private rawCall<T>(method: string, fromPlugin: boolean, params?: RequestParams): Promise<T> {
190return new Promise((resolve, reject) => {
191const id = this.messageIdCounter++;
192const metadata: RequestMetadata = {
193method,
194id,
195params,
196};
197
198if (this.sdkVersion < 1) {
199this.requestCallbacks.set(id, { reject, resolve, metadata });
200}
201
202const data = {
203id,
204method,
205params,
206};
207
208const plugin = params ? params.api : undefined;
209
210if (this.sdkVersion < 1) {
211if (this._connection) {
212this._connection.fireAndForget({ data: JSON.stringify(data) });
213}
214return;
215}
216
217if (!fromPlugin || this.isAcceptingMessagesFromPlugin(plugin)) {
218this._connection!.requestResponse({
219data: JSON.stringify(data),
220}).subscribe({
221onComplete: payload => {
222if (!fromPlugin || this.isAcceptingMessagesFromPlugin(plugin)) {
223const response: {
224success?: Record<string, any>;
225error?: ErrorType;
226} = JSON.parse(payload.data);
227
228this.onResponse(response, resolve, reject);
229}
230},
231onError: e => {
232reject(e);
233},
234});
235} else {
236reject(
237new Error(
238`Cannot send ${method}, client is not accepting messages for plugin ${plugin}`,
239),
240);
241}
242});
243}
244
245private onResponse(
246data: {
247success?: Record<string, any>;
248error?: ErrorType;
249},
250resolve: ((a: any) => any) | undefined,
251reject: (error: ErrorType) => any,
252): void {
253if (data.success) {
254resolve && resolve(data.success);
255} else if (data.error) {
256reject(data.error);
257const { error } = data;
258if (error) {
259this.logger.debug(error.message);
260}
261}
262}
263
264private isAcceptingMessagesFromPlugin(plugin: string | null | undefined): boolean {
265return !!(this._connection && (!plugin || this.activePlugins.has(plugin)));
266}
267}
268
269/**
270* @preserve
271* End region: https://github.com/facebook/flipper/blob/v0.79.1/desktop/app/src/Client.tsx
272*/