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

[Bug]: Android's WebViewCompat.addWebMessageListener fails when navigating to a local website with http scheme #7570

Closed
1 of 3 tasks
martin-braun opened this issue Jul 19, 2024 · 5 comments
Labels

Comments

@martin-braun
Copy link

martin-braun commented Jul 19, 2024

Capacitor Version

Capacitor Doctor 💊

Latest Dependencies:

@capacitor/cli: 6.1.1
@capacitor/core: 6.1.1
@capacitor/android: 6.1.1
@capacitor/ios: 6.1.1

Installed Dependencies:

@capacitor/ios: not installed
@capacitor/core: 6.1.1
@capacitor/android: 6.1.1
@capacitor/cli: 6.1.1

[success] Android looking great! 👌

Other API Details

`npm --version`: `10.8.1`
`node --version`: `v22.4.1`

Test device: Android 11

Platforms Affected

  • iOS
  • Android
  • Web

Current Behavior

When your app loads a website on the local network, such as http://192.168.77.166:8080 this will open a new browser until allowNavigation is supplied with 192.168.77.166 in the Capacitor configuration. When using the legacy bridge useLegacyBridge: true the MessageHandler would use webView.addJavascriptInterface to inject the window.androidBridge object into the remote website, so that the platform is recognized as android and the remote website would be able to communicate with the native plugins of Capactor, see:

webView.addJavascriptInterface(this, "androidBridge");

If the useLegacyBridge: false (default behavior), the MessageHandler will attempt to use WebViewCompat.addWebMessageListener to inject the androidBridge object:

WebViewCompat.addWebMessageListener(webView, "androidBridge", bridge.getAllowedOriginRules(), capListener);

This however isn't working if the target website has http:// instead of https:// scheme, thus androidBridge is null after navigating to unsafe remote websites.

  1. WebViewCompat.addWebMessageListener explicitly states:

Each allowedOriginRules entry must follow the format SCHEME "://" [ HOSTNAME_PATTERN [ ":" PORT ] ]

So, Capacitor requires allowNavigation to be a list of domains without scheme, such as example.org and you then make bridge.getAllowedOriginRules() return an array of such list with the proper scheme, which is https:// always. This is the wrong behavior on local websites that don't use SSL for obvious reasons.

  1. Even when doing useLegacyBridge: false or changing the code to prefix http:// instead, native plugins will still not work, until the domain is specified with a port another time within the allowNavigation list. Otherwise the pattern matching will fail and, despite the androidBridge not being null, won't have an implementation for the platform and report so.

I was able to bypass both issues by having this in my configuration:

  "server": {
    "allowNavigation": [
      "192.168.77.166",
      "192.168.77.166:8080",
      "http://192.168.77.166:8080"
    ]
  }

Now window.androidBridge is not null on the network website and my native plugins work.

Expected Behavior

We need a better way here. This was confusing, wasted a lot of time, is not documented. Providing http://192.168.0.80:8080 should be enough to satisfy all rules. I was going crazy testing this. There is no documentation explaining this.

Project Reproduction


Additional Information

I cannot share my private project, you should be able to reproduce with:

{
  "appId": "org.example.wrapper",
  "appName": "Example Navigation Wrapper",
  "bundledWebRuntime": false,
  "npmClient": "npm",
  "webDir": "mobile",
  "android": {
    "allowMixedContent": true,
    "hideLogs": false,
    "webContentsDebuggingEnabled": true
  },
  "plugins": {
    "SplashScreen": {
      "launchShowDuration": 0
    }
  },
  "cordova": {},
  "server": {
    "allowNavigation": [
      "192.168.77.166",
    ]
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Test</title>
  </head>
  <body>
    <script type="text/javascript" src="mobile.js"></script>
  </body>
</html>
// mobile.js
window.location.href = "http://192.168.77.166"

Use your own network IP and host a little web server on 0.0.0.0:8080 to see how it's not working, until you add all the allowNavigation entries.

@martin-braun martin-braun changed the title [Bug]: Android's WebViewCompat.addWebMessageListener fails when navigating to a remote website [Bug]: Android's WebViewCompat.addWebMessageListener fails when navigating to a local website with http scheme Jul 19, 2024
@martin-braun
Copy link
Author

martin-braun commented Jul 25, 2024

I have tested my above work around on an Android 7 POS device and this causes a crash of the app:

java.lang.RuntimeException: Unable to start activity ComponentInfo{..../.....MainActivity}: java.lang.IllegalArgumentException: allowedOriginRules https://192.168.77.166 is invalid

It seems older Android WebView's were more sensitive about allowOriginRules and didn't just ignore invalid rules.

Another reason why I think Capacitor isn't explicit enough about those allowOriginRules. The configuration should allow me to tell that my entry is http, instead of https and prevent those prefixes from being part of the URL set:

Screenshot 2024-07-25 at 19 13 00

Look at this breakpoint when the stuff is passed to the WebView within the bridge (192.168.77.166 in this example). If Capacitor would allow me to tell what's https and whats not.

I hate this black box magic. All I want is testing my Capacitor app with a locally hosted website, I wish this was actually tested.

@jcesarmobile
Copy link
Member

closing as duplicate of #7454

@jcesarmobile jcesarmobile closed this as not planned Won't fix, can't repro, duplicate, stale Jul 26, 2024
@martin-braun

This comment was marked as abuse.

@martin-braun

This comment was marked as abuse.

Copy link

ionitron-bot bot commented Aug 31, 2024

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Aug 31, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants