• 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 abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
20import bundleManager from '@ohos.bundle.bundleManager';
21import { BusinessError } from '@ohos.base';
22import { groups } from '../common/model/permissionGroup';
23import Constants from '../common/utils/constant';
24import { Log, verifyAccessToken, getGroupIdByPermission, supportPermission } from '../common/utils/utils';
25import { PermissionObj, AppInfo } from '../common/model/typedef';
26import { GlobalContext } from '../common/utils/globalContext';
27import { Permission } from '../common/model/definition';
28
29@Entry
30@Component
31struct appNamePlusPage {
32  private context = getContext(this) as common.UIAbilityContext;
33  @State allowedListItem: PermissionObj[] = []; // Array of allowed permissions
34  @State bannedListItem: PermissionObj[] = []; // array of forbidden permissions
35  @State applicationInfo: AppInfo = GlobalContext.load('applicationInfo'); // Routing jump data
36  @State bundleName: string = GlobalContext.load('bundleName');
37  @State label: string = '';
38  @State isTouch: string = '';
39  @State isGranted: number = Constants.PERMISSION_ALLOW;
40  @State folderStatus: boolean[] = [false, false, false];
41  @State reqUserPermissions: Permission[] = [];
42
43  @Builder ListItemLayout(item: PermissionObj, status: number) {
44    ListItem() {
45      Row() {
46        Column() {
47          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
48            Row() {
49              Text(item.groupName)
50                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
51                .fontColor($r('sys.color.font_primary'))
52                .fontWeight(FontWeight.Medium)
53                .flexGrow(Constants.FLEX_GROW)
54              SymbolGlyph($r('sys.symbol.chevron_forward'))
55                .width(Constants.IMAGE_WIDTH)
56                .height(Constants.IMAGE_HEIGHT)
57                .fontSize(Constants.FONT_SIZE_18_vp)
58                .fontColor([$r('sys.color.icon_tertiary')])
59                .fontWeight(FontWeight.Medium)
60            }
61            .width(Constants.FULL_WIDTH)
62            .height(Constants.LISTITEM_ROW_HEIGHT)
63          }
64        }.onClick(() => {
65          GlobalContext.store('currentPermissionGroup', item.group);
66          router.pushUrl({
67            url: item.group == 'OTHER' ? 'pages/other-permissions' : 'pages/application-tertiary',
68            params: {
69              bundleName: this.applicationInfo.bundleName,
70              backTitle: item.groupName,
71              permission: item.permission,
72              status,
73              tokenId: this.applicationInfo.tokenId
74            }
75          });
76        })
77      }
78    }.padding({ left: $r('sys.float.ohos_id_card_margin_start'), right: $r('sys.float.ohos_id_card_margin_end') })
79    .borderRadius($r('sys.float.ohos_id_corner_radius_default_l'))
80    .linearGradient((this.isTouch === item.group) ? {
81        angle: 90,
82        direction: GradientDirection.Right,
83        colors: [['#DCEAF9', 0.0], ['#FAFAFA', 1.0]]
84      } : {
85        angle: 90,
86        direction: GradientDirection.Right,
87        colors: [[$r('sys.color.comp_background_list_card'), 1], [$r('sys.color.comp_background_list_card'), 1]]
88      })
89    .onTouch(event => {
90      if (event === undefined) {
91        return;
92      }
93      if (event.type === TouchType.Down) {
94        this.isTouch = item.group;
95      }
96      if (event.type === TouchType.Up) {
97        this.isTouch = '';
98      }
99    })
100  }
101
102  async getReqUserPermissions(info: AppInfo) {
103    let acManager = abilityAccessCtrl.createAtManager();
104    if (info.permissions.length > 0) {
105      for (let j = 0; j < info.permissions.length; j++) {
106        let permission = info.permissions[j] as Permission;
107        let supportPermissions = supportPermission();
108        if (supportPermissions.indexOf(permission) == -1) {
109          continue;
110        }
111        try {
112          let flag = await acManager.getPermissionFlags(info.tokenId, permission);
113          if (flag == Constants.PERMISSION_SYSTEM_FIXED) {
114            continue;
115          }
116        } catch (err) {
117          Log.error('getPermissionFlags error: ' + JSON.stringify(err));
118        }
119        this.reqUserPermissions.push(permission);
120      }
121    }
122  }
123
124  async initApplicationInfo(info: AppInfo) {
125    Log.info(`labelResource: ` + JSON.stringify(info.labelResource));
126    let resourceManager = this.context.createBundleContext(info.bundleName).resourceManager;
127
128    if (info.labelResource.id !== 0) {
129      info.label = await this.context.resourceManager.getStringValue(info.labelResource);
130    } else {
131      info.label = await resourceManager.getStringValue(info.labelId);
132    }
133
134    try {
135      if (info.iconResource.id !== 0) {
136        let iconDescriptor = this.context.resourceManager.getDrawableDescriptor(info.iconResource);
137        info.icon = iconDescriptor?.getPixelMap();
138      } else {
139        let iconDescriptor = resourceManager.getDrawableDescriptor(info.iconId);
140        info.icon = iconDescriptor?.getPixelMap();
141      }
142    } catch (error) {
143      Log.error(`getDrawableDescriptor failed, error code: ${error.code}, message: ${error.message}.`);
144    }
145
146    if (!info.icon) {
147      info.icon = $r('app.media.icon');
148    }
149
150    this.reqUserPermissions = [];
151    await this.getReqUserPermissions(info);
152    let groupIds: number[] = [];
153    for (let i = 0; i < this.reqUserPermissions.length; i++) {
154      let groupId = getGroupIdByPermission(this.reqUserPermissions[i])
155      if (groupIds.indexOf(groupId) == -1) {
156        groupIds.push(groupId);
157      }
158    }
159    info.permissions = this.reqUserPermissions;
160    info.groupId = groupIds;
161  }
162
163  /**
164   * Initialize permission status information and group permission information
165   */
166  async initialPermissions() {
167    if (this.bundleName && !this.applicationInfo.groupId.length) {
168      await this.initApplicationInfo(this.applicationInfo);
169    }
170    let reqPermissions = this.applicationInfo.permissions;
171    let reqGroupIds = this.applicationInfo.groupId;
172
173    this.allowedListItem = [];
174    this.bannedListItem = [];
175
176    for (let i = 0; i < reqGroupIds.length; i++) {
177      let id = reqGroupIds[i];
178      let groupName = groups[id].groupName;
179      let group = groups[id].name;
180      let groupReqPermissions: Permissions[] = [];
181      for (let j = 0; j < reqPermissions.length; j++) {
182        let permission = reqPermissions[j];
183        if (groups[id].permissions.indexOf(permission) != -1) {
184          groupReqPermissions.push(permission);
185        }
186      }
187      this.isGranted = group === 'LOCATION' ? Constants.PERMISSION_BAN : Constants.PERMISSION_ALLOW;
188      this.folderStatus = [false, false, false];
189      await this.getStatus(groupReqPermissions, group);
190
191      if (
192        this.isGranted === Constants.PERMISSION_ALLOW || this.isGranted === Constants.PERMISSION_ALLOWED_ONLY_DURING_USE
193      ) {
194        this.allowedListItem.push(new PermissionObj(groupName, groupReqPermissions, group));
195      } else {
196        if (group === 'FOLDER' && this.folderStatus.includes(true)) {
197          this.allowedListItem.push(new PermissionObj(groupName, groupReqPermissions, group));
198        } else {
199          this.bannedListItem.push(new PermissionObj(groupName, groupReqPermissions, group));
200        }
201      }
202
203      GlobalContext.store('folderStatus', this.folderStatus);
204    }
205  }
206
207  async getStatus(groupReqPermissions: Permissions[], group: string) {
208    if (group === 'LOCATION') {
209      try {
210        let acManager = abilityAccessCtrl.createAtManager();
211        let fuzzyState = acManager.verifyAccessTokenSync(
212          this.applicationInfo.tokenId, Permission.APPROXIMATELY_LOCATION
213        );
214        fuzzyState === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED ?
215          this.isGranted = Constants.PERMISSION_ALLOWED_ONLY_DURING_USE : null;
216        let backgroundState = acManager.verifyAccessTokenSync(
217          this.applicationInfo.tokenId, Permission.LOCATION_IN_BACKGROUND
218        );
219        backgroundState === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED ?
220          this.isGranted = Constants.PERMISSION_ALLOW : null;
221        await acManager.getPermissionFlags(this.applicationInfo.tokenId, Permission.APPROXIMATELY_LOCATION )
222        .then(flag => {
223          flag === Constants.PERMISSION_ALLOW_THIS_TIME ? this.isGranted = Constants.PERMISSION_ONLY_THIS_TIME : null;
224        })
225      } catch (err) {
226        Log.error('change location status error: ' + JSON.stringify(err));
227      }
228      GlobalContext.store('locationStatus', this.isGranted);
229      return true;
230    }
231    for (let i = 0; i < groupReqPermissions.length; i++) {
232      let permission = groupReqPermissions[i];
233      let res = await verifyAccessToken(this.applicationInfo.tokenId, permission);
234      if (res != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
235        this.isGranted = Constants.PERMISSION_BAN;
236      }
237      if (group === 'FOLDER' && res === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
238        switch (permission) {
239          case Permission.READ_WRITE_DOWNLOAD_DIRECTORY:
240            this.folderStatus[0] = true;
241            break;
242          case Permission.READ_WRITE_DESKTOP_DIRECTORY:
243            this.folderStatus[1] = true;
244            break;
245          case Permission.READ_WRITE_DOCUMENTS_DIRECTORY:
246            this.folderStatus[2] = true;
247            break;
248        }
249      }
250    }
251    return true;
252  }
253
254  /**
255   * Lifecycle function, triggered once when this page is displayed
256   */
257  onPageShow() {
258    this.initialPermissions();
259    bundleManager.getApplicationInfo(
260      this.applicationInfo.bundleName, bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT
261    ).then(appInfo => {
262      let bundleContext = this.context.createBundleContext(this.applicationInfo.bundleName)
263      bundleContext.resourceManager.getStringValue(appInfo.labelId, (error, value) => {
264        if (value) {
265          this.applicationInfo.label = value;
266          GlobalContext.store('applicationInfo', this.applicationInfo);
267          this.label = value
268        }
269      })
270    }).catch((error: BusinessError) => {
271      Log.error('getApplicationInfo error: ' + JSON.stringify(error));
272    })
273  }
274
275  build() {
276    Column() {
277      GridRow({ gutter: Constants.GUTTER, columns: {
278        xs: Constants.XS_COLUMNS, sm: Constants.SM_COLUMNS, md: Constants.MD_COLUMNS, lg: Constants.LG_COLUMNS } }) {
279        GridCol({
280          span: { xs: Constants.XS_SPAN, sm: Constants.SM_SPAN, md: Constants.MD_SPAN, lg: Constants.LG_SPAN },
281          offset: { xs: Constants.XS_OFFSET, sm: Constants.SM_OFFSET, md: Constants.MD_OFFSET, lg: Constants.LG_OFFSET }
282        }) {
283          Row() {
284            Column() {
285              Row() {
286                backBar({ title: JSON.stringify(this.label || this.applicationInfo.label), recordable: false })
287              }
288              Row() {
289                Column() {
290                  if (!this.allowedListItem.length && !this.bannedListItem.length) {
291                    Row() {
292                      List() {
293                        ListItem() {
294                          Row() {
295                            Column() {
296                              Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
297                                Row() {
298                                  Column() {
299                                    Row() {
300                                      Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
301                                        Text($r('app.string.no_permission'))
302                                          .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
303                                          .fontColor($r('sys.color.font_primary'))
304                                      }.margin({ top: Constants.FLEX_MARGIN_TOP, bottom: Constants.FLEX_MARGIN_BOTTOM })
305                                    }.height(Constants.FULL_HEIGHT)
306                                  }.flexGrow(Constants.FLEX_GROW)
307                                   .constraintSize({minHeight: Constants.CONSTRAINTSIZE_MINHEIGHT })
308                                }
309                                .width(Constants.FULL_WIDTH)
310                                .height(Constants.LISTITEM_ROW_HEIGHT)
311                              }
312                            }
313                          }
314                        }.padding({ left: Constants.LISTITEM_PADDING_LEFT, right: Constants.LISTITEM_PADDING_RIGHT })
315                      }
316                      .backgroundColor($r('sys.color.comp_background_list_card'))
317                      .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
318                      .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
319                    }.margin({ top: Constants.ROW_MARGIN_TOP })
320                     .padding({
321                       left: Constants.SECONDARY_LIST_PADDING_LEFT,
322                       right: Constants.SECONDARY_LIST_PADDING_RIGHT
323                     })
324                  } else {
325                    Scroll() {
326                      List() {
327                        if (this.allowedListItem.length) {
328                          ListItem() {
329                            Row() {
330                              Text($r('app.string.allowed'))
331                                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
332                                .fontColor($r('sys.color.font_secondary'))
333                                .fontWeight(FontWeight.Medium)
334                                .lineHeight(Constants.SUBTITLE_LINE_HEIGHT)
335                            }.constraintSize({ minHeight: Constants.SUBTITLE_MIN_HEIGHT })
336                            .width(Constants.FULL_WIDTH)
337                            .padding({ top: Constants.SUBTITLE_PADDING_TOP, bottom: Constants.SUBTITLE_PADDING_BOTTOM,
338                              left: Constants.SECONDARY_TEXT_MARGIN_LEFT})
339                          }
340
341                          ListItem() {
342                            Row() {
343                              List() {
344                                ForEach(this.allowedListItem, (item: PermissionObj) => {
345                                  this.ListItemLayout(item, Constants.PERMISSION_ALLOW)
346                                }, (item: PermissionObj) => JSON.stringify(item))
347                              }
348                              .backgroundColor($r('sys.color.comp_background_list_card'))
349                              .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
350                              .padding(Constants.LIST_PADDING_TOP)
351                              .divider({
352                                strokeWidth: Constants.DIVIDER,
353                                color: $r('sys.color.comp_divider'),
354                                startMargin: Constants.DEFAULT_MARGIN_START,
355                                endMargin: Constants.DEFAULT_MARGIN_END
356                              })
357                            }.margin({ top: Constants.ROW_MARGIN_TOP })
358                            .padding({
359                              left: Constants.SECONDARY_LIST_PADDING_LEFT,
360                              right: Constants.SECONDARY_LIST_PADDING_RIGHT
361                            })
362                          }
363                        }
364                        if (this.bannedListItem.length) {
365                          ListItem() {
366                            Row() {
367                              Text($r('app.string.banned'))
368                                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
369                                .fontColor($r('sys.color.font_secondary'))
370                                .fontWeight(FontWeight.Medium)
371                                .lineHeight(Constants.SUBTITLE_LINE_HEIGHT)
372                            }.constraintSize({ minHeight: Constants.SUBTITLE_MIN_HEIGHT })
373                            .width(Constants.FULL_WIDTH)
374                            .padding({ top: Constants.SUBTITLE_PADDING_TOP, bottom: Constants.SUBTITLE_PADDING_BOTTOM,
375                              left: Constants.SECONDARY_TEXT_MARGIN_LEFT})
376                          }
377
378                          ListItem() {
379                            Row() {
380                              List() {
381                                ForEach(this.bannedListItem, (item: PermissionObj) => {
382                                  this.ListItemLayout(item, Constants.PERMISSION_BAN)
383                                }, (item: PermissionObj) => JSON.stringify(item))
384                              }
385                              .backgroundColor($r('sys.color.comp_background_list_card'))
386                              .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
387                              .padding(Constants.LIST_PADDING_TOP)
388                              .divider({
389                                strokeWidth: Constants.DIVIDER,
390                                color: $r('sys.color.comp_divider'),
391                                startMargin: Constants.DEFAULT_MARGIN_START,
392                                endMargin: Constants.DEFAULT_MARGIN_END
393                              })
394                            }.margin({ top: Constants.ROW_MARGIN_TOP })
395                            .padding({
396                              left: Constants.SECONDARY_LIST_PADDING_LEFT,
397                              right: Constants.SECONDARY_LIST_PADDING_RIGHT
398                            })
399                          }
400                        }
401                      }
402                    }.scrollBar(BarState.Off)
403                  }
404                }
405                .width(Constants.FULL_WIDTH)
406                .height(Constants.FULL_HEIGHT)
407              }
408              .layoutWeight(Constants.LAYOUT_WEIGHT)
409            }
410          }
411          .height(Constants.FULL_HEIGHT)
412          .width(Constants.FULL_WIDTH)
413          .backgroundColor($r('sys.color.background_secondary'))
414        }
415      }.backgroundColor($r('sys.color.background_secondary'))
416    }
417  }
418}
419