Skip to content

Add support for checking the ESS config in Element Pro - #7302

Merged
jmartinesp merged 18 commits into
developfrom
feat/add-ess-config-endpoint-support
Aug 11, 2026
Merged

Add support for checking the ESS config in Element Pro#7302
jmartinesp merged 18 commits into
developfrom
feat/add-ess-config-endpoint-support

Conversation

@jmartinesp

@jmartinesp jmartinesp commented Jul 30, 2026

Copy link
Copy Markdown
Member

Content

  • Create ElementWellKnownSource enum to allow deciding where to get the remote enterprise config from.
  • Add RemoteEnterpriseConfigService to make this decision (this is implemented mostly in the enterprise code).
  • Add UrlContentFetcher which is a component to fetch data from any URL using a GET request and implement 2 versions: one with a temporary and unauthenticated SDK client for unauthenticated requests and another one with RustMatrixClient so we perform the request using the authenticated client in the SDK.
  • Remove SessionElementWelknownRetriever and move the logic to WellknownRetriever, allowing us to use any of the 2 UrlContentFetcher instances to actually fetch the data without having to create 2 variations of this class for the 2 DI scopes.
  • Use RemoteEnterpriseConfigService as much as possible. The only exception is in DefaultAccountProviderAccessControl because we want to always check the legacy element well known URL there to check for the requires_element_pro config there.

The PR in enterprise repo is https://github.com/element-hq/element-android-enterprise/pull/38.

Motivation and context

https://github.com/element-hq/element-enterprise/issues/297

Tests

With an Element Pro version, check the new endpoint is checked, then the existing well known one is.

You can also check unauthenticated ones go through OkHttp and authenticated ones from the SDK, based on the logs.

Tested devices

  • Physical
  • Emulator
  • OS version(s): 15

Checklist

  • I am aware of the etiquette.
  • This PR was made with the help of AI:
    • Yes. In this case, please request a review by Copilot.
    • No.
  • Changes have been tested on an Android device or Android emulator with API 24
  • UI change has been tested on both light and dark themes
  • Accessibility has been taken into account. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
  • Pull request is based on the develop branch
  • Pull request title will be used in the release note, it clearly defines what will change for the user
  • Pull request includes screenshots or videos if containing UI changes
  • You've made a self review of your PR

@jmartinesp jmartinesp added the PR-Element-Pro for Element Pro specific changes label Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📱 Scan the QR code below to install the build (arm64 only) for this PR.
QR code
If you can't scan the QR code you can install the build via this link: https://i.diawi.com/hUBz1U

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.71429% with 66 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.51%. Comparing base (6d6ca97) to head (4bfa9e6).
⚠️ Report is 2 commits behind head on develop.

Files with missing lines Patch % Lines
...impl/web/WebClientUrlForAuthenticationRetriever.kt 0.00% 17 Missing ⚠️
...libraries/matrix/impl/RustTemporaryMatrixClient.kt 25.00% 9 Missing ⚠️
...atrix/impl/auth/RustMatrixAuthenticationService.kt 11.11% 6 Missing and 2 partials ⚠️
...d/libraries/matrix/impl/RustMatrixClientFactory.kt 30.00% 5 Missing and 2 partials ⚠️
...libraries/wellknown/impl/SessionWellknownModule.kt 0.00% 7 Missing ⚠️
...raries/wellknown/impl/DefaultWellknownRetriever.kt 89.58% 3 Missing and 2 partials ⚠️
...ibraries/wellknown/api/WellknownRetrieverResult.kt 40.00% 1 Missing and 2 partials ⚠️
...atures/enterprise/impl/DefaultEnterpriseService.kt 0.00% 2 Missing ⚠️
...oteconfig/DefaultRemoteEnterpriseConfigProvider.kt 0.00% 2 Missing ⚠️
.../features/enterprise/test/FakeEnterpriseService.kt 60.00% 2 Missing ⚠️
... and 4 more
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #7302      +/-   ##
===========================================
- Coverage    80.55%   80.51%   -0.04%     
===========================================
  Files         2772     2780       +8     
  Lines        80738    80788      +50     
  Branches     11011    11017       +6     
===========================================
+ Hits         65040    65049       +9     
- Misses       11447    11484      +37     
- Partials      4251     4255       +4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jmartinesp
jmartinesp marked this pull request as ready for review July 31, 2026 12:21
@jmartinesp
jmartinesp requested a review from a team as a code owner July 31, 2026 12:21
@jmartinesp
jmartinesp requested review from ganfra and removed request for a team July 31, 2026 12:21
@jmartinesp

Copy link
Copy Markdown
Member Author

There is an implementation without OkHttp (creating temporary Rust clients like iOS does) in https://github.com/element-hq/element-x-android/tree/feat/add-ess-config-endpoint-support-with-assistedinject.

@jmartinesp
jmartinesp force-pushed the feat/add-ess-config-endpoint-support branch 2 times, most recently from 0cbd738 to fcad692 Compare August 10, 2026 12:29
@jmartinesp

Copy link
Copy Markdown
Member Author

I've merge the branch mentioned above, rebased the code and split it into new commits so it's hopefully easier to understand. I think you can review it now @ganfra .

FWIW the temporary client approach is what iOS does and should help keep the network stack consistent in the authenticating and already authenticated scopes.

@ganfra ganfra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, looking solid. Just small remarks!

return when (val cacheData = store.get(checkedHost)) {
is WellknownRetrieverResult.Success -> {
Timber.d("Using cached well-known for domain $checkedHost")
fetchElementWellKnown(checkedHost, source, store)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is the fetch here necessary? And if yes, should we launch the fetch on a separate coroutine?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Oops, you found some test code I forgot to remove. Thanks!


@BindingContainer
@ContributesTo(SessionScope::class)
@ContributesTo(SessionScope::class, replaces = [GetUrlResolver::class])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need this replaces? This sounds a bit weird


package io.element.android.libraries.matrix.api

fun interface GetUrlResolver {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

GetUrl is a bit misleading? On first hand I though it was just returning an url I know it comes from the rust sdk name, but could be something like UrlContentFetcher or HttpGetExecutor?

* Note: this client implements an [AutoCloseable] interface, so using [AutoCloseable.close] or [AutoCloseable.use] will clean up any resources associated
* with it, such as temporary files.
*/
interface TemporaryMatrixClient : GetUrlResolver, AutoCloseable

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe it should be called UnauthenticatedMatrixClient? not sure...
Also, does it need to be part of the api module?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Maybe it should be called UnauthenticatedMatrixClient? not sure...

That's what I had at first, but I thought the temporary part was more important... now I'm not so sure.

Also, does it need to be part of the api module?

I think so, otherwise how would you use the TemporaryMatrixClientFactory to return one of these?

WellknownRetrieverResult.NotFound
} else {
WellknownRetrieverResult.Error(e)
val checkedHost = URL(host.ensureProtocol()).host ?: host

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think host never returns null, so the fallback doesn't work

@jmartinesp

Copy link
Copy Markdown
Member Author

@ganfra I uploaded some changes to fix the issues you mentioned, in case you want to double check. Also, remember the enterprise PR should be reviewed too before this one can be merged.

In the future, we want to move the enterprise config to the private Element Pro repo, this is a first step
This allows us to decide where to get the remote enterprise config from.
Implementations should just perform a GET request and return the raw body as bytes
For Pro, this will check different remote config sources and return the result. For FOSS, this will always return a `NotFound` result
This is an abstraction over an actual unauthenticated `Client` from the SDK that implements `GetUrlResolver`, and is supposed to be short-lived.

With this, we can use the SDK network stack to perform arbitrary GET url operations.

The `AutoCloseable` implementation makes it easier to clean up any leftover local config after using this temporary client.
Also, allow instantiating it using a factory: with this we can always decide where to take the config from and how to do it

Do the same for `ElementWellknownStore` so we can store and restore the values for different sources (endpoints) independently
… up to date in the store in `DefaultWellknownRetriever`
…ientFactory.createTemporaryMatrixClient` to just `create`
@jmartinesp
jmartinesp force-pushed the feat/add-ess-config-endpoint-support branch from 6822a1b to 4bfa9e6 Compare August 11, 2026 10:13
@sonarqubecloud

Copy link
Copy Markdown

@jmartinesp
jmartinesp merged commit 6c7f4d3 into develop Aug 11, 2026
34 of 37 checks passed
@jmartinesp
jmartinesp deleted the feat/add-ess-config-endpoint-support branch August 11, 2026 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR-Element-Pro for Element Pro specific changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants