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

Support custom scheme or domain for local content on Android #1004

Closed
AshleyScirra opened this issue Jun 22, 2020 · 12 comments
Closed

Support custom scheme or domain for local content on Android #1004

AshleyScirra opened this issue Jun 22, 2020 · 12 comments

Comments

@AshleyScirra
Copy link

AshleyScirra commented Jun 22, 2020

Feature Request

As of cordova-ios 6.0.0, you can use the following in config.xml:

<preference name="scheme" value="app"/>
<preference name="hostname" value="localhost"/>

Then the app runs on app://localhost instead of file://. This does not appear to work on Android though - having tried it the app still runs at a file:// URL.

Motivation Behind Feature

Running on file: brings a number of origin-related problems. Notably on file:, the browser treats every resource as a different origin, causing some features to be blocked. In particular, fetch() cannot be used at all, because it's actually written in to the specification that it can just throw on file: protocol and that's what Chromium chooses to do.

Further, this will allow Cordova Android apps to more closely align their codebases with iOS, since in both cases it can be running on the same URL (app://localhost) with identical capabilities regarding the security origin, use of fetch(), etc.

Alternatives or Workarounds

Right now we are forced to use cordova-plugin-file to read local files, and in many cases use some ugly code involving blobs and blob URLs to work around restrictions with file: URLs. We also have to maintain two significantly different codepaths, one using fetch(), the other using cordova-plugin-file methods.

@jcesarmobile
Copy link
Member

Google engineers have recommended to discourage custom schemes in Android apps in this ionic webview issue, so I don't think this is something we should do in cordova-android.

But maybe, as ionic webview does, intercept the requests so they load as http/https urls. That should fix some of the mentioned problems.

But even that, I don't think it should be in cordova-android for now, should start as a separate plugin as cordova-plugin-wkwebview-engine and if people uses it, integrate it in cordova-android later on.

@AshleyScirra
Copy link
Author

Ah, I see, interesting.

It sounds like an alternative could be to host on a custom local domain, e.g. https://cordova.local. I imagine this then makes it clear whether the request should be served locally by matching the cordova.local domain on the request, and then everything is still treated as same-origin and using the well-defined and stable https scheme. (Would that work? It seems odd to use https without a certificate, but if that will do the job then I think it's fine)

The real motivation here is to not use file: due to the cross-origin obstacles it would throw in the way, so a custom domain on https would still solve the original problem. So could that work instead?

@AshleyScirra AshleyScirra changed the title Support <preference name="scheme"> on Android Support custom scheme or domain on Android Jun 24, 2020
@AshleyScirra AshleyScirra changed the title Support custom scheme or domain on Android Support custom scheme or domain for local content on Android Jun 24, 2020
@brodybits
Copy link
Contributor

host on a custom local domain, e.g. https://cordova.local.

Or maybe use .localhost tld for an extra 0.001 % safety factor ref:

It seems odd to use https without a certificate

Maybe use http scheme?

@dpogue
Copy link
Member

dpogue commented Jun 24, 2020

A few notes:

  • The WebViewAssetLoader option mentioned by the Google folks requires using the AndroidX WebView, not the built-in WebView.
  • The default/suggested URL origin for WebViewAssetLoader is https://appassets.androidplatform.net
  • No certificate is needed for HTTPS because it's intercepted on the device before a request is made
  • HTTPS is encouraged because lots of web platform functionality is being disabled for non-secure origins

@AshleyScirra
Copy link
Author

A key detail is the webview should still think the page is in a secure context, since some features are gated behind that. I'm not sure if a URL like http://cordova.localhost will quality as a secure context. If it does not it would be preferable to use https.

@breautek
Copy link
Contributor

But even that, I don't think it should be in cordova-android for now, should start as a separate plugin as cordova-plugin-wkwebview-engine and if people uses it, integrate it in cordova-android later on.

Just noting that a solution like this should solve #560 ... where the current workaround is to use the ionic webview.

@AshleyScirra
Copy link
Author

Note: this may also be necessary to support JavaScript Modules (#1142).

@jcesarmobile
Copy link
Member

This PR that uses the WebViewAssetLoader will allow to load apps from https, the <preference name="hostname" value="localhost"/> will be available, the scheme will not, will always use https.

@hariprakashnagar
Copy link

Is it possible to change app://localhost to http://localhost/ on Cordova ios >6. We are facing an issue with Cross Origin because app://localhost is not a valid domain.

@breautek
Copy link
Contributor

breautek commented Apr 4, 2024

Is it possible to change app://localhost to http://localhost/ on Cordova ios >6. We are facing an issue with Cross Origin because app://localhost is not a valid domain.

Short answer is this isn't possible.

On iOS the WKURLSchemeHandler is the backing API and only allows you to use a scheme that is not already registered. This means that all well known standard schemes like http or https is automatically not supported by the iOS API.

On Android, the WebViewAssetLoader is the backing API and it only supports setting either http or https as the scheme. So this creates a situation where you cannot make the two platforms consistent.

Your backend must either enable all domains using a wildcard for the Access-Control-Allow-Origin response header, or your backend must read the request's Origin header and dynamically set the Access-Control-Allow-Origin response header accordingly if the Origin is a value that you expect.

@hariprakashnagar
Copy link

Is it possible to change app://localhost to http://localhost/ on Cordova ios >6. We are facing an issue with Cross Origin because app://localhost is not a valid domain.

Short answer is this isn't possible.

On iOS the WKURLSchemeHandler is the backing API and only allows you to use a scheme that is not already registered. This means that all well known standard schemes like http or https is automatically not supported by the iOS API.

On Android, the WebViewAssetLoader is the backing API and it only supports setting either http or https as the scheme. So this creates a situation where you cannot make the two platforms consistent.

Your backend must either enable all domains using a wildcard for the Access-Control-Allow-Origin response header, or your backend must read the request's Origin header and dynamically set the Access-Control-Allow-Origin response header accordingly if the Origin is a value that you expect.

Yes, we can do this but PDF embed viewer does not work with Web view [Mobile browser] if we use from hosted URL.

@breautek
Copy link
Contributor

breautek commented Apr 4, 2024

Yes, we can do this but PDF embed viewer does not work with Web view [Mobile browser] if we use from hosted URL.

This doesn't sound like a CORS issue then.

The scheme urls used by the webview is only accessible by that webview instance. So if the PDF viewer for example is either a third-party application OR a cordova plugin that attempts to use native APIs to fetch that resource (including native http APIs) then those requests aren't intercepted by the webview and you don't get access to your content. It sounds like your issue is this.

If you're trying to expose a local app asset, you might be able to form a file:// url instead. The file plugin has useful constants to get to your app's storage data. For iOS, cordova.file.applicationDirectory + "www/" should yield a file:// path that leads to your www directory.

On Android it should be the same, as your www folder will be inside file:///android_asset/. This path isn't accessible by the webview if you have schemes enabled, but it should still be accessible by native APIs, so it should still work in your use case if my assumption about your PDF viewer is correct.

If it isn't, or you still have trouble, it may be worth opening a discussion at https://github.com/apache/cordova/discussions for further support. I'll be locking this thread since it's now getting off-topic and I don't want to spam the OP.

@apache apache locked as off-topic and limited conversation to collaborators Apr 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants