Chrome · Mobile › Fullscreen
CVE-2026-113088
Memory Corruption in Mobile (Fullscreen)
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
BridgeImplchrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.cc |
modified | |
ifchrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.cc |
modified | |
TESTchrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc |
modified | |
forchrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc |
modified | |
TEST_Fchrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc |
modified |
Files Changed
chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.ccchrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.javachrome/browser/ui/messages/android/java/res/layout/floating_snackbar.xmlchrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.hchrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.ccchrome/android/junit/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubbleTest.javachrome/browser/ui/android/exclusive_access/BUILD.gnchrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubble.java
Patch
From b631f0a9e864ef5f3abaf7c4fef9c85d80bba258 Mon Sep 17 00:00:00 2001 From: Vikram Pasupathy <[email protected]> Date: Fri, 25 Sep 2026 13:20:20 -0700 Subject: [PATCH] fullscreen: Front-elide long origins in Android exclusive access bubble When entering fullscreen on Android, the exclusive access notice shows the origin so users know what site they're on. Right now, GetOriginString() doesn't cap or elide long hostnames, and the Android snackbar defaults to a hard 2-line limit without elision. A malicious site can take advantage of this by using a long subdomain prefix (like an accounts.google.com spoof) that fills up both lines, pushing the real domain and the exit instructions completely off-screen. To fix this, we budget GetOriginString() to 40 characters and front-elide subdomain labels so the registrable domain remains clearly visible. On the Android UI side, set setDefaultLines(false) on the snackbar so it can use up to 5 lines when needed, and add android:ellipsize="end" to the layout so text terminates cleanly on smaller screens. Repro: http://shortn/_WmGeLEgOu2 Fix Demo: http://shortn/_A4Vc3RMA2s Bug: 563812927 Change-Id: Ifdedebae855256932a6d2a190885449af5f868d0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8446467 Reviewed-by: Charles Hager <[email protected]> Commit-Queue: Vikram Pasupathy <[email protected]> Cr-Commit-Position: refs/heads/main@{#1705108} --- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubble.java index 5216c35a..689d1e83 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubble.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubble.java @@ -57,6 +57,9 @@ // The exclusive access notice is security-critical and should not // be discarded by the timeout of other action snackbars in the queue. .setHighPriority(true) + // Allow up to MAX_LINES (5) so the origin and exit instructions are + // never clipped on narrow screens. + .setDefaultLines(false) // Use a Java-side timeout so that the timer only starts when // the notice is actually visible to the user. .setDuration(EXCLUSIVE_ACCESS_SNACKBAR_DURATION_MS); diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubbleTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubbleTest.java index 4e320678..4f2e3f0e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubbleTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ui/ExclusiveAccessBubbleTest.java @@ -35,11 +35,19 @@ @Test public void testBubbleShowAndHide() { ExclusiveAccessBubble bubble = ExclusiveAccessBubble.create(mExclusiveAccessContext); + ArgumentCaptor<Snackbar> snackbarCaptor = ArgumentCaptor.forClass(Snackbar.class); Assert.assertFalse(bubble.isVisible()); bubble.update("Test text"); Assert.assertTrue(bubble.isVisible()); - Mockito.verify(mSnackbarManager, Mockito.times(1)).showSnackbar(Mockito.any()); + Mockito.verify(mSnackbarManager, Mockito.times(1)).showSnackbar(snackbarCaptor.capture()); + Assert.assertTrue(snackbarCaptor.getValue().isHighPriority()); + Assert.assertFalse(snackbarCaptor.getValue().getDefaultLines()); + + // Dynamic update while visible should also preserve non-default line limit. + bubble.update("Updated text"); + Mockito.verify(mSnackbarManager, Mockito.times(2)).showSnackbar(snackbarCaptor.capture()); + Assert.assertFalse(snackbarCaptor.getValue().getDefaultLines()); bubble.hide(); Assert.assertFalse(bubble.isVisible()); diff --git a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.cc b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.cc index 0dcf8e7..22bdeb3 100644 --- a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.cc +++ b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.cc @@ -11,20 +11,36 @@ #include "components/fullscreen_control/fullscreen_features.h" #include "components/url_formatter/elide_url.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/text_elider.h" #include "ui/strings/grit/ui_strings.h" // Must come after headers that provide symbols used by @JniType. #include "chrome/android/chrome_jni_headers/ExclusiveAccessBubble_jni.h" namespace { + +// Maximum character length for the origin displayed in the Android exclusive +// access notice snackbar. Longer origins are front-elided so that leading +// subdomains cannot push the registrable domain and exit instructions off +// screen. +constexpr size_t kMaxOriginLength = 40; + std::optional<std::u16string> GetOriginString(const url::Origin& origin) { if (origin.opaque() || !base::FeatureList::IsEnabled(features::kFullscreenBubbleShowOrigin)) { return std::nullopt; } - return url_formatter::FormatOriginForSecurityDisplay( + std::u16string formatted = url_formatter::FormatOriginForSecurityDisplay( origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC); + if (formatted.size() <= kMaxOriginLength) { + return formatted; + } + + return gfx::StringSlicer(formatted, gfx::kEllipsisUTF16, + /*elide_in_middle=*/false, + /*elide_at_beginning=*/true) + .CutString(kMaxOriginLength - 1, /*insert_ellipsis=*/true); } class BridgeImpl : public ExclusiveAccessBubbleAndroid::Bridge { @@ -206,6 +222,13 @@ return bridge_->IsVisible(); } +// static +std::optional<std::u16string> +ExclusiveAccessBubbleAndroid::GetOriginStringForTesting( + const url::Origin& origin) { + return GetOriginString(origin); +} + void ExclusiveAccessBubbleAndroid::RunHideCallbackIfNeeded( ExclusiveAccessBubbleHideReason reason) { if (first_hide_callback_) { diff --git a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.h b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.h index 8934002b..0da4b51 100644 --- a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.h +++ b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.h @@ -5,11 +5,13 @@ #ifndef CHROME_BROWSER_UI_ANDROID_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_BUBBLE_ANDROID_H_ #define CHROME_BROWSER_UI_ANDROID_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_BUBBLE_ANDROID_H_ +#include <optional> #include <string> #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_hide_callback.h" #include "third_party/jni_zero/jni_zero.h" +#include "url/origin.h" // The android implementation of ExclusiveAccessBubble, this class is used to // manage the exclusive access bubble for the APIs (fullscreen, keyboard lock & @@ -57,6 +59,13 @@ // Returns whether the popup is visible. bool IsVisible() const; + // Formats and budgets the origin to at most 40 characters for display in the + // exclusive access notice, front-eliding subdomain labels if necessary. + // Returns std::nullopt if the origin is opaque or if + // features::kFullscreenBubbleShowOrigin is disabled. + static std::optional<std::u16string> GetOriginStringForTesting( + const url::Origin& origin); + private: // ExclusiveAccessBubble: void Hide() override; diff --git a/chrome/browser/ui/messages/android/java/res/layout/floating_snackbar.xml b/chrome/browser/ui/messages/android/java/res/layout/floating_snackbar.xml index 16b2ca9..4179f20 100644 --- a/chrome/browser/ui/messages/android/java/res/layout/floating_snackbar.xml +++ b/chrome/browser/ui/messages/android/java/res/layout/floating_snackbar.xml @@ -39,6 +39,7 @@ android:layout_marginTop="@dimen/snackbar_message_margin" android:layout_marginBottom="@dimen/snackbar_message_margin" android:layout_weight="1" + android:ellipsize="end" android:textAlignment="viewStart" android:textAppearance="@style/TextAppearance.TextMedium.Primary.Baseline.Light" /> diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java index 6f4b9455c..c0dcaeb 100644 --- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java +++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java @@ -333,7 +333,8 @@ return mActionData; } - boolean getDefaultLines() { + @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) + public boolean getDefaultLines() { return mDefaultLines; } @@ -386,7 +387,8 @@ /** * @return Whether the snackbar is high priority. */ - boolean isHighPriority() { + @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) + public boolean isHighPriority() { return mIsHighPriority; } diff --git a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc index 330f55c..6a421050 100644 --- a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc +++ b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc @@ -5,13 +5,16 @@ #include "chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.h" #include <memory> +#include <optional> #include <string> #include <utility> #include "base/android/jni_string.h" #include "base/functional/callback_helpers.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/android/exclusive_access/exclusive_access_context_android.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/fullscreen_control/fullscreen_features.h" #include "components/url_formatter/elide_url.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -312,4 +315,115 @@ EXPECT_FALSE(bubble.params().has_download); } +TEST(ExclusiveAccessBubbleAndroidOriginElisionTest, GetOriginString) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + features::kFullscreenBubbleShowOrigin); + + struct TestCase { + const char* url; + std::optional<std::u16string> expected; + } const kTestCases[] = { + // 1. Standard origin well within the 40-character budget (no elision). + {"https://example.com", u"example.com"}, + {"http://example.com", u"http://example.com"}, + + // 2. Exactly 40 characters (https scheme omitted by security formatter): + // "abcdefghijklmnopqrstuvwxyz01.example.com" has 28 + 1 + 11 = 40 chars. + {"https://abcdefghijklmnopqrstuvwxyz01.example.com", + u"abcdefghijklmnopqrstuvwxyz01.example.com"}, + + // 3. Exceeds budget: front-elides leading characters to fit within 40 + // chars. + {"https://a.sub.1234567890123456789012345.example.com", + u"\u2026b.1234567890123456789012345.example.com"}, + + // 4. Realistic spoof attempt: an attacker using Google-themed subdomains. + // Front-elides leading subdomains while keeping the trailing registrable + // domain within the 40-char budget. + {"http://accounts.google.com.signin.verify.device-check.signin-attempt-4." + "evil.example", + u"\u2026ice-check.signin-attempt-4.evil.example"}, + + // 5. Max-length single label (63 chars) immediately preceding the eTLD+1. + {"https://" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "evil.example", + u"\u2026aaaaaaaaaaaaaaaaaaaaaaaaaa.evil.example"}, + + // 6. Non-standard port preservation. + {"http://verylongsubdomainprefix.evil.example:8080", + u"\u2026rylongsubdomainprefix.evil.example:8080"}, + + // 7. Extremely long registrable domain (> 39 chars). + {"https://" + "a-very-long-domain-name-that-exceeds-forty-characters-all-by-itself." + "example", + u"\u2026-forty-characters-all-by-itself.example"}, + + // 8. IP address and intranet host. + {"http://192.168.1.1:8080", u"http://192.168.1.1:8080"}, + {"http://localhost:8080", u"http://localhost:8080"}, + }; + + for (const auto& test_case : kTestCases) { + url::Origin origin = url::Origin::Create(GURL(test_case.url)); + std::optional<std::u16string> actual = + ExclusiveAccessBubbleAndroid::GetOriginStringForTesting(origin); + EXPECT_EQ(actual, test_case.expected) + << "Failed for URL: " << test_case.url; + if (actual.has_value()) { + EXPECT_LE(actual->size(), 40u) + << "Exceeded 40 char budget for URL: " << test_case.url; + } + } + + // Opaque origin returns std::nullopt. + EXPECT_EQ( + ExclusiveAccessBubbleAndroid::GetOriginStringForTesting(url::Origin()), + std::nullopt); +} + +TEST(ExclusiveAccessBubbleAndroidOriginElisionTest, + FeatureDisabledReturnsNullopt) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + features::kFullscreenBubbleShowOrigin); + + EXPECT_EQ(ExclusiveAccessBubbleAndroid::GetOriginStringForTesting( + url::Origin::Create(GURL("https://example.com"))), + std::nullopt); +} + +TEST_F(ExclusiveAccessBubbleAndroidTest, LongOriginIsElidedInBubbleNotice) { + ExclusiveAccessBubbleParams params; + params.type = EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION; + params.origin = url::Origin::Create( + GURL("http://accounts.google.com.signin.verify.device-check." + "signin-attempt-4.evil.example")); + + auto mock_bridge = std::make_unique<MockBridge>(); + auto* mock_bridge_ptr = mock_bridge.get(); + + std::u16string captured_text; + EXPECT_CALL(*mock_bridge_ptr, IsVisible()).WillOnce(Return(false)); + EXPECT_CALL(*mock_bridge_ptr, IsKeyboardConnected()).WillOnce(Return(true)); + EXPECT_CALL(*mock_bridge_ptr, Update(_)) + .WillOnce(testing::SaveArg<0>(&captured_text)); + EXPECT_CALL(*mock_bridge_ptr, Show()).Times(1); + + ExclusiveAccessBubbleAndroid bubble(params, base::DoNothing(), + std::move(mock_bridge)); + testing::Mock::VerifyAndClearExpectations(mock_bridge_ptr); + + std::u16string expected_text = + exclusive_access_bubble::GetInstructionTextForType( + EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION, + l10n_util::GetStringUTF16(IDS_APP_ESC_KEY), + u"\u2026ice-check.signin-attempt-4.evil.example", + /*has_download=*/false, /*notify_overridden=*/false); + EXPECT_EQ(captured_text, expected_text); + EXPECT_EQ(captured_text.find(u"accounts.google.com"), std::u16string::npos); +} + } // namespace diff --git a/chrome/browser/ui/android/exclusive_access/BUILD.gn b/chrome/browser/ui/android/exclusive_access/BUILD.gn index b4321be..26ee093 100644 --- a/chrome/browser/ui/android/exclusive_access/BUILD.gn +++ b/chrome/browser/ui/android/exclusive_access/BUILD.gn @@ -23,6 +23,7 @@ "//content/public/browser", "//third_party/jni_zero", "//ui/base", + "//ui/gfx", "//ui/strings", ] } @@ -35,7 +36,12 @@ "//base", "//chrome/test:test_support", "//chrome/test/base:chrome_render_view_host_test_harness", + "//components/fullscreen_control", + "//components/url_formatter", "//testing/gmock", "//testing/gtest", + "//ui/base", + "//ui/strings", + "//url", ] }
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc
index 330f55c..6a421050 100644
--- a/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc
+++ b/chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android_unittest.cc
@@ -5,13 +5,16 @@
#include "chrome/browser/ui/android/exclusive_access/exclusive_access_bubble_android.h"
#include <memory>
+#include <optional>
#include <string>
#include <utility>
#include "base/android/jni_string.h"
#include "base/functional/callback_helpers.h"
+#include "base/test/scoped_feature_list.h"
#include "chrome/browser/ui/android/exclusive_access/exclusive_access_context_android.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/fullscreen_control/fullscreen_features.h"
#include "components/url_formatter/elide_url.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -312,4 +315,115 @@
EXPECT_FALSE(bubble.params().has_download);
}
+TEST(ExclusiveAccessBubbleAndroidOriginElisionTest, GetOriginString) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kFullscreenBubbleShowOrigin);
+
+ struct TestCase {
+ const char* url;
+ std::optional<std::u16string> expected;
+ } const kTestCases[] = {
+ // 1. Standard origin well within the 40-character budget (no elision).
+ {"https://example.com", u"example.com"},
+ {"http://example.com", u"http://example.com"},
+
+ // 2. Exactly 40 characters (https scheme omitted by security formatter):
+ // "abcdefghijklmnopqrstuvwxyz01.example.com" has 28 + 1 + 11 = 40 chars.
+ {"https://abcdefghijklmnopqrstuvwxyz01.example.com",
+ u"abcdefghijklmnopqrstuvwxyz01.example.com"},
+
+ // 3. Exceeds budget: front-elides leading characters to fit within 40
+ // chars.
+ {"https://a.sub.1234567890123456789012345.example.com",
+ u"\u2026b.1234567890123456789012345.example.com"},
+
+ // 4. Realistic spoof attempt: an attacker using Google-themed subdomains.
+ // Front-elides leading subdomains while keeping the trailing registrable
+ // domain within the 40-char budget.
+ {"http://accounts.google.com.signin.verify.device-check.signin-attempt-4."
+ "evil.example",
+ u"\u2026ice-check.signin-attempt-4.evil.example"},
+
+ // 5. Max-length single label (63 chars) immediately preceding the eTLD+1.
+ {"https://"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
+ "evil.example",
+ u"\u2026aaaaaaaaaaaaaaaaaaaaaaaaaa.evil.example"},
+
+ // 6. Non-standard port preservation.
+ {"http://verylongsubdomainprefix.evil.example:8080",
+ u"\u2026rylongsubdomainprefix.evil.example:8080"},
+
+ // 7. Extremely long registrable domain (> 39 chars).
+ {"https://"
+ "a-very-long-domain-name-that-exceeds-forty-characters-all-by-itself."
+ "example",
+ u"\u2026-forty-characters-all-by-itself.example"},
+
+ // 8. IP address and intranet host.
+ {"http://192.168.1.1:8080", u"http://192.168.1.1:8080"},
+ {"http://localhost:8080", u"http://localhost:8080"},
+ };
+
+ for (const auto& test_case : kTestCases) {
+ url::Origin origin = url::Origin::Create(GURL(test_case.url));
+ std::optional<std::u16string> actual =
+ ExclusiveAccessBubbleAndroid::GetOriginStringForTesting(origin);
+ EXPECT_EQ(actual, test_case.expected)
+ << "Failed for URL: " << test_case.url;
+ if (actual.has_value()) {
+ EXPECT_LE(actual->size(), 40u)
+ << "Exceeded 40 char budget for URL: " << test_case.url;
+ }
+ }
+
+ // Opaque origin returns std::nullopt.
+ EXPECT_EQ(
+ ExclusiveAccessBubbleAndroid::GetOriginStringForTesting(url::Origin()),
+ std::nullopt);
+}
+
+TEST(ExclusiveAccessBubbleAndroidOriginElisionTest,
+ FeatureDisabledReturnsNullopt) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(
+ features::kFullscreenBubbleShowOrigin);
+
+ EXPECT_EQ(ExclusiveAccessBubbleAndroid::GetOriginStringForTesting(
+ url::Origin::Create(GURL("https://example.com"))),
+ std::nullopt);
+}
+
+TEST_F(ExclusiveAccessBubbleAndroidTest, LongOriginIsElidedInBubbleNotice) {
+ ExclusiveAccessBubbleParams params;
+ params.type = EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION;
+ params.origin = url::Origin::Create(
+ GURL("http://accounts.google.com.signin.verify.device-check."
+ "signin-attempt-4.evil.example"));
+
+ auto mock_bridge = std::make_unique<MockBridge>();
+ auto* mock_bridge_ptr = mock_bridge.get();
+
+ std::u16string captured_text;
+ EXPECT_CALL(*mock_bridge_ptr, IsVisible()).WillOnce(Return(false));
+ EXPECT_CALL(*mock_bridge_ptr, IsKeyboardConnected()).WillOnce(Return(true));
+ EXPECT_CALL(*mock_bridge_ptr, Update(_))
+ .WillOnce(testing::SaveArg<0>(&captured_text));
+ EXPECT_CALL(*mock_bridge_ptr, Show()).Times(1);
+
+ ExclusiveAccessBubbleAndroid bubble(params, base::DoNothing(),
+ std::move(mock_bridge));
+ testing::Mock::VerifyAndClearExpectations(mock_bridge_ptr);
+
+ std::u16string expected_text =
+ exclusive_access_bubble::GetInstructionTextForType(
+ EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION,
+ l10n_util::GetStringUTF16(IDS_APP_ESC_KEY),
+ u"\u2026ice-check.signin-attempt-4.evil.example",
+ /*has_download=*/false, /*notify_overridden=*/false);
+ EXPECT_EQ(captured_text, expected_text);
+ EXPECT_EQ(captured_text.find(u"accounts.google.com"), std::u16string::npos);
+}
+
} // namespace
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.
References
On This Page