forked from CIT/Vmeda.Online
		
	MOBILE-3098 iframe: Open in app links inside iframes
This commit is contained in:
		
							parent
							
								
									ea7caaed20
								
							
						
					
					
						commit
						8d64fea2af
					
				@ -12,11 +12,15 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Input, Output, OnInit, ViewChild, ElementRef, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
 | 
					import {
 | 
				
			||||||
 | 
					    Component, Input, Output, OnInit, ViewChild, ElementRef, EventEmitter, OnChanges, SimpleChange, Optional
 | 
				
			||||||
 | 
					} from '@angular/core';
 | 
				
			||||||
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
 | 
					import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
 | 
				
			||||||
 | 
					import { NavController } from 'ionic-angular';
 | 
				
			||||||
import { CoreLoggerProvider } from '@providers/logger';
 | 
					import { CoreLoggerProvider } from '@providers/logger';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreIframeUtilsProvider } from '@providers/utils/iframe';
 | 
					import { CoreIframeUtilsProvider } from '@providers/utils/iframe';
 | 
				
			||||||
 | 
					import { CoreSplitViewComponent } from '@components/split-view/split-view';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -38,7 +42,9 @@ export class CoreIframeComponent implements OnInit, OnChanges {
 | 
				
			|||||||
    protected IFRAME_TIMEOUT = 15000;
 | 
					    protected IFRAME_TIMEOUT = 15000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(logger: CoreLoggerProvider, private iframeUtils: CoreIframeUtilsProvider, private domUtils: CoreDomUtilsProvider,
 | 
					    constructor(logger: CoreLoggerProvider, private iframeUtils: CoreIframeUtilsProvider, private domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
            private sanitizer: DomSanitizer) {
 | 
					            private sanitizer: DomSanitizer, private navCtrl: NavController,
 | 
				
			||||||
 | 
					            @Optional() private svComponent: CoreSplitViewComponent) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.logger = logger.getInstance('CoreIframe');
 | 
					        this.logger = logger.getInstance('CoreIframe');
 | 
				
			||||||
        this.loaded = new EventEmitter<HTMLIFrameElement>();
 | 
					        this.loaded = new EventEmitter<HTMLIFrameElement>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -55,7 +61,8 @@ export class CoreIframeComponent implements OnInit, OnChanges {
 | 
				
			|||||||
        // Show loading only with external URLs.
 | 
					        // Show loading only with external URLs.
 | 
				
			||||||
        this.loading = !this.src || !!this.src.match(/^https?:\/\//i);
 | 
					        this.loading = !this.src || !!this.src.match(/^https?:\/\//i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.iframeUtils.treatFrame(iframe);
 | 
					        const navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl;
 | 
				
			||||||
 | 
					        this.iframeUtils.treatFrame(iframe, false, navCtrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.loading) {
 | 
					        if (this.loading) {
 | 
				
			||||||
            iframe.addEventListener('load', () => {
 | 
					            iframe.addEventListener('load', () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ import { CoreBlockDelegate } from '@core/block/providers/delegate';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class CoreSitePluginsBlockComponent extends CoreBlockBaseComponent implements OnChanges {
 | 
					export class CoreSitePluginsBlockComponent extends CoreBlockBaseComponent implements OnChanges {
 | 
				
			||||||
    @Input() block: any;
 | 
					    @Input() block: any;
 | 
				
			||||||
    @Input() contextLevel: number;
 | 
					    @Input() contextLevel: string;
 | 
				
			||||||
    @Input() instanceId: number;
 | 
					    @Input() instanceId: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChild(CoreSitePluginsPluginContentComponent) content: CoreSitePluginsPluginContentComponent;
 | 
					    @ViewChild(CoreSitePluginsPluginContentComponent) content: CoreSitePluginsPluginContentComponent;
 | 
				
			||||||
 | 
				
			|||||||
@ -352,7 +352,8 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
                this.utils.isTrueOrOne(this.singleLine), undefined, this.highlight);
 | 
					                this.utils.isTrueOrOne(this.singleLine), undefined, this.highlight);
 | 
				
			||||||
        }).then((formatted) => {
 | 
					        }).then((formatted) => {
 | 
				
			||||||
            const div = document.createElement('div'),
 | 
					            const div = document.createElement('div'),
 | 
				
			||||||
                canTreatVimeo = site && site.isVersionGreaterEqualThan(['3.3.4', '3.4']);
 | 
					                canTreatVimeo = site && site.isVersionGreaterEqualThan(['3.3.4', '3.4']),
 | 
				
			||||||
 | 
					                navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl;
 | 
				
			||||||
            let images,
 | 
					            let images,
 | 
				
			||||||
                anchors,
 | 
					                anchors,
 | 
				
			||||||
                audios,
 | 
					                audios,
 | 
				
			||||||
@ -405,12 +406,12 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            videos.forEach((video) => {
 | 
					            videos.forEach((video) => {
 | 
				
			||||||
                this.treatVideoFilters(video);
 | 
					                this.treatVideoFilters(video, navCtrl);
 | 
				
			||||||
                this.treatMedia(video);
 | 
					                this.treatMedia(video);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            iframes.forEach((iframe) => {
 | 
					            iframes.forEach((iframe) => {
 | 
				
			||||||
                this.treatIframe(iframe, site, canTreatVimeo);
 | 
					                this.treatIframe(iframe, site, canTreatVimeo, navCtrl);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Handle buttons with inner links.
 | 
					            // Handle buttons with inner links.
 | 
				
			||||||
@ -439,7 +440,7 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // Handle all kind of frames.
 | 
					            // Handle all kind of frames.
 | 
				
			||||||
            frames.forEach((frame: any) => {
 | 
					            frames.forEach((frame: any) => {
 | 
				
			||||||
                this.iframeUtils.treatFrame(frame);
 | 
					                this.iframeUtils.treatFrame(frame, false, navCtrl);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.domUtils.handleBootstrapTooltips(div);
 | 
					            this.domUtils.handleBootstrapTooltips(div);
 | 
				
			||||||
@ -508,8 +509,9 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
     * Treat video filters. Currently only treating youtube video using video JS.
 | 
					     * Treat video filters. Currently only treating youtube video using video JS.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {HTMLElement} el Video element.
 | 
					     * @param {HTMLElement} el Video element.
 | 
				
			||||||
 | 
					     * @param {NavController} navCtrl NavController to use.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected treatVideoFilters(video: HTMLElement): void {
 | 
					    protected treatVideoFilters(video: HTMLElement, navCtrl: NavController): void {
 | 
				
			||||||
        // Treat Video JS Youtube video links and translate them to iframes.
 | 
					        // Treat Video JS Youtube video links and translate them to iframes.
 | 
				
			||||||
        if (!video.classList.contains('video-js')) {
 | 
					        if (!video.classList.contains('video-js')) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@ -534,7 +536,7 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
        // Replace video tag by the iframe.
 | 
					        // Replace video tag by the iframe.
 | 
				
			||||||
        video.parentNode.replaceChild(iframe, video);
 | 
					        video.parentNode.replaceChild(iframe, video);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.iframeUtils.treatFrame(iframe);
 | 
					        this.iframeUtils.treatFrame(iframe, false, navCtrl);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -571,8 +573,9 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
     * @param {HTMLIFrameElement} iframe Iframe to treat.
 | 
					     * @param {HTMLIFrameElement} iframe Iframe to treat.
 | 
				
			||||||
     * @param {CoreSite} site Site instance.
 | 
					     * @param {CoreSite} site Site instance.
 | 
				
			||||||
     * @param {boolean} canTreatVimeo Whether Vimeo videos can be treated in the site.
 | 
					     * @param {boolean} canTreatVimeo Whether Vimeo videos can be treated in the site.
 | 
				
			||||||
 | 
					     * @param {NavController} navCtrl NavController to use.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected treatIframe(iframe: HTMLIFrameElement, site: CoreSite, canTreatVimeo: boolean): void {
 | 
					    protected treatIframe(iframe: HTMLIFrameElement, site: CoreSite, canTreatVimeo: boolean, navCtrl: NavController): void {
 | 
				
			||||||
        const src = iframe.src,
 | 
					        const src = iframe.src,
 | 
				
			||||||
            currentSite = this.sitesProvider.getCurrentSite();
 | 
					            currentSite = this.sitesProvider.getCurrentSite();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -583,7 +586,7 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
            currentSite.getAutoLoginUrl(src, false).then((finalUrl) => {
 | 
					            currentSite.getAutoLoginUrl(src, false).then((finalUrl) => {
 | 
				
			||||||
                iframe.src = finalUrl;
 | 
					                iframe.src = finalUrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this.iframeUtils.treatFrame(iframe);
 | 
					                this.iframeUtils.treatFrame(iframe, false, navCtrl);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@ -644,7 +647,7 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.iframeUtils.treatFrame(iframe);
 | 
					        this.iframeUtils.treatFrame(iframe, false, navCtrl);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Injectable, NgZone } from '@angular/core';
 | 
					import { Injectable, NgZone } from '@angular/core';
 | 
				
			||||||
import { Config, Platform } from 'ionic-angular';
 | 
					import { Config, Platform, NavController } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { Network } from '@ionic-native/network';
 | 
					import { Network } from '@ionic-native/network';
 | 
				
			||||||
import { CoreAppProvider } from '../app';
 | 
					import { CoreAppProvider } from '../app';
 | 
				
			||||||
@ -191,8 +191,9 @@ export class CoreIframeUtilsProvider {
 | 
				
			|||||||
     * @param {any} element Element to treat (iframe, embed, ...).
 | 
					     * @param {any} element Element to treat (iframe, embed, ...).
 | 
				
			||||||
     * @param {Window} contentWindow The window of the element contents.
 | 
					     * @param {Window} contentWindow The window of the element contents.
 | 
				
			||||||
     * @param {Document} contentDocument The document of the element contents.
 | 
					     * @param {Document} contentDocument The document of the element contents.
 | 
				
			||||||
 | 
					     * @param {NavController} [navCtrl] NavController to use if a link can be opened in the app.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    redefineWindowOpen(element: any, contentWindow: Window, contentDocument: Document): void {
 | 
					    redefineWindowOpen(element: any, contentWindow: Window, contentDocument: Document, navCtrl?: NavController): void {
 | 
				
			||||||
        if (contentWindow) {
 | 
					        if (contentWindow) {
 | 
				
			||||||
            // Intercept window.open.
 | 
					            // Intercept window.open.
 | 
				
			||||||
            contentWindow.open = (url: string, target: string): Window => {
 | 
					            contentWindow.open = (url: string, target: string): Window => {
 | 
				
			||||||
@ -229,13 +230,18 @@ export class CoreIframeUtilsProvider {
 | 
				
			|||||||
                        this.domUtils.showErrorModal(error);
 | 
					                        this.domUtils.showErrorModal(error);
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    // It's an external link, we will open with browser. Check if we need to auto-login.
 | 
					                    // It's an external link, check if it can be opened in the app.
 | 
				
			||||||
                    if (!this.sitesProvider.isLoggedIn()) {
 | 
					                    this.contentLinksHelper.handleLink(url, undefined, navCtrl, true, true).then((treated) => {
 | 
				
			||||||
                        // Not logged in, cannot auto-login.
 | 
					                        if (!treated) {
 | 
				
			||||||
                        this.utils.openInBrowser(url);
 | 
					                            // Not opened in the app, open with browser. Check if we need to auto-login
 | 
				
			||||||
                    } else {
 | 
					                            if (!this.sitesProvider.isLoggedIn()) {
 | 
				
			||||||
                        this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(url);
 | 
					                                // Not logged in, cannot auto-login.
 | 
				
			||||||
                    }
 | 
					                                this.utils.openInBrowser(url);
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(url);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                 // We cannot create new Window objects directly, return null which is a valid return value for Window.open().
 | 
					                 // We cannot create new Window objects directly, return null which is a valid return value for Window.open().
 | 
				
			||||||
@ -248,7 +254,7 @@ export class CoreIframeUtilsProvider {
 | 
				
			|||||||
            CoreIframeUtilsProvider.FRAME_TAGS.forEach((tag) => {
 | 
					            CoreIframeUtilsProvider.FRAME_TAGS.forEach((tag) => {
 | 
				
			||||||
                const elements = Array.from(contentDocument.querySelectorAll(tag));
 | 
					                const elements = Array.from(contentDocument.querySelectorAll(tag));
 | 
				
			||||||
                elements.forEach((subElement) => {
 | 
					                elements.forEach((subElement) => {
 | 
				
			||||||
                    this.treatFrame(subElement, true);
 | 
					                    this.treatFrame(subElement, true, navCtrl);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -260,14 +266,15 @@ export class CoreIframeUtilsProvider {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {any} element Element to treat (iframe, embed, ...).
 | 
					     * @param {any} element Element to treat (iframe, embed, ...).
 | 
				
			||||||
     * @param {boolean} [isSubframe] Whether it's a frame inside another frame.
 | 
					     * @param {boolean} [isSubframe] Whether it's a frame inside another frame.
 | 
				
			||||||
 | 
					     * @param {NavController} [navCtrl] NavController to use if a link can be opened in the app.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    treatFrame(element: any, isSubframe?: boolean): void {
 | 
					    treatFrame(element: any, isSubframe?: boolean, navCtrl?: NavController): void {
 | 
				
			||||||
        if (element) {
 | 
					        if (element) {
 | 
				
			||||||
            this.checkOnlineFrameInOffline(element, isSubframe);
 | 
					            this.checkOnlineFrameInOffline(element, isSubframe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let winAndDoc = this.getContentWindowAndDocument(element);
 | 
					            let winAndDoc = this.getContentWindowAndDocument(element);
 | 
				
			||||||
            // Redefine window.open in this element and sub frames, it might have been loaded already.
 | 
					            // Redefine window.open in this element and sub frames, it might have been loaded already.
 | 
				
			||||||
            this.redefineWindowOpen(element, winAndDoc.window, winAndDoc.document);
 | 
					            this.redefineWindowOpen(element, winAndDoc.window, winAndDoc.document, navCtrl);
 | 
				
			||||||
            // Treat links.
 | 
					            // Treat links.
 | 
				
			||||||
            this.treatFrameLinks(element, winAndDoc.document);
 | 
					            this.treatFrameLinks(element, winAndDoc.document);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -276,7 +283,7 @@ export class CoreIframeUtilsProvider {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // Element loaded, redefine window.open and treat links again.
 | 
					                // Element loaded, redefine window.open and treat links again.
 | 
				
			||||||
                winAndDoc = this.getContentWindowAndDocument(element);
 | 
					                winAndDoc = this.getContentWindowAndDocument(element);
 | 
				
			||||||
                this.redefineWindowOpen(element, winAndDoc.window, winAndDoc.document);
 | 
					                this.redefineWindowOpen(element, winAndDoc.window, winAndDoc.document, navCtrl);
 | 
				
			||||||
                this.treatFrameLinks(element, winAndDoc.document);
 | 
					                this.treatFrameLinks(element, winAndDoc.document);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (winAndDoc.window) {
 | 
					                if (winAndDoc.window) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user