Overview

High
Severity
5.1
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactMissing authorization in Android
DescriptionMissing authorization in Android
ComponentAndroid
Bug ClassAuthorization Error
Action tierwatch — information disclosure — security-relevant, below the RCE-class bar
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker549225472
Fix commitf44c857d8af9 (chromium/src) +302/-29
CWECWE-862
CVSS vectorCVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
CISA KEVNot listed
Creditedjodyritonga
Reported2026-08-20 (per vendor advisory)
Fix landed2026-09-10 (public git)
Disclosed2026-09-15
Patch gap5 days — fix public in source before the advisory

Background

Web app launch intent
An Android intent that starts an installed PWA/Trusted Web Activity in a Custom Tab, optionally carrying file-handling or share-target data (file content:// URIs) for the web content to consume.
`isValidLaunchUri`
A WebAppLaunchHandler helper that vets a launch/share Uri, rejecting unsupported schemes (e.g. file://) and Chrome’s own internal FileProvider authorities (such as content://<package>.FileProvider/...) so that only legitimate external content URIs are forwarded (behavior inferred; the helper body is not in the diff).
`doesCallerHavePermissionForUri`
A check that the intent’s caller or the current process holds FLAG_GRANT_READ_URI_PERMISSION on a Uri via checkUriPermission, which a Chrome-internal FileProvider URI passes because Chrome itself owns that provider.
Missing authorization
Because the caller-permission check alone accepts URIs Chrome can read on its own behalf, an unvalidated URI can reference internal Chrome files the web principal was never authorized to access.

Root Cause Analysis

The file-handling filter loop (the @@ -501 hunk, whose enclosing function is not named in the hunk header) and copyFilePermissions validated each file Uri only with doesCallerHavePermissionForUri, omitting the isValidLaunchUri scheme/authority check that the share-target paths (filterShareData, copyShareDataPermissions) already performed. Because checkUriPermission returns granted for Chrome’s own FileProvider content URIs — Chrome holds permission to its own provider — and for file:// URIs Chrome can open, an attacker-supplied launch intent could smuggle internal or unsupported URIs through the file-handling flow. The invariant violated is that every URI forwarded to launched web content must first be confirmed to be an external, supported content URI, not a Chrome-internal or file:// resource.

The fix inserts if (!isValidLaunchUri(uri)) { ...; continue; } before the permission check in both the file-handling filter loop and copyFilePermissions, so internal and file:// URIs are dropped before any URI is added to filteredUris/verifiedUris. It also refactors the two share-target loops that already contained isValidLaunchUri into the same two-guard ordering for consistency and clearer logging, without changing which URIs those paths accept. This change TIGHTENS the file-handling path by adding a validation step that was previously absent.

Key insight
File-handling launch URIs were never run through isValidLaunchUri even though share-target URIs were, so Chrome’s own internal FileProvider and file:// URIs slipped past the caller-permission gate; the fix applies the same validation to the file-handling path.

Attack Path

  1. Install a file-handling web app The victim has an installed PWA/Trusted Web Activity that registers as a file handler (or POST share target) opened in a Custom Tab.
  2. Craft a malicious launch intent A local malicious app builds a launch or share intent whose file Uri list includes a Chrome-internal URI such as content://<chrome package>.FileProvider/net_export/sample.txt or a file:///sdcard/... URI.
  3. Bypass the caller-permission gate In the pre-patch file-handling loop and copyFilePermissions, only doesCallerHavePermissionForUri runs; it returns granted for Chrome’s own FileProvider URI, so the internal URI is added to filteredUris/verifiedUris.
  4. Deliver internal file contents to web content The verified URIs are handed to the launched web app or passed to WebApkPostShareTargetNavigator as POST form data, exposing the internal file’s contents to the web principal.
  5. Exfiltrate (inferred) the web principal (a share-target POST endpoint) transmits the disclosed contents to an attacker-controlled server; the patch demonstrates only the disclosure to web content, not the network step.

Impact Assessment

A malicious local Android app can cause Chrome to read internal Chrome-owned files (or file:// resources) and disclose them to attacker-influenced web content via a file-handling launch or share-target intent — a missing-authorization / information-disclosure issue occurring in the Chrome browser process on Android. Preconditions are that a suitable file-handling or share-target web app is installed and that the attacker can deliver the crafted intent to it. The advisory classifies this as LogicError / “Missing authorization in Android”; it does not report exploitation in the wild, and any escalation beyond the information disclosure the patch demonstrates is (inferred).

Changed Functions

FunctionChangeNotes
for
chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java
modified
for
chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
modified
if
chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
modified

Files Changed

  • chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
  • chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
  • chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java
  • chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java

Audit Directions

  • Asymmetric validation across parallel paths
    When two flows (here file-handling vs share-target) consume the same kind of untrusted input, diff their per-item validation; a check present in one and absent in the other is a likely authorization gap.
  • Permission checks that trust the current process
    checkUriPermission / doesCallerHavePermissionForUri returns granted for URIs the app itself owns (Chrome’s FileProvider), so audit any intent-URI handling that gates only on process/caller permission without a scheme and authority allowlist.
  • Intent extras carrying URIs into web content
    Review all paths that forward externally supplied content:// / file:// URIs into launched web apps, share-target POSTs, or navigations to confirm each applies isValidLaunchUri-style filtering before trusting the URI.
From f44c857d8af9af119e2c281d021d6df0d191de2f Mon Sep 17 00:00:00 2001
From: Adriana Ixba <[email protected]>
Date: Thu, 10 Sep 2026 10:45:44 -0700
Subject: [PATCH] Validate launch URIs in WebAppLaunchHandler

Ensure that file URIs received via launch intents are verified with
isValidLaunchUri() in WebAppLaunchHandler prior to checking caller
permissions. This aligns file handling URI validation with share target
handling and ensures that unsupported or internal provider URIs are
consistently filtered out during intent processing.

Additionally, update copyFilePermissions() to enforce the same URI
validation when propagating verified launch data, and add test coverage
for launch intent URI filtering.

TAG=agy

Bug: 549225472
Change-Id: Idef1e9db1a6e12d39a3f7dd68aacccc96df58e7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8373702
Reviewed-by: Daniel Murphy <[email protected]>
Reviewed-by: Sinan Sahin <[email protected]>
Commit-Queue: Adriana Ixba <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1695502}
---
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java
index e1742af..5ab2f42 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java
@@ -501,16 +501,20 @@
 
         List<Uri> filteredUris = new ArrayList<>();
         for (Uri uri : fileHandlingData.uris) {
-            if (doesCallerHavePermissionForUri(
+            if (!isValidLaunchUri(uri)) {
+                Log.w(TAG, "Invalid launch URI: " + uri);
+                continue;
+            }
+            if (!doesCallerHavePermissionForUri(
                     mActivity,
                     caller,
                     intentDataProvider.getSession(),
                     uri,
                     Intent.FLAG_GRANT_READ_URI_PERMISSION)) {
-                filteredUris.add(uri);
-            } else {
                 Log.w(TAG, "Caller does not have read permission for URI: " + uri);
+                continue;
             }
+            filteredUris.add(uri);
         }
 
         if (filteredUris.isEmpty()) {
@@ -588,7 +592,7 @@
     public static void copyFilePermissions(
             Activity activity, Intent sourceIntent, Intent targetIntent) {
         // Strip EXTRA_VERIFIED_FILE_HANDLING_DATA/EXTRA_VERIFIED_FILE_CAN_WRITE if present on
-        // targetIntent so that they cannot be spoofed by CCT client apps.
+        // targetIntent so that they cannot be set by external client apps.
         IntentUtils.safeRemoveExtra(
                 targetIntent, CustomTabIntentDataProvider.EXTRA_VERIFIED_FILE_HANDLING_DATA);
         IntentUtils.safeRemoveExtra(
@@ -624,8 +628,13 @@
         List<Uri> verifiedUris = new ArrayList<>();
         List<Boolean> canWriteList = new ArrayList<>();
         for (Uri uri : fileHandlingData.uris) {
+            if (!isValidLaunchUri(uri)) {
+                Log.w(TAG, "Invalid launch URI: " + uri);
+                continue;
+            }
             if (!doesCallerHavePermissionForUri(
                     activity, caller, session, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)) {
+                Log.w(TAG, "Caller does not have read permission for URI: " + uri);
                 continue;
             }
             verifiedUris.add(uri);
@@ -666,8 +675,8 @@
      */
     public static void copyShareDataPermissions(
             Activity activity, Intent sourceIntent, Intent targetIntent) {
-        // Strip EXTRA_VERIFIED_SHARE_DATA if present on targetIntent so that it cannot be spoofed
-        // by CCT client apps.
+        // Strip EXTRA_VERIFIED_SHARE_DATA if present on targetIntent so that it cannot be set
+        // by external client apps.
         IntentUtils.safeRemoveExtra(
                 targetIntent, CustomTabIntentDataProvider.EXTRA_VERIFIED_SHARE_DATA);
 
@@ -704,17 +713,16 @@
         SessionHolder<?> session = SessionHolder.getSessionHolderFromIntent(sourceIntent);
         List<Uri> verifiedUris = new ArrayList<>();
         for (Uri uri : shareData.uris) {
-            if (isValidLaunchUri(uri)
-                    && doesCallerHavePermissionForUri(
-                            activity,
-                            caller,
-                            session,
-                            uri,
-                            Intent.FLAG_GRANT_READ_URI_PERMISSION)) {
-                verifiedUris.add(uri);
-            } else {
-                Log.w(TAG, "Caller does not have read permission for share URI: " + uri);
+            if (!isValidLaunchUri(uri)) {
+                Log.w(TAG, "Invalid launch URI: " + uri);
+                continue;
             }
+            if (!doesCallerHavePermissionForUri(
+                    activity, caller, session, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)) {
+                Log.w(TAG, "Caller does not have read permission for share URI: " + uri);
+                continue;
+            }
+            verifiedUris.add(uri);
         }
 
         ShareData verifiedShareData = new ShareData(shareData.title, shareData.text, verifiedUris);
@@ -761,17 +769,20 @@
 
         List<Uri> filteredUris = new ArrayList<>();
         for (Uri uri : shareData.uris) {
-            if (isValidLaunchUri(uri)
-                    && doesCallerHavePermissionForUri(
-                            activity,
-                            caller,
-                            intentDataProvider.getSession(),
-                            uri,
-                            Intent.FLAG_GRANT_READ_URI_PERMISSION)) {
-                filteredUris.add(uri);
-            } else {
-                Log.w(TAG, "Caller does not have read permission for share URI: " + uri);
+            if (!isValidLaunchUri(uri)) {
+                Log.w(TAG, "Invalid launch URI: " + uri);
+                continue;
             }
+            if (!doesCallerHavePermissionForUri(
+                    activity,
+                    caller,
+                    intentDataProvider.getSession(),
+                    uri,
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION)) {
+                Log.w(TAG, "Caller does not have read permission for share URI: " + uri);
+                continue;
+            }
+            filteredUris.add(uri);
         }
 
         return new ShareData(shareData.title, shareData.text, filteredUris);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
index 2d5dbbc..8e96f00 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
@@ -9,12 +9,14 @@
 import static org.chromium.chrome.browser.browserservices.TrustedWebActivityTestUtil.spoofVerification;
 
 import android.content.Intent;
+import android.net.Uri;
 
 import androidx.browser.trusted.TrustedWebActivityIntentBuilder;
 import androidx.browser.trusted.sharing.ShareData;
 import androidx.browser.trusted.sharing.ShareTarget;
 import androidx.test.filters.MediumTest;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -59,6 +61,19 @@
                     null,
                     new ShareTarget.Params("received_title", "received_text", null));
 
+    private static final ShareTarget POST_MULTIPART_FILE_SHARE_TARGET =
+            new ShareTarget(
+                    "https://pwa.rocks/share.html",
+                    "POST",
+                    "multipart/form-data",
+                    new ShareTarget.Params(
+                            "received_title",
+                            "received_text",
+                            Collections.singletonList(
+                                    new ShareTarget.FileFormField(
+                                            "received_file",
+                                            Collections.singletonList("text/plain")))));
+
     @Rule
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
 
@@ -172,7 +187,44 @@
                 () -> mCustomTabActivityTestRule.getActivity().onNewIntent(intent));
     }
 
+    @Test
+    @MediumTest
+    public void sharesDataWithPost_FiltersUnauthorizedFileUris() throws Exception {
+        Uri internalUri =
+                Uri.parse("content://" + PACKAGE_NAME + ".FileProvider/net_export/sample.txt");
+        ShareData shareData =
+                new ShareData("test_title", "test_text", Collections.singletonList(internalUri));
+        mIntent.putExtra(TrustedWebActivityIntentBuilder.EXTRA_SHARE_DATA, shareData.toBundle());
+        mIntent.putExtra(
+                TrustedWebActivityIntentBuilder.EXTRA_SHARE_TARGET,
+                POST_MULTIPART_FILE_SHARE_TARGET.toBundle());
+
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntentNotWaitingForFirstFrame(mIntent);
+        assertPostNavigatorCalled();
+
+        Assert.assertNotNull(mPostNavigatorNatives.mIsValueFileUris);
+        for (boolean isFileUri : mPostNavigatorNatives.mIsValueFileUris) {
+            Assert.assertFalse(isFileUri);
+        }
+        Assert.assertNotNull(mPostNavigatorNatives.mValues);
+        for (String value : mPostNavigatorNatives.mValues) {
+            Assert.assertFalse(value.contains("sample.txt"));
+            Assert.assertFalse(value.contains("FileProvider"));
+        }
+        if (mPostNavigatorNatives.mFilenames != null) {
+            for (String filename : mPostNavigatorNatives.mFilenames) {
+                Assert.assertFalse(filename.contains("sample.txt"));
+            }
+        }
+    }
+
     private class MockPostNavigatorNatives implements WebApkPostShareTargetNavigator.Natives {
+        public String[] mNames;
+        public String[] mValues;
+        public boolean[] mIsValueFileUris;
+        public String[] mFilenames;
+        public String[] mTypes;
+
         @Override
         public void nativeLoadViewForShareTargetPost(
                 boolean isMultipartEncoding,
@@ -183,6 +235,11 @@
                 String[] types,
                 String startUrl,
                 WebContents webContents) {
+            mNames = names;
+            mValues = values;
+            mIsValueFileUris = isValueFileUris;
+            mFilenames = filenames;
+            mTypes = types;
             mPostNavigatorCallback.notifyCalled();
         }
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
index 23624362..2e0137e5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
@@ -2807,4 +2807,12 @@
         assertEquals("title", result.title);
         assertEquals(fileUri, result.uris.get(0));
     }
+
+    @Test
+    public void testGetShareData_NullWhenMissing() {
+        Intent intent = new Intent();
+        CustomTabIntentDataProvider dataProvider =
+                new CustomTabIntentDataProvider(intent, mContext, COLOR_SCHEME_LIGHT);
+        assertNull(dataProvider.getShareData());
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java
index 0960e84..4375338 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java
@@ -32,14 +32,18 @@
 import android.content.pm.ProviderInfo;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Process;
 import android.text.TextUtils;
 
 import androidx.annotation.Nullable;
+import androidx.browser.customtabs.CustomTabsIntent;
 import androidx.browser.customtabs.CustomTabsSessionToken;
 import androidx.browser.trusted.FileHandlingData;
 import androidx.browser.trusted.LaunchHandlerClientMode;
+import androidx.browser.trusted.TrustedWebActivityIntentBuilder;
 import androidx.browser.trusted.sharing.ShareData;
 
 import org.junit.Assert;
@@ -466,7 +470,8 @@
         String packageName = ContextUtils.getApplicationContext().getPackageName();
         Uri privateUri = Uri.parse("content://" + packageName + ".FileProvider/foo");
         mFileHandlingData = new FileHandlingData(Arrays.asList(Uri.parse(CONTENT_URI), privateUri));
-        mExpectedFileList = new String[0]; // Expect empty because one is Chrome private
+        mExpectedFileList = new String[] {CONTENT_URI};
+        mExpectedCanWriteList = new boolean[] {true};
         doTestHandleIntent(
                 LaunchHandlerClientMode.AUTO,
                 INITIAL_URL,
@@ -480,7 +485,8 @@
         // Bypass using exactly package name as authority (no trailing dot in prefix check)
         Uri bypassUri1 = Uri.parse("content://" + packageName + "/foo");
         mFileHandlingData = new FileHandlingData(Arrays.asList(Uri.parse(CONTENT_URI), bypassUri1));
-        mExpectedFileList = new String[0]; // Expect empty because one is Chrome private (bypassed)
+        mExpectedFileList = new String[] {CONTENT_URI};
+        mExpectedCanWriteList = new boolean[] {true};
         doTestHandleIntent(
                 LaunchHandlerClientMode.AUTO,
                 INITIAL_URL,
@@ -494,7 +500,8 @@
         // Bypass using userinfo
         Uri bypassUri1 = Uri.parse("content://user@" + packageName + ".FileProvider/foo");
         mFileHandlingData = new FileHandlingData(Arrays.asList(Uri.parse(CONTENT_URI), bypassUri1));
-        mExpectedFileList = new String[0]; // Expect empty because one is Chrome private (bypassed)
+        mExpectedFileList = new String[] {CONTENT_URI};
+        mExpectedCanWriteList = new boolean[] {true};
         doTestHandleIntent(
                 LaunchHandlerClientMode.AUTO,
                 INITIAL_URL,
@@ -995,4 +1002,194 @@
         Assert.assertEquals(1, result.uris.size());
         Assert.assertEquals(authorizedUri, result.uris.get(0));
     }
+
+    @Test
+    public void testFilterShareData_InvalidUrisFiltered() {
+        Intent intent = new Intent();
+        Uri internalUri =
+                Uri.parse(
+                        "content://"
+                                + ContextUtils.getApplicationContext().getPackageName()
+                                + ".FileProvider/net_export/sample.txt");
+        Uri fileSchemeUri = Uri.parse("file:///sdcard/sample.txt");
+        Uri validUri = Uri.parse("content://com.example/valid.jpg");
+        ShareData rawData =
+                new ShareData("title", "text", Arrays.asList(internalUri, fileSchemeUri, validUri));
+
+        CustomTabIntentDataProvider dataProvider = mock(CustomTabIntentDataProvider.class);
+        when(dataProvider.getIntent()).thenReturn(intent);
+        when(dataProvider.getShareData()).thenReturn(rawData);
+        when(dataProvider.getSession()).thenReturn(mSessionMock);
+
+        when(mActivityMock.checkUriPermission(
+                        eq(validUri),
+                        anyInt(),
+                        anyInt(),
+                        eq(Intent.FLAG_GRANT_READ_URI_PERMISSION)))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+        when(mActivityMock.checkUriPermission(
+                        eq(internalUri),
+                        anyInt(),
+                        anyInt(),
+                        eq(Intent.FLAG_GRANT_READ_URI_PERMISSION)))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+        ShareData result = WebAppLaunchHandler.filterShareData(dataProvider, mActivityMock, null);
+        Assert.assertNotNull(result);
+        Assert.assertEquals("title", result.title);
+        Assert.assertEquals(1, result.uris.size());
+        Assert.assertEquals(validUri, result.uris.get(0));
+    }
+
+    @Test
+    public void testFilterFileHandlingData_InvalidUrisFiltered() {
+        Intent intent = new Intent();
+        Uri internalUri =
+                Uri.parse(
+                        "content://"
+                                + ContextUtils.getApplicationContext().getPackageName()
+                                + ".FileProvider/net_export/sample.txt");
+        Uri fileSchemeUri = Uri.parse("file:///sdcard/sample.txt");
+        Uri validUri = Uri.parse("content://com.example/valid.jpg");
+        FileHandlingData rawData =
+                new FileHandlingData(Arrays.asList(internalUri, fileSchemeUri, validUri));
+
+        CustomTabIntentDataProvider dataProvider = mock(CustomTabIntentDataProvider.class);
+        when(dataProvider.getIntent()).thenReturn(intent);
+        when(dataProvider.getFileHandlingData()).thenReturn(rawData);
+        when(dataProvider.getSession()).thenReturn(mSessionMock);
+        when(dataProvider.getUrlToLoad()).thenReturn(INITIAL_URL);
+        when(dataProvider.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+        when(mActivityMock.checkUriPermission(
+                        eq(validUri),
+                        anyInt(),
+                        anyInt(),
+                        eq(Intent.FLAG_GRANT_READ_URI_PERMISSION)))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+        when(mActivityMock.checkUriPermission(
+                        eq(internalUri),
+                        anyInt(),
+                        anyInt(),
+                        eq(Intent.FLAG_GRANT_READ_URI_PERMISSION)))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+        WebAppLaunchHandler launchHandler = createWebAppLaunchHandler();
+        launchHandler.handleInitialIntent(dataProvider);
+
+        verify(mWebAppLaunchHandlerJniMock)
+                .prepareForLaunch(
+                        any(),
+                        anyLong(),
+                        eq(INITIAL_URL),
+                        eq(TEST_PACKAGE_NAME),
+                        eq(new String[] {validUri.toString()}),
+                        any(),
+                        any(),
+                        anyBoolean());
... (file diff truncated)
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.