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