diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a51f06f3f..c70564c1d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -17,6 +17,7 @@ import { Platform, Nav } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; import { CoreEventsProvider } from '../providers/events'; +import { CoreLoggerProvider } from '../providers/logger'; import { CoreLoginHelperProvider } from '../core/login/providers/helper'; @Component({ @@ -25,9 +26,13 @@ import { CoreLoginHelperProvider } from '../core/login/providers/helper'; export class MyApp implements AfterViewInit { @ViewChild(Nav) navCtrl; rootPage:any = 'CoreLoginInitPage'; + protected logger; + protected lastUrls = {}; - constructor(private platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, + constructor(private platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, logger: CoreLoggerProvider, private eventsProvider: CoreEventsProvider, private loginHelper: CoreLoginHelperProvider) { + this.logger = logger.getInstance('AppComponent'); + platform.ready().then(() => { // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. @@ -86,8 +91,25 @@ export class MyApp implements AfterViewInit { }, 1000); }); - // @todo: Register observer to check if the app was launched via URL scheme. - // $mmURLDelegate.register('mmLoginSSO', appLaunchedByURL); + // Handle app launched with a certain URL (custom URL scheme). + (window).handleOpenURL = (url: string) => { + // First check that the URL hasn't been treated a few seconds ago. Sometimes this function is called more than once. + if (this.lastUrls[url] && Date.now() - this.lastUrls[url] < 3000) { + // Function called more than once, stop. + return; + } + + this.logger.debug('App launched by URL ', url); + + this.lastUrls[url] = Date.now(); + + this.eventsProvider.trigger(CoreEventsProvider.APP_LAUNCHED_URL, url); + }; + + // Listen for app launched URLs. If we receive one, check if it's a SSO authentication. + this.eventsProvider.on(CoreEventsProvider.APP_LAUNCHED_URL, (url) => { + this.loginHelper.appLaunchedByURL(url); + }); } } diff --git a/src/core/login/providers/helper.ts b/src/core/login/providers/helper.ts index 13e18440a..6a0fa8e32 100644 --- a/src/core/login/providers/helper.ts +++ b/src/core/login/providers/helper.ts @@ -112,7 +112,7 @@ export class CoreLoginHelperProvider { // App opened using custom URL scheme. Probably an SSO authentication. this.appProvider.startSSOAuthentication(); - this.logger.debug('App launched by URL'); + this.logger.debug('App launched by URL with an SSO'); // Delete the sso scheme from the URL. url = url.replace(ssoScheme, ''); @@ -205,6 +205,8 @@ export class CoreLoginHelperProvider { promise.then(() => { this.openBrowserForSSOLogin(siteUrl, typeOfLogin, service, launchUrl); + }, () => { + // User cancelled, ignore. }); } @@ -934,7 +936,7 @@ export class CoreLoginHelperProvider { return Promise.reject(null); } - let launchSiteURL = data.siteurl, + let launchSiteURL = data.siteUrl, passport = data.passport; // Reset temporary values. diff --git a/src/providers/app.ts b/src/providers/app.ts index 6a546eed9..46dac2a50 100644 --- a/src/providers/app.ts +++ b/src/providers/app.ts @@ -224,19 +224,24 @@ export class CoreAppProvider { * NOT when the browser is opened. */ startSSOAuthentication() : void { + let cancelTimeout, + resolvePromise; + this.ssoAuthenticationPromise = new Promise((resolve, reject) => { - // Store the resolve function in the promise itself. - (this.ssoAuthenticationPromise).resolve = resolve; + resolvePromise = resolve; // Resolve it automatically after 10 seconds (it should never take that long). - let cancel = setTimeout(() => { + cancelTimeout = setTimeout(() => { this.finishSSOAuthentication(); }, 10000); + }); - // If the promise is resolved because finishSSOAuthentication is called, stop the cancel promise. - this.ssoAuthenticationPromise.then(() => { - clearTimeout(cancel); - }); + // Store the resolve function in the promise itself. + (this.ssoAuthenticationPromise).resolve = resolvePromise; + + // If the promise is resolved because finishSSOAuthentication is called, stop the cancel promise. + this.ssoAuthenticationPromise.then(() => { + clearTimeout(cancelTimeout); }); }; diff --git a/src/providers/events.ts b/src/providers/events.ts index a153b1112..60d8cf9f6 100644 --- a/src/providers/events.ts +++ b/src/providers/events.ts @@ -45,6 +45,7 @@ export class CoreEventsProvider { public static LOGIN_SITE_UNCHECKED = 'login_site_unchecked'; public static IAB_LOAD_START = 'inappbrowser_load_start'; public static IAB_EXIT = 'inappbrowser_exit'; + public static APP_LAUNCHED_URL = 'app_launched_url'; // App opened with a certain URL (custom URL scheme). logger; observables = {}; diff --git a/src/providers/utils/utils.ts b/src/providers/utils/utils.ts index 6cfb1ba4f..32857be31 100644 --- a/src/providers/utils/utils.ts +++ b/src/providers/utils/utils.ts @@ -790,17 +790,27 @@ export class CoreUtilsProvider { options.location = 'no'; } + // Convert the options to a string. + let optionsArray = [], + optionsString; + for (let name in options) { + optionsArray.push(`${name}=${options[name]}`) + } + optionsString = optionsArray.join(','); + this.iabInstance = this.iab.create(url, '_blank', options); - // Trigger global events when a url is loaded or the window is closed. This is to make it work like in Ionic 1. - let loadStartSubscription = this.iabInstance.on('loadstart').subscribe((event) => { - this.eventsProvider.trigger(CoreEventsProvider.IAB_LOAD_START, event); - }); - let exitSubscription = this.iabInstance.on('exit').subscribe((event) => { - loadStartSubscription.unsubscribe(); - exitSubscription.unsubscribe(); - this.eventsProvider.trigger(CoreEventsProvider.IAB_EXIT, event); - }); + if (this.appProvider.isDesktop() || this.appProvider.isMobile()) { + // Trigger global events when a url is loaded or the window is closed. This is to make it work like in Ionic 1. + let loadStartSubscription = this.iabInstance.on('loadstart').subscribe((event) => { + this.eventsProvider.trigger(CoreEventsProvider.IAB_LOAD_START, event); + }); + let exitSubscription = this.iabInstance.on('exit').subscribe((event) => { + loadStartSubscription.unsubscribe(); + exitSubscription.unsubscribe(); + this.eventsProvider.trigger(CoreEventsProvider.IAB_EXIT, event); + }); + } return this.iabInstance; }