xref: /aosp_15_r20/development/tools/winscope/src/app/components/adb_proxy_component.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import {Component, EventEmitter, Input, Output} from '@angular/core';
17import {Download} from 'common/download';
18import {UrlUtils} from 'common/url_utils';
19import {ConnectionState} from 'trace_collection/connection_state';
20import {ProxyConnection} from 'trace_collection/proxy_connection';
21
22@Component({
23  selector: 'adb-proxy',
24  template: `
25    <ng-container [ngSwitch]="state">
26      <ng-container *ngSwitchCase="${ConnectionState.NOT_FOUND}">
27        <div class="further-adb-info-text">
28          <p class="mat-body-1">
29            Launch the Winscope ADB Connect proxy to capture traces directly from your browser.
30          </p>
31          <p class="mat-body-1">Python 3.10+ and ADB are required. Run this command:</p>
32          <mat-form-field class="proxy-command-form" appearance="outline">
33            <input matInput readonly [value]="proxyCommand" />
34            <button
35              mat-icon-button
36              matSuffix
37              [cdkCopyToClipboard]="proxyCommand"
38              matTooltip="Copy command">
39              <mat-icon>content_copy</mat-icon>
40            </button>
41          </mat-form-field>
42          <p class="mat-body-1">Or download below.</p>
43        </div>
44
45        <div class="further-adb-info-actions">
46          <button
47            class="download-proxy-btn"
48            color="primary"
49            mat-stroked-button
50            (click)="onDownloadProxyClick()">
51            Download Proxy
52          </button>
53          <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()">
54            Retry
55          </button>
56        </div>
57      </ng-container>
58
59      <ng-container *ngSwitchCase="${ConnectionState.INVALID_VERSION}">
60        <div class="further-adb-info-text">
61          <p class="icon-information mat-body-1">
62            <mat-icon class="adb-icon">update</mat-icon>
63            <span class="adb-info">Your local proxy version is incompatible with Winscope.</span>
64          </p>
65          <p class="mat-body-1">
66            Please update the proxy to version {{ proxyVersion }}. Run this command:
67          </p>
68          <mat-form-field class="proxy-command-container" appearance="outline">
69            <input matInput readonly [value]="proxyCommand" />
70            <button
71              mat-icon-button
72              matSuffix
73              [cdkCopyToClipboard]="proxyCommand"
74              matTooltip="Copy command">
75              <mat-icon>content_copy</mat-icon>
76            </button>
77          </mat-form-field>
78          <p class="mat-body-1">Or download below.</p>
79        </div>
80
81        <div class="further-adb-info-actions">
82          <button
83            class="download-proxy-btn"
84            color="primary"
85            mat-stroked-button
86            (click)="onDownloadProxyClick()">
87            Download Proxy
88          </button>
89          <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()">
90            Retry
91          </button>
92        </div>
93      </ng-container>
94
95      <ng-container *ngSwitchCase="${ConnectionState.UNAUTH}">
96        <div class="further-adb-info-text">
97          <p class="icon-information mat-body-1">
98            <mat-icon class="adb-icon">lock</mat-icon>
99            <span class="adb-info">Proxy authorization required.</span>
100          </p>
101          <p class="mat-body-1">Enter Winscope proxy token:</p>
102          <mat-form-field
103            class="proxy-token-input-field"
104            (keydown.enter)="onKeydownEnterProxyTokenInput($event)">
105            <input matInput [(ngModel)]="proxyToken" name="proxy-token" />
106          </mat-form-field>
107          <p class="mat-body-1">
108            The proxy token is printed to console on proxy launch, copy and paste it above.
109          </p>
110        </div>
111
112        <div class="further-adb-info-actions">
113          <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()">
114            Connect
115          </button>
116        </div>
117      </ng-container>
118
119      <ng-container *ngSwitchDefault></ng-container>
120    </ng-container>
121  `,
122  styles: [
123    `
124      .icon-information {
125        display: flex;
126        flex-direction: row;
127        align-items: center;
128      }
129      .further-adb-info-text {
130        display: flex;
131        flex-direction: column;
132        overflow-wrap: break-word;
133        gap: 10px;
134        margin-bottom: 10px;
135      }
136      .further-adb-info-actions {
137        display: flex;
138        flex-direction: row;
139        flex-wrap: wrap;
140        gap: 10px;
141      }
142      /* TODO(b/300063426): remove after migration to angular 15, replace with subscriptSizing */
143      ::ng-deep .proxy-command-form .mat-form-field-wrapper {
144        padding: 0;
145      }
146      .proxy-command-text {
147        user-select: all;
148        overflow: auto;
149      }
150      .adb-info {
151        margin-left: 5px;
152      }
153    `,
154  ],
155})
156export class AdbProxyComponent {
157  @Input() state: ConnectionState | undefined;
158  @Output() readonly retryConnection = new EventEmitter<string>();
159
160  readonly downloadProxyUrl: string =
161    UrlUtils.getRootUrl() + 'winscope_proxy.py';
162  readonly proxyCommand: string =
163    'python3 $ANDROID_BUILD_TOP/development/tools/winscope/src/adb/winscope_proxy.py';
164  readonly proxyVersion = ProxyConnection.VERSION;
165  proxyToken = '';
166
167  onRetryButtonClick() {
168    if (this.state !== ConnectionState.UNAUTH || this.proxyToken.length > 0) {
169      this.retryConnection.emit(this.proxyToken);
170    }
171  }
172
173  onKeydownEnterProxyTokenInput(event: MouseEvent) {
174    (event.target as HTMLInputElement).blur();
175    this.onRetryButtonClick();
176  }
177
178  onDownloadProxyClick() {
179    Download.fromUrl(this.downloadProxyUrl, 'winscope_proxy.py');
180  }
181}
182