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}