MOBILE-4018 iframe: Make open iframe links more consistent
parent
0af6865703
commit
02df883a03
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,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…
Reference in New Issue