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 HeadComponent from '../common/component/headComponent'; 18import CmFaPresenter from '../presenter/CmFaPresenter'; 19import { GlobalContext } from '../common/GlobalContext'; 20import ComponentConfig from '../common/component/ComponentConfig'; 21import router from '@ohos.router'; 22import { CustomContentDialog } from '@ohos.arkui.advanced.Dialog'; 23import checkUserAuthModel from '../model/CheckUserAuthModel'; 24import { NavEntryKey } from '../common/NavEntryKey'; 25import picker from '@ohos.file.picker'; 26import FileIoModel from '../model/FileIoModel'; 27import CmInstallPresenter from '../presenter/CmInstallPresenter'; 28import { BusinessError } from '@ohos.base'; 29import { RouterFileVo } from '../model/CertManagerVo/RouterInfoVo'; 30import { CredPwdInputParam } from './detail/CredPwdInputPage'; 31import { SheetParam } from '../common/util/SheetParam'; 32import FilterParams from '../common/constants/FileFilterParams'; 33import { UIContext } from '@kit.ArkUI'; 34import { common } from '@kit.AbilityKit'; 35 36const COPIES_NUM: number = 12; 37 38const TAG: string = 'CertInstallFromStorage: '; 39 40@Entry 41@Component 42export struct CertInstallFromStorage { 43 @State columnMargin: string = '12vp'; 44 @State mFaPresenter: CmFaPresenter = CmFaPresenter.getInstance(); 45 @State installCertFlag: boolean = false; 46 private context: Context = getContext(this); 47 48 isStartBySheetFirst: boolean = false; 49 isStartBySheet: boolean = false; 50 selected?: (path: string, param?: Object) => void; 51 @Prop sheetParam: SheetParam; 52 @State private headRectHeight: number = 64; 53 @State private headRectHeightReal: number = 0; 54 private scroller: Scroller = new Scroller(); 55 @State private scrollerHeight: number = 0; 56 57 @Styles normalStyle() { 58 .backgroundColor($r('sys.color.ohos_id_color_card_bg')) 59 .borderRadius($r('app.float.user_list_divider_borderRadius_value')) 60 }; 61 @Styles pressedStyle() { 62 .backgroundColor($r('sys.color.ohos_id_color_click_effect')) 63 .borderRadius($r('app.float.user_list_divider_borderRadius_value')) 64 }; 65 66 rootCertificateDialog: CustomDialogController = new CustomDialogController({ 67 alignment: DialogAlignment.Center, 68 builder: CustomContentDialog({ 69 contentBuilder: () => { 70 this.rootCertificateContent(); 71 }, 72 contentAreaPadding: { right: $r('app.float.wh_value_0') }, 73 buttons: [ 74 { 75 value: $r('app.string.root_certificate_cancel'), 76 buttonStyle: ButtonStyleMode.TEXTUAL, 77 action: () => { 78 } 79 }, 80 { 81 value: $r('app.string.root_certificate_continue'), 82 buttonStyle: ButtonStyleMode.TEXTUAL, 83 action: () => { 84 this.installCertFlag = true; 85 this.checkUserAuth(); 86 } 87 } 88 ] 89 }) 90 }) 91 92 @Builder 93 rootCertificateContent(): void { 94 Column() { 95 Text($r('app.string.root_certificate')) 96 .height($r('app.float.wh_value_56')) 97 .fontSize($r('sys.float.ohos_id_text_size_dialog_tittle')) 98 .fontColor($r('sys.color.ohos_id_color_text_primary')) 99 .fontWeight(FontWeight.Medium) 100 .margin({ 101 left: $r('app.float.wh_value_24'), 102 right: $r('app.float.wh_value_24') 103 }) 104 .alignSelf(ItemAlign.Start) 105 106 Text($r('app.string.root_certificate_message')) 107 .fontSize($r('sys.float.ohos_id_text_size_body1')) 108 .fontWeight(FontWeight.Regular) 109 .fontColor($r('sys.color.ohos_id_color_primary')) 110 .margin({ 111 left: $r('app.float.wh_value_24'), 112 right: $r('app.float.wh_value_24') 113 }) 114 .alignSelf(ItemAlign.Start) 115 } 116 .width(WidthPercent.WH_100_100) 117 .borderRadius($r('app.float.user_list_divider_borderRadius_value')) 118 .backgroundColor($r('sys.color.ohos_id_color_dialog_bg')) 119 } 120 121 checkUserAuth() { 122 let titleStr = getContext().resourceManager.getStringSync($r('app.string.Identity_Authentication')); 123 checkUserAuthModel.auth(titleStr, (authResult: boolean) => { 124 if (authResult) { 125 console.info('checkUserAuth success'); 126 if (this.installCertFlag) { 127 if (this.isStartBySheet) { 128 this.startInstallCertBySheet(); 129 } else { 130 this.mFaPresenter.startInstallCert(this.context); 131 } 132 } else { 133 if (this.isStartBySheet) { 134 this.startInstallEvidenceBySheet(); 135 } else { 136 this.mFaPresenter.startInstallEvidence(this.context); 137 } 138 } 139 } 140 }) 141 } 142 143 startInstallCertBySheet(): void { 144 try { 145 let documentSelectOptions = new picker.DocumentSelectOptions(); 146 documentSelectOptions.maxSelectNumber = FilterParams.MAX_SELECT_FILE_NUM; 147 documentSelectOptions.fileSuffixFilters = FilterParams.CERT_FILE_SUFFIX; 148 let documentPicker = new picker.DocumentViewPicker(this.context); 149 console.info(TAG + 'start documentPicker.select'); 150 documentPicker.select(documentSelectOptions).then((documentSelectResult) => { 151 if (documentSelectResult.length >= 1) { 152 this.routeToNextInstallCert(String(documentSelectResult[0])) 153 } else { 154 console.error(TAG + 'documentPicker.select length invalid:' + documentSelectResult.length); 155 } 156 }).catch((err: BusinessError) => { 157 console.error(TAG + 'documentPicker.select failed with err, message: ' + err.message + ', code: ' + err.code); 158 }); 159 } catch (err) { 160 let e: BusinessError = err as BusinessError; 161 console.error(TAG + 'DocumentViewPicker failed with err, message: ' + e.message + ', code: ' + e.code); 162 } 163 } 164 165 routeToNextInstallCert(fileUri: string): void { 166 FileIoModel.getMediaFileSuffix(fileUri, (suffix: string | undefined) => { 167 if (suffix !== undefined) { 168 console.debug(TAG, 'suffix = ', suffix); 169 if ((suffix === 'cer') || (suffix === 'pem') || (suffix === 'crt') || (suffix === 'der') || 170 (suffix === 'p7b') || (suffix === 'spc')) { 171 CmInstallPresenter.getInstance().installCert(fileUri, '', suffix, false); 172 } else { 173 this.mFaPresenter.unrecognizedFileTips(); 174 } 175 } 176 }) 177 } 178 179 startInstallEvidenceBySheet(): void { 180 try { 181 let documentSelectOptions = new picker.DocumentSelectOptions(); 182 documentSelectOptions.maxSelectNumber = FilterParams.MAX_SELECT_FILE_NUM; 183 documentSelectOptions.fileSuffixFilters = FilterParams.CREDENTIAL_FILE_SUFFIX; 184 let documentPicker = new picker.DocumentViewPicker(this.context); 185 console.info(TAG + 'start documentPicker.select'); 186 documentPicker.select(documentSelectOptions).then((documentSelectResult) => { 187 if (documentSelectResult.length >= 1) { 188 this.routeToNextInstallEvidence(String(documentSelectResult[0])) 189 } else { 190 console.error(TAG + 'documentPicker.select length invalid:' + documentSelectResult.length); 191 } 192 }).catch((err: BusinessError) => { 193 console.error(TAG + 'documentPicker.select failed with err, message: ' + err.message + ', code: ' + err.code); 194 }); 195 } catch (err) { 196 let e: BusinessError = err as BusinessError; 197 console.error(TAG + 'DocumentViewPicker failed with err, message: ' + e.message + ', code: ' + e.code); 198 } 199 } 200 201 routeToNextInstallEvidence(fileUri: string): void { 202 FileIoModel.getMediaFileSuffix(fileUri, (suffix: string | undefined) => { 203 if (suffix !== undefined) { 204 console.debug(TAG, 'suffix = ', suffix); 205 if ((suffix === 'p12') || (suffix === 'pfx')) { 206 this.selected?.(NavEntryKey.CRED_PWD_INPUT_ENTRY, new CredPwdInputParam(new RouterFileVo(fileUri, suffix))); 207 } else { 208 this.mFaPresenter.unrecognizedFileTips(); 209 } 210 } 211 }) 212 } 213 214 build() { 215 Column() { 216 GridRow({ 217 columns: COPIES_NUM, 218 gutter: vp2px(1) === 2 ? $r('app.float.wh_value_12') : $r('app.float.wh_value_0') 219 }) { 220 GridCol({ span: COPIES_NUM }) { 221 Row({}) { 222 Stack({ alignContent: Alignment.Top }) { 223 Column() { 224 HeadComponent({ headName: $r('app.string.installInStorageDevice'), isStartBySheet: this.isStartBySheet, 225 icBackIsVisibility: !this.isStartBySheetFirst, 226 onBackClicked: () => { 227 this.selected?.(NavEntryKey.POP); 228 }}) 229 .margin({ 230 top: this.isStartBySheet ? 8 : 0, 231 left: 12, 232 right: 12 233 }) 234 }.zIndex(1) 235 .onAreaChange((oldArea, newArea) => { 236 this.headRectHeight = newArea.height as number; 237 this.headRectHeightReal = newArea.height as number; 238 }) 239 240 Stack({ alignContent: Alignment.TopEnd }) { 241 Scroll(this.scroller) { 242 Column() { 243 Row() { 244 Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 245 Text($r('app.string.CA_cert')) 246 .fontSize($r('sys.float.ohos_id_text_size_body1')) 247 .fontColor($r('sys.color.ohos_id_color_text_primary')) 248 .fontWeight(FontWeight.Medium) 249 .margin({ left: $r('app.float.wh_value_12') }) 250 .textAlign(TextAlign.Start) 251 } 252 } 253 .stateStyles({ 254 normal: this.normalStyle, 255 pressed: this.pressedStyle 256 }) 257 .constraintSize({ 258 minHeight: $r('app.float.wh_value_48') 259 }) 260 .onClick(() => { 261 this.rootCertificateDialog.open(); 262 }) 263 264 Divider() 265 .color($r('sys.color.ohos_id_color_list_separator')) 266 .margin({ 267 left: $r('app.float.wh_value_12'), 268 right: $r('app.float.wh_value_12') 269 }) 270 271 Row() { 272 Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 273 Text($r('app.string.system_credentials')) 274 .fontSize($r('sys.float.ohos_id_text_size_body1')) 275 .fontColor($r('sys.color.ohos_id_color_text_primary')) 276 .fontWeight(FontWeight.Medium) 277 .margin({ left: $r('app.float.wh_value_12') }) 278 .textAlign(TextAlign.Start) 279 } 280 .onClick(() => { 281 this.installCertFlag = false; 282 AppStorage.setOrCreate('installSystemCred', true); 283 AppStorage.setOrCreate('installUserCred', false); 284 if (this.isStartBySheet) { 285 this.startInstallEvidenceBySheet(); 286 } else { 287 this.mFaPresenter.startInstallEvidence(this.context); 288 } 289 }) 290 } 291 .stateStyles({ 292 normal: this.normalStyle, 293 pressed: this.pressedStyle 294 }) 295 .constraintSize({ 296 minHeight: $r('app.float.wh_value_48') 297 }) 298 299 Divider() 300 .color($r('sys.color.ohos_id_color_list_separator')) 301 .margin({ 302 left: $r('app.float.wh_value_12'), 303 right: $r('app.float.wh_value_12') 304 }) 305 306 Row() { 307 Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 308 Text($r('app.string.user_certificate_credentials')) 309 .fontSize($r('sys.float.ohos_id_text_size_body1')) 310 .fontColor($r('sys.color.ohos_id_color_text_primary')) 311 .fontWeight(FontWeight.Medium) 312 .margin({ left: $r('app.float.wh_value_12') }) 313 .textAlign(TextAlign.Start) 314 } 315 .onClick(() => { 316 this.installCertFlag = false; 317 AppStorage.setOrCreate('installUserCred', true); 318 AppStorage.setOrCreate('installSystemCred', false); 319 if (this.isStartBySheet) { 320 this.startInstallEvidenceBySheet(); 321 } else { 322 this.mFaPresenter.startInstallEvidence(this.context); 323 new UIContext().getHostContext() as common.Context; 324 } 325 }) 326 } 327 .stateStyles({ 328 normal: this.normalStyle, 329 pressed: this.pressedStyle 330 }) 331 .constraintSize({ 332 minHeight: $r('app.float.wh_value_48') 333 }) 334 } 335 .padding($r('app.float.wh_value_4')) 336 .backgroundColor($r('sys.color.ohos_id_color_card_bg')) 337 .borderRadius($r('app.float.radius_20')) 338 .width(ComponentConfig.WH_100_100) 339 } 340 .align(Alignment.Top) 341 .scrollable(ScrollDirection.Vertical) 342 .scrollBar(BarState.Off) 343 .width(WidthPercent.WH_100_100) 344 .edgeEffect(EdgeEffect.Spring) 345 .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100) 346 .padding({ 347 left: 16, 348 right: 16, 349 bottom: $r('app.float.wh_value_24') 350 }).constraintSize({ 351 minHeight: this.getScrollMinHeight() 352 }).onAreaChange((oldArea, newArea) => { 353 this.scrollerHeight = newArea.height as number; 354 }) 355 356 Column() { 357 ScrollBar({ 358 scroller: this.scroller, 359 direction: ScrollBarDirection.Vertical, 360 state: BarState.Auto 361 }).margin({ 362 bottom: $r('app.float.wh_value_24') 363 }) 364 }.height(this.scrollerHeight) 365 }.padding({ 366 top: this.headRectHeight 367 }) 368 } 369 .backgroundColor($r('sys.color.ohos_id_color_sub_background')) 370 .width(WidthPercent.WH_100_100) 371 .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100) 372 } 373 .width(WidthPercent.WH_100_100) 374 .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100); 375 } 376 } 377 .width(WidthPercent.WH_100_100) 378 .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100); 379 } 380 .backgroundColor($r('sys.color.ohos_id_color_sub_background')) 381 .width(WidthPercent.WH_100_100) 382 .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100); 383 } 384 385 getScrollMinHeight() { 386 if (this.sheetParam === undefined || this.headRectHeightReal === 0 || 387 this.sheetParam.sheetMinHeight < this.headRectHeightReal) { 388 return 0; 389 } 390 return this.sheetParam.sheetMinHeight - this.headRectHeightReal; 391 } 392 393 onPageShow() { 394 let uiExtensionFlag = GlobalContext.getContext().getFlag(); 395 let installType: string = GlobalContext.getContext().getAbilityWant().parameters?.installType as string; 396 let uri = GlobalContext.getContext().getAbilityWant().uri || 397 GlobalContext.getContext().getAbilityWant().parameters?.uri; 398 GlobalContext.getContext().clearAbilityWantUri(); 399 GlobalContext.getContext().clearAbilityWantParamsUri(); 400 if (uri === 'certInstall') { 401 router.pushUrl({ 402 url: 'pages/certInstallFromStorage' 403 }) 404 } else if (uri === 'requestAuthorize') { 405 this.mFaPresenter.startRequestAuth(GlobalContext.getContext().getAbilityWant().parameters?.appUid as string); 406 } else if (uiExtensionFlag && uri === 'systemCredInstall' && installType === 'systemCred') { 407 AppStorage.setOrCreate('installSystemCred', true); 408 AppStorage.setOrCreate('installUserCred', false); 409 this.mFaPresenter.startInstallEvidence(this.context); 410 } else if (uiExtensionFlag && uri === 'specifyInstall') { 411 let fileUri = GlobalContext.getContext().getAbilityWant().parameters?.fileUri as string; 412 this.mFaPresenter.startInstall(installType, fileUri); 413 } else { 414 console.error('The want type is not supported'); 415 } 416 } 417}