MOBILE-3523 ios: Fix embedded iframes cookies in iOS
parent
514ccda794
commit
0124b4d567
|
@ -24,9 +24,6 @@ import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
|||
import { CoreIframeUtilsProvider } from '@providers/utils/iframe';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { CoreUrl } from '@singletons/url';
|
||||
import { CoreApp } from '@providers/app';
|
||||
import { WKWebViewCookiesWindow } from 'cordova-plugin-wkwebview-cookies';
|
||||
|
||||
@Component({
|
||||
selector: 'core-iframe',
|
||||
|
@ -107,24 +104,7 @@ export class CoreIframeComponent implements OnChanges {
|
|||
if (changes.src) {
|
||||
const url = this.urlUtils.getYoutubeEmbedUrl(changes.src.currentValue) || changes.src.currentValue;
|
||||
|
||||
if (CoreApp.instance.isIOS() && url && !this.urlUtils.isLocalFileUrl(url)) {
|
||||
// Save a "fake" cookie for the iframe's domain to fix a bug in WKWebView.
|
||||
try {
|
||||
const win = <WKWebViewCookiesWindow> window;
|
||||
const urlParts = CoreUrl.parse(url);
|
||||
|
||||
if (urlParts.domain) {
|
||||
await win.WKWebViewCookies.setCookie({
|
||||
name: 'MoodleAppCookieForWKWebView',
|
||||
value: '1',
|
||||
domain: urlParts.domain,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore errors.
|
||||
this.logger.error('Error setting cookie', err);
|
||||
}
|
||||
}
|
||||
await this.iframeUtils.fixIframeCookies(url);
|
||||
|
||||
this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(CoreFile.instance.convertFileSrc(url));
|
||||
|
||||
|
|
|
@ -450,6 +450,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
const div = document.createElement('div'),
|
||||
canTreatVimeo = site && site.isVersionGreaterEqualThan(['3.3.4', '3.4']),
|
||||
navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl;
|
||||
const promises = [];
|
||||
|
||||
div.innerHTML = formatted;
|
||||
|
||||
|
@ -504,7 +505,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
});
|
||||
|
||||
iframes.forEach((iframe) => {
|
||||
this.treatIframe(iframe, site, canTreatVimeo, navCtrl);
|
||||
promises.push(this.treatIframe(iframe, site, canTreatVimeo, navCtrl));
|
||||
});
|
||||
|
||||
svgImages.forEach((image) => {
|
||||
|
@ -543,10 +544,9 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
this.domUtils.handleBootstrapTooltips(div);
|
||||
|
||||
// Wait for images to load.
|
||||
let promise: Promise<any> = null;
|
||||
if (externalImages.length) {
|
||||
// Automatically reject the promise after 5 seconds to prevent blocking the user forever.
|
||||
promise = this.utils.timeoutPromise(this.utils.allPromises(externalImages.map((externalImage): any => {
|
||||
promises.push(this.utils.timeoutPromise(this.utils.allPromises(externalImages.map((externalImage): any => {
|
||||
if (externalImage.loaded) {
|
||||
// Image has already been loaded, no need to wait.
|
||||
return Promise.resolve();
|
||||
|
@ -558,12 +558,10 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
resolve();
|
||||
});
|
||||
});
|
||||
})), 5000);
|
||||
} else {
|
||||
promise = Promise.resolve();
|
||||
})), 5000));
|
||||
}
|
||||
|
||||
return promise.catch(() => {
|
||||
return Promise.all(promises).catch(() => {
|
||||
// Ignore errors. So content gets always shown.
|
||||
}).then(() => {
|
||||
result.div = div;
|
||||
|
@ -665,7 +663,8 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
* @param canTreatVimeo Whether Vimeo videos can be treated in the site.
|
||||
* @param navCtrl NavController to use.
|
||||
*/
|
||||
protected treatIframe(iframe: HTMLIFrameElement, site: CoreSite, canTreatVimeo: boolean, navCtrl: NavController): void {
|
||||
protected async treatIframe(iframe: HTMLIFrameElement, site: CoreSite, canTreatVimeo: boolean, navCtrl: NavController)
|
||||
: Promise<void> {
|
||||
const src = iframe.src,
|
||||
currentSite = this.sitesProvider.getCurrentSite();
|
||||
|
||||
|
@ -673,15 +672,19 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
|
||||
if (currentSite && currentSite.containsUrl(src)) {
|
||||
// URL points to current site, try to use auto-login.
|
||||
currentSite.getAutoLoginUrl(src, false).then((finalUrl) => {
|
||||
iframe.src = finalUrl;
|
||||
const finalUrl = await currentSite.getAutoLoginUrl(src, false);
|
||||
|
||||
this.iframeUtils.treatFrame(iframe, false, navCtrl);
|
||||
});
|
||||
await this.iframeUtils.fixIframeCookies(finalUrl);
|
||||
|
||||
iframe.src = finalUrl;
|
||||
|
||||
this.iframeUtils.treatFrame(iframe, false, navCtrl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.iframeUtils.fixIframeCookies(src);
|
||||
|
||||
if (src && canTreatVimeo) {
|
||||
// Check if it's a Vimeo video. If it is, use the wsplayer script instead to make restricted videos work.
|
||||
const matches = iframe.src.match(/https?:\/\/player\.vimeo\.com\/video\/([0-9]+)/);
|
||||
|
@ -714,6 +717,9 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
if (site && !site.isVersionGreaterEqualThan('3.7')) {
|
||||
newUrl += '&width=' + width + '&height=' + height;
|
||||
}
|
||||
|
||||
await this.iframeUtils.fixIframeCookies(newUrl);
|
||||
|
||||
iframe.src = newUrl;
|
||||
|
||||
if (!iframe.width) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import { makeSingleton } from '@singletons/core.singletons';
|
|||
import { CoreUrl } from '@singletons/url';
|
||||
import { CoreWindow } from '@singletons/window';
|
||||
import { WKUserScriptWindow, WKUserScriptInjectionTime } from 'cordova-plugin-wkuserscript';
|
||||
import { WKWebViewCookiesWindow } from 'cordova-plugin-wkwebview-cookies';
|
||||
|
||||
/*
|
||||
* "Utils" service with helper functions for iframes, embed and similar.
|
||||
|
@ -488,6 +489,36 @@ export class CoreIframeUtilsProvider {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix cookies for an iframe URL.
|
||||
*
|
||||
* @param url URL of the iframe.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async fixIframeCookies(url: string): Promise<void> {
|
||||
if (!CoreApp.instance.isIOS() || !url || this.urlUtils.isLocalFileUrl(url)) {
|
||||
// No need to fix cookies.
|
||||
return;
|
||||
}
|
||||
|
||||
// Save a "fake" cookie for the iframe's domain to fix a bug in WKWebView.
|
||||
try {
|
||||
const win = <WKWebViewCookiesWindow> window;
|
||||
const urlParts = CoreUrl.parse(url);
|
||||
|
||||
if (urlParts.domain) {
|
||||
await win.WKWebViewCookies.setCookie({
|
||||
name: 'MoodleAppCookieForWKWebView',
|
||||
value: '1',
|
||||
domain: urlParts.domain,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore errors.
|
||||
this.logger.error('Error setting cookie', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class CoreIframeUtils extends makeSingleton(CoreIframeUtilsProvider) {}
|
||||
|
|
Loading…
Reference in New Issue