forked from EVOgeek/Vmeda.Online
		
	Merge pull request #4276 from dpalou/MOBILE-4018
MOBILE-4018 iframe: Make open iframe links more consistent
This commit is contained in:
		
						commit
						b130e32423
					
				@ -21,12 +21,11 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Redefine window.open.
 | 
			
		||||
    const originalWindowOpen = window.open;
 | 
			
		||||
    window.open = function(url, name, specs) {
 | 
			
		||||
        if (name == '_self') {
 | 
			
		||||
            // Link should be loaded in the same frame.
 | 
			
		||||
            location.href = toAbsolute(url);
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
            // Link will be opened in the same frame, no need to treat it.
 | 
			
		||||
            return originalWindowOpen(url, name, specs);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getRootWindow(window).postMessage({
 | 
			
		||||
@ -34,7 +33,7 @@
 | 
			
		||||
            context: 'iframe',
 | 
			
		||||
            action: 'window_open',
 | 
			
		||||
            frameUrl: location.href,
 | 
			
		||||
            url: url,
 | 
			
		||||
            url: toAbsolute(url),
 | 
			
		||||
            name: name,
 | 
			
		||||
            specs: specs,
 | 
			
		||||
        }, '*');
 | 
			
		||||
@ -164,24 +163,19 @@
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const linkScheme = getUrlScheme(link.href);
 | 
			
		||||
        const pageScheme = getUrlScheme(location.href);
 | 
			
		||||
        const isTargetSelf = !link.target || link.target == '_self';
 | 
			
		||||
        if (!link.target || link.target == '_self') {
 | 
			
		||||
            // Link needs to be opened in the same iframe. This is already handled properly, we don't need to do anything else.
 | 
			
		||||
            // Links opened in the same iframe won't be captured by the app.
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!link.href || linkScheme == 'javascript') {
 | 
			
		||||
        if (!link.href || getUrlScheme(link.href) == 'javascript') {
 | 
			
		||||
            // Links with no URL and Javascript links are ignored.
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        event.preventDefault();
 | 
			
		||||
 | 
			
		||||
        if (isTargetSelf && (isLocalFileUrlScheme(linkScheme) || !isLocalFileUrlScheme(pageScheme))) {
 | 
			
		||||
            // Link should be loaded in the same frame. Don't do it if link is online and frame is local.
 | 
			
		||||
            location.href = toAbsolute(link.href);
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getRootWindow(window).postMessage({
 | 
			
		||||
            environment: 'moodleapp',
 | 
			
		||||
            context: 'iframe',
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,6 @@ import { WKWebViewCookiesWindow } from 'cordova-plugin-wkwebview-cookies';
 | 
			
		||||
 | 
			
		||||
import { CoreNetwork } from '@services/network';
 | 
			
		||||
import { CoreFile } from '@services/file';
 | 
			
		||||
import { CoreFileHelper } from '@services/file-helper';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { CoreUrl } from '@singletons/url';
 | 
			
		||||
@ -313,7 +312,13 @@ export class CoreIframeUtilsProvider {
 | 
			
		||||
    ): void {
 | 
			
		||||
        if (contentWindow) {
 | 
			
		||||
            // Intercept window.open.
 | 
			
		||||
            const originalWindowOpen = contentWindow.open;
 | 
			
		||||
            contentWindow.open = (url: string, name: string) => {
 | 
			
		||||
                if (name === '_self') {
 | 
			
		||||
                    // Link will be opened in the same frame, no need to treat it.
 | 
			
		||||
                    return originalWindowOpen(url, name);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.windowOpen(url, name, element);
 | 
			
		||||
 | 
			
		||||
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
			
		||||
@ -410,7 +415,7 @@ export class CoreIframeUtilsProvider {
 | 
			
		||||
 | 
			
		||||
            // Add click listener to the link, this way if the iframe has added a listener to the link it will be executed first.
 | 
			
		||||
            link.treated = true;
 | 
			
		||||
            link.addEventListener('click', event => this.linkClicked(link, element, event));
 | 
			
		||||
            link.addEventListener('click', event => this.linkClicked(link, event));
 | 
			
		||||
        }, {
 | 
			
		||||
            capture: true, // Use capture to fix this listener not called if the element clicked is too deep in the DOM.
 | 
			
		||||
        });
 | 
			
		||||
@ -447,26 +452,11 @@ export class CoreIframeUtilsProvider {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (name == '_self') {
 | 
			
		||||
            // Link should be loaded in the same frame.
 | 
			
		||||
            if (!element) {
 | 
			
		||||
                this.logger.warn('Cannot load URL in iframe because the element was not supplied', url);
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (element.tagName.toLowerCase() === 'object') {
 | 
			
		||||
                element.setAttribute('data', url);
 | 
			
		||||
            } else {
 | 
			
		||||
                element.setAttribute('src', url);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            try {
 | 
			
		||||
                // It's an external link or a local file, check if it can be opened in the app.
 | 
			
		||||
                await CoreWindow.open(url, name);
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                CoreDomUtils.showErrorModal(error);
 | 
			
		||||
            }
 | 
			
		||||
        try {
 | 
			
		||||
            // It's an external link or a local file, check if it can be opened in the app.
 | 
			
		||||
            await CoreWindow.open(url, name);
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModal(error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -474,13 +464,11 @@ export class CoreIframeUtilsProvider {
 | 
			
		||||
     * A link inside a frame was clicked.
 | 
			
		||||
     *
 | 
			
		||||
     * @param link Link clicked, or data of the link clicked.
 | 
			
		||||
     * @param element Frame element.
 | 
			
		||||
     * @param event Click event.
 | 
			
		||||
     * @returns Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    protected async linkClicked(
 | 
			
		||||
        link: CoreIframeHTMLAnchorElement | {href: string; target?: string; originalHref?: string},
 | 
			
		||||
        element?: CoreFrameElement,
 | 
			
		||||
        event?: Event,
 | 
			
		||||
    ): Promise<void> {
 | 
			
		||||
        if (event && event.defaultPrevented) {
 | 
			
		||||
@ -488,69 +476,24 @@ export class CoreIframeUtilsProvider {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!link.target || link.target === '_self') {
 | 
			
		||||
            // Link needs to be opened in the same iframe. This is already handled properly, we don't need to do anything else.
 | 
			
		||||
            // Links opened in the same iframe won't be captured by the app.
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const urlParts = CoreUrl.parse(link.href);
 | 
			
		||||
        const originalHref = 'getAttribute' in link ? link.getAttribute('href') : link.originalHref;
 | 
			
		||||
        if (!link.href || !originalHref || originalHref == '#' || !urlParts || urlParts.protocol === 'javascript') {
 | 
			
		||||
        if (!link.href || !originalHref || originalHref === '#' || !urlParts || urlParts.protocol === 'javascript') {
 | 
			
		||||
            // Links with no URL and Javascript links are ignored.
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (urlParts.protocol && !CoreUrl.isLocalFileUrlScheme(urlParts.protocol, urlParts.domain || '')) {
 | 
			
		||||
            // Scheme suggests it's an external resource.
 | 
			
		||||
            event && event.preventDefault();
 | 
			
		||||
 | 
			
		||||
            const frameSrc = element && ((<HTMLIFrameElement> element).src || (<HTMLObjectElement> element).data);
 | 
			
		||||
 | 
			
		||||
            // If the frame is not local, check the target to identify how to treat the link.
 | 
			
		||||
            if (
 | 
			
		||||
                element &&
 | 
			
		||||
                frameSrc &&
 | 
			
		||||
                !CoreUrl.isLocalFileUrl(frameSrc) &&
 | 
			
		||||
                (!link.target || link.target == '_self')
 | 
			
		||||
            ) {
 | 
			
		||||
                // Load the link inside the frame itself.
 | 
			
		||||
                if (element.tagName.toLowerCase() === 'object') {
 | 
			
		||||
                    element.setAttribute('data', link.href);
 | 
			
		||||
                } else {
 | 
			
		||||
                    element.setAttribute('src', link.href);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // The frame is local or the link needs to be opened in a new window. Open in browser.
 | 
			
		||||
            if (!CoreSites.isLoggedIn()) {
 | 
			
		||||
                CoreOpener.openInBrowser(link.href);
 | 
			
		||||
            } else {
 | 
			
		||||
                await CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(link.href);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (link.target == '_parent' || link.target == '_top' || link.target == '_blank') {
 | 
			
		||||
            // Opening links with _parent, _top or _blank can break the app. We'll open it in InAppBrowser.
 | 
			
		||||
            event && event.preventDefault();
 | 
			
		||||
 | 
			
		||||
            const filename = link.href.substring(link.href.lastIndexOf('/') + 1);
 | 
			
		||||
 | 
			
		||||
            if (!CoreFileHelper.isOpenableInApp({ filename })) {
 | 
			
		||||
                try {
 | 
			
		||||
                    await CoreFileHelper.showConfirmOpenUnsupportedFile(false, { filename });
 | 
			
		||||
                } catch (error) {
 | 
			
		||||
                    return; // Cancelled, stop.
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                await CoreOpener.openFile(link.href);
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                CoreDomUtils.showErrorModal(error);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (CorePlatform.isIOS() && (!link.target || link.target == '_self') && element) {
 | 
			
		||||
            // In cordova ios 4.1.0 links inside iframes stopped working. We'll manually treat them.
 | 
			
		||||
            event && event.preventDefault();
 | 
			
		||||
            if (element.tagName.toLowerCase() === 'object') {
 | 
			
		||||
                element.setAttribute('data', link.href);
 | 
			
		||||
            } else {
 | 
			
		||||
                element.setAttribute('src', link.href);
 | 
			
		||||
            }
 | 
			
		||||
        try {
 | 
			
		||||
            event?.preventDefault();
 | 
			
		||||
            await CoreWindow.open(link.href, link.target);
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModal(error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -67,7 +67,7 @@ export class CoreWindow {
 | 
			
		||||
        } else {
 | 
			
		||||
            let treated = false;
 | 
			
		||||
 | 
			
		||||
            if (name != '_system') {
 | 
			
		||||
            if (name !== '_system') {
 | 
			
		||||
                // Check if it can be opened in the app.
 | 
			
		||||
                treated = await CoreContentLinksHelper.handleLink(url, undefined, true, true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user