import { Injectable , NgZone , Inject } from '@angular/core' ; import { ModalController , Platform } from '@ionic/angular' ; import { ComponentRef , ModalOptions } from '@ionic/core' ; import { PluginListenerHandle } from '@capacitor/core' ; import { Warning , WarningModalPage } from '../../pages/warning-modal/warning-modal.page' ; import { ErrorCategory , handleErrorLocal } from '../error-handler/error-handler.service' ; import { NavigationService } from '../navigation/navigation.service' ; import { SECURITY_UTILS_PLUGIN } from 'src/app/capacitor-plugins/injection-tokens' ; import { SecurityUtilsPlugin } from 'src/app/capacitor-plugins/definitions' ; @ Injectable ( { providedIn : 'root' } ) export class DeviceService { private screenCaptureStateChangedListeners : PluginListenerHandle [ ] = [ ] ; private screenshotTakenListeners : PluginListenerHandle [ ] = [ ] ; constructor ( private readonly ngZone , private readonly platform , private readonly modalController , protected readonly navigationService , @ Inject ( SECURITY_UTILS_PLUGIN ) private readonly securityUtils ) { } public enableScreenshotProtection ( options ? ) { this . setSecureWindow ( ) ; this . onScreenCaptureStateChanged ( ( captured ) => { if ( captured ) { this . presentModal ( WarningModalPage , { errorType : Warning . SCREENSHOT } , ( ) => { options ? this . navigationService . routeBack ( options . routeBack ) : this . navigationService . back ( ) ; } ) . catch ( handleErrorLocal ( ErrorCategory . INIT_CHECK ) ) ; } } ) ; this . onScreenshotTaken ( ( ) => { this . presentModal ( WarningModalPage , { errorType : Warning . SCREENSHOT } , ( ) => { options ? this . navigationService . routeBack ( options . routeBack ) : this . navigationService . back ( ) ; } ) . catch ( handleErrorLocal ( ErrorCategory . INIT_CHECK ) ) ; } ) ; } public disableScreenshotProtection ( ) { this . clearSecureWindow ( ) ; this . removeScreenCaptureObservers ( ) ; this . removeScreenshotObservers ( ) ; } private async presentModal ( page , properties , callback ) { const modal = await this . modalController . create ( { component : page , componentProps : properties , backdropDismiss : false } ) ; modal . onDidDismiss ( ) . then ( ( ) => { callback ( ) ; } ) . catch ( handleErrorLocal ( ErrorCategory . IONIC_MODAL ) ) ; modal . present ( ) . then ( ( ) => { console . log ( 'check modal presented' ) ; } ) . catch ( handleErrorLocal ( ErrorCategory . IONIC_MODAL ) ) ; } public async checkForRoot ( ) { if ( this . platform . is ( 'hybrid' ) ) { const result = await this . securityUtils . assessDeviceIntegrity ( ) ; return ! result . value ; } else { console . warn ( 'root detection skipped - no supported platform' ) ; return false ; } } public onScreenCaptureStateChanged ( callback ) { if ( this . platform . is ( 'ios' ) && this . platform . is ( 'hybrid' ) ) { const listener = this . securityUtils . addListener ( 'screenCaptureStateChanged' , ( event ) => { this . ngZone . run ( ( ) => { callback ( event . captured ) ; } ) ; } ) ; this . screenCaptureStateChangedListeners . push ( listener ) ; } } public setSecureWindow ( ) { if ( this . platform . is ( 'android' ) && this . platform . is ( 'hybrid' ) ) { this . securityUtils . setWindowSecureFlag ( ) ; } } public clearSecureWindow ( ) { if ( this . platform . is ( 'android' ) && this . platform . is ( 'hybrid' ) ) { this . securityUtils . clearWindowSecureFlag ( ) ; } } public removeScreenCaptureObservers ( ) { if ( this . platform . is ( 'ios' ) && this . platform . is ( 'hybrid' ) ) { this . removeListeners ( this . screenCaptureStateChangedListeners ) ; this . screenCaptureStateChangedListeners = [ ] ; } } public onScreenshotTaken ( callback ) { if ( this . platform . is ( 'ios' ) && this . platform . is ( 'hybrid' ) ) { const listener = this . securityUtils . addListener ( 'screenshotTaken' , ( ) => { this . ngZone . run ( ( ) => { callback ( ) ; } ) ; } ) ; this . screenCaptureStateChangedListeners . push ( listener ) ; } } public removeScreenshotObservers ( ) { if ( this . platform . is ( 'ios' ) && this . platform . is ( 'hybrid' ) ) { this . removeListeners ( this . screenshotTakenListeners ) ; this . screenshotTakenListeners = [ ] ; } } public async checkForElectron ( ) { return typeof navigator === 'object' && typeof navigator . userAgent === 'string' && navigator . userAgent . indexOf ( 'Electron' ) >= 0 ; } private removeListeners ( listeners ) { listeners . forEach ( ( listener ) => { listener . remove ( ) ; } ) ; } }