MOBILE-3401 android: Use default scheme in Android
parent
a475f3e188
commit
1f4ae8563d
|
@ -43,7 +43,6 @@
|
||||||
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
|
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
|
||||||
<preference name="CustomURLSchemePluginClearsAndroidIntent" value="true" />
|
<preference name="CustomURLSchemePluginClearsAndroidIntent" value="true" />
|
||||||
<preference name="iosPersistentFileLocation" value="Compatibility" />
|
<preference name="iosPersistentFileLocation" value="Compatibility" />
|
||||||
<preference name="Scheme" value="moodleappfs" />
|
|
||||||
<preference name="iosScheme" value="moodleappfs" />
|
<preference name="iosScheme" value="moodleappfs" />
|
||||||
<preference name="WKWebViewOnly" value="true" />
|
<preference name="WKWebViewOnly" value="true" />
|
||||||
<feature name="StatusBar">
|
<feature name="StatusBar">
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { CoreSyncProvider } from '@providers/sync';
|
||||||
import { CoreWSProvider } from '@providers/ws';
|
import { CoreWSProvider } from '@providers/ws';
|
||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||||
|
import { CoreUrlUtils } from '@providers/utils/url';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { AddonModScormOfflineProvider } from './scorm-offline';
|
import { AddonModScormOfflineProvider } from './scorm-offline';
|
||||||
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||||
|
@ -1403,7 +1404,7 @@ export class AddonModScormProvider {
|
||||||
protected isExternalLink(link: string): boolean {
|
protected isExternalLink(link: string): boolean {
|
||||||
link = link.toLowerCase();
|
link = link.toLowerCase();
|
||||||
|
|
||||||
if (link.match(/https?:\/\//)) {
|
if (link.match(/^https?:\/\//i) && !CoreUrlUtils.instance.isLocalFileUrl(link)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (link.substr(0, 4) == 'www.') {
|
} else if (link.substr(0, 4) == 'www.') {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -162,10 +162,10 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
||||||
// Local file.
|
// Local file.
|
||||||
this.utils.openFile(this.file.toURL());
|
this.utils.openFile(this.file.toURL());
|
||||||
} else if (this.fileUrl) {
|
} else if (this.fileUrl) {
|
||||||
if (this.fileUrl.indexOf('http') === 0) {
|
if (this.urlUtils.isLocalFileUrl(this.fileUrl)) {
|
||||||
this.utils.openOnlineFile(this.urlUtils.unfixPluginfileURL(this.fileUrl));
|
|
||||||
} else {
|
|
||||||
this.utils.openFile(this.fileUrl);
|
this.utils.openFile(this.fileUrl);
|
||||||
|
} else {
|
||||||
|
this.utils.openOnlineFile(this.urlUtils.unfixPluginfileURL(this.fileUrl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ export class CoreIframeComponent implements OnInit, OnChanges {
|
||||||
this.allowFullscreen = this.utils.isTrueOrOne(this.allowFullscreen);
|
this.allowFullscreen = this.utils.isTrueOrOne(this.allowFullscreen);
|
||||||
|
|
||||||
// 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.urlUtils.isLocalFileUrl(this.src);
|
||||||
|
|
||||||
const navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl;
|
const navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl;
|
||||||
this.iframeUtils.treatFrame(iframe, false, navCtrl);
|
this.iframeUtils.treatFrame(iframe, false, navCtrl);
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
"enableanalytics": false,
|
"enableanalytics": false,
|
||||||
"enableonboarding": true,
|
"enableonboarding": true,
|
||||||
"forceColorScheme": "",
|
"forceColorScheme": "",
|
||||||
"webviewscheme": "moodleappfs",
|
"ioswebviewscheme": "moodleappfs",
|
||||||
"appstores": {
|
"appstores": {
|
||||||
"android": "com.moodle.moodlemobile",
|
"android": "com.moodle.moodlemobile",
|
||||||
"ios": "id633359593",
|
"ios": "id633359593",
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||||
|
import { CoreUrlUtils } from '@providers/utils/url';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay,
|
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay,
|
||||||
CoreCourseOptionsMenuHandlerToDisplay } from './options-delegate';
|
CoreCourseOptionsMenuHandlerToDisplay } from './options-delegate';
|
||||||
|
@ -615,7 +616,8 @@ export class CoreCourseHelperProvider {
|
||||||
// File shouldn't be opened in browser. Download the module if it needs to be downloaded.
|
// File shouldn't be opened in browser. Download the module if it needs to be downloaded.
|
||||||
return this.downloadModuleWithMainFileIfNeeded(module, courseId, component, componentId, files, siteId)
|
return this.downloadModuleWithMainFileIfNeeded(module, courseId, component, componentId, files, siteId)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.path.indexOf('http') === 0) {
|
|
||||||
|
if (!CoreUrlUtils.instance.isLocalFileUrl(result.path)) {
|
||||||
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
||||||
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
||||||
result.path = result.path + '#moodlemobile-embedded';
|
result.path = result.path + '#moodlemobile-embedded';
|
||||||
|
|
|
@ -214,7 +214,9 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!url || !url.match(/^https?:\/\//i) || (tagName === 'A' && !this.urlUtils.isDownloadableUrl(url))) {
|
if (!url || !url.match(/^https?:\/\//i) || this.urlUtils.isLocalFileUrl(url) ||
|
||||||
|
(tagName === 'A' && !this.urlUtils.isDownloadableUrl(url))) {
|
||||||
|
|
||||||
this.logger.debug('Ignoring non-downloadable URL: ' + url);
|
this.logger.debug('Ignoring non-downloadable URL: ' + url);
|
||||||
if (tagName === 'SOURCE') {
|
if (tagName === 'SOURCE') {
|
||||||
// Restoring original src.
|
// Restoring original src.
|
||||||
|
@ -244,7 +246,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
|
||||||
finalUrl = CoreFile.instance.convertFileSrc(finalUrl);
|
finalUrl = CoreFile.instance.convertFileSrc(finalUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finalUrl.match(/^https?:\/\//i)) {
|
if (!this.urlUtils.isLocalFileUrl(finalUrl)) {
|
||||||
/* In iOS, if we use the same URL in embedded file and background download then the download only
|
/* In iOS, if we use the same URL in embedded file and background download then the download only
|
||||||
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
||||||
finalUrl = finalUrl + '#moodlemobile-embedded';
|
finalUrl = finalUrl + '#moodlemobile-embedded';
|
||||||
|
@ -264,7 +266,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set events to download big files (not downloaded automatically).
|
// Set events to download big files (not downloaded automatically).
|
||||||
if (finalUrl.indexOf('http') === 0 && targetAttr != 'poster' &&
|
if (!this.urlUtils.isLocalFileUrl(finalUrl) && targetAttr != 'poster' &&
|
||||||
(tagName == 'VIDEO' || tagName == 'AUDIO' || tagName == 'A' || tagName == 'SOURCE')) {
|
(tagName == 'VIDEO' || tagName == 'AUDIO' || tagName == 'A' || tagName == 'SOURCE')) {
|
||||||
const eventName = tagName == 'A' ? 'click' : 'play';
|
const eventName = tagName == 'A' ? 'click' : 'play';
|
||||||
let clickableEl = this.element;
|
let clickableEl = this.element;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { CoreFilepoolProvider } from './filepool';
|
||||||
import { CoreSitesProvider } from './sites';
|
import { CoreSitesProvider } from './sites';
|
||||||
import { CoreWSProvider } from './ws';
|
import { CoreWSProvider } from './ws';
|
||||||
import { CoreDomUtilsProvider } from './utils/dom';
|
import { CoreDomUtilsProvider } from './utils/dom';
|
||||||
|
import { CoreUrlUtils } from './utils/url';
|
||||||
import { CoreUtilsProvider } from './utils/utils';
|
import { CoreUtilsProvider } from './utils/utils';
|
||||||
import { CoreConstants } from '@core/constants';
|
import { CoreConstants } from '@core/constants';
|
||||||
import { FileEntry } from '@ionic-native/file';
|
import { FileEntry } from '@ionic-native/file';
|
||||||
|
@ -74,7 +75,7 @@ export class CoreFileHelperProvider {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.indexOf('http') === 0) {
|
if (!CoreUrlUtils.instance.isLocalFileUrl(url)) {
|
||||||
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
||||||
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
||||||
url = url + '#moodlemobile-embedded';
|
url = url + '#moodlemobile-embedded';
|
||||||
|
|
|
@ -1319,7 +1319,9 @@ export class CoreFileProvider {
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
return src.replace(CoreConfigConstants.webviewscheme + '://localhost/_app_file_', 'file://');
|
const scheme = this.platform.is('ios') ? CoreConfigConstants.ioswebviewscheme : 'http';
|
||||||
|
|
||||||
|
return src.replace(scheme + '://localhost/_app_file_', 'file://');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3179,7 +3179,7 @@ export class CoreFilepoolProvider {
|
||||||
|
|
||||||
urls.forEach((url) => {
|
urls.forEach((url) => {
|
||||||
// Download the file only if it's an online URL.
|
// Download the file only if it's an online URL.
|
||||||
if (url.indexOf('http') == 0) {
|
if (!this.urlUtils.isLocalFileUrl(url)) {
|
||||||
promises.push(this.downloadUrl(siteId, url, false, component, componentId, 0, undefined, undefined, undefined,
|
promises.push(this.downloadUrl(siteId, url, false, component, componentId, 0, undefined, undefined, undefined,
|
||||||
revision).then((fileUrl) => {
|
revision).then((fileUrl) => {
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { CoreUrlUtilsProvider } from './url';
|
||||||
import { CoreUtilsProvider } from './utils';
|
import { CoreUtilsProvider } from './utils';
|
||||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||||
import { makeSingleton } from '@singletons/core.singletons';
|
import { makeSingleton } from '@singletons/core.singletons';
|
||||||
|
import { CoreUrl } from '@singletons/url';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Utils" service with helper functions for iframes, embed and similar.
|
* "Utils" service with helper functions for iframes, embed and similar.
|
||||||
|
@ -54,7 +55,7 @@ export class CoreIframeUtilsProvider {
|
||||||
checkOnlineFrameInOffline(element: any, isSubframe?: boolean): boolean {
|
checkOnlineFrameInOffline(element: any, isSubframe?: boolean): boolean {
|
||||||
const src = element.src || element.data;
|
const src = element.src || element.data;
|
||||||
|
|
||||||
if (src && src.match(/^https?:\/\//i) && !this.appProvider.isOnline()) {
|
if (src && !this.urlUtils.isLocalFileUrl(src) && !this.appProvider.isOnline()) {
|
||||||
if (element.classList.contains('core-iframe-offline-disabled')) {
|
if (element.classList.contains('core-iframe-offline-disabled')) {
|
||||||
// Iframe already hidden, stop.
|
// Iframe already hidden, stop.
|
||||||
return true;
|
return true;
|
||||||
|
@ -347,13 +348,13 @@ export class CoreIframeUtilsProvider {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const scheme = this.urlUtils.getUrlScheme(link.href);
|
const urlParts = CoreUrl.parse(link.href);
|
||||||
if (!link.href || (scheme && scheme == 'javascript')) {
|
if (!link.href || (urlParts.protocol && urlParts.protocol == 'javascript')) {
|
||||||
// Links with no URL and Javascript links are ignored.
|
// Links with no URL and Javascript links are ignored.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.urlUtils.isLocalFileUrlScheme(scheme)) {
|
if (!this.urlUtils.isLocalFileUrlScheme(urlParts.protocol, urlParts.domain)) {
|
||||||
// Scheme suggests it's an external resource.
|
// Scheme suggests it's an external resource.
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { CoreLangProvider } from '../lang';
|
||||||
import { CoreTextUtilsProvider } from './text';
|
import { CoreTextUtilsProvider } from './text';
|
||||||
import { makeSingleton } from '@singletons/core.singletons';
|
import { makeSingleton } from '@singletons/core.singletons';
|
||||||
import { CoreConfigConstants } from '../../configconstants';
|
import { CoreConfigConstants } from '../../configconstants';
|
||||||
|
import { CoreUrl } from '@singletons/url';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Utils" service with helper functions for URLs.
|
* "Utils" service with helper functions for URLs.
|
||||||
|
@ -432,17 +433,28 @@ export class CoreUrlUtilsProvider {
|
||||||
* @return Whether the URL belongs to a local file.
|
* @return Whether the URL belongs to a local file.
|
||||||
*/
|
*/
|
||||||
isLocalFileUrl(url: string): boolean {
|
isLocalFileUrl(url: string): boolean {
|
||||||
return this.isLocalFileUrlScheme(this.getUrlScheme(url));
|
const urlParts = CoreUrl.parse(url);
|
||||||
|
|
||||||
|
return this.isLocalFileUrlScheme(urlParts.protocol, urlParts.domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether a URL scheme belongs to a local file.
|
* Check whether a URL scheme belongs to a local file.
|
||||||
*
|
*
|
||||||
* @param scheme Scheme to check.
|
* @param scheme Scheme to check.
|
||||||
|
* @param domain The domain. Needed because in Android the WebView scheme is http.
|
||||||
* @return Whether the scheme belongs to a local file.
|
* @return Whether the scheme belongs to a local file.
|
||||||
*/
|
*/
|
||||||
isLocalFileUrlScheme(scheme: string): boolean {
|
isLocalFileUrlScheme(scheme: string, domain: string): boolean {
|
||||||
return scheme == 'cdvfile' || scheme == 'file' || scheme == 'filesystem' || scheme == CoreConfigConstants.webviewscheme;
|
if (scheme) {
|
||||||
|
scheme = scheme.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return scheme == 'cdvfile' ||
|
||||||
|
scheme == 'file' ||
|
||||||
|
scheme == 'filesystem' ||
|
||||||
|
scheme == CoreConfigConstants.ioswebviewscheme ||
|
||||||
|
(scheme == 'http' && domain == 'localhost');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue