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 {UrlUtils} from 'common/url_utils'; 18import { 19 proxyClient, 20 ProxyClient, 21 ProxyState, 22} from 'trace_collection/proxy_client'; 23 24@Component({ 25 selector: 'adb-proxy', 26 template: ` 27 <ng-container [ngSwitch]="proxy.state"> 28 <ng-container *ngSwitchCase="states.NO_PROXY"> 29 <div class="further-adb-info-text"> 30 <p class="mat-body-1"> 31 Launch the Winscope ADB Connect proxy to capture traces directly from your browser. 32 </p> 33 <p class="mat-body-1">Python 3.5+ and ADB are required. Run this command:</p> 34 <mat-form-field class="proxy-command-form" appearance="outline"> 35 <input matInput readonly [value]="proxyCommand" /> 36 <button 37 mat-icon-button 38 matSuffix 39 [cdkCopyToClipboard]="proxyCommand" 40 matTooltip="Copy command"> 41 <mat-icon>content_copy</mat-icon> 42 </button> 43 </mat-form-field> 44 <p class="mat-body-1">Or download below.</p> 45 </div> 46 47 <div class="further-adb-info-actions"> 48 <button 49 class="download-proxy-btn" 50 color="primary" 51 mat-stroked-button 52 (click)="onDownloadProxyClick()"> 53 Download Proxy 54 </button> 55 <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()"> 56 Retry 57 </button> 58 </div> 59 </ng-container> 60 61 <ng-container *ngSwitchCase="states.INVALID_VERSION"> 62 <div class="further-adb-info-text"> 63 <p class="icon-information mat-body-1"> 64 <mat-icon class="adb-icon">update</mat-icon> 65 <span class="adb-info">Your local proxy version is incompatible with Winscope.</span> 66 </p> 67 <p class="mat-body-1"> 68 Please update the proxy to version {{ proxyVersion }}. Run this command: 69 </p> 70 <mat-form-field class="proxy-command-container" appearance="outline"> 71 <input matInput readonly [value]="proxyCommand" /> 72 <button 73 mat-icon-button 74 matSuffix 75 [cdkCopyToClipboard]="proxyCommand" 76 matTooltip="Copy command"> 77 <mat-icon>content_copy</mat-icon> 78 </button> 79 </mat-form-field> 80 <p class="mat-body-1">Or download below.</p> 81 </div> 82 83 <div class="further-adb-info-actions"> 84 <button 85 class="download-proxy-btn" 86 color="primary" 87 mat-stroked-button 88 (click)="onDownloadProxyClick()"> 89 Download Proxy 90 </button> 91 <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()"> 92 Retry 93 </button> 94 </div> 95 </ng-container> 96 97 <ng-container *ngSwitchCase="states.UNAUTH"> 98 <div class="further-adb-info-text"> 99 <p class="icon-information mat-body-1"> 100 <mat-icon class="adb-icon">lock</mat-icon> 101 <span class="adb-info">Proxy authorisation required.</span> 102 </p> 103 <p class="mat-body-1">Enter Winscope proxy token:</p> 104 <mat-form-field 105 class="proxy-key-input-field" 106 (keydown.enter)="onKeydownEnterProxyKeyInput($event)"> 107 <input matInput [(ngModel)]="proxyKeyItem" name="proxy-key" /> 108 </mat-form-field> 109 <p class="mat-body-1"> 110 The proxy token is printed to console on proxy launch, copy and paste it above. 111 </p> 112 </div> 113 114 <div class="further-adb-info-actions"> 115 <button color="primary" mat-stroked-button class="retry" (click)="onRetryButtonClick()"> 116 Connect 117 </button> 118 </div> 119 </ng-container> 120 121 <ng-container *ngSwitchDefault></ng-container> 122 </ng-container> 123 `, 124 styles: [ 125 ` 126 .icon-information { 127 display: flex; 128 flex-direction: row; 129 align-items: center; 130 } 131 .further-adb-info-text { 132 display: flex; 133 flex-direction: column; 134 overflow-wrap: break-word; 135 gap: 10px; 136 margin-bottom: 10px; 137 } 138 .further-adb-info-actions { 139 display: flex; 140 flex-direction: row; 141 flex-wrap: wrap; 142 gap: 10px; 143 } 144 /* TODO(b/300063426): remove after migration to angular 15, replace with subscriptSizing */ 145 ::ng-deep .proxy-command-form .mat-form-field-wrapper { 146 padding: 0; 147 } 148 .proxy-command-text { 149 user-select: all; 150 overflow: auto; 151 } 152 .adb-info { 153 margin-left: 5px; 154 } 155 `, 156 ], 157}) 158export class AdbProxyComponent { 159 @Input() 160 proxy: ProxyClient = proxyClient; 161 162 @Output() 163 readonly proxyChange = new EventEmitter<ProxyClient>(); 164 165 @Output() 166 readonly addKey = new EventEmitter<string>(); 167 168 states = ProxyState; 169 proxyKeyItem = ''; 170 readonly proxyVersion = this.proxy.VERSION; 171 readonly downloadProxyUrl: string = 172 UrlUtils.getRootUrl() + 'winscope_proxy.py'; 173 readonly proxyCommand: string = 174 'python3 $ANDROID_BUILD_TOP/development/tools/winscope/src/adb/winscope_proxy.py'; 175 176 async onRetryButtonClick() { 177 if (this.proxyKeyItem.length > 0) { 178 this.addKey.emit(this.proxyKeyItem); 179 } 180 await this.proxy.setState(this.states.CONNECTING); 181 this.proxyChange.emit(this.proxy); 182 } 183 184 async onKeydownEnterProxyKeyInput(event: MouseEvent) { 185 (event.target as HTMLInputElement).blur(); 186 await this.onRetryButtonClick(); 187 } 188 189 onDownloadProxyClick() { 190 window.open(this.downloadProxyUrl, '_blank')?.focus(); 191 } 192} 193