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