Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cordova 10 on android, disabled AndroidInsecureFileModeEnabled and local Files/cdvfiles #1361

Closed
3 tasks done
boredom2 opened this issue Sep 29, 2021 · 11 comments · Fixed by apache/cordova-plugin-file#513
Closed
3 tasks done
Labels

Comments

@boredom2
Copy link

boredom2 commented Sep 29, 2021

Bug Report

Problem

We are creating local Image files, that should be displayed in an <img src="LOCAL" />
Until cordova 9, that worked with "file:///..." (and CSP including file:, filesystem: and cdvfile:)

What is expected to happen?

Images should load the local File - with "file:///" URL or at least with cdvfile:// URL.

What does actually happen?

Now, "file:" does not work at all (not allowed to load) - after converting the local ULR to a cdvfile though, the Request dies with "net::ERR_UNKNOWN_URL_SCHEME"

If I set "AndroidInsecureFileModeEnabled" to TRUE, everything is working again fine. But I would really prefer to not use this Setting for other reasons. These Images are the only time, the WebView comes in contact with local Files.

Environment, Platform, Device

all devices

Version information

Cordova 10 on android 11, android 12 Beta 4.

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above

I was able to solve this by a very annoying hack - i use Cordova Filesystem Methods to create a data: String out of the File. But thats very time-consuming, ugly and complicated to handle with a lot of Files. Do I missed some kind of Setting or anything similar, that stops this Functionality from working?

@breautek
Copy link
Contributor

Images should load the local File - with "file:///" URL

With cordova-android@10, by default the WebViewAssetLoader is used. Direct file:// access is intentionally disabled as it's considered insecure. (Always has been, but there Android never provided a solution until WebViewAssetLoader) The AndroidInsecureFileModeEnabled preference is the escape hatch to make cordova-android behave like older versions, which does not use the WebViewAssetLoader.

or at least with cdvfile:// URL.

cdvfile:// file paths is suppose to still work, but it is known that it does not. I'll attach the bug label to this for this reason.

@breautek breautek added the bug label Oct 19, 2021
@vdias38
Copy link

vdias38 commented Nov 16, 2021

Hi,

I face similar issue, using cdvfile:// to handle local images.
Does it exist a workaround or hotfix we can apply to migrate to cordova-android 10 until a resolution on a stable release ?

Thanks for your help

@alextapia007
Copy link

downgrade cordova 9 its posible solution?

@breautek
Copy link
Contributor

downgrade cordova 9 its posible solution?

Could be. You'll need <preference name="android-targetSdkVersion" value="30" /> to satisfy to Google Play store requirements. API 30 isn't officially supported on cordova-android@9 but I had that configuration working for my own apps for awhile.

@jackysee
Copy link

jackysee commented Nov 25, 2021

My workaround is convert those file:// to __file__ in js.
And create a pathHandler in plugin.
In my case I just clone cdv photo plugin and modify the source.
One thing to notice that you cannot get query parameter in path, so in the case of cdvphotolibrary I need to specially handle them.
Only url that needs DOM access should be converted. file:// url can work fine when using e.g. fs.getFile

  @Override   
  public CordovaPluginPathHandler getPathHandler() {
      return new CordovaPluginPathHandler(new WebViewAssetLoader.PathHandler() {
            @Nullable
            @Override
            public WebResourceResponse handle(@NonNull String path) {
                Log.d(TAG, "Path Handler " + path);
                //e.g. cdvphotolibrary/thumbnail/photoId=3112&width=512&height=384&quality=0.8
                if(path.startsWith(PHOTO_LIBRARY_PROTOCOL)) {
                    path = path.replaceAll("^cdvphotolibrary/", "cdvphotolibrary://");
                    path = path.replaceAll("thumbnail/", "thumbnail?");
                    path = path.replaceAll("photo/", "photo?");
                    Uri uri = Uri.parse(path);
                    Log.d(TAG, "URI " + uri);
                    Uri remappedUri = remapUri(uri);
                    Log.d(TAG, "RemappedUri " + uri);
                    if(remappedUri != null) {
                        try {
                            CordovaResourceApi.OpenForReadResult result = handleOpenForRead(remappedUri);
                            Log.d(TAG, "Result " + result.inputStream.available());
                            return new WebResourceResponse(result.mimeType, "utf-8", result.inputStream);
                        } catch (IOException e) {
                            LOG.e(TAG, "error open cdvphotolibrary resource "+ e);
                        }
                    }
                }

                if(path.startsWith("__file__/")) {
                    File file = new File(path.replaceAll("^__file__/", "/"));
                    Uri fileUri = Uri.fromFile(file);
                    Log.d(TAG, "fileUri " + fileUri);
                    String mimeType = webView.getResourceApi().getMimeType(fileUri);
                    Log.d(TAG, "mimeType " + mimeType);
                    try {
                        InputStream is = getContext().getContentResolver().openInputStream(fileUri);
                        Log.d(TAG, "Result " + is.available());
                        return new WebResourceResponse(mimeType, "utf-8", is);
                    } catch(Exception e) {
                        LOG.e(TAG, "error open file resource "+ e);
                    }
                }
                return null;
            }
        });
  }

@vdias38
Copy link

vdias38 commented Nov 25, 2021

downgrade cordova 9 its posible solution?

We must target at least Android 11 (API level 30) and it's only supported by cordova-android 10.

Thanks @breautek for the hack (downgrade to cordova 9 with <preference name="android-targetSdkVersion" value="30" />), I'll test it tomorrow.

@zoranmil
Copy link

zoranmil commented Dec 28, 2021

preference name="scheme" value="http"
solve my problem

@vdias38
Copy link

vdias38 commented Dec 28, 2021

downgrade cordova 9 its posible solution?

We must target at least Android 11 (API level 30) and it's only supported by cordova-android 10.

Thanks @breautek for the hack (downgrade to cordova 9 with <preference name="android-targetSdkVersion" value="30" />), I'll test it tomorrow.

I did as @breautek suggested and it works.

@zoranmil be careful your workaround should not work if used on iOS

@M3skar
Copy link

M3skar commented Feb 2, 2022

cordova-android@10 : overriden remapUri in plugin is not being called in plugin even if "AndroidInsecureFileModeEnabled" is enabled.
still using cordova-android@9

@bobobobo
Copy link

Is this the same issue as #1329 ?

@plexorama
Copy link

cordova-android@10 : overriden remapUri in plugin is not being called in plugin even if "AndroidInsecureFileModeEnabled" is enabled. still using cordova-android@9

I've encountered the same issue with cordova-android@10, remapUri is never called. The reason is for this is, the deprecated shouldInterceptRequest(WebView view, String url) method - implement in the cordova SystemWebViewClient-class - is never called by the WebView. As a consequence, the remapUri-method is never invoked. However, there are two versions of the shouldInterceptRequest-method. The 'new' version of shouldInterceptRequest is called by WebView, which then invokes assetLoader.shouldInterceptRequest - that however is wrong in my opinion. It should call the old shouldInterceptRequest-method first and if that returns null, the assetLoader.shouldInterceptRequest-method should be invoked as a fallback.

if you want to re-enable the remapUri-invocation, change the new shouldInterceptRequest-method CordovaLib/src/org/apache/cordova/engine/SystemWebViewClient.java as follows:

replace this method:

public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {

        return this.assetLoader.shouldInterceptRequest(request.getUrl());
}

with the following code:

public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {

        Log.d(TAG, String.format("shouldInterceptRequest(): request=%s",request.getUrl()));
        WebResourceResponse response = shouldInterceptRequest(view,request.getUrl().toString());
        if (response != null){
            return response;
        }
        return this.assetLoader.shouldInterceptRequest(request.getUrl());
}

This will re-enable the old remapUri-behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants