• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2023 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 { backBar } from "../common/components/backBar";
17import router from '@ohos.router';
18import common from '@ohos.app.ability.common';
19import bundleManager from '@ohos.bundle.bundleManager';
20import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
21import { BusinessError } from '@ohos.base';
22import { showSubpermissionsGrop } from "../common/model/permissionGroup";
23import { verifyAccessToken, getPermissionLabel } from "../common/utils/utils";
24import Constants from '../common/utils/constant';
25import { MediaDocObj, routerParams_3, appInfo } from '../common/utils/typedef';
26import { GlobalContext } from '../common/utils/globalContext';
27
28const TAG = 'PermissionManager_MainAbility:';
29const PRECISE_LOCATION_PERMISSION = 'ohos.permission.LOCATION';
30let api: number = 0;
31let nowGrantResult = Constants.PERMISSION_NUM; // Authorization results now
32let nowRevokeResult = Constants.PERMISSION_NUM; // Now deauthorize results
33let GrantResultFlag: number[] = []; // Authorization result Flag
34let RevokeResultFlag: number[] = []; // Cancel authorization result Flag
35let accessTokenId: number = 0;
36let reqPermissionInfo: bundleManager.ReqPermissionDetail;
37
38@Entry
39@Component
40struct mediaDocumentPage {
41  private backTitle: ResourceStr = (router.getParams() as routerParams_3).backTitle;
42  private permissions: Permissions[] = (router.getParams() as routerParams_3).permission;
43  private tokenId: number = (router.getParams() as routerParams_3).tokenId;
44  @State refresh: boolean = false;
45  @State isCheckList: boolean[] = []; // Permission status array
46  @State isRefreshReason: number = 0
47
48  build() {
49    Column() {
50      GridRow({ gutter: Constants.GUTTER, columns: {
51        xs: Constants.XS_COLUMNS, sm: Constants.SM_COLUMNS, md: Constants.MD_COLUMNS, lg: Constants.LG_COLUMNS } }) {
52        GridCol({ span: { xs: Constants.XS_SPAN, sm: Constants.SM_SPAN, md: Constants.MD_SPAN, lg: Constants.LG_SPAN },
53          offset: { xs: Constants.XS_OFFSET, sm: Constants.SM_OFFSET, md: Constants.MD_OFFSET, lg: Constants.LG_OFFSET } }) {
54          Row() {
55            Column() {
56              Row() {
57                backBar({ title: JSON.stringify(this.backTitle), recordable: false })
58              }
59              Row() {
60                Column() {
61                  mediaDocumentItem({ isCheckList: $isCheckList, isRefreshReason: $isRefreshReason })
62                }.width(Constants.FULL_WIDTH)
63              }
64              .margin({ top: Constants.TITLE_MARGIN_BOTTOM })
65              .layoutWeight(Constants.LAYOUT_WEIGHT)
66            }
67          }
68          .height(Constants.FULL_HEIGHT)
69          .width(Constants.FULL_WIDTH)
70          .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
71        }
72      }.backgroundColor($r("sys.color.ohos_id_color_sub_background"))
73    }
74  }
75
76  onPageShow() {
77    console.log(TAG + 'onPageShow');
78    if (this.refresh) this.refreshStatus();
79    this.refresh = true;
80  }
81
82  async refreshStatus() {
83    this.isRefreshReason ++;
84    console.log(TAG + 'Refresh permission status');
85    let isGranted = true;
86    for (let i = 0; i < this.permissions.length; i++) {
87      let permission = this.permissions[i];
88      if (api >= Constants.API_VERSION_SUPPORT_STAGE && permission == PRECISE_LOCATION_PERMISSION) {
89        continue;
90      }
91      let res = await verifyAccessToken(this.tokenId, permission);
92      if (res != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
93        isGranted = false;
94      }
95    }
96    console.log(TAG + 'isGranted: ' + JSON.stringify(isGranted));
97
98    if (isGranted) {
99      this.isCheckList = [true, false];
100    } else {
101      this.isCheckList = [false, true];
102    }
103  }
104}
105
106@Component
107struct mediaDocumentItem {
108  private context = getContext(this) as common.UIAbilityContext;
109  private backTitle: ResourceStr = (router.getParams() as routerParams_3).backTitle;
110  private bundleName: string = (router.getParams() as routerParams_3).bundleName;
111  private permissions: Permissions[] = (router.getParams() as routerParams_3).permission;
112  private status: number = (router.getParams() as routerParams_3).status;
113  @State currentGroup: string = GlobalContext.load('currentPermissionGroup');
114  @State applicationInfo: appInfo = GlobalContext.load('applicationInfo');
115  @State mediaDocListItem: MediaDocObj[] = []; // Permission information array
116  @Link isCheckList: boolean[]; // Permission status array
117  @State accurateIsOn: boolean = true;
118  @State api: number = 0;
119  @State isRisk: boolean = false; // Whether it is a risky application
120  @State isTouch: number = -1;
121  @State reason: string = '';
122  @State label: string = '';
123  @State version: string = '';
124  @State permissionLabels: Array<ResourceStr> = [];
125  @Link @Watch("updateReason") isRefreshReason: number;
126
127  /**
128   * Grant permissions to the app
129   * @param {Number} accessTokenId
130   * @param {String} permission permission name
131   */
132  grantUserGrantedPermission(accessTokenId: number, permission: Permissions) {
133    abilityAccessCtrl.createAtManager().grantUserGrantedPermission(accessTokenId, permission, Constants.PERMISSION_FLAG)
134      .then(() => {
135        nowGrantResult = Constants.PERMISSION_INDEX;
136      })
137      .catch((error: BusinessError) => {
138        console.error(TAG + 'grantUserGrantedPermission failed. Cause: ' + JSON.stringify(error));
139      })
140  }
141
142  /**
143   * Deauthorize the app
144   * @param {Number} accessTokenId
145   * @param {String} permission permission name
146   */
147  revokeUserGrantedPermission(accessTokenId: number, permission: Permissions) {
148    abilityAccessCtrl.createAtManager().revokeUserGrantedPermission(accessTokenId, permission, Constants.PERMISSION_FLAG)
149      .then(() => {
150        nowRevokeResult = Constants.PERMISSION_INDEX;
151      })
152      .catch((error: BusinessError) => {
153        console.error(TAG + 'revokeUserGrantedPermission failed. Cause: ' + JSON.stringify(error));
154      })
155  }
156
157  /**
158   * Update reason
159   */
160  updateReason() {
161    bundleManager.getApplicationInfo(this.applicationInfo.bundleName, bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT).then(appInfo => {
162      let bundleContext = this.context.createBundleContext(this.bundleName)
163      bundleContext.resourceManager.getStringValue(appInfo.labelId, (error, value) => {
164        if (value) {
165          this.applicationInfo.label = value;
166          GlobalContext.store('applicationInfo', this.applicationInfo);
167          this.label = value
168        }
169      })
170    }).catch((error: BusinessError) => {
171      console.error(TAG + 'getApplicationInfo error: ' + JSON.stringify(error));
172    })
173    let context = this.context.createModuleContext(this.bundleName, reqPermissionInfo.moduleName);
174    context.resourceManager.getStringValue(reqPermissionInfo.reasonId).then(value => {
175      if (value !== undefined) {
176        this.reason = value.slice(Constants.START_SUBSCRIPT, Constants.END_SUBSCRIPT);
177      }
178    })
179  }
180
181  /**
182   * Lifecycle function, executed when the page is initialized
183   */
184  aboutToAppear() {
185    this.label = this.applicationInfo.label;
186    if (showSubpermissionsGrop.indexOf(this.currentGroup) != -1) {
187      this.permissions.forEach((permission, idx) => {
188        if (idx > 0) {
189          this.permissionLabels.push($r("app.string.and"))
190        }
191        let label = getPermissionLabel(permission)
192        this.permissionLabels.push(label);
193      })
194    }
195    let hasReason = false;
196    bundleManager.getBundleInfo(this.bundleName, bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION).then(info => {
197      this.permissions.forEach(permission => {
198        info.reqPermissionDetails.forEach(reqPermissionDetail => {
199          if (reqPermissionDetail.name == permission) {
200            console.info("reqPermissionDetail: " + JSON.stringify(reqPermissionDetail));
201            let context = this.context.createModuleContext(this.bundleName, reqPermissionDetail.moduleName);
202            context.resourceManager.getStringValue(reqPermissionDetail.reasonId).then(value => {
203              if (value !== undefined && !hasReason) {
204                this.reason = value.slice(Constants.START_SUBSCRIPT, Constants.END_SUBSCRIPT);
205                reqPermissionInfo = reqPermissionDetail;
206                hasReason = true;
207              }
208            })
209          }
210        })
211      })
212    })
213    bundleManager.getBundleInfo(this.bundleName, bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).then(res => {
214      this.api = res.targetVersion;
215      this.version = res.versionName;
216      api = res.targetVersion;
217      accessTokenId = res.appInfo.accessTokenId;
218      let acManager = abilityAccessCtrl.createAtManager();
219      let accurateStatus = acManager.verifyAccessTokenSync(res.appInfo.accessTokenId, PRECISE_LOCATION_PERMISSION);
220      this.accurateIsOn = (accurateStatus == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) ? true : false;
221      try {
222        acManager.getPermissionFlags(res.appInfo.accessTokenId, this.permissions[0]).then((data) => {
223          console.log(TAG + `getPermissionFlags success, data->${JSON.stringify(data)}`);
224          this.isRisk = (data == Constants.PERMISSION_POLICY_FIXED) ? true : false;
225        })
226      } catch(err) {
227        console.log(TAG + 'acManager.getPermissionFlags failed. Cause: ' + JSON.stringify(err));
228      }
229      this.mediaDocListItem.push(
230        new MediaDocObj($r('app.string.allow'), res.appInfo.accessTokenId, this.permissions, 0)
231      );
232      this.mediaDocListItem.push(
233        new MediaDocObj($r('app.string.ban'), res.appInfo.accessTokenId, this.permissions, 1)
234      );
235    }).catch((error: BusinessError) => {
236      console.error(TAG + 'bundle.getBundleInfo failed. Cause: ' + JSON.stringify(error));
237      this.mediaDocListItem.push(
238        new MediaDocObj($r('app.string.allow'), 0, this.permissions, 0)
239      );
240      this.mediaDocListItem.push(
241        new MediaDocObj($r('app.string.ban'), 0, this.permissions, 1)
242      );
243    })
244    // Get permission status
245    if (!this.status) {
246      this.isCheckList = [true, false];
247    } else {
248      this.isCheckList = [false, true];
249    }
250  }
251
252  build(){
253    Column() {
254      Row() {
255        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
256          Image(this.applicationInfo.icon)
257            .width(Constants.TERTIARY_IMAGE_WIDTH)
258            .height(Constants.TERTIARY_IMAGE_HEIGHT)
259            .margin({ left: Constants.TERTIARY_IMAGE_MARGIN_LEFT, right: Constants.TERTIARY_IMAGE_MARGIN_RIGHT })
260          Column() {
261            Row() {
262              Text(this.label)
263                .maxLines(Constants.MAXIMUM_HEADER_LINES)
264                .textOverflow({ overflow: TextOverflow.Ellipsis })
265                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
266                .fontColor($r('sys.color.ohos_id_color_text_primary'))
267                .fontWeight(FontWeight.Bold)
268                .textAlign(TextAlign.Start)
269            }
270            .width(Constants.TERTIARY_HALF_WIDTH)
271            .margin({ bottom: Constants.TERTIARY_LABEL_MARGIN_BOTTOM })
272            Row() {
273              Text($r('app.string.version'))
274                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
275                .fontColor($r('sys.color.ohos_id_color_text_secondary'))
276                .textAlign(TextAlign.Start)
277              Text(this.version)
278                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
279                .fontColor($r('sys.color.ohos_id_color_text_secondary'))
280                .textAlign(TextAlign.Start)
281            }
282            .width(Constants.TERTIARY_HALF_WIDTH)
283          }
284        }.margin({ left: Constants.TERTIARY_MARGIN_LEFT })
285      }
286      if (this.reason || this.permissionLabels.length > 0) {
287        Row() {
288          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
289            Row() {
290              Text() {
291                if (this.permissionLabels.length > 0) {
292                  ForEach(this.permissionLabels, (item: ResourceStr) => {
293                    Span(item)
294                  })
295                  Span(this.reason ? $r("app.string.comma") : $r("app.string.period"))
296                }
297                Span(this.reason)
298              }
299                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
300                .fontColor($r('sys.color.ohos_id_color_secondary'))
301                .textAlign(TextAlign.Start)
302            }.margin({ left: Constants.TERTIARY_IMAGE_MARGIN_LEFT, right: Constants.TERTIARY_IMAGE_MARGIN_RIGHT })
303          }
304        }
305        .margin({ top: Constants.TERTIARY_ROW_MARGIN_TOP, left: Constants.DEFAULT_MARGIN_START, bottom: Constants.DEFAULT_MARGIN_BOTTOM })
306      }
307      if (this.isRisk) {
308        Row() {
309          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
310            Row() {
311              Image($r('app.media.ic_public_fail'))
312                .fillColor($r('sys.color.ohos_id_color_secondary'))
313                .width(Constants.TERTIARY_RADIO_IMAGE_WIDTH)
314                .height(Constants.TERTIARY_RADIO_IMAGE_HEIGHT)
315                .margin({ right: Constants.TERTIARY_IMAGE_MARGIN_RIGHT })
316              Text($r('app.string.risk_warning'))
317                .fontColor($r('sys.color.ohos_id_color_text_primary'))
318                .fontSize($r('sys.float.ohos_id_text_size_body1'))
319                .fontWeight(FontWeight.Regular)
320            }.margin({ left: Constants.DEFAULT_PADDING_START, right: Constants.DEFAULT_PADDING_END })
321          }
322        }.backgroundColor($r('sys.color.ohos_id_color_click_effect'))
323        .borderRadius($r('sys.float.ohos_id_corner_radius_default_l'))
324        .padding({ top: Constants.DEFAULT_PADDING_TOP, bottom: Constants.DEFAULT_PADDING_BOTTOM })
325        .margin({ left: Constants.DEFAULT_MARGIN_START, right: Constants.DEFAULT_MARGIN_END })
326      }
327      Row() {
328        Text() {
329          Span(this.backTitle)
330          Span($r('app.string.access_permission'))
331        }
332          .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
333          .fontColor($r('sys.color.ohos_id_color_secondary'))
334          .fontWeight(FontWeight.Medium)
335          .textAlign(TextAlign.Start)
336          .lineHeight(Constants.SUBTITLE_LINE_HEIGHT)
337      }.width(Constants.FULL_WIDTH)
338      .constraintSize({ minHeight: Constants.SUBTITLE_MIN_HEIGHT })
339      .padding({ top: Constants.SUBTITLE_PADDING_TOP, bottom: Constants.SUBTITLE_PADDING_BOTTOM,
340        left: Constants.TERTIARY_TEXT_MARGIN_LEFT, right: Constants.TERTIARY_IMAGE_MARGIN_RIGHT})
341      Column() {
342        List() {
343          ForEach(this.mediaDocListItem, (item: MediaDocObj) => {
344            ListItem() {
345              Column() {
346                Row() {
347                  Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
348                    Row() {
349                      Text(item.name)
350                        .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
351                        .fontColor($r('sys.color.ohos_id_color_text_primary'))
352                        .fontWeight(FontWeight.Medium)
353                        .flexGrow(Constants.FLEX_GROW)
354                      Radio({ value: 'Radio', group: 'radioGroup' })
355                        .checked(this.isCheckList[item.index])
356                        .touchable(false)
357                        .height(Constants.SHAPE_DIA)
358                        .width(Constants.SHAPE_DIA)
359                    }
360                    .width(Constants.FULL_WIDTH)
361                    .height(Constants.LISTITEM_ROW_HEIGHT)
362                    .onClick(() => {
363                        let index = item.index;
364                        item.permissions.forEach((permission): boolean => {
365                          if (!index) {
366                            if ((this.api >= Constants.API_VERSION_SUPPORT_STAGE) && (permission == PRECISE_LOCATION_PERMISSION)) {
367                              return false;
368                            }
369                            this.grantUserGrantedPermission(item.accessTokenId, permission);
370                            if (nowGrantResult != Constants.PERMISSION_INDEX) {
371                              GrantResultFlag.push(-1);
372                            } else {
373                              GrantResultFlag.push(0);
374                            }
375                          } else {
376                            if ((permission == PRECISE_LOCATION_PERMISSION) && (this.api >= Constants.API_VERSION_SUPPORT_STAGE)) {
377                              if (this.accurateIsOn) {
378                                this.revokeUserGrantedPermission(item.accessTokenId, permission);
379                                this.accurateIsOn = false;
380                              }
381                            } else {
382                              this.revokeUserGrantedPermission(item.accessTokenId, permission);
383                            }
384
385                            if (nowRevokeResult != Constants.PERMISSION_INDEX) {
386                              RevokeResultFlag.push(-1);
387                            } else {
388                              RevokeResultFlag.push(0);
389                            }
390                          }
391                          return true;
392                        })
393                        if (!index) {
394                          if (GrantResultFlag.indexOf(-1) <= -1) {
395                            this.isCheckList = [true, false];
396                          }
397                        } else {
398                          if (RevokeResultFlag.indexOf(-1) <= -1) {
399                            this.isCheckList = [false, true];
400                          }
401                        }
402                    })
403                  }
404                }
405              }
406            }
407            .padding({ left: $r('sys.float.ohos_id_card_margin_start'), right: $r('sys.float.ohos_id_card_margin_end') })
408            .borderRadius($r("sys.float.ohos_id_corner_radius_default_l"))
409            .linearGradient((this.isTouch === item.index) ? {
410                angle: 90,
411                direction: GradientDirection.Right,
412                colors: [['#DCEAF9', 0.0], ['#FAFAFA', 1.0]]
413              } : {
414                angle: 90,
415                direction: GradientDirection.Right,
416                colors: [[$r("sys.color.ohos_id_color_list_card_bg"), 1], [$r("sys.color.ohos_id_color_list_card_bg"), 1]]
417              })
418            .onTouch(event => {
419              if (event === undefined) {
420                return;
421              }
422              if (event.type === TouchType.Down) {
423                this.isTouch = item.index;
424              }
425              if (event.type === TouchType.Up) {
426                this.isTouch = -1;
427              }
428            })
429            .margin({ top: Constants.TERTIARY_LISTITEM_MARGIN_TOP })
430          }, (item: MediaDocObj) => JSON.stringify(item))
431        }
432        .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
433        .backgroundColor($r('sys.color.ohos_id_color_list_card_bg'))
434        .padding(Constants.LIST_PADDING_TOP)
435        .divider({
436          strokeWidth: Constants.DIVIDER,
437          color: $r('sys.color.ohos_id_color_list_separator'),
438          startMargin: Constants.DEFAULT_MARGIN_START,
439          endMargin: Constants.DEFAULT_MARGIN_END
440        })
441
442        if ((this.api >= Constants.API_VERSION_SUPPORT_STAGE) && (this.permissions.includes(PRECISE_LOCATION_PERMISSION))) {
443          Column() {
444            Row() {
445              Text($r('app.string.precise_location'))
446                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
447                .fontColor($r('sys.color.ohos_id_color_text_primary'))
448                .fontWeight(FontWeight.Medium)
449                .flexGrow(Constants.FLEX_GROW)
450              Toggle({ type: ToggleType.Switch, isOn: this.accurateIsOn })
451                .selectedColor($r('sys.color.ohos_id_color_toolbar_icon_actived'))
452                .switchPointColor($r('sys.color.ohos_id_color_foreground_contrary'))
453                .onChange((isOn: boolean) => {
454                  let acManager = abilityAccessCtrl.createAtManager()
455                  if (isOn) {
456                    acManager.grantUserGrantedPermission(accessTokenId, PRECISE_LOCATION_PERMISSION, Constants.PERMISSION_FLAG)
457                      .then(() => { this.accurateIsOn = true })
458                  } else {
459                    acManager.revokeUserGrantedPermission(accessTokenId, PRECISE_LOCATION_PERMISSION, Constants.PERMISSION_FLAG)
460                      .then(() => { this.accurateIsOn = false })
461                  }
462                })
463                .padding({ right: 0 })
464                .enabled(this.isCheckList[0])
465            }.width(Constants.FULL_WIDTH)
466            .height(Constants.LISTITEM_ROW_HEIGHT)
467          }.margin({ top: Constants.LOCATION_MARGIN_TOP, bottom: Constants.LOCATION_MARGIN_BOTTOM })
468          .padding({
469            left: Constants.DEFAULT_PADDING_START,
470            right: Constants.DEFAULT_PADDING_END,
471            top: Constants.TERTIARY_LIST_PADDING_TOP,
472            bottom: Constants.TERTIARY_LIST_PADDING_BOTTOM
473          })
474          .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
475          .backgroundColor($r('sys.color.ohos_id_color_list_card_bg'))
476
477          Row() {
478            Text($r('app.string.get_the_exact_position'))
479              .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
480              .fontColor($r('sys.color.ohos_id_color_text_secondary'))
481              .lineHeight(Constants.TEXT_SMALL_LINE_HEIGHT)
482          }.width(Constants.FULL_WIDTH)
483          .padding({
484            left: Constants.DEFAULT_PADDING_START,
485            right: Constants.DEFAULT_PADDING_END,
486          })
487        }
488      }
489      .padding({
490        left: Constants.LIST_PADDING_LEFT,
491        right: Constants.LIST_PADDING_LEFT
492      })
493      .width(Constants.FULL_WIDTH)
494      .height(Constants.FULL_HEIGHT)
495      .enabled(!this.isRisk)
496      .opacity(this.isRisk ? $r('sys.float.ohos_id_alpha_disabled') : 1)
497    }
498    .width(Constants.FULL_WIDTH)
499  }
500}
501