1/** 2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { WidthPercent } from '../../common/util/ConfigData'; 17import { CertificateComponent } from '../certManagerFa'; 18import { NavEntryKey } from '../../common/NavEntryKey'; 19import { CaCertPage } from './CaCertPage'; 20import { CredListPage } from './CredListPage'; 21import { InstallPage } from './InstallPage'; 22import { CaSystemDetailPage } from '../detail/CaSystemDetailPage'; 23import { CaUserDetailPage } from '../detail/CaUserDetailPage'; 24import { CredSystemDetailPage } from '../detail/CredSystemDetailPage'; 25import { CredUserDetailPage } from '../detail/CredUserDetailPage'; 26import { AuthorizedAppManagementPage } from '../detail/AuthorizedAppManagementPage'; 27import { CredPwdInputPage } from '../detail/CredPwdInputPage'; 28import Want from '@ohos.app.ability.Want'; 29import deviceInfo from '@ohos.deviceInfo'; 30import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; 31import { TrustedEvidence } from '../trustedCa'; 32import { evidenceList } from '../cerEvidenceFa'; 33import { CertInstallFromStorage } from '../certInstallFromStorage'; 34import window from '@ohos.window'; 35import { SheetParam } from '../../common/util/SheetParam'; 36import uiExtensionHost from '@ohos.uiExtensionHost'; 37import { BusinessError } from '@ohos.base'; 38import PreventScreenshotsPresenter from '../../model/PreventScreenshotsModel'; 39 40const TAG: string = 'CertManagerSheetFa:'; 41 42let storage = LocalStorage.getShared(); 43 44const PAGE_MAIN: number = 1; 45const PAGE_CA_CERTIFICATE: number = 2; 46const PAGE_CREDENTIAL: number = 3; 47const PAGE_INSTALL_CERTIFICATE: number = 4; 48const PAGE_TYPE: string = 'pageType'; 49 50const BOTTOM_SHEET_MIN_PERCENT = 0.6; 51const CENTER_SHEET_MAX_PERCENT = 0.9; 52const CENTER_SHEET_MIN_HEIGHT = 560; 53 54interface AvoidAreaParam { 55 type: window.AvoidAreaType; 56 area: window.AvoidArea; 57} 58 59@Entry(storage) 60@Component 61export struct CertManagerSheetFa { 62 private sheetSession: UIExtensionContentSession = 63 storage.get<UIExtensionContentSession>('session') as UIExtensionContentSession; 64 private want: Want = storage.get<Want>('want') as Want; 65 private preventScreenshotsPresenter: PreventScreenshotsPresenter = PreventScreenshotsPresenter.getInstance(); 66 67 @State @Watch('onSheetPageChanged') private stack: NavPathStack = new NavPathStack(); 68 @State private sheetParam: SheetParam = new SheetParam(); 69 @State private pageType: number = PAGE_MAIN; 70 @State private maxSheetPageHeight: number = 0; 71 @State private rootWidth: number = 0; 72 @State private rootHeight: number = 0; 73 @State private statusBarHeight: number = 0; 74 @State private aiBarHeight: number = 0; 75 76 private avoidAreaChangedCallback: Callback<AvoidAreaParam> = (avoidArea) => { 77 if (avoidArea.type === window.AvoidAreaType.TYPE_SYSTEM) { 78 this.statusBarHeight = px2vp(avoidArea.area.topRect.height); 79 this.updateSheetHeightLimit(); 80 } else if (avoidArea.type === window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) { 81 this.aiBarHeight = px2vp(avoidArea.area.bottomRect.height); 82 this.updateSheetHeightLimit(); 83 } else { 84 console.warn(TAG + 'avoidAreaChangedCallback, sheet type is invalid:' + this.sheetParam.sheetType); 85 } 86 } 87 88 onSheetPageChanged(): void { 89 let allPageArray = this.stack.getAllPathName(); 90 if (allPageArray === undefined || allPageArray.length === 0) { 91 this.preventScreenshotsPresenter.PreventScreenshots(false, this.sheetSession); 92 this.sheetParam.lastSheetPage = ''; 93 return; 94 } 95 let lastPage = allPageArray[allPageArray.length - 1]; 96 this.sheetParam.lastSheetPage = lastPage; 97 if (lastPage !== NavEntryKey.CRED_PWD_INPUT_ENTRY) { 98 this.preventScreenshotsPresenter.PreventScreenshots(false, this.sheetSession); 99 return; 100 } 101 this.preventScreenshotsPresenter.PreventScreenshots(true, this.sheetSession); 102 } 103 104 aboutToAppear(): void { 105 this.registerAvoidChangedListener(); 106 const parameters = this.want?.parameters; 107 if (parameters === undefined || parameters[PAGE_TYPE] === undefined) { 108 console.warn(TAG + 'page type param is undefined'); 109 return; 110 } 111 this.pageType = parameters[PAGE_TYPE] as number; 112 console.log(TAG + 'page type = ' + this.pageType); 113 } 114 115 aboutToDisappear(): void { 116 this.unregisterAvoidChangedListener(); 117 } 118 119 initStatusBarHeight(extWindow: uiExtensionHost.UIExtensionHostWindowProxy): void { 120 try { 121 let avoidArea: window.AvoidArea = extWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM); 122 if (avoidArea === undefined) { 123 console.warn(TAG + 'initStatusBarHeight, avoid area is undefined'); 124 } 125 this.statusBarHeight = px2vp(avoidArea.topRect.height); 126 } catch (err) { 127 let error = err as BusinessError; 128 console.error(TAG + 'initStatusBarHeight, occur error:' + error?.code + ', msg:' + error?.message); 129 } 130 } 131 132 initAiBarHeight(extWindow: uiExtensionHost.UIExtensionHostWindowProxy): void { 133 try { 134 let avoidArea: window.AvoidArea = extWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR); 135 if (avoidArea === undefined) { 136 console.warn(TAG + 'initAiBarHeight, avoid area is undefined'); 137 } 138 this.aiBarHeight = px2vp(avoidArea.bottomRect.height); 139 } catch (err) { 140 let error = err as BusinessError; 141 console.error(TAG + 'initAiBarHeight, occur error:' + error?.code + ', msg:' + error?.message); 142 } 143 } 144 145 registerAvoidChangedListener(): void { 146 try { 147 let extWindow: uiExtensionHost.UIExtensionHostWindowProxy = this.sheetSession?.getUIExtensionHostWindowProxy(); 148 if (extWindow === undefined) { 149 console.error(TAG + 'registerAvoidChangedListener, get extra window is undefined'); 150 return; 151 } 152 this.initStatusBarHeight(extWindow); 153 this.initAiBarHeight(extWindow); 154 extWindow.on('avoidAreaChange', this.avoidAreaChangedCallback); 155 } catch (err) { 156 let error = err as BusinessError; 157 console.error(TAG + 'registerAvoidChangedListener, occur error:' + error?.code + ', msg:' + error?.message); 158 } 159 } 160 161 unregisterAvoidChangedListener(): void { 162 try { 163 let extWindow: uiExtensionHost.UIExtensionHostWindowProxy = this.sheetSession?.getUIExtensionHostWindowProxy(); 164 if (extWindow === undefined) { 165 console.error(TAG + 'unregisterAvoidChangedListener, get extra window is undefined'); 166 return; 167 } 168 extWindow.off('avoidAreaChange', this.avoidAreaChangedCallback); 169 } catch (err) { 170 let error = err as BusinessError; 171 console.error(TAG + 'unregisterAvoidChangedListener, occur error:' + error?.code + ', msg:' + error?.message); 172 } 173 } 174 175 private updateSheetHeightLimit(): void { 176 if (this.rootHeight === 0) { 177 return; 178 } 179 if (this.sheetParam.sheetType === SheetType.BOTTOM) { 180 this.maxSheetPageHeight = this.rootHeight - this.statusBarHeight - 8; 181 this.sheetParam.sheetMinHeight = this.rootHeight * BOTTOM_SHEET_MIN_PERCENT; 182 } else if (this.sheetParam.sheetType === SheetType.CENTER) { 183 let shortSide = Math.min(this.rootWidth, (this.rootHeight - this.statusBarHeight - this.aiBarHeight)); 184 this.maxSheetPageHeight = shortSide * CENTER_SHEET_MAX_PERCENT; 185 this.sheetParam.sheetMinHeight = CENTER_SHEET_MIN_HEIGHT; 186 } else { 187 console.warn(TAG + 'updateSheetHeightLimit, sheet type is invalid:' + this.sheetParam.sheetType); 188 } 189 } 190 191 @Builder 192 private routerMap(name: string, param?: Object) { 193 if (name === NavEntryKey.CA_CERTIFICATE_ENTRY) { 194 CaCertPage({ 195 sheetParam: this.sheetParam 196 }) 197 } else if (name === NavEntryKey.CREDENTIAL_LIST_ENTRY) { 198 CredListPage({ 199 sheetParam: this.sheetParam 200 }) 201 } else if (name === NavEntryKey.INSTALL_ENTRY) { 202 InstallPage({ 203 sheetParam: this.sheetParam 204 }) 205 } else if (name === NavEntryKey.CA_SYSTEM_DETAIL_ENTRY) { 206 CaSystemDetailPage({ 207 sheetParam: this.sheetParam 208 }) 209 } else if (name === NavEntryKey.CA_USER_DETAIL_ENTRY) { 210 CaUserDetailPage({ 211 sheetParam: this.sheetParam 212 }) 213 } else if (name === NavEntryKey.CRED_SYSTEM_DETAIL_ENTRY) { 214 CredSystemDetailPage({ 215 sheetParam: this.sheetParam 216 }) 217 } else if (name === NavEntryKey.CRED_USER_DETAIL_ENTRY) { 218 CredUserDetailPage({ 219 sheetParam: this.sheetParam 220 }) 221 } else if (name === NavEntryKey.AUTHORIZED_APP_ENTRY) { 222 AuthorizedAppManagementPage({ 223 sheetParam: this.sheetParam 224 }) 225 } else if (name === NavEntryKey.CRED_PWD_INPUT_ENTRY) { 226 CredPwdInputPage({ 227 sheetParam: this.sheetParam 228 }) 229 } 230 } 231 232 build() { 233 Column() { 234 Column() { 235 }.bindSheet(true, this.buildContent(), { 236 height: SheetSize.FIT_CONTENT, 237 preferType: ['2in1', 'tablet'].includes(deviceInfo.deviceType) ? SheetType.CENTER : null, 238 showClose: true, 239 onTypeDidChange: (type) => { 240 this.sheetParam.sheetType = type; 241 console.log(TAG + 'sheet type:' + this.sheetParam.sheetType); 242 if (this.rootHeight === 0) { 243 return; 244 } 245 this.updateSheetHeightLimit(); 246 }, 247 onDisappear: () => { 248 console.debug(TAG + 'Sheet page disappear, session is undefined?' + (this.sheetSession === undefined)); 249 this.sheetSession?.sendData({'action': 'exit'}) 250 } 251 }) 252 } 253 .width(WidthPercent.WH_100_100) 254 .height(WidthPercent.WH_100_100) 255 .onAreaChange((oldArea, newArea) => { 256 this.rootWidth = newArea.width as number; 257 this.rootHeight = newArea.height as number; 258 this.updateSheetHeightLimit(); 259 }) 260 } 261 262 @Builder 263 private buildContent() { 264 Navigation(this.stack) { 265 if (this.pageType === PAGE_CA_CERTIFICATE) { 266 this.buildCaCertPage() 267 } else if (this.pageType === PAGE_CREDENTIAL) { 268 this.buildCredListPage() 269 } else if (this.pageType === PAGE_INSTALL_CERTIFICATE) { 270 this.buildInstallPage() 271 } else { 272 this.buildHomePage() 273 } 274 } 275 .hideTitleBar(true) 276 .titleMode(NavigationTitleMode.Mini) 277 .mode(NavigationMode.Stack) 278 .navDestination(this.routerMap) 279 .width(WidthPercent.WH_100_100) 280 .height(WidthPercent.WH_AUTO) 281 .constraintSize({ 282 maxHeight: this.maxSheetPageHeight 283 }) 284 .backgroundColor($r('sys.color.background_secondary')) 285 } 286 287 @Builder 288 private buildHomePage() { 289 Column() { 290 CertificateComponent({ 291 isStartBySheet: true, 292 sheetParam: this.sheetParam, 293 selected: (path) => { 294 if (path === undefined || path === null || path.length === 0) { 295 console.warn(TAG + 'buildHomePage, empty path'); 296 return; 297 } 298 this.stack.pushPath(new NavPathInfo(path, '')); 299 } 300 }) 301 } 302 .width(WidthPercent.WH_100_100) 303 .height(WidthPercent.WH_AUTO) 304 } 305 306 @Builder 307 private buildCaCertPage() { 308 Column() { 309 TrustedEvidence({ 310 isStartBySheetFirst: true, 311 isStartBySheet: true, 312 sheetParam: this.sheetParam, 313 selected: (path, param) => { 314 if (path === undefined || path === null || path.length === 0) { 315 console.warn(TAG + 'buildCaCertPage, empty path'); 316 return; 317 } 318 if (path === NavEntryKey.POP) { 319 this.stack?.pop(); 320 } else { 321 this.stack?.pushPath(new NavPathInfo(path, param)); 322 } 323 } 324 }) 325 } 326 .width(WidthPercent.WH_100_100) 327 .height(WidthPercent.WH_AUTO) 328 } 329 330 @Builder 331 private buildCredListPage() { 332 Column() { 333 evidenceList({ 334 isStartBySheetFirst: true, 335 isStartBySheet: true, 336 sheetParam: this.sheetParam, 337 selected: (path, param) => { 338 if (path === undefined || path === null || path.length === 0) { 339 console.warn(TAG + 'buildCredListPage, empty path'); 340 return; 341 } 342 if (path === NavEntryKey.POP) { 343 this.stack?.pop(); 344 } else { 345 this.stack?.pushPath(new NavPathInfo(path, param)); 346 } 347 } 348 }) 349 } 350 .width(WidthPercent.WH_100_100) 351 .height(WidthPercent.WH_AUTO) 352 } 353 354 @Builder 355 private buildInstallPage() { 356 Column() { 357 CertInstallFromStorage({ 358 isStartBySheetFirst: true, 359 isStartBySheet: true, 360 sheetParam: this.sheetParam, 361 selected: (path, param) => { 362 if (path === undefined || path === null || path.length === 0) { 363 console.warn(TAG + 'buildInstallPage, empty path'); 364 return; 365 } 366 if (path === NavEntryKey.POP) { 367 this.stack?.pop(); 368 } else { 369 this.stack?.pushPath(new NavPathInfo(path, param)); 370 } 371 } 372 }) 373 } 374 .width(WidthPercent.WH_100_100) 375 .height(WidthPercent.WH_AUTO) 376 } 377}