Merge pull request #2562 from dpalou/MOBILE-3523

Mobile 3523
main
Juan Leyva 2020-10-16 13:13:28 +02:00 committed by GitHub
commit 3a27eda256
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 154 additions and 128 deletions

View File

@ -47,96 +47,96 @@
"windows.store": "npx electron-windows-store --input-directory .\\desktop\\dist\\win-unpacked --output-directory .\\desktop\\store -a .\\resources\\desktop -m .\\desktop\\assets\\windows\\AppXManifest.xml --package-version 0.0.0.0 --package-name MoodleDesktop" "windows.store": "npx electron-windows-store --input-directory .\\desktop\\dist\\win-unpacked --output-directory .\\desktop\\store -a .\\resources\\desktop -m .\\desktop\\assets\\windows\\AppXManifest.xml --package-version 0.0.0.0 --package-name MoodleDesktop"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "^5.2.11", "@angular/animations": "5.2.11",
"@angular/common": "^5.2.11", "@angular/common": "5.2.11",
"@angular/compiler": "^5.2.11", "@angular/compiler": "5.2.11",
"@angular/compiler-cli": "^5.2.11", "@angular/compiler-cli": "5.2.11",
"@angular/core": "^5.2.11", "@angular/core": "5.2.11",
"@angular/forms": "^5.2.11", "@angular/forms": "5.2.11",
"@angular/platform-browser": "^5.2.11", "@angular/platform-browser": "5.2.11",
"@angular/platform-browser-dynamic": "^5.2.11", "@angular/platform-browser-dynamic": "5.2.11",
"@ionic-native/badge": "^4.20.0", "@ionic-native/badge": "4.20.0",
"@ionic-native/camera": "^4.20.0", "@ionic-native/camera": "4.20.0",
"@ionic-native/chooser": "^4.20.0", "@ionic-native/chooser": "4.20.0",
"@ionic-native/clipboard": "^4.20.0", "@ionic-native/clipboard": "4.20.0",
"@ionic-native/core": "^4.20.0", "@ionic-native/core": "4.20.0",
"@ionic-native/device": "^4.20.0", "@ionic-native/device": "4.20.0",
"@ionic-native/diagnostic": "^4.2.0", "@ionic-native/diagnostic": "4.2.0",
"@ionic-native/file": "^4.20.0", "@ionic-native/file": "4.20.0",
"@ionic-native/file-opener": "^4.20.0", "@ionic-native/file-opener": "4.20.0",
"@ionic-native/file-transfer": "^4.20.0", "@ionic-native/file-transfer": "4.20.0",
"@ionic-native/geolocation": "^4.20.0", "@ionic-native/geolocation": "4.20.0",
"@ionic-native/globalization": "^4.20.0", "@ionic-native/globalization": "4.20.0",
"@ionic-native/http": "^4.20.0", "@ionic-native/http": "4.20.0",
"@ionic-native/in-app-browser": "^4.20.0", "@ionic-native/in-app-browser": "4.20.0",
"@ionic-native/keyboard": "^4.20.0", "@ionic-native/keyboard": "4.20.0",
"@ionic-native/local-notifications": "^4.20.0", "@ionic-native/local-notifications": "4.20.0",
"@ionic-native/media": "^4.20.0", "@ionic-native/media": "4.20.0",
"@ionic-native/media-capture": "^4.20.0", "@ionic-native/media-capture": "4.20.0",
"@ionic-native/network": "^4.20.0", "@ionic-native/network": "4.20.0",
"@ionic-native/push": "^4.20.0", "@ionic-native/push": "4.20.0",
"@ionic-native/qr-scanner": "^4.20.0", "@ionic-native/qr-scanner": "4.20.0",
"@ionic-native/screen-orientation": "^4.20.0", "@ionic-native/screen-orientation": "4.20.0",
"@ionic-native/splash-screen": "^4.20.0", "@ionic-native/splash-screen": "4.20.0",
"@ionic-native/sqlite": "^4.20.0", "@ionic-native/sqlite": "4.20.0",
"@ionic-native/status-bar": "^4.20.0", "@ionic-native/status-bar": "4.20.0",
"@ionic-native/web-intent": "^4.20.0", "@ionic-native/web-intent": "4.20.0",
"@ionic-native/zip": "^4.20.0", "@ionic-native/zip": "4.20.0",
"@ngx-translate/core": "^8.0.0", "@ngx-translate/core": "8.0.0",
"@ngx-translate/http-loader": "^2.0.1", "@ngx-translate/http-loader": "2.0.1",
"ajv": "^6.11.0", "ajv": "6.11.0",
"chart.js": "^2.9.3", "chart.js": "2.9.3",
"com-darryncampbell-cordova-plugin-intent": "^1.3.0", "com-darryncampbell-cordova-plugin-intent": "1.3.0",
"cordova": "^10.0.0", "cordova": "10.0.0",
"cordova-android": "^8.1.0", "cordova-android": "8.1.0",
"cordova-android-support-gradle-release": "^3.0.1", "cordova-android-support-gradle-release": "3.0.1",
"cordova-clipboard": "^1.3.0", "cordova-clipboard": "1.3.0",
"cordova-ios": "^5.1.1", "cordova-ios": "5.1.1",
"cordova-plugin-advanced-http": "^2.4.1", "cordova-plugin-advanced-http": "2.4.1",
"cordova-plugin-badge": "^0.8.8", "cordova-plugin-badge": "0.8.8",
"cordova-plugin-camera": "^4.1.0", "cordova-plugin-camera": "4.1.0",
"cordova-plugin-chooser": "^1.3.2", "cordova-plugin-chooser": "1.3.2",
"cordova-plugin-customurlscheme": "^5.0.1", "cordova-plugin-customurlscheme": "5.0.1",
"cordova-plugin-device": "^2.0.3", "cordova-plugin-device": "2.0.3",
"cordova-plugin-file": "^6.0.2", "cordova-plugin-file": "6.0.2",
"cordova-plugin-file-opener2": "^3.0.4", "cordova-plugin-file-opener2": "3.0.4",
"cordova-plugin-file-transfer": "^1.7.1", "cordova-plugin-file-transfer": "1.7.1",
"cordova-plugin-geolocation": "git+https://github.com/apache/cordova-plugin-geolocation.git#89cf51d222e8f225bdfb661965b3007d669c40ff", "cordova-plugin-geolocation": "git+https://github.com/apache/cordova-plugin-geolocation.git#89cf51d222e8f225bdfb661965b3007d669c40ff",
"cordova-plugin-globalization": "^1.11.0", "cordova-plugin-globalization": "1.11.0",
"cordova-plugin-inappbrowser": "git+https://github.com/moodlemobile/cordova-plugin-inappbrowser.git#moodle", "cordova-plugin-inappbrowser": "git+https://github.com/moodlemobile/cordova-plugin-inappbrowser.git#moodle",
"cordova-plugin-ionic-keyboard": "2.1.3", "cordova-plugin-ionic-keyboard": "2.1.3",
"cordova-plugin-ionic-webview": "git+https://github.com/moodlemobile/cordova-plugin-ionic-webview.git#500-moodle", "cordova-plugin-ionic-webview": "git+https://github.com/moodlemobile/cordova-plugin-ionic-webview.git#500-moodle",
"cordova-plugin-local-notification": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#moodle", "cordova-plugin-local-notification": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#moodle",
"cordova-plugin-media": "^5.0.3", "cordova-plugin-media": "5.0.3",
"cordova-plugin-media-capture": "^3.0.3", "cordova-plugin-media-capture": "3.0.3",
"cordova-plugin-network-information": "^2.0.2", "cordova-plugin-network-information": "2.0.2",
"cordova-plugin-qrscanner": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#dist", "cordova-plugin-qrscanner": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#dist",
"cordova-plugin-screen-orientation": "^3.0.2", "cordova-plugin-screen-orientation": "3.0.2",
"cordova-plugin-splashscreen": "^6.0.0", "cordova-plugin-splashscreen": "6.0.0",
"cordova-plugin-statusbar": "^2.4.3", "cordova-plugin-statusbar": "2.4.3",
"cordova-plugin-whitelist": "^1.3.4", "cordova-plugin-whitelist": "1.3.4",
"cordova-plugin-wkuserscript": "git+https://github.com/moodlemobile/cordova-plugin-wkuserscript.git", "cordova-plugin-wkuserscript": "git+https://github.com/moodlemobile/cordova-plugin-wkuserscript.git",
"cordova-plugin-wkwebview-cookies": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git", "cordova-plugin-wkwebview-cookies": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git",
"cordova-plugin-zip": "^3.1.0", "cordova-plugin-zip": "3.1.0",
"cordova-sqlite-storage": "^4.0.0", "cordova-sqlite-storage": "4.0.0",
"cordova-support-google-services": "^1.3.2", "cordova-support-google-services": "1.3.2",
"es6-promise-plugin": "^4.2.2", "es6-promise-plugin": "4.2.2",
"font-awesome": "^4.7.0", "font-awesome": "4.7.0",
"inquirer": "^7.3.2", "inquirer": "^7.3.2",
"ionic-angular": "3.9.9", "ionic-angular": "3.9.9",
"ionicons": "3.0.0", "ionicons": "3.0.0",
"jszip": "^3.1.5", "jszip": "3.1.5",
"mathjax": "2.7.7", "mathjax": "2.7.7",
"moment": "^2.24.0", "moment": "2.24.0",
"nl.kingsquare.cordova.background-audio": "^1.0.1", "nl.kingsquare.cordova.background-audio": "1.0.1",
"phonegap-plugin-multidex": "^1.0.0", "phonegap-plugin-multidex": "1.0.0",
"phonegap-plugin-push": "git+https://github.com/moodlemobile/phonegap-plugin-push.git#moodle-v3", "phonegap-plugin-push": "git+https://github.com/moodlemobile/phonegap-plugin-push.git#moodle-v3",
"promise.prototype.finally": "3.1.0", "promise.prototype.finally": "3.1.0",
"rxjs": "^5.5.12", "rxjs": "5.5.12",
"sw-toolbox": "^3.6.0", "sw-toolbox": "3.6.0",
"ts-md5": "^1.2.7", "ts-md5": "1.2.7",
"web-animations-js": "^2.3.2", "web-animations-js": "2.3.2",
"zone.js": "^0.8.29" "zone.js": "0.8.29"
}, },
"devDependencies": { "devDependencies": {
"@ionic/app-scripts": "3.2.3", "@ionic/app-scripts": "3.2.3",

View File

@ -24,9 +24,6 @@ import { CoreUrlUtilsProvider } from '@providers/utils/url';
import { CoreIframeUtilsProvider } from '@providers/utils/iframe'; import { CoreIframeUtilsProvider } from '@providers/utils/iframe';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreSplitViewComponent } from '@components/split-view/split-view'; 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({ @Component({
selector: 'core-iframe', selector: 'core-iframe',
@ -107,24 +104,7 @@ export class CoreIframeComponent implements OnChanges {
if (changes.src) { if (changes.src) {
const url = this.urlUtils.getYoutubeEmbedUrl(changes.src.currentValue) || changes.src.currentValue; const url = this.urlUtils.getYoutubeEmbedUrl(changes.src.currentValue) || changes.src.currentValue;
if (CoreApp.instance.isIOS() && url && !this.urlUtils.isLocalFileUrl(url)) { await this.iframeUtils.fixIframeCookies(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);
}
}
this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(CoreFile.instance.convertFileSrc(url)); this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(CoreFile.instance.convertFileSrc(url));

View File

@ -191,7 +191,7 @@ export class CoreContentLinksDelegate {
// Add them to the list. // Add them to the list.
linkActions.push({ linkActions.push({
priority: handler.priority, priority: handler.priority || 0,
actions: actions actions: actions
}); });
} }

View File

@ -405,7 +405,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
promises.push(Promise.resolve(getFunction.call(handler, injector, course)).then((data) => { promises.push(Promise.resolve(getFunction.call(handler, injector, course)).then((data) => {
handlersToDisplay.push({ handlersToDisplay.push({
data: data, data: data,
priority: handler.priority, priority: handler.priority || 0,
prefetch: handler.prefetch && handler.prefetch.bind(handler), prefetch: handler.prefetch && handler.prefetch.bind(handler),
name: handler.name name: handler.name
}); });

View File

@ -15,6 +15,7 @@
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, AfterContentInit, OnDestroy, Optional } import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, AfterContentInit, OnDestroy, Optional }
from '@angular/core'; from '@angular/core';
import { TextInput, Content, Platform, Slides } from 'ionic-angular'; import { TextInput, Content, Platform, Slides } from 'ionic-angular';
import { Device } from '@ionic-native/device';
import { CoreApp } from '@providers/app'; import { CoreApp } from '@providers/app';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreFilepoolProvider } from '@providers/filepool';
@ -118,7 +119,8 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe
protected events: CoreEventsProvider, protected events: CoreEventsProvider,
protected utils: CoreUtilsProvider, protected utils: CoreUtilsProvider,
protected platform: Platform, protected platform: Platform,
protected editorOffline: CoreEditorOfflineProvider) { protected editorOffline: CoreEditorOfflineProvider,
protected device: Device) {
this.contentChanged = new EventEmitter<string>(); this.contentChanged = new EventEmitter<string>();
this.element = elementRef.nativeElement as HTMLDivElement; this.element = elementRef.nativeElement as HTMLDivElement;
this.pageInstance = 'app_' + Date.now(); // Generate a "unique" ID based on timestamp. this.pageInstance = 'app_' + Date.now(); // Generate a "unique" ID based on timestamp.
@ -236,7 +238,7 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe
if (CoreApp.instance.isAndroid()) { if (CoreApp.instance.isAndroid()) {
// In Android we ignore the keyboard height because it is not part of the web view. // In Android we ignore the keyboard height because it is not part of the web view.
height = this.domUtils.getContentHeight(this.content) - this.getSurroundingHeight(this.element); height = this.domUtils.getContentHeight(this.content) - this.getSurroundingHeight(this.element);
} else if (CoreApp.instance.isIOS() && this.kbHeight > 0 && this.platform.version().major < 12) { } else if (CoreApp.instance.isIOS() && this.kbHeight > 0 && Number(this.device.version.split('.')[0]) < 12) {
// Keyboard open in iOS 11 or previous. The window height changes when the keyboard is open. // Keyboard open in iOS 11 or previous. The window height changes when the keyboard is open.
height = window.innerHeight - this.getSurroundingHeight(this.element); height = window.innerHeight - this.getSurroundingHeight(this.element);

View File

@ -177,7 +177,7 @@ export class CoreFileUploaderDelegate extends CoreDelegate {
} }
const data: CoreFileUploaderHandlerDataToReturn = handler.getData(); const data: CoreFileUploaderHandlerDataToReturn = handler.getData();
data.priority = handler.priority; data.priority = handler.priority || 0;
data.mimetypes = supportedMimetypes; data.mimetypes = supportedMimetypes;
handlers.push(data); handlers.push(data);
} }

View File

@ -44,8 +44,7 @@ export class CoreFileUploaderFileHandler implements CoreFileUploaderHandler {
* @return True or promise resolved with true if enabled. * @return True or promise resolved with true if enabled.
*/ */
isEnabled(): boolean | Promise<boolean> { isEnabled(): boolean | Promise<boolean> {
return CoreApp.instance.isAndroid() || !CoreApp.instance.isMobile() || return true;
(CoreApp.instance.isIOS() && this.platform.version().major >= 9);
} }
/** /**

View File

@ -46,6 +46,7 @@ export class CoreMainMenuPage implements OnDestroy {
protected urlToOpen: string; protected urlToOpen: string;
protected mainMenuId: number; protected mainMenuId: number;
protected keyboardObserver: any; protected keyboardObserver: any;
protected resizeFunction;
@ViewChild('mainTabs') mainTabs: CoreIonTabsComponent; @ViewChild('mainTabs') mainTabs: CoreIonTabsComponent;
@ -115,7 +116,8 @@ export class CoreMainMenuPage implements OnDestroy {
} }
}); });
window.addEventListener('resize', this.initHandlers.bind(this)); this.resizeFunction = this.initHandlers.bind(this);
window.addEventListener('resize', this.resizeFunction);
if (CoreApp.instance.isIOS()) { if (CoreApp.instance.isIOS()) {
// In iOS, the resize event is triggered before the keyboard is opened/closed and not triggered again once done. // In iOS, the resize event is triggered before the keyboard is opened/closed and not triggered again once done.
@ -241,7 +243,7 @@ export class CoreMainMenuPage implements OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
this.subscription && this.subscription.unsubscribe(); this.subscription && this.subscription.unsubscribe();
this.redirectObs && this.redirectObs.off(); this.redirectObs && this.redirectObs.off();
window.removeEventListener('resize', this.initHandlers.bind(this)); window.removeEventListener('resize', this.resizeFunction);
CoreApp.instance.setMainMenuOpen(this.mainMenuId, false); CoreApp.instance.setMainMenuOpen(this.mainMenuId, false);
this.keyboardObserver && this.keyboardObserver.off(); this.keyboardObserver && this.keyboardObserver.off();
} }

View File

@ -162,7 +162,7 @@ export class CoreMainMenuDelegate extends CoreDelegate {
handlersData.push({ handlersData.push({
name: name, name: name,
data: data, data: data,
priority: handler.priority priority: handler.priority || 0,
}); });
} }

View File

@ -177,6 +177,7 @@ export class CorePushNotificationsDelegate {
this.logger.log(`Registered addon '${handler.name}'`); this.logger.log(`Registered addon '${handler.name}'`);
this.clickHandlers[handler.name] = handler; this.clickHandlers[handler.name] = handler;
handler.priority = handler.priority || 0;
return true; return true;
} }

View File

@ -108,7 +108,7 @@ export class CoreSettingsDelegate extends CoreDelegate {
handlersData.push({ handlersData.push({
data: data, data: data,
priority: handler.priority priority: handler.priority || 0,
}); });
} }

View File

@ -35,7 +35,7 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl
protected utils: CoreUtilsProvider) { protected utils: CoreUtilsProvider) {
super(name); super(name);
this.priority = handlerSchema.priority; this.priority = handlerSchema.priority || 0;
this.isMenuHandler = !!handlerSchema.ismenuhandler; this.isMenuHandler = !!handlerSchema.ismenuhandler;
} }

View File

@ -25,7 +25,7 @@ export class CoreSitePluginsMainMenuHandler extends CoreSitePluginsBaseHandler i
protected initResult: any) { protected initResult: any) {
super(name); super(name);
this.priority = handlerSchema.priority; this.priority = handlerSchema.priority || 0;
} }
/** /**

View File

@ -32,7 +32,7 @@ export class CoreSitePluginsMessageOutputHandler extends CoreSitePluginsBaseHand
*/ */
getDisplayData(): AddonMessageOutputHandlerData { getDisplayData(): AddonMessageOutputHandlerData {
return { return {
priority: this.handlerSchema.priority, priority: this.handlerSchema.priority || 0,
label: this.title, label: this.title,
icon: this.handlerSchema.displaydata.icon, icon: this.handlerSchema.displaydata.icon,
page: 'CoreSitePluginsPluginPage', page: 'CoreSitePluginsPluginPage',

View File

@ -25,7 +25,7 @@ export class CoreSitePluginsSettingsHandler extends CoreSitePluginsBaseHandler i
protected initResult: any) { protected initResult: any) {
super(name); super(name);
this.priority = handlerSchema.priority; this.priority = handlerSchema.priority || 0;
} }
/** /**

View File

@ -43,7 +43,7 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle
protected utils: CoreUtilsProvider) { protected utils: CoreUtilsProvider) {
super(name); super(name);
this.priority = handlerSchema.priority; this.priority = handlerSchema.priority || 0;
// Only support TYPE_COMMUNICATION and TYPE_NEW_PAGE. // Only support TYPE_COMMUNICATION and TYPE_NEW_PAGE.
this.type = handlerSchema.type != CoreUserDelegate.TYPE_COMMUNICATION ? this.type = handlerSchema.type != CoreUserDelegate.TYPE_COMMUNICATION ?

View File

@ -260,7 +260,7 @@ export class CoreUserDelegate extends CoreDelegate {
userData.handlers.push({ userData.handlers.push({
name: name, name: name,
data: handler.getDisplayData(user, courseId), data: handler.getDisplayData(user, courseId),
priority: handler.priority, priority: handler.priority || 0,
type: handler.type || CoreUserDelegate.TYPE_NEW_PAGE type: handler.type || CoreUserDelegate.TYPE_NEW_PAGE
}); });
} }

View File

@ -450,6 +450,7 @@ export class CoreFormatTextDirective implements OnChanges {
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; navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl;
const promises = [];
div.innerHTML = formatted; div.innerHTML = formatted;
@ -504,7 +505,7 @@ export class CoreFormatTextDirective implements OnChanges {
}); });
iframes.forEach((iframe) => { iframes.forEach((iframe) => {
this.treatIframe(iframe, site, canTreatVimeo, navCtrl); promises.push(this.treatIframe(iframe, site, canTreatVimeo, navCtrl));
}); });
svgImages.forEach((image) => { svgImages.forEach((image) => {
@ -543,10 +544,9 @@ export class CoreFormatTextDirective implements OnChanges {
this.domUtils.handleBootstrapTooltips(div); this.domUtils.handleBootstrapTooltips(div);
// Wait for images to load. // Wait for images to load.
let promise: Promise<any> = null;
if (externalImages.length) { if (externalImages.length) {
// Automatically reject the promise after 5 seconds to prevent blocking the user forever. // 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) { if (externalImage.loaded) {
// Image has already been loaded, no need to wait. // Image has already been loaded, no need to wait.
return Promise.resolve(); return Promise.resolve();
@ -558,12 +558,10 @@ export class CoreFormatTextDirective implements OnChanges {
resolve(); resolve();
}); });
}); });
})), 5000); })), 5000));
} else {
promise = Promise.resolve();
} }
return promise.catch(() => { return Promise.all(promises).catch(() => {
// Ignore errors. So content gets always shown. // Ignore errors. So content gets always shown.
}).then(() => { }).then(() => {
result.div = div; result.div = div;
@ -665,7 +663,8 @@ export class CoreFormatTextDirective implements OnChanges {
* @param canTreatVimeo Whether Vimeo videos can be treated in the site. * @param canTreatVimeo Whether Vimeo videos can be treated in the site.
* @param navCtrl NavController to use. * @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, const src = iframe.src,
currentSite = this.sitesProvider.getCurrentSite(); currentSite = this.sitesProvider.getCurrentSite();
@ -673,15 +672,19 @@ export class CoreFormatTextDirective implements OnChanges {
if (currentSite && currentSite.containsUrl(src)) { if (currentSite && currentSite.containsUrl(src)) {
// URL points to current site, try to use auto-login. // URL points to current site, try to use auto-login.
currentSite.getAutoLoginUrl(src, false).then((finalUrl) => { const finalUrl = await currentSite.getAutoLoginUrl(src, false);
iframe.src = finalUrl;
this.iframeUtils.treatFrame(iframe, false, navCtrl); await this.iframeUtils.fixIframeCookies(finalUrl);
});
iframe.src = finalUrl;
this.iframeUtils.treatFrame(iframe, false, navCtrl);
return; return;
} }
await this.iframeUtils.fixIframeCookies(src);
if (src && canTreatVimeo) { if (src && canTreatVimeo) {
// Check if it's a Vimeo video. If it is, use the wsplayer script instead to make restricted videos work. // 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]+)/); 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')) { if (site && !site.isVersionGreaterEqualThan('3.7')) {
newUrl += '&width=' + width + '&height=' + height; newUrl += '&width=' + width + '&height=' + height;
} }
await this.iframeUtils.fixIframeCookies(newUrl);
iframe.src = newUrl; iframe.src = newUrl;
if (!iframe.width) { if (!iframe.width) {

View File

@ -1549,11 +1549,16 @@ export class CoreSitesProvider {
await this.dbReady; await this.dbReady;
const site = await this.getSite(siteId); const site = await this.getSite(siteId);
const newValues = { const newValues: any = {
token: '', // Erase the token for security.
loggedOut: loggedOut ? 1 : 0 loggedOut: loggedOut ? 1 : 0
}; };
if (loggedOut) {
// Erase the token for security.
newValues.token = '';
site.token = '';
}
site.setLoggedOut(loggedOut); site.setLoggedOut(loggedOut);
return this.appDB.updateRecords(CoreSitesProvider.SITES_TABLE, newValues, { id: siteId }); return this.appDB.updateRecords(CoreSitesProvider.SITES_TABLE, newValues, { id: siteId });

View File

@ -30,6 +30,7 @@ import { makeSingleton } from '@singletons/core.singletons';
import { CoreUrl } from '@singletons/url'; import { CoreUrl } from '@singletons/url';
import { CoreWindow } from '@singletons/window'; import { CoreWindow } from '@singletons/window';
import { WKUserScriptWindow, WKUserScriptInjectionTime } from 'cordova-plugin-wkuserscript'; import { WKUserScriptWindow, WKUserScriptInjectionTime } from 'cordova-plugin-wkuserscript';
import { WKWebViewCookiesWindow } from 'cordova-plugin-wkwebview-cookies';
/* /*
* "Utils" service with helper functions for iframes, embed and similar. * "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) {} export class CoreIframeUtils extends makeSingleton(CoreIframeUtilsProvider) {}