GoogleChrome / GoogleChrome/android-browser-helper

Broken Splash Screen Since Chrome 152

Open
#623 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
832
Forks
370
Avg merge
1d 3h
Merged PRs (30d)
6

Description

**Describe the bug**

Since Chrome 152, the TWA splash screen silently stops appearing. The app launches
straight into the web content with no splash and no branded transition. There is no
crash and no user-visible error.

The only signal is a logcat warning from the library:

```
W/PwaWrapperSplashScreenStrategy: Failed to transfer splash image.
```

**Root cause (from source analysis)**

`SplashImageTransferTask` → `TrustedWebUtils.transferSplashImage()` →
`CustomTabsSession.receiveFile()`. Chrome 152 added two new security checks to
`CustomTabsConnection.receiveFile()`, so that call now returns `false` in cases
where it previously returned `true`:

- [`[Android] Require a registered session for receiveFile`](https://chromium-review.googlesource.com/c/chromium/src/+/8032890) (`a34728fb28`, main@{#1655817})
```java
// CustomTabsConnection.receiveFile
+ SessionHolder session = new SessionHolder<>(sessionToken);
+ if (!mClientManager.isSessionValid(session)) return false;

// CustomTabsConnectionServiceImpl.receiveFile
+ if (!isFirstRunDone()) return false;
```
From the commit message: *"Unlike the other CustomTabsService entry points,
receiveFile did not check that the caller had completed first run or that the
supplied session token had been registered via newSession() before opening the
supplied URI and decoding it as a TWA splash image."*

- [`[CCT] Check caller URI permission in receiveFile()`](https://chromium-review.googlesource.com/c/chromium/src/+/8031565) (`f7e33e945a`, main@{#1655765})

Both landed on 2026-07-01, after the M151 branch point (main@{#1654411}) and before
M152 (main@{#1669021}) — so **Chrome 152 (stable 2026-08-25) is the first release
containing them.**

**Why the failure is total and silent**

When the transfer fails, `PwaWrapperSplashScreenStrategy.onSplashImageTransferred()`
returns *before* applying the splash params:

```java
if (!success) {
Log.w(TAG, "Failed to transfer splash image.");
onReadyCallback.run();
return; // setSplashScreenParams() never runs
}
builder.setSplashScreenParams(makeSplashScreenParamsBundle());
```

With no `EXTRA_SPLASH_SCREEN_PARAMS` on the intent, Chrome's
`TwaSplashController.intentIsForTwaWithSplashScreen()` returns `false`, so Chrome
never enters the splash code path at all. The result is no splash rather than a
degraded one, and nothing surfaces to the app.

**To Reproduce**

1. Build a TWA that configures `SPLASH_IMAGE_DRAWABLE`,
`SPLASH_SCREEN_BACKGROUND_COLOR` and `FILE_PROVIDER_AUTHORITY` (standard
bubblewrap output).
2. Install on a device with **Chrome 152 or later**.
3. Cold-launch the app.
4. No splash screen is shown. `adb logcat | grep -i "Failed to transfer splash image"`
shows the warning.

Reverting the device to Chrome 151 restores the splash screen with no app changes.

**Expected behavior**

Either the splash screen keeps working, or the library detects the rejected transfer
and recovers — e.g. re-establishing the `CustomTabsSession` via `newSession()` and
retrying once — instead of silently launching without splash params.

**Did this ever used to work**

Yes. It worked on Chrome 151 and every earlier version. Nothing changed in the app;
the break tracks the Chrome update exactly.

**Which check is firing**

I have not yet confirmed *which* of the three conditions rejects the call in the
field, and it matters for the fix:

- `isFirstRunDone()` — plausible for TWA users, who often never open Chrome as a
browser and so never complete its first-run flow. **The client app cannot detect
or influence this**, so a library-side retry would not help.
- `isSessionValid()` — a retry with a fresh `newSession()` would fix this.
- URI permission — unlikely, since the app owns its own non-exported FileProvider.

Guidance on which of these apps are expected to satisfy, and how, would be very
helpful — as would exposing the transfer failure to the client app so it can
fall back to its own splash and measure the impact.

**Environment**

- androidbrowserhelper: 2.7.3
- androidx.browser: 1.6.0
- Chrome: 152 (broken), 151 (working)
- Android: reproduces across multiple versions
- targetSdk / compileSdk: 36

**Possibly related**

#560 (Chrome 141 splash-screen regression) — different symptom, same subsystem.

Contributor guide

Open the contributing guide

Research direction

Start with SplashImageTransferTask, TrustedWebUtils.transferSplashImage(), and PwaWrapperSplashScreenStrategy.onSplashImageTransferred(), then reproduce on Chrome 152 with the listed TWA configuration and inspect the logcat warning. Trace the CustomTabsSession.receiveFile() path and determine which Chrome 152 check rejects the transfer. Done means the library no longer silently loses splash parameters and has verified behavior on affected and working Chrome versions.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, java
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.