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