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

Add --android_tunnel flag to emrun (cross-origin isolation on Android device) #20783

Merged
merged 4 commits into from
Nov 30, 2023

Conversation

lippinj
Copy link
Contributor

@lippinj lippinj commented Nov 27, 2023

I am proposing a new flag --android_tunnel for emrun.

The --android_tunnel flag has the following effects:

  1. --android option is set (i.e., --android_tunnel implies --android)
  2. hostname is set to localhost
  3. adb reverse tcp:{port} tcp:{port} is invoked before launching (establishes a reverse socket connection)

The page running on the Android device can then have cross-origin isolation. Cross-origin isolation is (typically) required for certain browser features, in particular for SharedArrayBuffer, without which builds with pthreads cannot be run on an Android device.

This flag does two things:

 1. we use 'localhost' as the hostname
 2. we invoke 'adb reverse tcp:{port} tcp:{port}' before launching

This means that the page will run with cross-origin isolation.

Without cross-origin isolation, we typically can't have features
such as SharedArrayBuffer, which is needed for apps using pthreads.
@lippinj lippinj changed the title Add --android_tunnel flag to emrun (gives cross-origin isolation) Add --android_tunnel flag to emrun (cross-origin isolation on Android device) Nov 27, 2023
@sbc100
Copy link
Collaborator

sbc100 commented Nov 27, 2023

Do you know why cross-origin isolation doesn't work with the regular hostname + networked? Doesn't emrun send the correct header for cross-origin to work?

@lippinj
Copy link
Contributor Author

lippinj commented Nov 28, 2023

In the regular setup, we load the page over HTTP. Any non-localhost origin over HTTP counts as "Not Trustworthy", so a reasonably security-conscious browser will ignore the COOP header as a security measure. At least Chrome does this, logging the following error:

The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.

We can get around this by disabling security features on the browser or by promoting to HTTPS (e.g. by going through ngrok), but to my mind the port tunnel is the most straightforward option.

@sbc100
Copy link
Collaborator

sbc100 commented Nov 28, 2023

In the regular setup, we load the page over HTTP. Any non-localhost origin over HTTP counts as "Not Trustworthy", so a reasonably security-conscious browser will ignore the COOP header as a security measure. At least Chrome does this, logging the following error:

The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.

We can get around this by disabling security features on the browser or by promoting to HTTPS (e.g. by going through ngrok), but to my mind the port tunnel is the most straightforward option.

I see, so an alternative would be use HTTPS, but that would require some kind of certificate which might be tricky?

@lippinj
Copy link
Contributor Author

lippinj commented Nov 29, 2023

I see, so an alternative would be use HTTPS, but that would require some kind of certificate which might be tricky?

Yes. Especially since we commonly serve from a private IP address.

I am not that well versed in TLS, but this is how I understand it. We might self-sign a certificate, which means we have to dismiss a security warning on the Android device each time (that is, if the browser does not reject a certificate for a private IP address out of hand, which it might for all I know). For a certificate from a CA, we presumably need to also set up a domain name that resolves to the machine we want (I doubt they issue certs for private IP addresses).

I think the tunneling solution is less laborious and less invasive than either of these options.

emrun.py Outdated
@@ -1636,7 +1647,12 @@ def run():
if not file_to_serve_is_url:
if len(options.cmdlineparams):
url += '?' + '&'.join(options.cmdlineparams)
hostname = socket.gethostbyname(socket.gethostname()) if options.android else options.hostname
if options.android_tunnel:
hostname = 'localhost'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This files uses two-space indention.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed indents to two spaces.

@sbc100 sbc100 enabled auto-merge (squash) November 29, 2023 18:50
@sbc100 sbc100 merged commit 65cd1d8 into emscripten-core:main Nov 30, 2023
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants