• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {proxySetupStyles} from 'app/styles/proxy_setup.styles';
18import {Download} from 'common/download';
19import {getRootUrl} from 'common/url_utils';
20import {ConnectionState} from 'trace_collection/connection_state';
21import {VERSION} from 'trace_collection/winscope_proxy/utils';
22
23@Component({
24  selector: 'winscope-proxy-setup',
25  template: `
26    <ng-container [ngSwitch]="state">
27      <ng-container *ngSwitchCase="${ConnectionState.CONNECTING}">
28        <p class="connecting-message mat-body-1">
29          Connecting...
30        </p>
31      </ng-container>
32      <ng-container *ngSwitchCase="${ConnectionState.NOT_FOUND}">
33        <div class="further-adb-info-text">
34          <p class="mat-body-1">
35            Launch the Winscope ADB Connect proxy to capture traces directly from your browser.
36          </p>
37          <p class="mat-body-1">Python 3.10+ and ADB are required. Run this command:</p>
38          <mat-form-field class="proxy-command-form" appearance="outline">
39            <input matInput readonly [value]="proxyCommand" />
40            <button
41              mat-icon-button
42              matSuffix
43              [cdkCopyToClipboard]="proxyCommand"
44              matTooltip="Copy command">
45              <mat-icon>content_copy</mat-icon>
46            </button>
47          </mat-form-field>
48          <p class="mat-body-1">Or download below.</p>
49        </div>
50
51        <div class="further-adb-info-actions">
52          <button
53            class="download-proxy-btn"
54            color="primary"
55            mat-stroked-button
56            (click)="onDownloadProxyClick()">
57            Download Proxy
58          </button>
59          <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()">
60            Retry
61          </button>
62        </div>
63      </ng-container>
64
65      <ng-container *ngSwitchCase="${ConnectionState.INVALID_VERSION}">
66        <div class="further-adb-info-text">
67          <p class="icon-information mat-body-1">
68            <mat-icon class="adb-icon">update</mat-icon>
69            <span class="adb-info">Your local proxy version is incompatible with Winscope.</span>
70          </p>
71          <p class="mat-body-1">
72            Please update the proxy to version {{ proxyVersion }}. Run this command:
73          </p>
74          <mat-form-field class="proxy-command-container" appearance="outline">
75            <input matInput readonly [value]="proxyCommand" />
76            <button
77              mat-icon-button
78              matSuffix
79              [cdkCopyToClipboard]="proxyCommand"
80              matTooltip="Copy command">
81              <mat-icon>content_copy</mat-icon>
82            </button>
83          </mat-form-field>
84          <p class="mat-body-1">Or download below.</p>
85        </div>
86
87        <div class="further-adb-info-actions">
88          <button
89            class="download-proxy-btn"
90            color="primary"
91            mat-stroked-button
92            (click)="onDownloadProxyClick()">
93            Download Proxy
94          </button>
95          <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()">
96            Retry
97          </button>
98        </div>
99      </ng-container>
100
101      <ng-container *ngSwitchCase="${ConnectionState.UNAUTH}">
102        <div class="further-adb-info-text">
103          <p class="icon-information mat-body-1">
104            <mat-icon class="adb-icon">lock</mat-icon>
105            <span class="adb-info">Proxy authorization required.</span>
106          </p>
107          <p class="mat-body-1">Enter Winscope proxy token:</p>
108          <mat-form-field
109            class="proxy-token-input-field"
110            (keydown.enter)="onKeydownEnterProxyTokenInput($event)">
111            <input matInput [(ngModel)]="proxyToken" name="proxy-token" />
112          </mat-form-field>
113          <p class="mat-body-1">
114            The proxy token is printed to console on proxy launch, copy and paste it above.
115          </p>
116        </div>
117
118        <div class="further-adb-info-actions">
119          <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()">
120            Connect
121          </button>
122        </div>
123      </ng-container>
124
125      <ng-container *ngSwitchDefault></ng-container>
126    </ng-container>
127  `,
128  styles: [
129    `
130      /* TODO(b/300063426): remove after migration to angular 15, replace with subscriptSizing */
131      ::ng-deep .proxy-command-form .mat-form-field-wrapper {
132        padding: 0;
133      }
134      .proxy-command-text {
135        user-select: all;
136        overflow: auto;
137      }
138    `,
139    proxySetupStyles,
140  ],
141})
142export class WinscopeProxySetupComponent {
143  @Input() state: ConnectionState | undefined;
144  @Output() readonly retryConnection = new EventEmitter<string>();
145
146  readonly downloadProxyUrl: string = getRootUrl() + 'winscope_proxy.py';
147  readonly proxyCommand: string =
148    'python3 $ANDROID_BUILD_TOP/development/tools/winscope/src/adb/winscope_proxy.py';
149  readonly proxyVersion = VERSION;
150  proxyToken = '';
151
152  onRetryButtonClick() {
153    if (this.state !== ConnectionState.UNAUTH || this.proxyToken.length > 0) {
154      this.retryConnection.emit(this.proxyToken);
155    }
156  }
157
158  onKeydownEnterProxyTokenInput(event: MouseEvent) {
159    (event.target as HTMLInputElement).blur();
160    this.onRetryButtonClick();
161  }
162
163  onDownloadProxyClick() {
164    Download.fromUrl(this.downloadProxyUrl, 'winscope_proxy.py');
165  }
166}
167