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 abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
17import bundleManager from '@ohos.bundle.bundleManager';
18import rpc from '@ohos.rpc';
19import window from '@ohos.window';
20import common from '@ohos.app.ability.common';
21import pasteboard from '@ohos.pasteboard';
22import { BusinessError } from '@ohos.base';
23import { CustomContentDialog } from '@ohos.arkui.advanced.Dialog';
24import {
25  Log,
26  getPermissionGroup,
27  titleTrim,
28  getPermissionLabel,
29  getFontSizeScale,
30  getLimitFontSize
31} from '../common/utils/utils';
32import { GroupInfo, WantInfo } from '../common/model/typedef';
33import { GlobalContext } from '../common/utils/globalContext';
34import Constants from '../common/utils/constant';
35import { showSubPermissionsGroup, userGrantPermissions } from '../common/model/permissionGroup';
36import { LocationCanvas } from '../common/components/location';
37
38@Extend(Button)function customizeButton() {
39  .buttonStyle(ButtonStyleMode.TEXTUAL)
40  .fontColor($r('sys.color.font_emphasize'))
41  .width(Constants.HALF_LENGTH)
42}
43
44const FUZZY_LOCATION_PERMISSION = 'ohos.permission.APPROXIMATELY_LOCATION';
45const PRECISE_LOCATION_PERMISSION = 'ohos.permission.LOCATION';
46const PASTE = 'ohos.permission.READ_PASTEBOARD';
47const APP_TRACKING_CONSENT = 'ohos.permission.APP_TRACKING_CONSENT';
48const DOWNLOAD_PERMISSION = 'ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY';
49const DESKTOP_PERMISSION = 'ohos.permission.READ_WRITE_DESKTOP_DIRECTORY';
50const DOCUMENTS_PERMISSION = 'ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY';
51const fuzzyMarks = [Constants.LOCATION_FUZZY, Constants.LOCATION_BOTH_FUZZY, Constants.LOCATION_BOTH_PRECISE];
52const preciseMarks = [Constants.LOCATION_UPGRADE, Constants.LOCATION_BOTH_PRECISE];
53let storage = LocalStorage.getShared();
54
55@Entry(storage)
56@Component
57struct dialogPlusPage {
58  @LocalStorageLink('want') want: WantInfo = new WantInfo([]);
59  @LocalStorageLink('win') win: window.Window = {} as window.Window;
60  private context = getContext(this) as common.ServiceExtensionContext;
61  @State count: number = 0;
62  @State result: Array<number> = [];
63  @State accessTokenId: number = 0;
64  @State initStatus: number = Constants.INIT_NEED_TO_WAIT;
65  @State reqPerms: Array<string> = [];
66  @State grantGroups: Array<GroupInfo> = [];
67  @State userFixedFlag: number = 2; // means user fixed
68  @State grantStatus: number = -1;
69  @State appName: string = '';
70  @State locationFlag: number = Constants.LOCATION_NONE;
71  @State reqPermissionDetails: bundleManager.ReqPermissionDetail[] = [];
72  @State refresh: number = 0;
73  @State pasteBoardName: string = '';
74  @State isUpdate: number = -1;
75
76  dialogController: CustomDialogController | null = new CustomDialogController({
77    builder: CustomContentDialog({
78      contentBuilder: () => {
79        this.buildContent();
80      },
81      contentAreaPadding: { right: 0 }
82    }),
83    autoCancel: false
84  });
85
86  @Builder
87  buildContent(): void {
88    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
89      Column() {
90        if ((this.initStatus != Constants.INIT_NEED_TO_WAIT) && this.verify()) {
91          Image(this.currentGroup().icon)
92            .width(Constants.DIALOG_ICON_WIDTH)
93            .height(Constants.DIALOG_ICON_HEIGHT)
94            .fillColor($r('sys.color.font_primary'))
95            .margin({ top: Constants.DIALOG_ICON_MARGIN_TOP })
96          if (this.grantGroups.length > 1) {
97            Text(`${this.count + 1} / ${this.grantGroups.length}`)
98              .fontSize(Constants.DIALOG_LABEL_FONT_SIZE)
99              .fontColor($r('sys.color.font_secondary'))
100              .lineHeight(Constants.DIALOG_LABEL_LINE_HEIGHT)
101              .margin({ top: Constants.DIALOG_LABEL_MARGIN_TOP })
102          }
103          Scroll() {
104            Column() {
105              Row() {
106                Column() {
107                  Text($r(this.showTitle(), this.appName))
108                  .textAlign(TextAlign.Center)
109                  .fontSize($r('sys.float.Title_S'))
110                  .fontColor($r('sys.color.font_primary'))
111                  .fontWeight(FontWeight.Bold)
112                  .textOverflow({ overflow: TextOverflow.Ellipsis })
113                  .maxLines(Constants.SECURITY_HEADER_MAX_LINES)
114                  .minFontSize(
115                    getLimitFontSize(getFontSizeScale(),
116                    Constants.DIALOG_TITLE_MAX_SCALE,
117                    $r('sys.float.Subtitle_M'),
118                    $r('sys.float.Title_S'))
119                  )
120                  .maxFontSize(
121                    getLimitFontSize(getFontSizeScale(),
122                    Constants.DIALOG_TITLE_MAX_SCALE,
123                    $r('sys.float.Title_S'),
124                    $r('sys.float.Title_S'))
125                  )
126                  .heightAdaptivePolicy(TextHeightAdaptivePolicy.MIN_FONT_SIZE_FIRST)
127                }
128                .constraintSize({ minHeight: Constants.HEADLINE_HEIGHT })
129                .justifyContent(FlexAlign.Center)
130                .padding({
131                  top: Constants.DEFAULT_PADDING_TOP,
132                  bottom: Constants.DEFAULT_PADDING_BOTTOM,
133                  left: Constants.PADDING_24,
134                  right: Constants.PADDING_24
135                })
136              }
137
138              Row() {
139                Flex({ justifyContent: FlexAlign.Center }) {
140                  Text() {
141                    if (
142                      this.currentGroup().name === 'LOCATION' &&
143                      ((this.locationFlag == Constants.LOCATION_FUZZY) ||
144                      (this.locationFlag == Constants.LOCATION_BOTH_FUZZY))
145                    ) {
146                      Span($r('app.string.close_exact_position'))
147                    } else if (this.currentGroup().name === 'PASTEBOARD') {
148                      if (this.pasteBoardName) {
149                        Span($r('app.string.pasteBoard_app', this.pasteBoardName))
150                      } else {
151                        Span($r('app.string.pasteBoard_desc'))
152                      }
153                    } else {
154                      if (this.currentGroup().description.length > 0) {
155                        ForEach(this.currentGroup().description, (item: ResourceStr) => {
156                          Span(item)
157                        })
158                        Span(this.currentGroup().reason ? $r('app.string.comma') : $r('app.string.period'))
159                      }
160                      Span(this.refresh >= 0 ? this.currentGroup().reason : '')
161                    }
162                  }
163                  .textAlign(TextAlign.Start)
164                  .fontColor($r('sys.color.font_primary'))
165                  .fontSize($r('sys.float.Body_L'))
166                  .maxFontScale(Constants.DIALOG_TEXT_MAX_SCALE)
167                  .margin({
168                    left: Constants.DIALOG_DESP_MARGIN_LEFT,
169                    right: Constants.DIALOG_DESP_MARGIN_RIGHT,
170                    bottom: Constants.DIALOG_DESP_MARGIN_BOTTOM
171                  })
172                }
173              }
174
175              if (this.locationFlag > Constants.LOCATION_NONE && this.currentGroup().name === 'LOCATION') {
176                LocationCanvas({ locationFlag: $locationFlag })
177              }
178            }
179          }.constraintSize({ maxHeight: Constants.MAXIMUM_HEADER_HEIGHT })
180          if (this.currentGroup().name === 'LOCATION') {
181            Column() {
182              Button($r('app.string.allowed_only_during_use'))
183                .customizeButton()
184                .width(Constants.FULL_WIDTH)
185                .margin({ bottom: Constants.MARGIN_4 })
186                .onClick(() => {
187                  this.privacyAccept(
188                    this.grantGroups[this.count], this.accessTokenId, this.reqPerms, this.userFixedFlag
189                  )
190                })
191              Button($r('app.string.allow_this_time'))
192                .customizeButton()
193                .width(Constants.FULL_WIDTH)
194                .margin({ bottom: Constants.MARGIN_4 })
195                .onClick(() => {
196                  this.privacyAccept(
197                    this.grantGroups[this.count],
198                    this.accessTokenId,
199                    this.reqPerms,
200                    Constants.PERMISSION_ALLOW_THIS_TIME
201                  )
202                })
203              Button($r('app.string.cancel'))
204                .customizeButton()
205                .width(Constants.FULL_WIDTH)
206                .onClick(() => {
207                  this.count ++;
208                })
209            }
210            .padding({ left: Constants.PADDING_16, right: Constants.PADDING_16 })
211          } else {
212            Row() {
213              Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
214                Button($r('app.string.ban'))
215                  .onClick(() => {
216                    this.privacyCancel(
217                      this.grantGroups[this.count], this.accessTokenId, this.reqPerms, this.userFixedFlag
218                    )
219                  }).customizeButton()
220                Divider()
221                  .color($r('sys.color.comp_divider'))
222                  .vertical(true)
223                  .strokeWidth(Constants.DIALOG_DIVIDER)
224                  .height(Constants.DIVIDER_HEIGHT)
225                  .opacity(0.2)
226                  .margin({ left: Constants.MARGIN_8, right: Constants.MARGIN_8 })
227                Button(
228                  this.currentGroup().name === 'PASTEBOARD' ? $r('app.string.This_time_only') : $r('app.string.allow')
229                )
230                  .onClick(() => {
231                    this.privacyAccept(
232                      this.grantGroups[this.count],
233                      this.accessTokenId,
234                      this.reqPerms,
235                      this.currentGroup().name === 'PASTEBOARD' ?
236                      Constants.PERMISSION_ALLOW_THIS_TIME : this.userFixedFlag
237                    )
238                  }).customizeButton()
239              }.margin({
240                left: Constants.BUTTON_MARGIN_LEFT,
241                right: Constants.BUTTON_MARGIN_RIGHT,
242                bottom: Constants.MARGIN_8
243              })
244            }
245          }
246        }
247      }
248      .padding({ bottom: Constants.PADDING_8 })
249      .clip(true)
250    }
251  }
252
253  build() {}
254
255  showTitle(): string {
256    let index = this.count >= this.grantGroups.length ? this.grantGroups.length - 1 : this.count;
257    if (this.grantGroups[index].name == 'LOCATION') {
258      if (this.locationFlag == Constants.LOCATION_FUZZY) {
259        return 'app.string.access_general_location';
260      }
261      if (this.locationFlag == Constants.LOCATION_UPGRADE) {
262        return 'app.string.fuzzy_to_exact';
263      }
264    }
265    return this.grantGroups[index].label;
266  }
267
268  currentGroup(): GroupInfo {
269    let index = this.count >= this.grantGroups.length ? this.grantGroups.length - 1 : this.count;
270    return this.grantGroups[index];
271  }
272
273  async privacyAccept(group: GroupInfo, accessTokenId: number, permissionList: string[], userFixedFlag: number) {
274    let num = 0;
275    group.permissions.forEach(async permission => {
276      this.grantStatus = -1;
277      if (showSubPermissionsGroup.indexOf(group.name) == -1) {
278        if (group.name == 'LOCATION') {
279          if (fuzzyMarks.includes(this.locationFlag) && permission === FUZZY_LOCATION_PERMISSION) {
280            await this.operationPermission(true, accessTokenId, permission, userFixedFlag);
281          }
282          if (preciseMarks.includes(this.locationFlag) && permission === PRECISE_LOCATION_PERMISSION) {
283            await this.operationPermission(true, accessTokenId, permission, userFixedFlag);
284          }
285        } else {
286          await this.operationPermission(true, accessTokenId, permission, userFixedFlag);
287        }
288      } else {
289        if (permissionList.includes(permission)) {
290          await this.operationPermission(true, accessTokenId, permission, userFixedFlag);
291        }
292      }
293      if (this.grantStatus == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
294        permissionList.forEach((req, idx) => {
295          if (req == permission) {
296            this.result[idx] = abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
297          }
298        })
299      }
300      num ++;
301      if (num == group.permissions.length) {
302        this.count ++;
303      }
304    })
305  }
306
307  async privacyCancel(group: GroupInfo, accessTokenId: number, permissionList: string[], userFixedFlag: number) {
308    group.permissions.forEach(async permission => {
309      if (showSubPermissionsGroup.indexOf(group.name) == -1) {
310        await this.operationPermission(false, accessTokenId, permission, userFixedFlag);
311      } else {
312        if (permissionList.includes(permission)) {
313          await this.operationPermission(false, accessTokenId, permission, userFixedFlag);
314        }
315      }
316    })
317    this.count ++;
318  }
319
320  async operationPermission(status: boolean, token: number, permission: Permissions, flag: number) {
321    if (status) {
322      try {
323        Log.info('grantUserGrantedPermission: ' + permission);
324        await abilityAccessCtrl.createAtManager().grantUserGrantedPermission(token, permission, flag).then(() => {
325          this.grantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
326        })
327      } catch (err) {
328        Log.error('failed to grant permission: ' + permission);
329      }
330    } else {
331      try {
332        Log.info('revokeUserGrantedPermission: ' + permission)
333        await abilityAccessCtrl.createAtManager().revokeUserGrantedPermission(token, permission, flag);
334      } catch (err) {
335        Log.error('failed to revoke permission:' + permission);
336      }
337    }
338  }
339
340  aboutToAppear() {
341    this.count = 0;
342    this.initStatus = Constants.INIT_NEED_TO_WAIT;
343    this.result = [];
344    this.reqPerms = this.want.parameters['ohos.user.grant.permission'];
345    this.accessTokenId = this.want.parameters['ohos.aafwk.param.callerToken'];
346    if (this.reqPerms == undefined || this.accessTokenId == undefined || this.reqPerms.length == 0) {
347      Log.info('invalid parameters');
348      this.initStatus = Constants.INIT_NEED_TO_TERMINATED;
349      return;
350    }
351    Log.info('request permission=' + JSON.stringify(this.reqPerms) + ', tokenId = ' + this.accessTokenId);
352    Log.info('permission state=' + JSON.stringify(this.want.parameters['ohos.user.grant.permission.state']));
353    this.result = new Array(this.reqPerms.length).fill(-1);
354    this.getPasteBoardInfo();
355    let bundleName: string = this.want.parameters['ohos.aafwk.param.callerBundleName'];
356    bundleManager.getBundleInfo(bundleName, bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION)
357    .then(bundleInfo => {
358      this.reqPermissionDetails = bundleInfo.reqPermissionDetails;
359      this.getGrantGroups(this.want.parameters['ohos.user.grant.permission.state']);
360      this.getApplicationName(bundleName);
361      this.dialogController?.open();
362    }).catch((err: BusinessError) => {
363      Log.error('getBundleInfo error :' + JSON.stringify(err));
364      this.initStatus = Constants.INIT_NEED_TO_TERMINATED;
365    })
366  }
367
368  aboutToDisappear() {
369    this.dialogController = null;
370  }
371
372  onPageShow() {
373    if (this.isUpdate > 0) {
374      this.getApplicationName(this.want.parameters['ohos.aafwk.param.callerBundleName'])
375    }
376    this.isUpdate ++;
377  }
378
379  getPasteBoardInfo() {
380    if (this.reqPerms.includes(PASTE)) {
381      let systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard();
382      this.pasteBoardName = systemPasteboard.getDataSource();
383    }
384  }
385
386  getGrantGroups(stateGroup: number[]) {
387    if (this.reqPerms.includes(FUZZY_LOCATION_PERMISSION)) {
388      this.locationFlag = Constants.LOCATION_FUZZY;
389      if (this.reqPerms.includes(PRECISE_LOCATION_PERMISSION)) {
390        this.locationFlag = Constants.LOCATION_BOTH_PRECISE;
391        let fuzzyIndex = this.reqPerms.indexOf(FUZZY_LOCATION_PERMISSION);
392        if (stateGroup[fuzzyIndex] == Constants.PASS_OPER) {
393          this.locationFlag = Constants.LOCATION_UPGRADE;
394        }
395      }
396    } else if (this.reqPerms.includes(PRECISE_LOCATION_PERMISSION)) {
397      this.locationFlag = Constants.LOCATION_UPGRADE;
398    }
399
400    this.reqPerms.forEach(async (permission, idx) => {
401      if (permission === APP_TRACKING_CONSENT) {
402        let toggleStatus = await this.appTrackHandle(idx);
403        if (toggleStatus === abilityAccessCtrl.PermissionRequestToggleStatus.CLOSED) {
404          return;
405        }
406      }
407      if (stateGroup[idx] == Constants.PASS_OPER) {
408        Log.info('permission has been fixed:' + permission);
409        this.result[idx] = abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
410      } else if (stateGroup[idx] == Constants.DYNAMIC_OPER) {
411        if (!userGrantPermissions.includes(permission)) {
412          Log.info('permission not find:' + permission);
413        } else {
414          this.addGroup(permission);
415        }
416      }
417    })
418    this.initStatus = Constants.INIT_NEED_TO_VERIFY;
419  }
420
421  async appTrackHandle(index: number): Promise<abilityAccessCtrl.PermissionRequestToggleStatus> {
422    try {
423      let acManager = abilityAccessCtrl.createAtManager();
424      let toggleStatus = await acManager.getPermissionRequestToggleStatus(APP_TRACKING_CONSENT);
425      Log.info(`APP_TRACKING_CONSENT toggleStatus: ${toggleStatus}.`);
426      if (toggleStatus === abilityAccessCtrl.PermissionRequestToggleStatus.CLOSED) {
427        await acManager.grantUserGrantedPermission(this.accessTokenId, APP_TRACKING_CONSENT, this.userFixedFlag);
428        this.result[index] = abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
429        Log.info('APP_TRACKING_CONSENT grant success.');
430      }
431      return toggleStatus;
432    } catch (err) {
433      Log.error(`APP_TRACKING_CONSENT getToggleStatus or grant fail: ${JSON.stringify(err)}`);
434      return abilityAccessCtrl.PermissionRequestToggleStatus.OPEN;
435    }
436  }
437
438  addGroup(permission: string) {
439    let group = getPermissionGroup(permission);
440    if (group.name === 'FOLDER') {
441      switch (permission) {
442        case DOWNLOAD_PERMISSION:
443          let downloadGroup = new GroupInfo(group.name, group.groupName, 'app.string.group_label_download_folder',
444            group.icon, group.description, group.reason, [DOWNLOAD_PERMISSION], group.isShow)
445          this.grantGroups.push(downloadGroup);
446          break;
447        case DESKTOP_PERMISSION:
448          let desktopGroup = new GroupInfo(group.name, group.groupName, 'app.string.group_label_desktop_folder',
449            group.icon, group.description, group.reason, [DESKTOP_PERMISSION], group.isShow)
450          this.grantGroups.push(desktopGroup);
451          break;
452        case DOCUMENTS_PERMISSION:
453          let documentGroup = new GroupInfo(group.name, group.groupName, 'app.string.group_label_document_folder',
454            group.icon, group.description, group.reason, [DOCUMENTS_PERMISSION], group.isShow)
455          this.grantGroups.push(documentGroup);
456          break;
457      }
458      return
459    }
460    let exist = this.grantGroups.find(grantGroup => grantGroup.name == group.name);
461    if (showSubPermissionsGroup.indexOf(group.name) != -1) {
462      let label = getPermissionLabel(permission)
463      if (!exist) {
464        group.description.push(label);
465        this.grantGroups.push(group);
466      } else {
467        if (exist.description.indexOf(label) == -1) {
468          exist.description.push($r('app.string.and'));
469          exist.description.push(label);
470        }
471      }
472    } else {
473      if (!exist) {
474        this.grantGroups.push(group);
475      }
476    }
477  }
478
479  getApplicationName(bundleName: string) {
480    Log.info('getApplicationName bundleName:' + bundleName);
481    bundleManager.getApplicationInfo(bundleName, bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT)
482    .then(applicationInfo => {
483      let context = this.context.createBundleContext(bundleName);
484      context.resourceManager.getStringValue(applicationInfo.labelId, (err, value) => {
485        if (value == undefined) {
486          this.appName = titleTrim(applicationInfo.label);
487        } else {
488          this.appName = titleTrim(value);
489        }
490        Log.info('hap label:' + applicationInfo.label + ', value:' + this.appName);
491      })
492    }).catch((err: BusinessError) => {
493      Log.error('applicationInfo error :' + err);
494      this.initStatus = Constants.INIT_NEED_TO_TERMINATED;
495    })
496    this.grantGroups.forEach((group) => {
497      group.reason = '';
498      this.getReason(group, bundleName);
499    })
500  }
501
502  getReason(group: GroupInfo, bundleName: string) {
503    group.permissions.forEach(permission => {
504      if (this.reqPerms.indexOf(permission) != -1) {
505        this.reqPermissionDetails.forEach(reqPermissionDetail => {
506          if (reqPermissionDetail.name == permission) {
507            Log.info('reqPermissionDetail: ' + JSON.stringify(reqPermissionDetail));
508            let context = this.context.createModuleContext(bundleName, reqPermissionDetail.moduleName);
509            context.resourceManager.getStringValue(reqPermissionDetail.reasonId, (err, value) => {
510              if (value !== undefined && group.reason === '') {
511                group.reason = value.slice(Constants.START_SUBSCRIPT, Constants.END_SUBSCRIPT);
512                this.refresh ++;
513              }
514              this.initStatus = Constants.INIT_NEED_TO_REFRESH;
515            })
516          }
517        })
518      }
519    })
520  }
521
522  verify() {
523    if ((this.initStatus == Constants.INIT_NEED_TO_TERMINATED) || (this.count >= this.grantGroups.length)) {
524      this.answerRequest();
525      this.initStatus = Constants.INIT_NEED_TO_WAIT;
526      return false;
527    }
528    return true;
529  }
530
531  answerRequest() {
532    let ret: number = Constants.RESULT_SUCCESS;
533    if (this.initStatus == Constants.INIT_NEED_TO_TERMINATED) {
534      ret = Constants.RESULT_FAILURE;
535    }
536    this.answer(ret, this.reqPerms);
537  }
538
539  answer(ret: number, reqPerms: string[]) {
540    Log.info('code:' + ret + ', perms=' + JSON.stringify(reqPerms) + ', result=' + JSON.stringify(this.result));
541    let perms: string[] = [];
542    let results: number[] = [];
543    reqPerms.forEach(perm => {
544      perms.push(perm);
545    })
546    this.result.forEach(result => {
547      results.push(result);
548    })
549    let option = new rpc.MessageOption();
550    let data = new rpc.MessageSequence();
551    let setDialogData = new rpc.MessageSequence();
552    let reply = new rpc.MessageSequence();
553    Promise.all([
554      data.writeInterfaceToken(Constants.ACCESS_TOKEN),
555      data.writeStringArray(perms),
556      data.writeIntArray(results),
557      setDialogData.writeInterfaceToken(Constants.ACCESS_TOKEN),
558    ]).then(() => {
559      let proxy = this.want.parameters['ohos.ability.params.callback'].value as rpc.RemoteObject;
560      proxy.sendMessageRequest(Constants.RESULT_CODE, data, reply, option);
561      proxy.sendMessageRequest(Constants.RESULT_CODE_1, setDialogData, reply, option);
562    }).catch(() => {
563      Log.error('write result failed!');
564    }).finally(() => {
565      data.reclaim();
566      reply.reclaim();
567      setDialogData.reclaim();
568      this.destruction();
569    })
570  }
571
572  destruction() {
573    let windowNum: number = GlobalContext.load('windowNum');
574    windowNum --;
575    Log.info('windowNum:' + windowNum);
576    GlobalContext.store('windowNum', windowNum);
577    this.win.destroyWindow();
578    if (windowNum == 0) {
579      this.context.terminateSelf();
580    }
581  }
582}