diff --git a/AUTHORS b/AUTHORS index 2b97684b..818bb32c 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -1061,6 +1061,7 @@ Minggang Wang <minggang.wang@intel.com> Mingmin Xie <melvinxie@gmail.com> Mingming Xu <mingming1.xu@intel.com> +Mingtao Zhou <mingtaoxt@gmail.com> Mingyue Ji <myandyji@gmail.com> Minjeong Kim <deoxyribonucleicacid150@gmail.com> Minjeong Lee <apenr1234@gmail.com>
diff --git a/DEPS b/DEPS index 7c98e0d..41b2849 100644 --- a/DEPS +++ b/DEPS
@@ -305,11 +305,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'ee7ed7723eb64518a8ca03d91fd4041e3a319574', + 'src_internal_revision': '5b3a0932dc6e77ec5474737c28832c127f9eba80', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '2a9fe9cde3e8e2184db9c225b638dabc1debd5fa', + 'skia_revision': '845ec125e94ce32aa235aeca99409dabf15f9f76', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -317,7 +317,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'e893313ccef7686c9f4c4444c9a605b0578b1534', + 'angle_revision': 'fe30cd1a5fecfc2bb7581a742c15e0eb1fd77296', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -397,7 +397,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'e5b234e858cfd029bf8eafa13455f80f460643f2', + 'devtools_frontend_revision': '2a744510a5faabae24e3c6d2ca34928f91392653', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -1212,7 +1212,7 @@ 'packages': [ { 'package': 'chromium/chrome/android/orderfiles/arm64', - 'version': '0zO7HtkBIb3zVMKfFnuZel8fcZRmCjiU7RU4a9GUIgYC', + 'version': 'OG2xVTYyF5XeAkroHFyzHm7NayCDgU2lcr4x7HGNS2oC', }, ], 'condition': 'checkout_android', @@ -1763,7 +1763,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 's12rOiGNzd60313qCbH7ZkS2V2gdqpFJOpp97EuPawUC', + 'version': 'YC4HhXF5HZSHJivwdkTTUDHtKx_CuLz0IV2DwraDhBAC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2641,7 +2641,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '313e4b6b9117daa3241863a5ce31c203c218164a', + Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '55c592489062e1569fddcc59a4b9b5479a6b988f', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -3012,7 +3012,7 @@ Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'd7169bf89fc40930c49e083ec7969dfdd7650407', + Var('webrtc_git') + '/src.git' + '@' + '8d31c4add2eb4685afff353a35b705b089d5f21f', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -3134,7 +3134,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/boca_receiver_app/app', - 'version': 'XmR-MHAoVgK8NkVe5Wzmg6sF0rjD_0i8eerPGNn7uH4C', + 'version': 'VDuf4Yr9R_yFPnNKg7CivrtnMZ-ICJAsxIK05AvzjcoC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3200,7 +3200,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'XtCUqIiftsKThLvaqajK4yJo2ezvnTl8rBqUTrvgUGUC', + 'version': '7dZy2XxTgdbg3Fq1sWoWLlr6vOQaD6jfh6l6d6Yi7loC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h index cbb3c78f..75311dc 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h +++ b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h
@@ -32,7 +32,8 @@ #elif (PA_BUILDFLAG(IS_ANDROID) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS)) || \ (PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64)) || \ - (PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_PPC64)) + (PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_PPC64)) || \ + (PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64)) // This should work for all POSIX (if needed), but currently all other // supported OS/architecture combinations use either hard-coded values // (such as x86) or have means to determine these values without needing @@ -130,7 +131,7 @@ // compiled for 64kB are likely to work on 4kB systems, 64kB is a good choice // here. return 16; // 64kB -#elif defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) +#elif defined(_MIPS_ARCH_LOONGSON) return 14; // 16kB #elif PA_BUILDFLAG(IS_APPLE) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS) return static_cast<size_t>(vm_page_shift); @@ -140,7 +141,7 @@ // compiled for 64kB are likely to work on 4kB systems, 64kB is a good choice // here. return 16; // 64kB -#elif defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) +#elif defined(_MIPS_ARCH_LOONGSON) return 14; // 16kB #elif PA_BUILDFLAG(IS_APPLE) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS) return static_cast<size_t>(vm_page_shift);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h index 0e8d54c..e941d16 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h +++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h
@@ -112,7 +112,7 @@ PartitionPageShift() { return PageAllocationGranularityShift() + 2; } -#elif defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) +#elif defined(_MIPS_ARCH_LOONGSON) PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t PartitionPageShift() { return 16; // 64 KiB
diff --git a/cc/layers/tile_display_layer_impl_unittest.cc b/cc/layers/tile_display_layer_impl_unittest.cc index 090c0f01..c9f27c4 100644 --- a/cc/layers/tile_display_layer_impl_unittest.cc +++ b/cc/layers/tile_display_layer_impl_unittest.cc
@@ -504,4 +504,35 @@ EXPECT_EQ(render_pass->quad_list.front()->resource_id, low_res_resource_id); } +// Verifies that RemoveTiling correctly removes a tiling. +TEST_F(TileDisplayLayerImplTest, RemoveTilingRemovesTiling) { + auto layer = std::make_unique<TileDisplayLayerImpl>( + CHECK_DEREF(host_impl()->active_tree()), /*id=*/42); + auto* raw_layer = layer.get(); + host_impl()->active_tree()->AddLayer(std::move(layer)); + + // Add a tiling. + raw_layer->GetOrCreateTilingFromScaleKey(1.0); + ASSERT_NE(raw_layer->GetTilingForTesting(1.0), nullptr); + + // Remove the tiling. + raw_layer->RemoveTiling(1.0); + EXPECT_EQ(raw_layer->GetTilingForTesting(1.0), nullptr); +} + +// Verifies that calling RemoveTiling() for a tiling that doesn't exist doesn't +// crash. +TEST_F(TileDisplayLayerImplTest, RemoveTilingOnNonExistentTilingDoesNotCrash) { + auto layer = std::make_unique<TileDisplayLayerImpl>( + CHECK_DEREF(host_impl()->active_tree()), /*id=*/42); + auto* raw_layer = layer.get(); + host_impl()->active_tree()->AddLayer(std::move(layer)); + + ASSERT_EQ(raw_layer->GetTilingForTesting(1.0), nullptr); + + // This should not crash. + raw_layer->RemoveTiling(1.0); + EXPECT_EQ(raw_layer->GetTilingForTesting(1.0), nullptr); +} + } // namespace cc
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index fb790a87..f480339 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -277,8 +277,7 @@ MenuOrKeyboardActionController, CompositorViewHolder.Initializer, TabModelInitializer, - ThemeResourceWrapperProvider, - UmaActivityObserver.UmaSessionAwareActivity { + ThemeResourceWrapperProvider { public static final String UNFOLD_LATENCY_BEGIN_TIMESTAMP = "unfold_latency_begin_timestamp"; public static final String IS_FROM_RECREATING = "is_from_recreating";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaActivityObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaActivityObserver.java index 7e5caa5..b37b6a3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaActivityObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaActivityObserver.java
@@ -4,12 +4,8 @@ package org.chromium.chrome.browser.metrics; -import android.app.Activity; import android.content.Context; -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationState; -import org.chromium.base.ApplicationStatus; import org.chromium.build.annotations.Initializer; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; @@ -35,43 +31,10 @@ private TabModelSelector mLatestTabModelSelector; private AndroidPermissionDelegate mLatestAndroidPermissionDelegate; - /** Activities that implement this interface manage their own UMA Session starting/ending. */ - public interface UmaSessionAwareActivity {} - - private static ApplicationStatus.@Nullable ActivityStateListener sAppActivityListener; - - static { - doStaticInit(); - } - - private static void doStaticInit() { - // Handles the case where we open a non-UMA aware activity like Bookmarks over CTA, and then - // the user hides the Bookmarks Activity (which should end the session). - sAppActivityListener = - new ApplicationStatus.ActivityStateListener() { - @Override - public void onActivityStateChange(Activity activity, int newState) { - if (activity instanceof UmaSessionAwareActivity) return; - if (newState != ActivityState.STOPPED - && newState != ActivityState.DESTROYED) { - return; - } - if (sActiveObserver == null) return; - if (ApplicationStatus.getStateForApplication() - == ApplicationState.HAS_RUNNING_ACTIVITIES) { - return; - } - sActiveObserver.endUmaSessionInternal(false, true); - } - }; - ApplicationStatus.registerStateListenerForAllActivities(sAppActivityListener); - } - public UmaActivityObserver( Context context, ActivityLifecycleDispatcher lifecycleDispatcher, @ActivityType int activityType) { - assert context instanceof UmaSessionAwareActivity; mUmaSessionStats = new UmaSessionStats(context); lifecycleDispatcher.register(this); mActivityType = activityType; @@ -103,7 +66,7 @@ sActiveObserver = this; return; } - sActiveObserver.endUmaSessionInternal(false, false); + sActiveObserver.endUmaSessionInternal(false); } sActiveObserver = this; @@ -138,15 +101,8 @@ */ public void endUmaSession() { if (ChromeFeatureList.isEnabled(ChromeFeatureList.UMA_SESSION_CORRECTNESS_FIXES)) { - for (Activity activity : ApplicationStatus.getRunningActivities()) { - if (activity instanceof UmaSessionAwareActivity) continue; - if (ApplicationStatus.getStateForActivity(activity) == ActivityState.RESUMED) { - // Don't end the session if an Activity like Settings/Bookmarks is still - // visible. - return; - } - } - endUmaSessionInternal(true, true); + sVisibleObservers.remove(this); + endUmaSessionInternal(true); } else { if (sActiveObserver == null) { return; @@ -158,12 +114,8 @@ } } - private void endUmaSessionInternal(boolean startNextVisibleSession, boolean removeObserver) { - if (removeObserver) { - sVisibleObservers.remove(this); - } + private void endUmaSessionInternal(boolean startNextVisibleSession) { if (sActiveObserver != this) return; - // Record session metrics. mUmaSessionStats.logAndEndSession(); sActiveObserver = null; @@ -185,7 +137,7 @@ public void onDestroy() { if (sActiveObserver == null) return; // Ensures native library has been initialized. if (ChromeFeatureList.isEnabled(ChromeFeatureList.UMA_SESSION_CORRECTNESS_FIXES)) { - endUmaSessionInternal(true, true); + endUmaSession(); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java index 062cdbc..e186f36 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
@@ -91,10 +91,7 @@ /** Queries the user's default search engine and shows autocomplete suggestions. */ public class SearchActivity extends AsyncInitializationActivity - implements SnackbarManageable, - BackKeyBehaviorDelegate, - UrlFocusChangeListener, - UmaActivityObserver.UmaSessionAwareActivity { + implements SnackbarManageable, BackKeyBehaviorDelegate, UrlFocusChangeListener { // Shared with other org.chromium.chrome.browser.searchwidget classes. protected static final String TAG = "searchwidget";
diff --git a/chrome/android/javatests/BUILD.gn b/chrome/android/javatests/BUILD.gn index a184537..a991108 100644 --- a/chrome/android/javatests/BUILD.gn +++ b/chrome/android/javatests/BUILD.gn
@@ -843,7 +843,6 @@ "src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java", "src/org/chromium/chrome/browser/metrics/SessionMetricsTest.java", "src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java", - "src/org/chromium/chrome/browser/metrics/UmaActivityObserverTest.java", ] deps = [ ":chrome_test_java_helper" ]
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/PartnerBookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/PartnerBookmarkTest.java index 6e1f6c4..f25e405a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/PartnerBookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/PartnerBookmarkTest.java
@@ -169,9 +169,9 @@ assertEquals(View.GONE, more2.getVisibility()); } - // Disabled on android.emulator_12l_landscape - crbug.com/442769979. @Test @MediumTest + @DisabledTest(message = "https://crbug.com/443216305") public void testCannotSelectPartner() throws Exception { mBookmarkTestRule.openFolder(mBookmarkTestRule.getMobileFolder()); View partner = mBookmarkManagerTestingDelegate.getBookmarkViewHolderByPosition(0).itemView;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UmaActivityObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UmaActivityObserverTest.java deleted file mode 100644 index 80408a7..0000000 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UmaActivityObserverTest.java +++ /dev/null
@@ -1,229 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.metrics; - -import static org.mockito.ArgumentMatchers.anyLong; - -import android.content.ComponentName; -import android.content.Intent; -import android.net.Uri; - -import androidx.test.filters.LargeTest; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InOrder; -import org.mockito.Mockito; -import org.mockito.Spy; - -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationStatus; -import org.chromium.base.ThreadUtils; -import org.chromium.base.test.transit.TravelException; -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DoNotBatch; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.base.test.util.Restriction; -import org.chromium.chrome.browser.customtabs.CustomTabActivity; -import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; -import org.chromium.chrome.browser.customtabs.CustomTabsIntentTestUtils; -import org.chromium.chrome.browser.flags.ActivityType; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.transit.ChromeTransitTestRules; -import org.chromium.chrome.test.transit.FreshCtaTransitTestRule; -import org.chromium.chrome.test.transit.page.WebPageStation; -import org.chromium.chrome.test.transit.settings.SettingsStation; -import org.chromium.ui.base.DeviceFormFactor; -import org.chromium.ui.test.util.DeviceRestriction; - -/** Public Transit tests for the UmaActivityObserver. */ -@RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@DoNotBatch(reason = "Batching not yet supported in multi-window") -// In phones, the New Window option in the app menu is only enabled when already in multi-window or -// multi-display mode with Chrome not running in an adjacent window. -@Restriction({DeviceFormFactor.TABLET_OR_DESKTOP, DeviceRestriction.RESTRICTION_TYPE_NON_AUTO}) -@EnableFeatures({ChromeFeatureList.UMA_SESSION_CORRECTNESS_FIXES}) -public class UmaActivityObserverTest { - @Rule - public FreshCtaTransitTestRule mCtaTestRule = - ChromeTransitTestRules.freshChromeTabbedActivityRule(); - - @Rule public CustomTabActivityTestRule mCctTestRule = new CustomTabActivityTestRule(); - - @Spy private UmaSessionStats.Natives mUmaSessionStatsJniSpy; - InOrder mInOrder; - - @Before - public void setUp() { - mUmaSessionStatsJniSpy = Mockito.spy(UmaSessionStatsJni.get()); - UmaSessionStatsJni.setInstanceForTesting(mUmaSessionStatsJniSpy); - mInOrder = Mockito.inOrder(mUmaSessionStatsJniSpy); - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityType.PRE_FIRST_TAB, - UmaActivityObserver.getCurrentActivityType()); - }); - } - - @Test - @LargeTest - public void testMultiWindowMetrics() throws Exception { - WebPageStation pageInFirstWindow = mCtaTestRule.startOnBlankPage(); - - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityType.TABBED, UmaActivityObserver.getCurrentActivityType()); - }); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaResumeSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaEndSession(anyLong()); - - // Create second CTA window. This should be unnecessary but I cannot figure out how to - // convince Android to create an adjacent window for a new Activity. In any case, this - // is useful to ensure the session isn't restarted. - try { - pageInFirstWindow.openRegularTabAppMenu().openNewWindow(); - } catch (TravelException e) { - // On android_32_google_apis_x64_foldable the screen size is too small for the search - // box to become fully visible with two windows. We don't care as we don't interact with - // it. - if (!e.getMessage().contains("id/search_box")) throw e; - } - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityType.TABBED, UmaActivityObserver.getCurrentActivityType()); - }); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaResumeSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaEndSession(anyLong()); - - // Start a CCT over the second window. - Intent intent = - CustomTabsIntentTestUtils.createMinimalCustomTabIntent( - mCtaTestRule.getActivity(), - mCtaTestRule - .getTestServer() - .getURL("/chrome/test/data/android/about.html")); - intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setComponent(new ComponentName(mCtaTestRule.getActivity(), CustomTabActivity.class)); - - mCctTestRule.startCustomTabActivityWithIntent(intent); - CriteriaHelper.pollUiThread( - () -> UmaActivityObserver.getCurrentActivityType() == ActivityType.CUSTOM_TAB); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaEndSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaResumeSession(anyLong()); - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityState.RESUMED, - ApplicationStatus.getStateForActivity(mCtaTestRule.getActivity())); - Assert.assertEquals( - ActivityState.RESUMED, - ApplicationStatus.getStateForActivity(mCctTestRule.getActivity())); - }); - - // Focus existing CTA in first window. - Intent intent2 = mCtaTestRule.getActivity().getIntent(); - intent2.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); - intent2.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - mCctTestRule.getActivity().startActivity(intent2); - - CriteriaHelper.pollUiThread( - () -> UmaActivityObserver.getCurrentActivityType() == ActivityType.TABBED); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaEndSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaResumeSession(anyLong()); - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityState.RESUMED, - ApplicationStatus.getStateForActivity(mCtaTestRule.getActivity())); - Assert.assertEquals( - ActivityState.RESUMED, - ApplicationStatus.getStateForActivity(mCctTestRule.getActivity())); - }); - - // Close the CTA, resuming the CCT session. - mCtaTestRule.getActivity().finish(); - - CriteriaHelper.pollUiThread( - () -> UmaActivityObserver.getCurrentActivityType() == ActivityType.CUSTOM_TAB); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaEndSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaResumeSession(anyLong()); - } - - @Test - @LargeTest - public void testSessionPreservedInSettings() throws Exception { - WebPageStation pageInFirstWindow = mCtaTestRule.startOnBlankPage(); - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityType.TABBED, UmaActivityObserver.getCurrentActivityType()); - }); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaResumeSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaEndSession(anyLong()); - - // Open settings, preserving the session. - SettingsStation settingsStation = pageInFirstWindow.openRegularTabAppMenu().openSettings(); - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityType.TABBED, UmaActivityObserver.getCurrentActivityType()); - }); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaResumeSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaEndSession(anyLong()); - - // Start dialer for result so we can close it. - int requestCode = 1234; - Intent dialerIntent = new Intent(Intent.ACTION_DIAL); - dialerIntent.setData(Uri.parse("tel:0123456789")); - try { - settingsStation.getActivity().startActivityForResult(dialerIntent, 1234); - CriteriaHelper.pollUiThread( - () -> - ApplicationStatus.getStateForActivity(settingsStation.getActivity()) - == ActivityState.STOPPED); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaResumeSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaEndSession(anyLong()); - } finally { - // Close dialer. - settingsStation.getActivity().finishActivity(requestCode); - } - - CriteriaHelper.pollUiThread( - () -> - ApplicationStatus.getStateForActivity(settingsStation.getActivity()) - == ActivityState.RESUMED); - - // Ideally we would re-start the session here, but this is complicated and enough of an edge - // case that it's not worth fixing for now. - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaResumeSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaEndSession(anyLong()); - - // Close settings and return to Tabbed activity. - settingsStation.getActivity().finish(); - CriteriaHelper.pollUiThread( - () -> - ApplicationStatus.getStateForActivity(mCtaTestRule.getActivity()) - == ActivityState.RESUMED); - - ThreadUtils.runOnUiThreadBlocking( - () -> { - Assert.assertEquals( - ActivityType.TABBED, UmaActivityObserver.getCurrentActivityType()); - }); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(1)).umaResumeSession(anyLong()); - mInOrder.verify(mUmaSessionStatsJniSpy, Mockito.times(0)).umaEndSession(anyLong()); - } -}
diff --git a/chrome/android/modules/on_demand/javatests/src/org/chromium/chrome/browser/data_import/TargetServiceGrpcTest.java b/chrome/android/modules/on_demand/javatests/src/org/chromium/chrome/browser/data_import/TargetServiceGrpcTest.java index ce4182b8..6a243dd 100644 --- a/chrome/android/modules/on_demand/javatests/src/org/chromium/chrome/browser/data_import/TargetServiceGrpcTest.java +++ b/chrome/android/modules/on_demand/javatests/src/org/chromium/chrome/browser/data_import/TargetServiceGrpcTest.java
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.chromium.base.ThreadUtils.runOnUiThreadBlocking; @@ -43,10 +44,8 @@ import org.chromium.components.bookmarks.BookmarkId; import org.chromium.url.GURL; -import java.io.FileOutputStream; +import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.List; import java.util.concurrent.TimeoutException; @@ -121,47 +120,12 @@ @Test @MediumTest public void testImportBookmarks_Basic() throws Exception { - String bookmarksFilePath = - UrlUtils.getTestFilePath("android/bookmarks/Valid_entries.html"); - byte[] bookmarksContent = Files.readAllBytes(Paths.get(bookmarksFilePath)); + String bookmarksFilePath = UrlUtils.getTestFilePath("android/bookmarks/Valid_entries.html"); + ParcelFileDescriptor file = + ParcelFileDescriptor.open( + new File(bookmarksFilePath), ParcelFileDescriptor.MODE_READ_ONLY); - ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); - ParcelFileDescriptor readSide = pipe[0]; - - // The write side of the pipe will be closed automatically by the AutoCloseOutputStream. - try (FileOutputStream fos = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1])) { - fos.write(bookmarksContent); - } - - Metadata headers = new Metadata(); - headers.put( - DataImporterServiceImpl.ParcelableMetadataInterceptor.PFD_METADATA_KEY, readSide); - - BrowserFileMetadata fileMetadata = - BrowserFileMetadata.newBuilder() - .setFileType(BrowserFileType.BROWSER_FILE_TYPE_BOOKMARKS) - .build(); - ImportItemRequest request = - ImportItemRequest.newBuilder() - .setItemType(SystemAppApiItemType.SYSTEM_APP_API_ITEM_TYPE_BROWSER_DATA) - .setSessionId(SESSION_ID) - .setFileMetadata( - Proto3Any.newBuilder().setValue(fileMetadata.toByteString())) - .build(); - - TargetServiceGrpc.TargetServiceBlockingStub stubWithHeaders = - mStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(headers)); - stubWithHeaders.importItem(request); - - ImportItemsDoneRequest doneRequest = - ImportItemsDoneRequest.newBuilder() - .setItemType(SystemAppApiItemType.SYSTEM_APP_API_ITEM_TYPE_BROWSER_DATA) - .setSessionId(SESSION_ID) - .setStatus(ImportItemsDoneRequest.CompleteStatus.COMPLETE_STATUS_SUCCESS) - .build(); - ImportItemsDoneResponse doneResponse = mStub.importItemsDone(doneRequest); - assertEquals( - /* amount of successful imported files */ 1, doneResponse.getSuccessItemCount()); + importBrowserFile(file, BrowserFileType.BROWSER_FILE_TYPE_BOOKMARKS); final BookmarkModel bookmarkModel = waitForBookmarkModelLoaded(); runOnUiThreadBlocking( @@ -198,6 +162,78 @@ }); } + @Test + @MediumTest + public void testImportReadingList() throws Exception { + String readinglistFilePath = + UrlUtils.getTestFilePath("android/bookmarks/Valid_reading_list_entry.html"); + ParcelFileDescriptor file = + ParcelFileDescriptor.open( + new File(readinglistFilePath), ParcelFileDescriptor.MODE_READ_ONLY); + + importBrowserFile(file, BrowserFileType.BROWSER_FILE_TYPE_READING_LIST); + + runOnUiThreadBlocking( + () -> ChromeBrowserInitializer.getInstance().handleSynchronousStartup()); + final BookmarkModel bookmarkModel = waitForBookmarkModelLoaded(); + runOnUiThreadBlocking( + () -> { + BookmarkId readingListFolder = + bookmarkModel.getLocalOrSyncableReadingListFolder(); + assertFalse( + "Reading list should not be empty", + bookmarkModel.getChildIds(readingListFolder).isEmpty()); + GURL url = new GURL("https://www.chromium.org/"); + assertTrue( + "Reading list item should be present", bookmarkModel.isBookmarked(url)); + List<BookmarkId> bookmarkIds = bookmarkModel.searchBookmarks(url.getSpec(), 1); + assertFalse("Bookmark ID list should not be empty", bookmarkIds.isEmpty()); + BookmarkId bookmarkId = bookmarkIds.get(0); + assertEquals( + "Reading list item title should match", + "Chromium", + bookmarkModel.getBookmarkById(bookmarkId).getTitle()); + assertEquals( + "Item should be in reading list folder", + readingListFolder, + bookmarkModel.getBookmarkById(bookmarkId).getParentId()); + }); + } + + private void importBrowserFile(ParcelFileDescriptor readSide, BrowserFileType fileType) { + Metadata headers = new Metadata(); + headers.put( + DataImporterServiceImpl.ParcelableMetadataInterceptor.PFD_METADATA_KEY, readSide); + + BrowserFileMetadata fileMetadata = + BrowserFileMetadata.newBuilder().setFileType(fileType).build(); + ImportItemRequest request = + ImportItemRequest.newBuilder() + .setItemType(SystemAppApiItemType.SYSTEM_APP_API_ITEM_TYPE_BROWSER_DATA) + .setSessionId(SESSION_ID) + .setFileMetadata( + Proto3Any.newBuilder().setValue(fileMetadata.toByteString())) + .build(); + + TargetServiceGrpc.TargetServiceBlockingStub stubWithHeaders = + mStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(headers)); + ImportItemResponse response = stubWithHeaders.importItem(request); + assertNotNull(response); + assertEquals( + ImportItemResponse.TransferError.TRANSFER_ERROR_UNSPECIFIED, + response.getTransferError()); + + ImportItemsDoneRequest doneRequest = + ImportItemsDoneRequest.newBuilder() + .setItemType(SystemAppApiItemType.SYSTEM_APP_API_ITEM_TYPE_BROWSER_DATA) + .setSessionId(SESSION_ID) + .setStatus(ImportItemsDoneRequest.CompleteStatus.COMPLETE_STATUS_SUCCESS) + .build(); + ImportItemsDoneResponse doneResponse = mStub.importItemsDone(doneRequest); + assertEquals( + /* amount of successful imported files */ 1, doneResponse.getSuccessItemCount()); + } + /** * Waits until the bookmark model is loaded, i.e. until {@link * BookmarkModel#isBookmarkModelLoaded()} is true.
diff --git a/chrome/android/profiles/arm.newest.txt b/chrome/android/profiles/arm.newest.txt index 643980f..936015f 100644 --- a/chrome/android/profiles/arm.newest.txt +++ b/chrome/android/profiles/arm.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-142.0.7391.0_pre1509560_rc-r1-merged.afdo.bz2 +chromeos-chrome-arm-142.0.7394.0_pre1510892_rc-r2-merged.afdo.bz2
diff --git a/chrome/browser/accessibility/image_annotation_browsertest.cc b/chrome/browser/accessibility/image_annotation_browsertest.cc index 72b3af2..c515127d 100644 --- a/chrome/browser/accessibility/image_annotation_browsertest.cc +++ b/chrome/browser/accessibility/image_annotation_browsertest.cc
@@ -138,6 +138,26 @@ return; } + processors_.emplace_back(std::move(image_processor)); + processors_.back()->GetJpgImageData(base::BindOnce( + &FakeAnnotator::OnJpgImageDataReceived, base::Unretained(this), + std::move(image_id), std::move(description_language_tag), + std::move(callback))); + } + + void OnJpgImageDataReceived(const std::string& image_id, + const std::string& description_language_tag, + AnnotateImageCallback callback, + const std::vector<uint8_t>& image_bytes, + const int32_t width, + const int32_t height) { + if (image_bytes.empty()) { + std::move(callback).Run( + image_annotation::mojom::AnnotateImageResult::NewErrorCode( + image_annotation::mojom::AnnotateImageError::kFailure)); + return; + } + // Use the filename to create annotation strings. Check a map from filename // to desired label, otherwise just construct a string based on the // filename. Adds some trailing whitespace and punctuation to check that @@ -173,6 +193,8 @@ private: mojo::ReceiverSet<image_annotation::mojom::Annotator> receivers_; + std::vector<mojo::Remote<image_annotation::mojom::ImageProcessor>> + processors_; static bool return_ocr_results_; static bool return_label_results_; static std::map<std::string, std::string> custom_label_result_mapping_; @@ -649,3 +671,34 @@ snapshot = content::GetAccessibilityTreeSnapshot(web_contents); } } + +IN_PROC_BROWSER_TEST_F(ImageAnnotationBrowserTest, LazyLoadingImages) { + FakeAnnotator::SetReturnOcrResults(true); + FakeAnnotator::SetReturnLabelResults(true); + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), + https_server_.GetURL("/accessibility/page_with_lazy_image.html"))); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + content::WaitForAccessibilityTreeToContainNodeWithName( + web_contents, + "Appears to say: green.png Annotation. Appears to be: green.png 'en' " + "Label"); + EXPECT_EQ(1u, DescribeNodesWithAnnotations( + content::GetAccessibilityTreeSnapshot(web_contents)) + .size()); + + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, run_loop.QuitWhenIdleClosure(), base::Milliseconds(500)); + run_loop.Run(); + web_contents->ScrollToBottomOfDocument(); + + content::WaitForAccessibilityTreeToContainNodeWithName( + web_contents, + "Appears to say: red.png Annotation. Appears to be: red.png 'en' Label"); + EXPECT_EQ(2u, DescribeNodesWithAnnotations( + content::GetAccessibilityTreeSnapshot(web_contents)) + .size()); +}
diff --git a/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc b/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc index 00939499..3e7f0aa 100644 --- a/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc +++ b/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc
@@ -118,7 +118,8 @@ arc_toplevel->SetProperty(chromeos::kAppTypeKey, chromeos::AppType::ARC_APP); ASSERT_TRUE(IsArcWindow(arc_toplevel)); aura::Window* arc_window = - aura::test::CreateTestWindowWithBounds(gfx::Rect(), arc_toplevel); + aura::test::CreateTestWindow({.bounds = gfx::Rect()}, arc_toplevel) + .release(); ASSERT_TRUE(IsArcWindow(arc_window->GetToplevelWindow())); // Crostini: @@ -128,7 +129,8 @@ chromeos::AppType::CROSTINI_APP); ASSERT_TRUE(crostini::IsCrostiniWindow(crostini_toplevel)); aura::Window* crostini_window = - aura::test::CreateTestWindowWithBounds(gfx::Rect(), crostini_toplevel); + aura::test::CreateTestWindow({.bounds = gfx::Rect()}, crostini_toplevel) + .release(); ASSERT_TRUE(crostini::IsCrostiniWindow(crostini_window->GetToplevelWindow())); // Plugin VM: @@ -137,7 +139,8 @@ exo::SetShellApplicationId(plugin_vm_toplevel, "org.chromium.plugin_vm_ui"); ASSERT_TRUE(plugin_vm::IsPluginVmAppWindow(plugin_vm_toplevel)); aura::Window* plugin_vm_window = - aura::test::CreateTestWindowWithBounds(gfx::Rect(), plugin_vm_toplevel); + aura::test::CreateTestWindow({.bounds = gfx::Rect()}, plugin_vm_toplevel) + .release(); ASSERT_TRUE( plugin_vm::IsPluginVmAppWindow(plugin_vm_window->GetToplevelWindow()));
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector_unittest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_unittest.cc index 57e81b6..1f2a1940 100644 --- a/chrome/browser/ash/policy/status_collector/device_status_collector_unittest.cc +++ b/chrome/browser/ash/policy/status_collector/device_status_collector_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/status_collector/device_status_collector.h" #include <stddef.h> @@ -24,6 +19,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "base/check_deref.h" +#include "base/containers/span.h" #include "base/environment.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -391,10 +387,10 @@ test_clock_->SetNow(base::Time::Now().LocalMidnight() + kHour); } - void Simulate(ui::IdleState* states, int len) { - for (int i = 0; i < len; i++) { + void Simulate(base::span<const ui::IdleState> states) { + for (const auto& state : states) { test_clock_->Advance(DeviceStatusCollector::kIdlePollInterval); - ProcessIdleState(states[i]); + ProcessIdleState(state); } } @@ -1261,8 +1257,8 @@ TEST_F(DeviceStatusCollectorTest, AllIdle) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE, - ui::IDLE_STATE_IDLE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); @@ -1272,14 +1268,13 @@ EXPECT_EQ(0, GetActiveMilliseconds(device_status_)); // Test reporting with a single idle sample. - status_collector_->Simulate(test_states, 1); + status_collector_->Simulate(base::span(test_states).first(1u)); GetStatus(); EXPECT_EQ(0, device_status_.active_periods_size()); EXPECT_EQ(0, GetActiveMilliseconds(device_status_)); // Test reporting with multiple consecutive idle samples. - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(0, device_status_.active_periods_size()); EXPECT_EQ(0, GetActiveMilliseconds(device_status_)); @@ -1287,13 +1282,13 @@ TEST_F(DeviceStatusCollectorTest, AllActive) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); // Test a single active sample. - status_collector_->Simulate(test_states, 1); + status_collector_->Simulate(base::span(test_states).first(1u)); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_EQ(1 * ActivePeriodMilliseconds(), @@ -1301,8 +1296,7 @@ device_status_.clear_active_periods(); // Clear the result protobuf. // Test multiple consecutive active samples. - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_EQ(4 * ActivePeriodMilliseconds(), @@ -1311,15 +1305,14 @@ TEST_F(DeviceStatusCollectorTest, MixedStates) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, - ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 7> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, ui::IDLE_STATE_ACTIVE, + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE, + ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); @@ -1328,7 +1321,7 @@ // For kiosks report total uptime instead of only active periods. TEST_F(DeviceStatusCollectorTest, MixedStatesForKiosk) { DisableDefaultSettings(); - ui::IdleState test_states[] = { + const std::array<ui::IdleState, 6> test_states = { ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE, }; @@ -1336,8 +1329,7 @@ ash::LoginState::LOGGED_IN_ACTIVE, ash::LoginState::LOGGED_IN_USER_KIOSK); scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(6 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); @@ -1345,20 +1337,18 @@ TEST_F(DeviceStatusCollectorTest, StateKeptInPref) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, - ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE}; + const std::array<ui::IdleState, 6> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, ui::IDLE_STATE_ACTIVE, + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE, ui::IDLE_STATE_IDLE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); // Process the list a second time after restarting the collector. It should be // able to count the active periods found by the original collector, because // the results are stored in a pref. RestartStatusCollector(CreateEmptyDeviceStatusCollectorOptions()); - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(6 * ActivePeriodMilliseconds(), @@ -1372,10 +1362,9 @@ EXPECT_THAT(profile_pref_service_.GetDict(prefs::kUserActivityTimes), IsEmpty()); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_EQ(3 * ActivePeriodMilliseconds(), @@ -1389,7 +1378,8 @@ TEST_F(DeviceStatusCollectorTest, MaxStoredPeriods) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_IDLE}; + const std::array<ui::IdleState, 2> test_states = {ui::IDLE_STATE_ACTIVE, + ui::IDLE_STATE_IDLE}; const int kMaxDays = 10; scoped_testing_cros_settings_.device_settings()->SetBoolean( @@ -1401,8 +1391,7 @@ // Simulate 12 active periods. for (int i = 0; i < kMaxDays + 2; i++) { - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); // Advance the simulated clock by a day. test_clock_.Advance(base::Days(1)); } @@ -1413,8 +1402,7 @@ // Simulate some future times. for (int i = 0; i < kMaxDays + 2; i++) { - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + status_collector_->Simulate(test_states); // Advance the simulated clock by a day. test_clock_.Advance(base::Days(1)); } @@ -1422,7 +1410,7 @@ test_clock_.Advance(-base::Days(20)); // Collect one more data point to trigger pruning. - status_collector_->Simulate(test_states, 1); + status_collector_->Simulate(base::span(test_states).first(1u)); // Check that we don't exceed the max number of periods. device_status_.clear_active_periods(); @@ -1432,10 +1420,9 @@ TEST_F(DeviceStatusCollectorTest, ActivityTimesEnabledByDefault) { // Device activity times should be reported by default. - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_EQ(3 * ActivePeriodMilliseconds(), @@ -1446,10 +1433,9 @@ // Device activity times should not be reported while disabled. scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, false); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; - status_collector_->Simulate(test_states, - sizeof(test_states) / sizeof(ui::IdleState)); + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(0, device_status_.active_periods_size()); EXPECT_EQ(0, GetActiveMilliseconds(device_status_)); @@ -1457,14 +1443,14 @@ TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 1> test_states = {ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); // Set the baseline time to 20 seconds before midnight. test_clock_.SetNow(base::Time::Now().LocalMidnight() - base::Seconds(20)); - status_collector_->Simulate(test_states, 1); + status_collector_->Simulate(test_states); GetStatus(); ASSERT_EQ(2, device_status_.active_periods_size()); @@ -1487,7 +1473,7 @@ TEST_F(DeviceStatusCollectorTest, ActivityTimesKeptUntilSubmittedSuccessfully) { DisableDefaultSettings(); - ui::IdleState test_states[] = { + const std::array<ui::IdleState, 2> test_states = { ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, }; @@ -1499,7 +1485,7 @@ scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); - status_collector_->Simulate(test_states, 2); + status_collector_->Simulate(base::span(test_states).first(2u)); GetStatus(); EXPECT_EQ(2 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); @@ -1516,7 +1502,7 @@ // After indicating a successful submit, the submitted status gets cleared, // and prior activity is no longer showing. - status_collector_->Simulate(test_states, 1); + status_collector_->Simulate(base::span(test_states).first(1u)); status_collector_->OnSubmittedSuccessfully(); GetStatus(); EXPECT_EQ(0, GetActiveMilliseconds(device_status_)); @@ -1524,8 +1510,8 @@ TEST_F(DeviceStatusCollectorTest, ActivityNoUser) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); scoped_testing_cros_settings_.device_settings()->SetBoolean( @@ -1534,7 +1520,7 @@ EXPECT_FALSE(status_collector_->IsReportingActivityTimes()); EXPECT_FALSE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_TRUE(device_status_.active_periods(0).user_email().empty()); @@ -1543,8 +1529,8 @@ TEST_F(DeviceStatusCollectorTest, ActivityWithPublicSessionUser) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); scoped_testing_cros_settings_.device_settings()->SetBoolean( @@ -1560,7 +1546,7 @@ EXPECT_FALSE(status_collector_->IsReportingActivityTimes()); EXPECT_FALSE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_TRUE(device_status_.active_periods(0).user_email().empty()); @@ -1570,8 +1556,8 @@ TEST_F(DeviceStatusCollectorTest, ActivityWithKioskUser) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); scoped_testing_cros_settings_.device_settings()->SetBoolean( @@ -1587,7 +1573,7 @@ EXPECT_FALSE(status_collector_->IsReportingActivityTimes()); EXPECT_FALSE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_TRUE(device_status_.active_periods(0).user_email().empty()); @@ -1597,8 +1583,8 @@ TEST_F(DeviceStatusCollectorTest, ActivityWithIwaKioskUser) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); scoped_testing_cros_settings_.device_settings()->SetBoolean( @@ -1614,7 +1600,7 @@ EXPECT_FALSE(status_collector_->IsReportingActivityTimes()); EXPECT_FALSE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_TRUE(device_status_.active_periods(0).user_email().empty()); @@ -1624,8 +1610,8 @@ TEST_F(DeviceStatusCollectorTest, ActivityWithAffiliatedUser) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); scoped_testing_cros_settings_.device_settings()->SetBoolean( @@ -1640,7 +1626,7 @@ EXPECT_TRUE(status_collector_->IsReportingActivityTimes()); EXPECT_TRUE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_EQ(account_id0.GetUserEmail(), @@ -1655,7 +1641,7 @@ EXPECT_TRUE(status_collector_->IsReportingActivityTimes()); EXPECT_FALSE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_TRUE(device_status_.active_periods(0).user_email().empty()); @@ -1664,8 +1650,8 @@ TEST_F(DeviceStatusCollectorTest, ActivityWithNotAffiliatedUser) { DisableDefaultSettings(); - ui::IdleState test_states[] = {ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, - ui::IDLE_STATE_ACTIVE}; + const std::array<ui::IdleState, 3> test_states = { + ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE, ui::IDLE_STATE_ACTIVE}; scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportDeviceActivityTimes, true); scoped_testing_cros_settings_.device_settings()->SetBoolean( @@ -1680,7 +1666,7 @@ EXPECT_FALSE(status_collector_->IsReportingActivityTimes()); EXPECT_FALSE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_TRUE(device_status_.active_periods(0).user_email().empty()); @@ -1693,7 +1679,7 @@ EXPECT_FALSE(status_collector_->IsReportingActivityTimes()); EXPECT_FALSE(status_collector_->IsReportingUsers()); - status_collector_->Simulate(test_states, 3); + status_collector_->Simulate(test_states); GetStatus(); EXPECT_EQ(1, device_status_.active_periods_size()); EXPECT_TRUE(device_status_.active_periods(0).user_email().empty()); @@ -2691,21 +2677,22 @@ scoped_testing_cros_settings_.device_settings()->SetBoolean( ash::kReportOsUpdateStatus, true); - const char* kRequiredPlatformVersions[] = {"1234", "1234.0", "1234.0.0"}; + const std::array<const char*, 3> kRequiredPlatformVersions = { + "1234", "1234.0", "1234.0.0"}; - for (size_t i = 0; i < std::size(kRequiredPlatformVersions); ++i) { + for (const char* version : kRequiredPlatformVersions) { MockAutoLaunchKioskAppWithRequiredPlatformVersion( - fake_kiosk_device_local_account_, kRequiredPlatformVersions[i]); + fake_kiosk_device_local_account_, version); GetStatus(); ASSERT_TRUE(device_status_.has_os_update_status()) - << "Required platform version=" << kRequiredPlatformVersions[i]; + << "Required platform version=" << version; EXPECT_EQ(em::OsUpdateStatus::OS_UP_TO_DATE, device_status_.os_update_status().update_status()) - << "Required platform version=" << kRequiredPlatformVersions[i]; - EXPECT_EQ(kRequiredPlatformVersions[i], + << "Required platform version=" << version; + EXPECT_EQ(version, device_status_.os_update_status().new_required_platform_version()) - << "Required platform version=" << kRequiredPlatformVersions[i]; + << "Required platform version=" << version; } } @@ -2739,14 +2726,14 @@ EXPECT_EQ(em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_NOT_STARTED, device_status_.os_update_status().update_status()); - const update_engine::Operation kUpdateEngineOps[] = { + const std::array<update_engine::Operation, 3> kUpdateEngineOps = { update_engine::Operation::DOWNLOADING, update_engine::Operation::VERIFYING, update_engine::Operation::FINALIZING, }; - for (size_t i = 0; i < std::size(kUpdateEngineOps); ++i) { - update_status.set_current_operation(kUpdateEngineOps[i]); + for (const auto op : kUpdateEngineOps) { + update_status.set_current_operation(op); update_status.set_new_version("1235.1.2"); update_engine_client_->PushLastStatus(update_status); @@ -2788,14 +2775,14 @@ ASSERT_FALSE( device_status_.os_update_status().has_new_required_platform_version()); - const update_engine::Operation kUpdateEngineOps[] = { + const std::array<update_engine::Operation, 3> kUpdateEngineOps = { update_engine::Operation::DOWNLOADING, update_engine::Operation::VERIFYING, update_engine::Operation::FINALIZING, }; - for (size_t i = 0; i < std::size(kUpdateEngineOps); ++i) { - update_status.set_current_operation(kUpdateEngineOps[i]); + for (const auto op : kUpdateEngineOps) { + update_status.set_current_operation(op); update_status.set_new_version("1235.1.2"); update_engine_client_->PushLastStatus(update_status); @@ -2844,12 +2831,12 @@ // Check update multiple times, the timestamp stored in device status should // change accordingly. - const int64 kLastCheckedTimes[] = {10, 20, 30}; + const std::array<int64_t, 3> kLastCheckedTimes = {10, 20, 30}; - for (size_t i = 0; i < std::size(kLastCheckedTimes); ++i) { + for (const auto time : kLastCheckedTimes) { update_engine::StatusResult update_status; update_status.set_new_version(kDefaultPlatformVersion); - update_status.set_last_checked_time(kLastCheckedTimes[i]); + update_status.set_last_checked_time(time); update_engine_client_->PushLastStatus(update_status); GetStatus(); @@ -2858,7 +2845,7 @@ // The timestamp precision in UpdateEngine is in seconds, but the // DeviceStatusCollector is in milliseconds. Therefore, the number should be // multiplied by 1000 before validation. - ASSERT_EQ(kLastCheckedTimes[i] * 1000, + ASSERT_EQ(time * 1000, device_status_.os_update_status().last_checked_timestamp()); } } @@ -3289,15 +3276,16 @@ // Create a test uploads.log file. One |upload_time| is within last 24 hours, // the other is not. base::Time now = base::Time::Now(); - base::Time timestamps[] = {now - base::Hours(22), now - base::Hours(24)}; + std::array<base::Time, 2> timestamps = {now - base::Hours(22), + now - base::Hours(24)}; std::stringstream stream; - for (int i = 0; i <= 1; ++i) { + for (const auto& timestamp : timestamps) { stream << "{"; - stream << "\"upload_time\":\"" << timestamps[i].ToTimeT() << "\","; + stream << "\"upload_time\":\"" << timestamp.ToTimeT() << "\","; stream << "\"upload_id\":\"" << kTestUploadId << "\","; stream << "\"local_id\":\"" << kTestLocalID << "\","; - stream << "\"capture_time\":\"" << timestamps[i].ToTimeT() << "\","; + stream << "\"capture_time\":\"" << timestamp.ToTimeT() << "\","; stream << "\"state\":" << static_cast<int>(UploadList::UploadInfo::State::Uploaded) << ","; stream << "\"source\":\"" << kTestCauseKernel << "\"";
diff --git a/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc b/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc index 0a8e19ab..eacd57d 100644 --- a/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc +++ b/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc
@@ -124,9 +124,10 @@ // Notify user that their address is saved only in Chrome and can be migrated // to their Google account. if (is_migration_to_account_) { + // TODO(crbug.com/40066949): Simplify once ConsentLevel::kSync is not used + // anymore, and thus IsSyncFeatureEnabledForAutofill() will always be false. return l10n_util::GetStringFUTF16( - personal_data_->address_data_manager() - .IsAutofillUserSelectableTypeEnabled() + personal_data_->address_data_manager().IsSyncFeatureEnabledForAutofill() ? IDS_AUTOFILL_SYNCABLE_PROFILE_MIGRATION_PROMPT_NOTICE : IDS_AUTOFILL_LOCAL_PROFILE_MIGRATION_PROMPT_NOTICE, base::UTF8ToUTF16(account->email));
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_util.cc b/chrome/browser/extensions/api/autofill_private/autofill_util.cc index ee0e765..212d532 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_util.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_util.cc
@@ -46,7 +46,6 @@ #include "components/autofill/core/common/credit_card_network_identifiers.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" -#include "components/sync/base/features.h" #include "components/sync/base/user_selectable_type.h" #include "components/variations/service/variations_service.h" #include "extensions/browser/extensions_browser_client.h" @@ -356,13 +355,8 @@ api::autofill_private::AccountInfo api_account; api_account.email = account->email; - // TODO(crbug.com/40066949): Remove `is_sync_enabled_for_autofill_profiles` - // from `AccountInfo` in favor of `is_autofill_sync_toggle_enabled` after - // Sync-the-feature users are migrated to ConsentLevel::kSignin. api_account.is_sync_enabled_for_autofill_profiles = - base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) - ? adm.IsAutofillUserSelectableTypeEnabled() - : adm.IsSyncFeatureEnabledForAutofill(); + adm.IsSyncFeatureEnabledForAutofill(); api_account.is_eligible_for_address_account_storage = adm.IsEligibleForAddressAccountStorage(); api_account.is_autofill_sync_toggle_enabled =
diff --git a/chrome/browser/local_network_access/OWNERS b/chrome/browser/local_network_access/OWNERS index c8542ff..930bd8f 100644 --- a/chrome/browser/local_network_access/OWNERS +++ b/chrome/browser/local_network_access/OWNERS
@@ -1,5 +1 @@ -clamy@chromium.org -cthomp@chromium.org -estark@chromium.org -hchao@chromium.org -jdeblasio@chromium.org +file://content/browser/security/local_network_access/OWNERS
diff --git a/chrome/browser/password_manager/android/credential_leak_controller_android.cc b/chrome/browser/password_manager/android/credential_leak_controller_android.cc index 75ac004..b290cd7 100644 --- a/chrome/browser/password_manager/android/credential_leak_controller_android.cc +++ b/chrome/browser/password_manager/android/credential_leak_controller_android.cc
@@ -8,7 +8,6 @@ #include "base/android/jni_android.h" #include "chrome/browser/password_manager/android/password_checkup_launcher_helper.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/android/passwords/credential_leak_dialog_view_android.h" #include "components/password_manager/core/browser/features/password_features.h"
diff --git a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc index 0a8175eb..c6a2791 100644 --- a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc +++ b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc
@@ -12,7 +12,6 @@ #include "base/functional/bind.h" #include "base/metrics/histogram_functions.h" #include "base/strings/strcat.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/password_manager/android/password_manager_lifecycle_helper_impl.h" #include "chrome/browser/password_manager/android/password_settings_updater_android_bridge_helper.h" #include "components/password_manager/core/browser/features/password_features.h"
diff --git a/chrome/browser/password_manager/android/password_settings_updater_android_dispatcher_bridge_impl.cc b/chrome/browser/password_manager/android/password_settings_updater_android_dispatcher_bridge_impl.cc index 08b2708d..754e0981 100644 --- a/chrome/browser/password_manager/android/password_settings_updater_android_dispatcher_bridge_impl.cc +++ b/chrome/browser/password_manager/android/password_settings_updater_android_dispatcher_bridge_impl.cc
@@ -8,7 +8,6 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/password_manager/android/password_settings_updater_android_dispatcher_bridge.h" #include "chrome/browser/password_manager/android/password_settings_updater_android_receiver_bridge.h" #include "components/password_manager/core/browser/password_manager_setting.h"
diff --git a/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc b/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc index 2434fc90..2b3ab4f 100644 --- a/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc +++ b/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/password_manager/android/fake_password_manager_lifecycle_helper.h" #include "chrome/browser/password_manager/android/mock_password_store_android_backend_bridge_helper.h" #include "chrome/browser/password_manager/android/mock_password_sync_controller_delegate_bridge.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/password_manager/android/password_manager_lifecycle_helper.h" #include "chrome/browser/password_manager/android/password_store_android_backend_api_error_codes.h" #include "chrome/browser/password_manager/android/password_store_android_backend_dispatcher_bridge.h"
diff --git a/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc b/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc index 88225d3..6ecb1238 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc
@@ -14,7 +14,6 @@ #include "base/task/bind_post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/password_manager/android/password_store_android_backend_dispatcher_bridge.h" #include "chrome/browser/password_manager/android/password_store_android_backend_receiver_bridge.h" #include "components/password_manager/core/browser/password_form.h"
diff --git a/chrome/browser/password_manager/android/password_store_android_backend_dispatcher_bridge_impl.cc b/chrome/browser/password_manager/android/password_store_android_backend_dispatcher_bridge_impl.cc index d46555a..a36b014 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend_dispatcher_bridge_impl.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend_dispatcher_bridge_impl.cc
@@ -11,7 +11,6 @@ #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/password_manager/android/protos/list_passwords_result.pb.h" #include "chrome/browser/password_manager/android/protos/password_with_local_data.pb.h" #include "chrome/browser/password_manager/android/unified_password_manager_proto_utils.h"
diff --git a/chrome/browser/password_manager/android/password_sync_controller_delegate_bridge_impl.cc b/chrome/browser/password_manager/android/password_sync_controller_delegate_bridge_impl.cc index 590917bd..15f59df 100644 --- a/chrome/browser/password_manager/android/password_sync_controller_delegate_bridge_impl.cc +++ b/chrome/browser/password_manager/android/password_sync_controller_delegate_bridge_impl.cc
@@ -6,7 +6,6 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "components/password_manager/core/browser/password_store/android_backend_error.h" #include "components/password_manager/core/common/password_manager_features.h"
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc index 1288ddd0..cf1cada 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc
@@ -15,7 +15,6 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/android/android_theme_resources.h" #include "chrome/browser/android/resource_mapper.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h"
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index e99698e..d801a81 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -155,7 +155,6 @@ #include "chrome/browser/password_manager/android/one_time_passwords/android_sms_otp_backend_factory.h" #include "chrome/browser/password_manager/android/password_checkup_launcher_helper_impl.h" #include "chrome/browser/password_manager/android/password_generation_controller.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/password_manager/android/password_manager_error_message_helper_bridge_impl.h" #include "chrome/browser/password_manager/android/password_manager_launcher_android.h" #include "chrome/browser/password_manager/android/password_manager_ui_util_android.h"
diff --git a/chrome/browser/safe_browsing/android/password_reuse_controller_android.cc b/chrome/browser/safe_browsing/android/password_reuse_controller_android.cc index 5e9559b..1158319 100644 --- a/chrome/browser/safe_browsing/android/password_reuse_controller_android.cc +++ b/chrome/browser/safe_browsing/android/password_reuse_controller_android.cc
@@ -9,7 +9,6 @@ #include "base/android/device_info.h" #include "base/functional/callback.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/ui/android/safe_browsing/password_reuse_dialog_view_android.h" #include "components/password_manager/core/browser/features/password_features.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc index 8061c06..9494837c 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -113,7 +113,6 @@ #if BUILDFLAG(IS_ANDROID) #include "chrome/browser/password_manager/android/password_checkup_launcher_helper_impl.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/safe_browsing/android/password_reuse_controller_android.h" #include "chrome/browser/safe_browsing/android/safe_browsing_referring_app_bridge_android.h" #include "components/enterprise/connectors/core/features.h"
diff --git a/chrome/browser/signin/android/signin_manager_android.cc b/chrome/browser/signin/android/signin_manager_android.cc index b2527e4..e8a67c6c 100644 --- a/chrome/browser/signin/android/signin_manager_android.cc +++ b/chrome/browser/signin/android/signin_manager_android.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h" #include "chrome/browser/enterprise/util/managed_browser_utils.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h" #include "chrome/browser/policy/cloud/user_policy_signin_service_mobile.h" #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/sync/sync_service_factory.cc b/chrome/browser/sync/sync_service_factory.cc index 0577da77..b2ec99d 100644 --- a/chrome/browser/sync/sync_service_factory.cc +++ b/chrome/browser/sync/sync_service_factory.cc
@@ -31,7 +31,6 @@ #include "chrome/browser/password_manager/password_receiver_service_factory.h" #include "chrome/browser/password_manager/profile_password_store_factory.h" #include "chrome/browser/plus_addresses/plus_address_setting_service_factory.h" -#include "chrome/browser/power_bookmarks/power_bookmark_service_factory.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" @@ -235,8 +234,6 @@ PlusAddressSettingServiceFactory::GetForBrowserContext(profile), WebDataServiceFactory::GetPlusAddressWebDataForProfile( profile, ServiceAccessType::IMPLICIT_ACCESS)); - builder.SetPowerBookmarkService( - PowerBookmarkServiceFactory::GetForBrowserContext(profile)); builder.SetPrefService(profile->GetPrefs()); builder.SetPrefServiceSyncable(PrefServiceSyncableFromProfile(profile)); builder.SetProductSpecificationsService( @@ -538,7 +535,6 @@ DependsOn(PlusAddressSettingServiceFactory::GetInstance()); DependsOn(commerce::ProductSpecificationsServiceFactory::GetInstance()); DependsOn(ProfilePasswordStoreFactory::GetInstance()); - DependsOn(PowerBookmarkServiceFactory::GetInstance()); DependsOn(SecurityEventRecorderFactory::GetInstance()); DependsOn(SendTabToSelfSyncServiceFactory::GetInstance());
diff --git a/chrome/browser/sync/test/integration/BUILD.gn b/chrome/browser/sync/test/integration/BUILD.gn index a932c756a..e5f42245 100644 --- a/chrome/browser/sync/test/integration/BUILD.gn +++ b/chrome/browser/sync/test/integration/BUILD.gn
@@ -156,7 +156,6 @@ "two_client_extensions_sync_test.cc", "two_client_history_sync_test.cc", "two_client_passwords_sync_test.cc", - "two_client_power_bookmarks_sync_test.cc", "two_client_preferences_sync_test.cc", "two_client_search_engines_sync_test.cc", "two_client_send_tab_to_self_sync_test.cc", @@ -235,8 +234,6 @@ "//components/favicon/core", "//components/history/content/browser", "//components/history/core/common", - "//components/power_bookmarks/common:test_support", - "//components/power_bookmarks/core", "//components/reading_list/core", "//components/saved_tab_groups/internal:tab_group_sync_bridge", "//components/search_engines", @@ -433,7 +430,6 @@ "//chrome/browser/favicon", "//chrome/test:test_support", "//components/autofill/content/browser", - "//components/power_bookmarks/core:features", ] deps = [
diff --git a/chrome/browser/sync/test/integration/DEPS b/chrome/browser/sync/test/integration/DEPS index f3d63cbb..2d838960 100644 --- a/chrome/browser/sync/test/integration/DEPS +++ b/chrome/browser/sync/test/integration/DEPS
@@ -3,18 +3,12 @@ ] specific_include_rules = { - "local_sync_test\\.cc": [ - "+components/power_bookmarks", - ], "single_client_nigori_sync_test\\.cc": [ "+ash/multi_user/multi_user_window_manager_impl.h", ], "single_client_plus_address_sync_test\\.cc": [ "+components/plus_addresses", ], - "two_client_power_bookmarks_sync_test\\.cc": [ - "+components/power_bookmarks", - ], "two_client_web_apps_integration_test_base\\.h": [ "+chrome/browser/ui/views", ],
diff --git a/chrome/browser/sync/test/integration/local_sync_test.cc b/chrome/browser/sync/test/integration/local_sync_test.cc index 1900e42..863d4c5 100644 --- a/chrome/browser/sync/test/integration/local_sync_test.cc +++ b/chrome/browser/sync/test/integration/local_sync_test.cc
@@ -19,7 +19,6 @@ #include "chrome/test/base/in_process_browser_test.h" #include "components/browser_sync/browser_sync_switches.h" #include "components/commerce/core/commerce_feature_list.h" -#include "components/power_bookmarks/core/power_bookmark_features.h" #include "components/sync/base/command_line_switches.h" #include "components/sync/base/data_type.h" #include "components/sync/base/features.h" @@ -116,10 +115,6 @@ syncer::WEB_APPS, syncer::NIGORI}; - if (base::FeatureList::IsEnabled(power_bookmarks::kPowerBookmarkBackend)) { - expected_active_data_types.Put(syncer::POWER_BOOKMARK); - } - if (base::FeatureList::IsEnabled(syncer::kSyncAutofillWalletCredentialData)) { expected_active_data_types.Put(syncer::AUTOFILL_WALLET_CREDENTIAL); }
diff --git a/chrome/browser/sync/test/integration/two_client_power_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_power_bookmarks_sync_test.cc deleted file mode 100644 index f0c4a61..0000000 --- a/chrome/browser/sync/test/integration/two_client_power_bookmarks_sync_test.cc +++ /dev/null
@@ -1,286 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <vector> - -#include "base/scoped_multi_source_observation.h" -#include "base/test/bind.h" -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/power_bookmarks/power_bookmark_service_factory.h" -#include "chrome/browser/sync/test/integration/contact_info_helper.h" -#include "chrome/browser/sync/test/integration/status_change_checker.h" -#include "chrome/browser/sync/test/integration/sync_test.h" -#include "components/power_bookmarks/common/power.h" -#include "components/power_bookmarks/common/power_bookmark_observer.h" -#include "components/power_bookmarks/common/power_test_util.h" -#include "components/power_bookmarks/core/power_bookmark_features.h" -#include "components/power_bookmarks/core/power_bookmark_service.h" -#include "components/sync/base/features.h" -#include "components/sync/test/fake_server_http_post_provider.h" -#include "content/public/test/browser_test.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -using ::testing::ContainerEq; - -std::string PowerToString(const power_bookmarks::Power& power) { - sync_pb::PowerBookmarkSpecifics specifics; - power.ToPowerBookmarkSpecifics(&specifics); - return specifics.SerializeAsString(); -} - -std::vector<std::string> GetPowersForURLAsString( - GURL url, - power_bookmarks::PowerBookmarkService* service) { - base::RunLoop run_loop; - std::vector<std::string> result; - service->GetPowersForURL( - url, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK, - base::BindOnce( - [](base::RunLoop* run_loop, std::vector<std::string>* result, - std::vector<std::unique_ptr<power_bookmarks::Power>> powers) { - for (auto& power : powers) { - result->push_back(PowerToString(*power)); - } - run_loop->Quit(); - }, - &run_loop, &result)); - run_loop.Run(); - return result; -} - -// Helper class to wait until the two services match for the given `url`. -class PowerBookmarkChecker : public StatusChangeChecker, - public power_bookmarks::PowerBookmarkObserver { - public: - PowerBookmarkChecker(power_bookmarks::PowerBookmarkService* service0, - power_bookmarks::PowerBookmarkService* service1, - GURL url) - : service0_(service0), service1_(service1), url_(url) { - power_bookmark_service_obs_.AddObservation(service0_); - power_bookmark_service_obs_.AddObservation(service1_); - } - - // StatusChangeChecker implementation. - bool IsExitConditionSatisfied(std::ostream* os) override { - testing::StringMatchResultListener result_listener; - bool matches = - ExplainMatchResult(testing::UnorderedElementsAreArray(service0_data_), - service1_data_, &result_listener); - *os << result_listener.str(); - return matches; - } - - // power_bookmarks::PowerBookmarkObserver implementation. - void OnPowersChanged() override { - service0_data_ = GetPowersForURLAsString(url_, service0_); - service1_data_ = GetPowersForURLAsString(url_, service1_); - - CheckExitCondition(); - } - - private: - const raw_ptr<power_bookmarks::PowerBookmarkService> service0_; - const raw_ptr<power_bookmarks::PowerBookmarkService> service1_; - const GURL url_; - - base::ScopedMultiSourceObservation<power_bookmarks::PowerBookmarkService, - power_bookmarks::PowerBookmarkObserver> - power_bookmark_service_obs_{this}; - std::vector<std::string> service0_data_; - std::vector<std::string> service1_data_; -}; - -class TwoClientPowerBookmarksSyncTest : public SyncTest { - public: - const GURL kGoogleURL = GURL("https://google.com"); - TwoClientPowerBookmarksSyncTest() : SyncTest(TWO_CLIENT) { - features_.InitWithFeatures( - /*enabled_features=*/{power_bookmarks::kPowerBookmarkBackend}, - /*disabled_features=*/{}); - } - - void SetupServices() { - service0_ = GetSyncService(0); - service1_ = GetSyncService(1); - } - - protected: - raw_ptr<power_bookmarks::PowerBookmarkService, AcrossTasksDanglingUntriaged> - service0_; - raw_ptr<power_bookmarks::PowerBookmarkService, AcrossTasksDanglingUntriaged> - service1_; - - private: - power_bookmarks::PowerBookmarkService* GetSyncService(int index) { - return PowerBookmarkServiceFactory::GetForBrowserContext(GetProfile(index)); - } - - base::test::ScopedFeatureList features_; -}; - -bool CreatePower(std::unique_ptr<power_bookmarks::Power> power, - power_bookmarks::PowerBookmarkService* service) { - base::RunLoop run_loop; - bool result = false; - service->CreatePower(std::move(power), - base::BindLambdaForTesting([&](bool success) { - result = success; - run_loop.Quit(); - })); - run_loop.Run(); - return result; -} - -bool UpdatePower(std::unique_ptr<power_bookmarks::Power> power, - power_bookmarks::PowerBookmarkService* service) { - base::RunLoop run_loop; - bool result = false; - service->UpdatePower(std::move(power), - base::BindLambdaForTesting([&](bool success) { - result = success; - run_loop.Quit(); - })); - run_loop.Run(); - return result; -} - -bool DeletePower(base::Uuid guid, - power_bookmarks::PowerBookmarkService* service) { - base::RunLoop run_loop; - bool result = false; - service->DeletePower(guid, base::BindLambdaForTesting([&](bool success) { - result = success; - run_loop.Quit(); - })); - run_loop.Run(); - return result; -} - -bool DeletePowersForURL(GURL url, - power_bookmarks::PowerBookmarkService* service) { - base::RunLoop run_loop; - bool result = false; - service->DeletePowersForURL(url, - sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK, - base::BindLambdaForTesting([&](bool success) { - result = success; - run_loop.Quit(); - })); - run_loop.Run(); - return result; -} -void VerifyPowersForURL(GURL url, - power_bookmarks::PowerBookmarkService* service0, - power_bookmarks::PowerBookmarkService* service1) { - EXPECT_THAT(GetPowersForURLAsString(url, service0), - ContainerEq(GetPowersForURLAsString(url, service1))); -} - -// TODO(crbug.com/40285326): This fails with the field trial testing config. -class TwoClientPowerBookmarksSyncTestNoTestingConfig - : public TwoClientPowerBookmarksSyncTest { - public: - void SetUpCommandLine(base::CommandLine* command_line) override { - TwoClientPowerBookmarksSyncTest::SetUpCommandLine(command_line); - command_line->AppendSwitch("disable-field-trial-config"); - } -}; - -IN_PROC_BROWSER_TEST_F(TwoClientPowerBookmarksSyncTestNoTestingConfig, - AddOnePower) { - ASSERT_TRUE(SetupSync()); - SetupServices(); - - // service0 adds a new power. - auto power1 = power_bookmarks::MakePower( - kGoogleURL, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK); - EXPECT_TRUE(CreatePower(power1->Clone(), service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); -} - -IN_PROC_BROWSER_TEST_F(TwoClientPowerBookmarksSyncTest, - // TODO(crbug.com/40901832): Re-enable this test. - DISABLED_UpdateOnePower) { - ASSERT_TRUE(SetupSync()); - SetupServices(); - - // service0 adds a new power. - auto power1 = power_bookmarks::MakePower( - kGoogleURL, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK); - base::Time now = base::Time::Now(); - power1->set_time_modified(now); - EXPECT_TRUE(CreatePower(power1->Clone(), service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); - VerifyPowersForURL(kGoogleURL, service0_, service1_); - - // service1 updates an existing power. - power1->set_time_modified(now + base::Seconds(1)); - EXPECT_TRUE(UpdatePower(std::move(power1), service1_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); - VerifyPowersForURL(kGoogleURL, service0_, service1_); -} - -IN_PROC_BROWSER_TEST_F(TwoClientPowerBookmarksSyncTest, DeleteOnePower) { - ASSERT_TRUE(SetupSync()); - SetupServices(); - - // service0 adds a new power. - auto power1 = power_bookmarks::MakePower( - kGoogleURL, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK); - auto guid = power1->guid(); - EXPECT_TRUE(CreatePower(power1->Clone(), service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); - - // service0 deletes a power. - EXPECT_TRUE(DeletePower(guid, service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); -} - -IN_PROC_BROWSER_TEST_F(TwoClientPowerBookmarksSyncTestNoTestingConfig, - AddMultiplePowers) { - ASSERT_TRUE(SetupSync()); - SetupServices(); - - // service0 adds a power. - base::RunLoop run_loop1; - auto power1 = power_bookmarks::MakePower( - kGoogleURL, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK); - EXPECT_TRUE(CreatePower(std::move(power1), service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); - - // service0 adds another power. - base::RunLoop run_loop3; - auto power2 = power_bookmarks::MakePower( - kGoogleURL, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK); - EXPECT_TRUE(CreatePower(std::move(power2), service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); -} - -IN_PROC_BROWSER_TEST_F(TwoClientPowerBookmarksSyncTest, DeletePowersForURL) { - ASSERT_TRUE(SetupSync()); - SetupServices(); - - // service0 adds a power. - base::RunLoop run_loop1; - auto power1 = power_bookmarks::MakePower( - kGoogleURL, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK); - EXPECT_TRUE(CreatePower(std::move(power1), service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); - - // service0 adds another power. - base::RunLoop run_loop3; - auto power2 = power_bookmarks::MakePower( - kGoogleURL, sync_pb::PowerBookmarkSpecifics::POWER_TYPE_MOCK); - EXPECT_TRUE(CreatePower(std::move(power2), service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); - - // service0 deletes powers for URL. - EXPECT_TRUE(DeletePowersForURL(kGoogleURL, service0_)); - EXPECT_TRUE(PowerBookmarkChecker(service0_, service1_, kGoogleURL).Wait()); -} - -} // namespace
diff --git a/chrome/browser/ui/autofill/BUILD.gn b/chrome/browser/ui/autofill/BUILD.gn index 5ec8611..79770363 100644 --- a/chrome/browser/ui/autofill/BUILD.gn +++ b/chrome/browser/ui/autofill/BUILD.gn
@@ -22,8 +22,6 @@ "autofill_suggestion_controller.h", "autofill_suggestion_controller_utils.h", "bubble_controller_base.h", - "bubble_manager.h", - "bubble_manager_impl.h", "chrome_autofill_client.h", "next_idle_barrier.h", "popup_controller_common.h", @@ -84,6 +82,8 @@ "autofill_field_promo_controller_impl.h", "autofill_field_promo_view.h", "autofill_popup_controller_impl.h", + "bubble_manager.h", + "bubble_manager_impl.h", "delete_address_profile_dialog_controller.h", "delete_address_profile_dialog_controller_impl.h", "delete_address_profile_dialog_view.h", @@ -124,8 +124,6 @@ "autofill_popup_hide_helper.cc", "autofill_suggestion_controller.cc", "autofill_suggestion_controller_utils.cc", - "bubble_manager.cc", - "bubble_manager_impl.cc", "chrome_autofill_client.cc", "next_idle_barrier.cc", "popup_controller_common.cc", @@ -199,6 +197,8 @@ "autofill_context_menu_manager.cc", "autofill_field_promo_controller_impl.cc", "autofill_popup_controller_impl.cc", + "bubble_manager.cc", + "bubble_manager_impl.cc", "delete_address_profile_dialog_controller_impl.cc", "edit_address_profile_dialog_controller_impl.cc", "save_address_bubble_controller.cc", @@ -239,7 +239,6 @@ sources = [ "autofill_client_provider_unittest.cc", "autofill_suggestion_controller_unittest.cc", - "bubble_manager_impl_unittest.cc", "chrome_autofill_client_unittest.cc", ] @@ -313,6 +312,7 @@ "address_editor_controller_unittest.cc", "autofill_field_promo_controller_impl_unittest.cc", "autofill_popup_controller_impl_unittest.cc", + "bubble_manager_impl_unittest.cc", "save_address_bubble_controller_unittest.cc", "update_address_bubble_controller_unittest.cc", ]
diff --git a/chrome/browser/ui/autofill/address_bubbles_controller.cc b/chrome/browser/ui/autofill/address_bubbles_controller.cc index 0845c3f..9f0dff7 100644 --- a/chrome/browser/ui/autofill/address_bubbles_controller.cc +++ b/chrome/browser/ui/autofill/address_bubbles_controller.cc
@@ -162,7 +162,7 @@ if (decision == AutofillClient::AddressPromptUserDecision::kEditDeclined) { // Reopen this bubble if the user canceled editing. shown_by_user_gesture_ = false; - ShowBubble(); + QueueOrShowBubble(/*force_show=*/true); return; } if (address_profile_save_prompt_callback_) { @@ -196,7 +196,7 @@ return; } shown_by_user_gesture_ = true; - ShowBubble(); + QueueOrShowBubble(/*force_show=*/true); } bool AddressBubblesController::IsBubbleActive() const {
diff --git a/chrome/browser/ui/autofill/address_bubbles_controller_interactive_uitest.cc b/chrome/browser/ui/autofill/address_bubbles_controller_interactive_uitest.cc index 5d8c527..67f68cc 100644 --- a/chrome/browser/ui/autofill/address_bubbles_controller_interactive_uitest.cc +++ b/chrome/browser/ui/autofill/address_bubbles_controller_interactive_uitest.cc
@@ -293,6 +293,9 @@ AutofillClient::AddressPromptUserDecision::kAccepted)); } +// TODO(crbug.com/356845298): Add a test for combining the `kAccountNameEmail` +// profile with one of the `kAccountHome`/`kAccountWork` profiles. + INSTANTIATE_TEST_SUITE_P(AllAutofillAddressStates, SaveAddressProfileTest, ::testing::Bool(),
diff --git a/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc b/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc index 505c6d3..12c097b 100644 --- a/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc +++ b/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc
@@ -61,12 +61,14 @@ if (IsShowingBubble()) { bubble_view_->Hide(); bubble_view_ = nullptr; +#if !BUILDFLAG(IS_ANDROID) if (base::FeatureList::IsEnabled( features::kAutofillShowBubblesBasedOnPriorities)) { if (auto* manager = BubbleManager::GetForWebContents(web_contents())) { manager->OnBubbleHiddenByController(*this); } } +#endif // !BUILDFLAG(IS_ANDROID) } }
diff --git a/chrome/browser/ui/autofill/bubble_manager.cc b/chrome/browser/ui/autofill/bubble_manager.cc index e5da61ab2..4cb69c68 100644 --- a/chrome/browser/ui/autofill/bubble_manager.cc +++ b/chrome/browser/ui/autofill/bubble_manager.cc
@@ -25,7 +25,7 @@ CHECK(base::FeatureList::IsEnabled( autofill::features::kAutofillShowBubblesBasedOnPriorities)); tabs::TabInterface* const tab_interface = - tabs::TabInterface::GetFromContents(web_contents); + tabs::TabInterface::MaybeGetFromContents(web_contents); if (!tab_interface) { return nullptr; }
diff --git a/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc b/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc index e79533b..4e51e29 100644 --- a/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc
@@ -15,7 +15,6 @@ #include "components/autofill/core/browser/data_manager/personal_data_manager.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/strings/grit/components_strings.h" -#include "components/sync/base/features.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" #include "ui/base/l10n/l10n_util.h" @@ -81,13 +80,10 @@ PersonalDataManager* pdm = PersonalDataManagerFactory::GetForBrowserContext( web_contents_->GetBrowserContext()); - const bool is_syncing = - base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) - ? pdm->address_data_manager().IsAutofillUserSelectableTypeEnabled() - : pdm->address_data_manager().IsSyncFeatureEnabledForAutofill(); return l10n_util::GetStringUTF16( - is_syncing ? IDS_AUTOFILL_DELETE_SYNC_ADDRESS_RECORD_TYPE_NOTICE - : IDS_AUTOFILL_DELETE_LOCAL_ADDRESS_RECORD_TYPE_NOTICE); + pdm->address_data_manager().IsSyncFeatureEnabledForAutofill() + ? IDS_AUTOFILL_DELETE_SYNC_ADDRESS_RECORD_TYPE_NOTICE + : IDS_AUTOFILL_DELETE_LOCAL_ADDRESS_RECORD_TYPE_NOTICE); } void DeleteAddressProfileDialogControllerImpl::OnAccepted() {
diff --git a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc index f12926b..f9762bd 100644 --- a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc
@@ -125,7 +125,7 @@ CHECK(current_bubble_type_ == IbanBubbleType::kManageSavedIban || current_bubble_type_ == IbanBubbleType::kUploadInProgress); } - ShowBubble(); + QueueOrShowBubble(/*force_show=*/true); } void IbanBubbleControllerImpl::ShowConfirmationBubbleView(
diff --git a/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc index bf9bc458..4fcb0a67 100644 --- a/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc
@@ -179,7 +179,7 @@ is_user_gesture_ = true; - ShowBubble(); + QueueOrShowBubble(/*force_show=*/true); } void OfferNotificationBubbleControllerImpl::DismissNotification() {
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_interactive_uitest.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_interactive_uitest.cc index 6057104..d9bc522 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_interactive_uitest.cc +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_interactive_uitest.cc
@@ -9,11 +9,13 @@ #include "base/memory/raw_ptr.h" #include "base/test/with_feature_override.h" #include "base/values.h" +#include "chrome/browser/ui/autofill/autofill_bubble_base.h" #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/autofill/payments/save_card_ui.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/test/test_browser_dialog.h" +#include "chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" @@ -24,6 +26,7 @@ #include "components/autofill/core/common/autofill_features.h" #include "content/public/test/browser_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/test/widget_test.h" namespace autofill { @@ -201,18 +204,26 @@ // Tests that opening a new tab will hide the save card bubble. IN_PROC_BROWSER_TEST_P(SaveCardBubbleControllerImplTest, NewTabHidesDialog) { - if (GetParam()) { - // TODO(crbug.com/432429605): Investigate. - GTEST_SKIP() << "The test is flaky."; - } ShowUi("LocalSave"); - EXPECT_NE(nullptr, controller()->GetPaymentBubbleView()); + AutofillBubbleBase* bubble_base = controller()->GetPaymentBubbleView(); + ASSERT_NE(nullptr, bubble_base); + + SaveCardBubbleViews* bubble_view = + static_cast<SaveCardBubbleViews*>(bubble_base); + + // Create a waiter that will return once the bubble's widget is destroyed. + views::test::WidgetDestroyedWaiter waiter(bubble_view->GetWidget()); + // Open a new tab page in the foreground. ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(chrome::kChromeUINewTabURL), WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB | ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + + // Wait until the bubble is actually gone. + waiter.Wait(); + EXPECT_EQ(nullptr, controller()->GetPaymentBubbleView()); }
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc index bbe213b0..3c17c8b 100644 --- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
@@ -87,7 +87,7 @@ } is_user_gesture_ = true; - ShowBubble(); + QueueOrShowBubble(/*force_show=*/true); } void VirtualCardEnrollBubbleControllerImpl::ShowConfirmationBubbleView(
diff --git a/chrome/browser/ui/autofill/save_address_bubble_controller.cc b/chrome/browser/ui/autofill/save_address_bubble_controller.cc index b7b71a70..eca34dc 100644 --- a/chrome/browser/ui/autofill/save_address_bubble_controller.cc +++ b/chrome/browser/ui/autofill/save_address_bubble_controller.cc
@@ -25,7 +25,6 @@ #include "components/autofill/core/browser/ui/addresses/autofill_address_util.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/strings/grit/components_strings.h" -#include "components/sync/base/features.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/image_model.h" #include "ui/base/resource/resource_bundle.h" @@ -56,6 +55,9 @@ return IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE; case autofill::AutofillClient::SaveAddressBubbleType::kMigrateToAccount: return IDS_AUTOFILL_ACCOUNT_MIGRATE_ADDRESS_PROMPT_TITLE; + case autofill::AutofillClient::SaveAddressBubbleType:: + kHomeWorkNameEmailMerge: + return IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_PROMPT_TITLE; } }()); } @@ -96,11 +98,7 @@ GetPrimaryAccountInfoFromBrowserContext( web_contents()->GetBrowserContext()); - const bool is_syncing = - base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) - ? pdm.address_data_manager().IsAutofillUserSelectableTypeEnabled() - : pdm.address_data_manager().IsSyncFeatureEnabledForAutofill(); - int string_id = is_syncing + int string_id = pdm.address_data_manager().IsSyncFeatureEnabledForAutofill() ? IDS_AUTOFILL_SYNCABLE_PROFILE_MIGRATION_PROMPT_NOTICE : IDS_AUTOFILL_LOCAL_PROFILE_MIGRATION_PROMPT_NOTICE; @@ -170,6 +168,22 @@ return IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_SAVE; case autofill::AutofillClient::SaveAddressBubbleType::kMigrateToAccount: return IDS_AUTOFILL_MIGRATE_ADDRESS_DIALOG_OK_BUTTON_LABEL_SAVE; + case autofill::AutofillClient::SaveAddressBubbleType:: + kHomeWorkNameEmailMerge: + return IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_OK_BUTTON_LABEL; + } + }()); +} + +std::u16string SaveAddressBubbleController::GetNegativeButtonLabel() const { + return l10n_util::GetStringUTF16([this] { + switch (save_address_bubble_type_) { + case AutofillClient::SaveAddressBubbleType::kSave: + case autofill::AutofillClient::SaveAddressBubbleType::kMigrateToAccount: + return IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL; + case autofill::AutofillClient::SaveAddressBubbleType:: + kHomeWorkNameEmailMerge: + return IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_CANCEL_BUTTON_LABEL; } }()); }
diff --git a/chrome/browser/ui/autofill/save_address_bubble_controller.h b/chrome/browser/ui/autofill/save_address_bubble_controller.h index 7729243..7ea4bd7 100644 --- a/chrome/browser/ui/autofill/save_address_bubble_controller.h +++ b/chrome/browser/ui/autofill/save_address_bubble_controller.h
@@ -45,6 +45,7 @@ virtual std::u16string GetProfileEmail() const; virtual std::u16string GetProfilePhone() const; virtual std::u16string GetOkButtonLabel() const; + std::u16string GetNegativeButtonLabel() const; const AutofillProfile& GetAutofillProfile() const { return address_profile_; } // The value returned by the cancel button callback depends on whether
diff --git a/chrome/browser/ui/autofill/save_address_bubble_controller_unittest.cc b/chrome/browser/ui/autofill/save_address_bubble_controller_unittest.cc index fb9a3576..f0787151 100644 --- a/chrome/browser/ui/autofill/save_address_bubble_controller_unittest.cc +++ b/chrome/browser/ui/autofill/save_address_bubble_controller_unittest.cc
@@ -16,9 +16,11 @@ #include "chrome/browser/ui/autofill/chrome_autofill_client.h" #include "chrome/test/base/testing_profile.h" #include "components/application_locale_storage/application_locale_storage.h" +#include "components/autofill/core/browser/data_model/addresses/autofill_profile.h" #include "components/autofill/core/browser/data_model/addresses/autofill_profile_test_api.h" #include "components/autofill/core/browser/foundations/autofill_client.h" #include "components/autofill/core/browser/test_utils/autofill_test_utils.h" +#include "components/autofill/core/browser/test_utils/test_profiles.h" #include "components/autofill/core/browser/ui/addresses/autofill_address_util.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_contents.h" @@ -186,5 +188,46 @@ EXPECT_TRUE(controller->GetFooterMessage().empty()); } +TEST_F(SaveAddressBubbleControllerTest, CombiningAccountsTypes) { + const AutofillProfile merged_profile = test::SupersetProfileOf( + {test::AccountNameEmailProfile(), + test::OnlyAddressProfile(AutofillProfile::RecordType::kAccountHome)}, + app_locale(), AutofillProfile::RecordType::kAccount); + std::unique_ptr<SaveAddressBubbleController> controller = CreateController( + merged_profile, + AutofillClient::SaveAddressBubbleType::kHomeWorkNameEmailMerge); + + EXPECT_EQ( + controller->GetWindowTitle(), + l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_PROMPT_TITLE)); + EXPECT_EQ( + controller->GetOkButtonLabel(), + l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_OK_BUTTON_LABEL)); + EXPECT_EQ( + controller->GetNegativeButtonLabel(), + l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_CANCEL_BUTTON_LABEL)); + EXPECT_EQ(controller->GetFooterMessage(), + l10n_util::GetStringFUTF16( + IDS_AUTOFILL_SAVE_IN_ACCOUNT_PROMPT_ADDRESS_SOURCE_NOTICE, + base::UTF8ToUTF16(GetPrimaryAccountInfoFromBrowserContext( + web_contents()->GetBrowserContext()) + ->email))); + EXPECT_NE(controller->GetHeaderImages(), std::nullopt); + EXPECT_TRUE(controller->GetBodyText().empty()); + + EXPECT_EQ(controller->GetAddressSummary(), + GetEnvelopeStyleAddress(merged_profile, app_locale(), + /*include_recipient=*/true, + /*include_country=*/true)); + EXPECT_EQ(controller->GetProfileEmail(), + merged_profile.GetInfo(EMAIL_ADDRESS, app_locale())); + + EXPECT_EQ(controller->GetCancelCallbackValue(), + AutofillClient::AddressPromptUserDecision::kDeclined); +} + } // namespace } // namespace autofill
diff --git a/chrome/browser/ui/color/material_chrome_color_mixer.cc b/chrome/browser/ui/color/material_chrome_color_mixer.cc index fc6e9126..f0e430f 100644 --- a/chrome/browser/ui/color/material_chrome_color_mixer.cc +++ b/chrome/browser/ui/color/material_chrome_color_mixer.cc
@@ -36,12 +36,9 @@ mixer[kColorAppMenuHighlightSeverityMedium] = {kColorAppMenuHighlightDefault}; mixer[kColorAppMenuHighlightSeverityHigh] = {kColorAppMenuHighlightDefault}; - if (base::FeatureList::IsEnabled( - features::kEnableAppMenuButtonColorsForDefaultAvatarButtonStates)) { - mixer[kColorAvatarButtonHighlightDefaultForeground] = { - kColorAppMenuExpandedForegroundDefault}; - mixer[kColorAvatarButtonHighlightDefault] = {kColorAppMenuHighlightDefault}; - } + mixer[kColorAvatarButtonHighlightDefaultForeground] = { + kColorAppMenuExpandedForegroundDefault}; + mixer[kColorAvatarButtonHighlightDefault] = {kColorAppMenuHighlightDefault}; mixer[kColorAvatarButtonHighlightManagementForeground] = { kColorAvatarButtonHighlightDefaultForeground}; @@ -281,12 +278,6 @@ ui::kColorSysOnTonalContainer}; mixer[kColorAppMenuChipInkDropHover] = {ui::kColorSysStateHoverOnSubtle}; mixer[kColorAppMenuChipInkDropRipple] = {ui::kColorSysStateRipplePrimary}; - if (!base::FeatureList::IsEnabled( - features::kEnableAppMenuButtonColorsForDefaultAvatarButtonStates)) { - mixer[kColorAvatarButtonHighlightDefault] = {ui::kColorSysTonalContainer}; - mixer[kColorAvatarButtonHighlightDefaultForeground] = { - ui::kColorSysOnTonalContainer}; - } mixer[kColorAvatarButtonHighlightSyncPaused] = { kColorAvatarButtonHighlightDefault}; mixer[kColorAvatarButtonHighlightSigninPaused] = {
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index 4098e3c..4341c2d 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -1279,7 +1279,6 @@ PasswordBubbleViewBase::CloseCurrentBubble(); // This will detach any existing bubble so OnBubbleHidden() isn't called. weak_ptr_factory_.InvalidateWeakPtrs(); - passwords_action_item->SetIsShowingBubble(true); PasswordBubbleViewBase::ShowBubble( web_contents(), LocationBarBubbleDelegateView::AUTOMATIC); // If the bubble appeared then the status is updated in OnBubbleShown().
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index 96b5572..ca148364 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -454,10 +454,6 @@ "ManagedProfileRequiredInterstitial", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kEnableAppMenuButtonColorsForDefaultAvatarButtonStates, - "EnableAppMenuButtonColorsForDefaultAvatarButtonStates", - base::FEATURE_ENABLED_BY_DEFAULT); - // Enables a web-based tab strip. See https://crbug.com/989131. Note this // feature only works when the ENABLE_WEBUI_TAB_STRIP buildflag is enabled. BASE_FEATURE(kWebUITabStrip,
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h index c9ed380..baec751 100644 --- a/chrome/browser/ui/ui_features.h +++ b/chrome/browser/ui/ui_features.h
@@ -311,10 +311,6 @@ BASE_DECLARE_FEATURE(kEnterpriseManagementDisclaimerUsesCustomLabel); BASE_DECLARE_FEATURE(kManagedProfileRequiredInterstitial); -// Enables using the same colors used for the default app menu button for the -// avatar button states using default colors. -BASE_DECLARE_FEATURE(kEnableAppMenuButtonColorsForDefaultAvatarButtonStates); - BASE_DECLARE_FEATURE(kWebUITabStrip); // Controls whether the context menu is shown on a touch press or a touch
diff --git a/chrome/browser/ui/views/autofill/save_address_profile_view.cc b/chrome/browser/ui/views/autofill/save_address_profile_view.cc index 33c2622..a029a29 100644 --- a/chrome/browser/ui/views/autofill/save_address_profile_view.cc +++ b/chrome/browser/ui/views/autofill/save_address_profile_view.cc
@@ -135,9 +135,7 @@ SetTitle(controller_->GetWindowTitle()); SetButtonLabel(ui::mojom::DialogButton::kOk, controller_->GetOkButtonLabel()); SetButtonLabel(ui::mojom::DialogButton::kCancel, - l10n_util::GetStringUTF16( - IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL)); - + controller_->GetNegativeButtonLabel()); SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, gfx::Insets(), views::LayoutProvider::Get()->GetDistanceMetric(
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index e48bf44..d771c499 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -2112,7 +2112,7 @@ overflow_button_->SetImageModel( views::Button::STATE_DISABLED, ui::GetDefaultDisabledIconFromImageModel(overflow_button_icon, - GetColorProvider())); + color_provider)); // Redraw the background. SchedulePaint();
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc index 4c107cba..85cd708c 100644 --- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc +++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -351,11 +351,7 @@ } bool AvatarToolbarButton::ShouldBlendHighlightColor() const { - if (base::FeatureList::IsEnabled( - features::kEnableAppMenuButtonColorsForDefaultAvatarButtonStates)) { - return false; - } - return GetWidget() && GetWidget()->GetCustomTheme(); + return false; } base::ScopedClosureRunner AvatarToolbarButton::SetExplicitButtonState( @@ -615,30 +611,10 @@ } SkColor AvatarToolbarButton::GetForegroundColor(ButtonState state) const { - if (base::FeatureList::IsEnabled( - features::kEnableAppMenuButtonColorsForDefaultAvatarButtonStates)) { - if (IsLabelPresentAndVisible()) { - return GetHighlightTextColor().value_or(GetColorProvider()->GetColor( - kColorAvatarButtonHighlightDefaultForeground)); - } - } else { - const bool has_custom_theme = - this->GetWidget() && this->GetWidget()->GetCustomTheme(); - - // If there is a custom theme use the `ToolbarButton` version of - // `GetForegroundColor()` This is to avoid creating new colorIds for icons - // for all the different states. With chrome refresh and without any custom - // theme, the color would be same as the label color. - if (!has_custom_theme && IsLabelPresentAndVisible()) { - const std::optional<SkColor> foreground_color = GetHighlightTextColor(); - const auto* const color_provider = GetColorProvider(); - return foreground_color.has_value() - ? foreground_color.value() - : color_provider->GetColor( - kColorAvatarButtonHighlightDefaultForeground); - } + if (IsLabelPresentAndVisible()) { + return GetHighlightTextColor().value_or(GetColorProvider()->GetColor( + kColorAvatarButtonHighlightDefaultForeground)); } - return ToolbarButton::GetForegroundColor(state); }
diff --git a/chrome/browser/ui/webui/signin/history_sync_optin_helper.cc b/chrome/browser/ui/webui/signin/history_sync_optin_helper.cc index 226e634..d60008b7 100644 --- a/chrome/browser/ui/webui/signin/history_sync_optin_helper.cc +++ b/chrome/browser/ui/webui/signin/history_sync_optin_helper.cc
@@ -21,8 +21,8 @@ #include "chrome/browser/ui/webui/signin/managed_user_profile_notice_ui.h" #include "chrome/browser/ui/webui/signin/turn_sync_on_helper_policy_fetch_tracker.h" #include "components/signin/public/base/signin_switches.h" -#include "components/signin/public/identity_manager/account_capability_fetcher.h" #include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/account_state_fetcher.h" #include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/tribool.h" @@ -142,25 +142,25 @@ : profile_(profile), account_info_(account_info), delegate_(delegate), - is_managed_capability_fetcher_(std::make_unique<AccountCapabilityFetcher>( - identity_manager, - account_info, - /*get_capability_state_callback=*/ - base::BindRepeating( - &HistorySyncOptinHelper::AccountIsManagedCapability, - base::Unretained(this)), - /*on_capability_fetched_callback=*/ - base::BindOnce( - &HistorySyncOptinHelper::ResumeShowHistorySyncOptinScreenFlow, - base::Unretained(this)))) { + account_state_fetcher_( + std::make_unique<AccountStateFetcher>( + identity_manager, + account_info, + /*get_account_state_callback=*/ + base::BindRepeating(&HistorySyncOptinHelper::AccountIsManaged, + base::Unretained(this)), + /*on_account_info_fetched_callback=*/ + base::BindOnce(&HistorySyncOptinHelper:: + ResumeShowHistorySyncOptinScreenFlow, + base::Unretained(this)))) { CHECK(base::FeatureList::IsEnabled(switches::kEnableHistorySyncOptin)); CHECK(delegate); } -HistorySyncOptinHelper::~HistorySyncOptinHelper() {} +HistorySyncOptinHelper::~HistorySyncOptinHelper() = default; void HistorySyncOptinHelper::StartHistorySyncOptinFlow() { - is_managed_capability_fetcher_->FetchCapability(); + account_state_fetcher_->FetchAccountInfo(); } void HistorySyncOptinHelper::MaybeShowAccountManagementScreen( @@ -265,7 +265,7 @@ } } -signin::Tribool HistorySyncOptinHelper::AccountIsManagedCapability( +signin::Tribool HistorySyncOptinHelper::AccountIsManaged( const AccountInfo& account_info) { if (!account_info.IsEmpty()) { return account_info.IsManaged();
diff --git a/chrome/browser/ui/webui/signin/history_sync_optin_helper.h b/chrome/browser/ui/webui/signin/history_sync_optin_helper.h index 5c47a9f2..23d5d8e 100644 --- a/chrome/browser/ui/webui/signin/history_sync_optin_helper.h +++ b/chrome/browser/ui/webui/signin/history_sync_optin_helper.h
@@ -17,7 +17,7 @@ #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/tribool.h" -class AccountCapabilityFetcher; +class AccountStateFetcher; class Profile; class TurnSyncOnHelperPolicyFetchTracker; @@ -113,8 +113,8 @@ void StartHistorySyncOptinFlow(); - AccountCapabilityFetcher* GetAccountCapabilityFetcherForTesting() { - return is_managed_capability_fetcher_.get(); + AccountStateFetcher* GetAccountStateFetcherForTesting() { + return account_state_fetcher_.get(); } SyncServiceStartupStateObserver* @@ -134,14 +134,12 @@ // screen. void OnAccountManagementScreenClosed(signin::SigninChoice result); - signin::Tribool AccountIsManagedCapability(const AccountInfo& account_info); + signin::Tribool AccountIsManaged(const AccountInfo& account_info); raw_ptr<Profile> profile_; const AccountInfo account_info_; raw_ptr<Delegate> delegate_; - // TODO(crbug.com/434964019): Rename this class and instances as they do not - // track capabilities anymore. - std::unique_ptr<AccountCapabilityFetcher> is_managed_capability_fetcher_; + std::unique_ptr<AccountStateFetcher> account_state_fetcher_; std::unique_ptr<SyncServiceStartupStateObserver> sync_startup_state_observer_; std::unique_ptr<HistorySyncOptinPolicyHelper> policy_helper_;
diff --git a/chrome/browser/ui/webui/signin/history_sync_optin_helper_browsertest.cc b/chrome/browser/ui/webui/signin/history_sync_optin_helper_browsertest.cc index d8333da..c0f9001 100644 --- a/chrome/browser/ui/webui/signin/history_sync_optin_helper_browsertest.cc +++ b/chrome/browser/ui/webui/signin/history_sync_optin_helper_browsertest.cc
@@ -27,8 +27,7 @@ #include "components/policy/core/common/mock_policy_service.h" #include "components/policy/core/common/policy_service.h" #include "components/signin/public/base/signin_switches.h" -#include "components/signin/public/identity_manager/account_capabilities_test_mutator.h" -#include "components/signin/public/identity_manager/account_capability_fetcher.h" +#include "components/signin/public/identity_manager/account_state_fetcher.h" #include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/signin_constants.h" #include "components/signin/public/identity_manager/tribool.h" @@ -73,13 +72,9 @@ } // Updates the fields relating to the account management. - void UpdateManagedUserCapabilities(AccountInfo& account_info, - bool is_managed) { + void UpdateAccountManagementInfo(AccountInfo& account_info, bool is_managed) { account_info.hosted_domain = is_managed ? "example.com" : signin::constants::kNoHostedDomainFound; - AccountCapabilitiesTestMutator mutator(&account_info.capabilities); - mutator.set_is_subject_to_account_level_enterprise_policies(is_managed); - CHECK(account_info.IsValid()); identity_test_env()->UpdateAccountInfoForAccount(account_info); } @@ -115,7 +110,7 @@ IN_PROC_BROWSER_TEST_F( HistorySyncOptinHelperBrowserTest, - TriggersHistorySyncScreenWhenCapabilityFetchedForConsumerAccount) { + TriggersHistorySyncScreenWhenAccountInfoFetchedForConsumerAccount) { AccountInfo account_info = MakeAccountInfoAvailable(); MockHistorySyncOptinHelperDelegate delegate; @@ -126,12 +121,12 @@ &delegate); history_sync_optin_helper.StartHistorySyncOptinFlow(); - // This triggers the flopw that reaches the delegate's + // This triggers the flow that reaches the delegate's // `ShowHistorySyncOptinScreen`. - UpdateManagedUserCapabilities(account_info, /*is_managed=*/false); + UpdateAccountManagementInfo(account_info, /*is_managed=*/false); // Subsequent updates should have no impact. - UpdateManagedUserCapabilities(account_info, /*is_managed=*/false); + UpdateAccountManagementInfo(account_info, /*is_managed=*/false); } IN_PROC_BROWSER_TEST_F( @@ -157,11 +152,11 @@ // This triggers the flow that reaches the delegate's // `ShowAccountManagementScreen`. - UpdateManagedUserCapabilities(account_info, /*is_managed=*/true); + UpdateAccountManagementInfo(account_info, /*is_managed=*/true); run_loop.Run(); // Subsequent updates should have no impact on the flow. - UpdateManagedUserCapabilities(account_info, /*is_managed=*/true); + UpdateAccountManagementInfo(account_info, /*is_managed=*/true); } IN_PROC_BROWSER_TEST_F( @@ -188,16 +183,17 @@ // This triggers the flow that reaches the delegate's // `ShowAccountManagementScreen`. - UpdateManagedUserCapabilities(account_info, /*is_managed=*/true); + UpdateAccountManagementInfo(account_info, /*is_managed=*/true); run_loop.Run(); // Subsequent updates should have no impact on the flow. - UpdateManagedUserCapabilities(account_info, /*is_managed=*/true); + UpdateAccountManagementInfo(account_info, /*is_managed=*/true); + } IN_PROC_BROWSER_TEST_F( HistorySyncOptinHelperBrowserTest, - TriggersHistorySyncScreenWhenCapabilityFetchingTimesOut) { + TriggersHistorySyncScreenWhenAccountInfoFetchingTimesOut) { AccountInfo account_info = MakeAccountInfoAvailable(); MockHistorySyncOptinHelperDelegate delegate; @@ -210,11 +206,11 @@ testing::Mock::VerifyAndClearExpectations(&delegate); EXPECT_CALL(delegate, ShowHistorySyncOptinScreen).Times(1); - history_sync_optin_helper.GetAccountCapabilityFetcherForTesting() + history_sync_optin_helper.GetAccountStateFetcherForTesting() ->EnforceTimeoutReachedForTesting(); - // After the timeout is reached, capability updates should have no impact. - UpdateManagedUserCapabilities(account_info, /*is_managed=*/true); + // After the timeout is reached, account info updates should have no impact. + UpdateAccountManagementInfo(account_info, /*is_managed=*/true); } IN_PROC_BROWSER_TEST_F(HistorySyncOptinHelperBrowserTest, @@ -224,7 +220,7 @@ syncer::SyncService::TransportState::INITIALIZING); AccountInfo account_info = MakeAccountInfoAvailable(); - UpdateManagedUserCapabilities(account_info, /*is_managed=*/false); + UpdateAccountManagementInfo(account_info, /*is_managed=*/false); MockHistorySyncOptinHelperDelegate delegate; HistorySyncOptinHelper history_sync_optin_helper( @@ -253,7 +249,7 @@ GetTestSyncService()->SetAllowedByEnterprisePolicy(false); AccountInfo account_info = MakeAccountInfoAvailable(); - UpdateManagedUserCapabilities(account_info, /*is_managed=*/false); + UpdateAccountManagementInfo(account_info, /*is_managed=*/false); MockHistorySyncOptinHelperDelegate delegate; EXPECT_CALL(delegate, ShowHistorySyncOptinScreen).Times(0);
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 34dc15a9..fa72310 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1757043039-4d675340696881c942eb9a6e8a9c5c971675e876-b0cf5b741cc5a090be8cd305f2bf79b325d00e11.profdata +chrome-android64-main-1757056825-7365af6de451bfae61f9feedebb33096e13e4b61-3c0e69a6b174ecc818878661c484832be6ced999.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt index dc20833f..68d4aaf3 100644 --- a/chrome/build/android-desktop-x64.pgo.txt +++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@ -chrome-android-desktop-x64-main-1757030166-bb7bb71b05595fa399f768add14dca25eb122afc-c78541b0a6e2d1bf8507bf96eb5353fe182f32e4.profdata +chrome-android-desktop-x64-main-1757051972-3e7ae86352ddf7cd199a38055f947281e5ee2919-e68792d4fddce29c7940fa84c482b19b3693dfcf.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index b7b7f06..f205ab2 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1757030166-76ffb00448a6d14d2f30152ebad0de28961e4185-c78541b0a6e2d1bf8507bf96eb5353fe182f32e4.profdata +chrome-mac-main-1757051972-fe027bb3f56eeda0249d3e394b1b8a04f995a47f-e68792d4fddce29c7940fa84c482b19b3693dfcf.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 6c478228d..2a62582 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1757030166-cc56838c8ab4e0607cc9943e1dcdedca62198d4c-c78541b0a6e2d1bf8507bf96eb5353fe182f32e4.profdata +chrome-win32-main-1757051972-1a19d8a65bdbea6024b36be237f7e4f91ad538eb-e68792d4fddce29c7940fa84c482b19b3693dfcf.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 9aac958..3183432 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1757030166-69050754091825cdb598ef786f1ed4c634010f1b-c78541b0a6e2d1bf8507bf96eb5353fe182f32e4.profdata +chrome-win64-main-1757041177-7e09cde8210417f0e4766b41802afcd61cca0340-d79ad90592249a53a847b0abcd617183034ecbd5.profdata
diff --git a/chrome/gpu/browser_exposed_gpu_interfaces.cc b/chrome/gpu/browser_exposed_gpu_interfaces.cc index 1778daa..ac93923 100644 --- a/chrome/gpu/browser_exposed_gpu_interfaces.cc +++ b/chrome/gpu/browser_exposed_gpu_interfaces.cc
@@ -61,7 +61,7 @@ mojo::MakeSelfOwnedReceiver( std::make_unique<arc::GpuArcVideoEncodeAccelerator>( gpu::ArcSharedImageInterface::Create( - gpu_service->gpu_channel_manager()), + gpu_service->gpu_channel_manager(), gpu_service->main_runner()), gpu_preferences, gpu_workarounds), std::move(receiver)); }
diff --git a/chrome/test/data/accessibility/page_with_lazy_image.html b/chrome/test/data/accessibility/page_with_lazy_image.html new file mode 100644 index 0000000..acc9412 --- /dev/null +++ b/chrome/test/data/accessibility/page_with_lazy_image.html
@@ -0,0 +1,7 @@ +<html> + <body> + <img src="green.png"> + <div id="box" style="height: 4000px"></div> + <img loading="lazy" style="height:16px; width:16px" src="red.png"> + </body> +</html>
diff --git a/chrome/test/data/android/bookmarks/Valid_reading_list_entry.html b/chrome/test/data/android/bookmarks/Valid_reading_list_entry.html new file mode 100644 index 0000000..a920244 --- /dev/null +++ b/chrome/test/data/android/bookmarks/Valid_reading_list_entry.html
@@ -0,0 +1,6 @@ +<!DOCTYPE NETSCAPE-Bookmark-file-1> +<TITLE>Reading List</TITLE> +<H1>Reading List</H1> +<DL><p> + <DT><A HREF="https://www.chromium.org/">Chromium</A> +</DL><p> \ No newline at end of file
diff --git a/chrome/test/data/webui/extensions/extensions_browsertest.cc b/chrome/test/data/webui/extensions/extensions_browsertest.cc index 08bb89f8c..b9c8f1d 100644 --- a/chrome/test/data/webui/extensions/extensions_browsertest.cc +++ b/chrome/test/data/webui/extensions/extensions_browsertest.cc
@@ -570,8 +570,6 @@ RunTestCase("ItemListVisibility"); } -// TODO(crbug.com/439447730): Enable on desktop android. -#if BUILDFLAG(ENABLE_EXTENSIONS) IN_PROC_BROWSER_TEST_F( CrExtensionsManagerTestWithMultipleExtensionTypesInstalled, SplitItems) { @@ -620,7 +618,6 @@ InstallPrerequisites(); RunTestCase("ShowUnsupportedDeveloperExtensionDisabledToast"); } -#endif // BUILDFLAG(ENABLE_EXTENSIONS) class CrExtensionsManagerTestWithIdQueryParam : public ExtensionSettingsTestBase {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index be723ed..4a9d96b 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -16408.0.0-1071485 \ No newline at end of file +16408.0.0-1071498 \ No newline at end of file
diff --git a/chromeos/ash/components/emoji/gif_tenor_api_fetcher.cc b/chromeos/ash/components/emoji/gif_tenor_api_fetcher.cc index 30b3c63..f7c6e24 100644 --- a/chromeos/ash/components/emoji/gif_tenor_api_fetcher.cc +++ b/chromeos/ash/components/emoji/gif_tenor_api_fetcher.cc
@@ -13,11 +13,13 @@ #include "base/check_deref.h" #include "base/functional/bind.h" +#include "base/json/json_reader.h" #include "base/memory/scoped_refptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/time/time.h" #include "base/types/expected.h" +#include "base/types/optional_ref.h" #include "base/values.h" #include "base/version_info/channel.h" #include "chromeos/ash/components/channel/channel_info.h" @@ -114,19 +116,13 @@ } const base::Value::List* FindList( - data_decoder::DataDecoder::ValueOrError& result, - const std::string& key) { + base::optional_ref<const base::Value::Dict> result, + std::string_view key) { if (!result.has_value()) { return nullptr; } - const auto* response = result->GetIfDict(); - if (!response) { - return nullptr; - } - - const auto* list = response->FindList(key); - return list ? list : nullptr; + return result->FindList(key); } std::vector<tenor::mojom::GifResponsePtr> ParseGifs( @@ -251,7 +247,7 @@ } base::expected<std::vector<std::string>, GifTenorApiFetcher::Error> -ParseCategoriesResponse(data_decoder::DataDecoder::ValueOrError result) { +ParseCategoriesResponse(base::optional_ref<const base::Value::Dict> result) { const auto* tags = FindList(result, "tags"); if (!tags) { return base::unexpected(GifTenorApiFetcher::Error::kHttpError); @@ -277,19 +273,19 @@ base::expected<tenor::mojom::PaginatedGifResponsesPtr, GifTenorApiFetcher::Error> -ParsePaginatedGifsResponse(data_decoder::DataDecoder::ValueOrError result) { +ParsePaginatedGifsResponse(base::optional_ref<const base::Value::Dict> result) { const auto* gifs = FindList(result, "results"); if (!gifs) { return base::unexpected(GifTenorApiFetcher::Error::kHttpError); } - const auto* next = result->GetDict().FindString("next"); + const auto* next = result->FindString("next"); return base::ok(tenor::mojom::PaginatedGifResponses::New(next ? *next : "", ParseGifs(gifs))); } base::expected<std::vector<tenor::mojom::GifResponsePtr>, GifTenorApiFetcher::Error> -ParseGifsResponse(data_decoder::DataDecoder::ValueOrError result) { +ParseGifsResponse(base::optional_ref<const base::Value::Dict> result) { const auto* gifs = FindList(result, "results"); if (!gifs) { return base::unexpected(GifTenorApiFetcher::Error::kHttpError); @@ -321,40 +317,39 @@ GifTenorApiFetcher::GetCategoriesCallback callback, std::unique_ptr<EndpointFetcher> endpoint_fetcher, std::unique_ptr<EndpointResponse> response) { - if (response->http_status_code == net::HTTP_OK) { - data_decoder::DataDecoder::ParseJsonIsolated( - response->response, - base::BindOnce(ParseCategoriesResponse).Then(std::move(callback))); + if (response->http_status_code != net::HTTP_OK) { + std::move(callback).Run(base::unexpected(GetError(std::move(response)))); return; } - std::move(callback).Run(base::unexpected(GetError(std::move(response)))); + + std::move(callback).Run(ParseCategoriesResponse( + base::JSONReader::ReadDict(response->response, base::JSON_PARSE_RFC))); } -// `endpoint_fetcher` may be null. void TenorGifsApiResponseHandler( GifTenorApiFetcher::TenorGifsApiCallback callback, std::unique_ptr<EndpointFetcher> endpoint_fetcher, std::unique_ptr<EndpointResponse> response) { - if (response->http_status_code == net::HTTP_OK) { - data_decoder::DataDecoder::ParseJsonIsolated( - response->response, - base::BindOnce(ParsePaginatedGifsResponse).Then(std::move(callback))); + if (response->http_status_code != net::HTTP_OK) { + std::move(callback).Run(base::unexpected(GetError(std::move(response)))); return; } - std::move(callback).Run(base::unexpected(GetError(std::move(response)))); + + std::move(callback).Run(ParsePaginatedGifsResponse( + base::JSONReader::ReadDict(response->response, base::JSON_PARSE_RFC))); } void FetchGifsByIdsResponseHandler( GifTenorApiFetcher::GetGifsByIdsCallback callback, std::unique_ptr<EndpointFetcher> endpoint_fetcher, std::unique_ptr<EndpointResponse> response) { - if (response->http_status_code == net::HTTP_OK) { - data_decoder::DataDecoder::ParseJsonIsolated( - response->response, - base::BindOnce(ParseGifsResponse).Then(std::move(callback))); + if (response->http_status_code != net::HTTP_OK) { + std::move(callback).Run(base::unexpected(GetError(std::move(response)))); return; } - std::move(callback).Run(base::unexpected(GetError(std::move(response)))); + + std::move(callback).Run(ParseGifsResponse( + base::JSONReader::ReadDict(response->response, base::JSON_PARSE_RFC))); } } // namespace
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index f9fdfe9..4fd0ce5e 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -320,6 +320,8 @@ "form_processing/name_processing_util.h", "form_processing/optimization_guide_proto_util.cc", "form_processing/optimization_guide_proto_util.h", + "form_qualifiers.cc", + "form_qualifiers.h", "form_structure.cc", "form_structure.h", "form_structure_rationalization_engine.cc", @@ -1455,6 +1457,7 @@ "form_processing/label_processing_util_unittest.cc", "form_processing/name_processing_util_unittest.cc", "form_processing/optimization_guide_proto_util_unittest.cc", + "form_qualifiers_unittest.cc", "form_structure_rationalization_engine_unittest.cc", "form_structure_rationalizer_unittest.cc", "form_structure_sectioning_util_unittest.cc",
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc index 780836fb..b2e3034 100644 --- a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc +++ b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
@@ -20,6 +20,7 @@ #include "components/autofill/core/browser/data_model/addresses/autofill_profile.h" #include "components/autofill/core/browser/data_model/payments/credit_card.h" #include "components/autofill/core/browser/form_import/form_data_importer.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/foundations/autofill_client.h" #include "components/autofill/core/browser/metrics/autofill_metrics.h" @@ -200,7 +201,7 @@ // is available to use as a baseline. std::vector<const AutofillProfile*> profiles = client_->GetPersonalDataManager().address_data_manager().GetProfiles(); - if (observed_submission && form->IsAutofillable()) { + if (observed_submission && IsAutofillable(*form)) { AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission( profiles.size()); } @@ -233,7 +234,7 @@ } FormStructure::FormAssociations form_associations; - if (form->IsAutofillable()) { + if (IsAutofillable(*form)) { form_associations = client_->GetFormDataImporter()->GetFormAssociations( form->form_signature()); } @@ -398,21 +399,21 @@ // If the form is submitted, we don't need to send pending votes from blur // (un-focus) events. - if (submitted_form->ShouldRunHeuristics() || - submitted_form->ShouldRunHeuristicsForSingleFields() || - submitted_form->ShouldBeQueried()) { + if (ShouldRunHeuristics(*submitted_form) || + ShouldRunHeuristicsForSingleFields(*submitted_form) || + ShouldBeQueried(*submitted_form)) { autofill_metrics::LogQualityMetrics( *submitted_form, submitted_form->form_parsed_timestamp(), initial_interaction_timestamp, submission_timestamp, client_->GetFormInteractionsUkmLogger(), ukm_source_id, observed_submission); } - if (!submitted_form->ShouldBeUploaded()) { + if (!ShouldBeUploaded(*submitted_form)) { return; } if (autofill_metrics::ShouldRecordUkm() && - submitted_form->ShouldUploadUkm( - /*require_classified_field=*/true)) { + ShouldUploadUkm(*submitted_form, + /*require_classified_field=*/true)) { AutofillMetrics::LogAutofillFieldInfoAfterSubmission( client_->GetUkmRecorder(), ukm_source_id, *submitted_form, submission_timestamp);
diff --git a/components/autofill/core/browser/data_manager/addresses/address_data_manager.cc b/components/autofill/core/browser/data_manager/addresses/address_data_manager.cc index 80074cc..7b30e04 100644 --- a/components/autofill/core/browser/data_manager/addresses/address_data_manager.cc +++ b/components/autofill/core/browser/data_manager/addresses/address_data_manager.cc
@@ -608,6 +608,11 @@ } bool AddressDataManager::IsAutofillSyncToggleAvailable() const { + if (base::FeatureList::IsEnabled( + syncer::kReplaceSyncPromosWithSignInPromos)) { + return false; + } + if (!pref_service_->GetBoolean(::prefs::kExplicitBrowserSignin)) { return false; }
diff --git a/components/autofill/core/browser/data_manager/addresses/address_data_manager_unittest.cc b/components/autofill/core/browser/data_manager/addresses/address_data_manager_unittest.cc index 6fec4c3..859e1b90 100644 --- a/components/autofill/core/browser/data_manager/addresses/address_data_manager_unittest.cc +++ b/components/autofill/core/browser/data_manager/addresses/address_data_manager_unittest.cc
@@ -33,6 +33,7 @@ #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/strike_database/test_inmemory_strike_database.h" +#include "components/sync/base/features.h" #include "components/sync/service/sync_user_settings.h" #include "components/sync/test/test_sync_service.h" #include "components/webdata/common/web_database_service.h" @@ -1221,12 +1222,18 @@ /*hosted_domain=*/"", "Full Name", "Given Name", "en-US", /*picture_url=*/""); - prefs_->SetBoolean(::prefs::kExplicitBrowserSignin, true); - EXPECT_TRUE(address_data_manager().IsAutofillSyncToggleAvailable()); prefs_->SetBoolean(::prefs::kExplicitBrowserSignin, false); EXPECT_FALSE(address_data_manager().IsAutofillSyncToggleAvailable()); } + +TEST_F(AddressDataManagerTest, AutofillSyncToggleNotAvailableWithSigninPromos) { + base::test::ScopedFeatureList feature_list{ + syncer::kReplaceSyncPromosWithSignInPromos}; + + prefs_->SetBoolean(::prefs::kExplicitBrowserSignin, true); + EXPECT_FALSE(address_data_manager().IsAutofillSyncToggleAvailable()); +} #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) // Tests that any `kAccountNameEmail` is created on construction of
diff --git a/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc b/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc index 6b695b4..0b6b6ef3 100644 --- a/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc +++ b/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc
@@ -48,11 +48,12 @@ case AutofillProfileImportType::kConfirmableMergeAndSilentUpdate: case AutofillProfileImportType::kNameEmailSuperset: case AutofillProfileImportType::kHomeAndWorkSuperset: - case AutofillProfileImportType::kHomeWorkNameEmailMerge: return AutofillClient::SaveAddressBubbleType::kSave; case AutofillProfileImportType::kProfileMigration: case AutofillProfileImportType::kProfileMigrationAndSilentUpdate: return AutofillClient::SaveAddressBubbleType::kMigrateToAccount; + case AutofillProfileImportType::kHomeWorkNameEmailMerge: + return AutofillClient::SaveAddressBubbleType::kHomeWorkNameEmailMerge; // Those import types do not cause save/update/migrate/merge bubble to be // displayed. case AutofillProfileImportType::kDuplicateImport:
diff --git a/components/autofill/core/browser/form_parsing/determine_regex_types.cc b/components/autofill/core/browser/form_parsing/determine_regex_types.cc index 90039ef84..efee0e6 100644 --- a/components/autofill/core/browser/form_parsing/determine_regex_types.cc +++ b/components/autofill/core/browser/form_parsing/determine_regex_types.cc
@@ -12,6 +12,7 @@ #include "components/autofill/core/browser/country_type.h" #include "components/autofill/core/browser/form_parsing/field_candidates.h" #include "components/autofill/core/browser/form_parsing/form_field_parser.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/form_structure_rationalizer.h" #include "components/autofill/core/browser/form_structure_sectioning_util.h" @@ -36,10 +37,10 @@ FieldCandidatesMap field_type_map; auto form_field_data_vector = base::ToVector(form.fields(), &ToPointer); - if (form.ShouldRunHeuristics()) { + if (ShouldRunHeuristics(form)) { FormFieldParser::ParseFormFields(context, form_field_data_vector, field_type_map); - } else if (form.ShouldRunHeuristicsForSingleFields()) { + } else if (ShouldRunHeuristicsForSingleFields(form)) { FormFieldParser::ParseSingleFields(context, form_field_data_vector, field_type_map); FormFieldParser::ParseStandaloneCVCFields(context, form_field_data_vector,
diff --git a/components/autofill/core/browser/form_qualifiers.cc b/components/autofill/core/browser/form_qualifiers.cc new file mode 100644 index 0000000..59c533b --- /dev/null +++ b/components/autofill/core/browser/form_qualifiers.cc
@@ -0,0 +1,300 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/form_qualifiers.h" + +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/logging/log_manager.h" +#include "components/autofill/core/common/autofill_internals/log_message.h" +#include "components/autofill/core/common/autofill_internals/logging_scope.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" +#include "components/autofill/core/common/autofill_util.h" +#include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/form_field_data.h" +#include "third_party/abseil-cpp/absl/functional/overload.h" + +namespace autofill { + +namespace internal { + +namespace { + +// Returns true if the scheme given by |url| is one for which autofill is +// allowed to activate. By default this only returns true for HTTP and HTTPS. +bool HasAllowedScheme(const GURL& url) { + return url.SchemeIsHTTPOrHTTPS(); +} + +template <typename T> +concept IsForm = std::same_as<T, FormStructure> || std::same_as<T, FormData>; + +const GURL& url(const FormData& form) { + return form.url(); +} +const GURL& url(const FormStructure& form) { + return form.source_url(); +} + +const GURL& action(const FormData& form) { + return form.action(); +} +const GURL& action(const FormStructure& form) { + return form.target_url(); +} + +const std::vector<FormFieldData>& fields(const FormData& form) { + return form.fields(); +} +const std::vector<std::unique_ptr<AutofillField>>& fields( + const FormStructure& form) { + return form.fields(); +} + +// A field is active if it contributes to the form signature and it is are +// included in queries to the Autofill server. +auto is_active = absl::Overload{ + [](const FormFieldData& field) { + return !IsCheckable(field.check_status()); + }, + [](const std::unique_ptr<AutofillField>& field) { + return !IsCheckable(field->check_status()); + }, +}; + +auto has_autocomplete = absl::Overload{ + [](const FormFieldData& field) { + return field.parsed_autocomplete().has_value(); + }, + [](const std::unique_ptr<AutofillField>& field) { + return field->parsed_autocomplete().has_value(); + }, +}; + +auto is_password_field = absl::Overload{ + [](const FormFieldData& field) { + return field.form_control_type() == FormControlType::kInputPassword; + }, + [](const std::unique_ptr<AutofillField>& field) { + return field->form_control_type() == FormControlType::kInputPassword; + }, +}; + +auto is_select_element = absl::Overload{ + [](const FormFieldData& field) { return field.IsSelectElement(); }, + [](const std::unique_ptr<AutofillField>& field) { + return field->IsSelectElement(); + }, +}; + +// Returns true if at least `num` fields satisfy `p`. +// This is useful if `num` is significantly smaller than `fields.size()` because +// it may avoid iterating over all of `fields`. It's equivalent to +// `std::range::count_if(fields, [](auto& f) { p(*f); }) >= num`. +template <typename T, typename Predicate> + requires IsForm<T> +bool AtLeastNumFieldsSatisfy(const T& form, size_t num, Predicate p) { + for (auto& field : fields(form)) { + if (num == 0) { + break; + } + if constexpr (std::same_as<T, FormStructure>) { + if (std::invoke(p, *field)) { + --num; + } + } else { + if (std::invoke(p, field)) { + --num; + } + } + } + return num == 0; +} + +template <typename T> + requires IsForm<T> +bool ShouldBeParsed(const T& form, + ShouldBeParsedParams params, + LogManager* log_manager) { + // Exclude URLs not on the web via HTTP(S). + if (!HasAllowedScheme(url(form))) { + LOG_AF(log_manager) << LoggingScope::kAbortParsing + << LogMessage::kAbortParsingNotAllowedScheme << form; + return false; + } + + if (!AtLeastNumFieldsSatisfy(form, params.min_required_fields, is_active) && + (!AtLeastNumFieldsSatisfy( + form, params.required_fields_for_forms_with_only_password_fields, + is_active) || + !std::ranges::all_of(fields(form), is_password_field)) && + std::ranges::none_of(fields(form), has_autocomplete)) { + LOG_AF(log_manager) << LoggingScope::kAbortParsing + << LogMessage::kAbortParsingNotEnoughFields + << std::ranges::count_if(fields(form), is_active) + << form; + return false; + } + + // Rule out search forms. + if (MatchesRegex<kUrlSearchActionRe>( + base::UTF8ToUTF16(action(form).path_piece()))) { + LOG_AF(log_manager) << LoggingScope::kAbortParsing + << LogMessage::kAbortParsingUrlMatchesSearchRegex + << form; + return false; + } + + bool has_text_field = + std::ranges::any_of(fields(form), std::not_fn(is_select_element)); + if (!has_text_field) { + LOG_AF(log_manager) << LoggingScope::kAbortParsing + << LogMessage::kAbortParsingFormHasNoTextfield << form; + } + return has_text_field; +} + +template <typename T> + requires IsForm<T> +bool ShouldRunHeuristics(const T& form) { + return AtLeastNumFieldsSatisfy(form, kMinRequiredFieldsForHeuristics, + is_active) && + HasAllowedScheme(url(form)); +} + +template <typename T> + requires IsForm<T> +bool ShouldRunHeuristicsForSingleFields(const T& form) { + return AtLeastNumFieldsSatisfy(form, 1, is_active) && + HasAllowedScheme(url(form)); +} + +bool ShouldBeQueried(const FormStructure& form) { + return (AtLeastNumFieldsSatisfy(form, kMinRequiredFieldsForQuery, + is_active) || + std::ranges::any_of(fields(form), is_password_field)) && + ShouldBeParsed(form, {}, nullptr); +} + +bool ShouldBeUploaded(const FormStructure& form) { + return AtLeastNumFieldsSatisfy(form, kMinRequiredFieldsForUpload, + is_active) && + ShouldBeParsed(form, {}, nullptr); +} + +bool ShouldUploadUkm(const FormStructure& form, bool require_classified_field) { + if (!ShouldBeParsed(form, {}, nullptr)) { + return false; + } + + auto is_focusable_text_field = + [](const std::unique_ptr<AutofillField>& field) { + return field->IsTextInputElement() && field->IsFocusable(); + }; + + // Return true if the field is a visible text input field which has predicted + // types from heuristics or the server. + auto is_focusable_predicted_text_field = + [](const std::unique_ptr<AutofillField>& field) { + return field->IsTextInputElement() && field->IsFocusable() && + ((field->server_type() != NO_SERVER_DATA && + field->server_type() != UNKNOWN_TYPE) || + field->heuristic_type() != UNKNOWN_TYPE || + field->html_type() != HtmlFieldType::kUnspecified); + }; + + size_t num_text_fields = std::ranges::count_if( + fields(form), require_classified_field ? is_focusable_predicted_text_field + : is_focusable_text_field); + if (num_text_fields == 0) { + return false; + } + + // If the form contains a single text field and this contains the string + // "search" in its name/id/placeholder, the function return false and the form + // is not recorded into UKM. The form is considered a search box. + if (num_text_fields == 1) { + auto it = std::ranges::find_if(fields(form), + require_classified_field + ? is_focusable_predicted_text_field + : is_focusable_text_field); + if (base::ToLowerASCII((*it)->placeholder()).find(u"search") != + std::string::npos || + base::ToLowerASCII((*it)->name()).find(u"search") != + std::string::npos || + base::ToLowerASCII((*it)->label()).find(u"search") != + std::string::npos || + base::ToLowerASCII((*it)->aria_label()).find(u"search") != + std::string::npos) { + return false; + } + } + + return true; +} + +} // namespace + +} // namespace internal + +bool ShouldBeParsed(const FormData& form, LogManager* log_manager) { + return internal::ShouldBeParsed(form, {}, log_manager); +} + +bool ShouldBeParsed(const FormStructure& form, LogManager* log_manager) { + return internal::ShouldBeParsed(form, {}, log_manager); +} + +bool ShouldRunHeuristics(const FormData& form) { + return internal::ShouldRunHeuristics(form); +} + +bool ShouldRunHeuristics(const FormStructure& form) { + return internal::ShouldRunHeuristics(form); +} + +bool ShouldRunHeuristicsForSingleFields(const FormData& form) { + return internal::ShouldRunHeuristicsForSingleFields(form); +} + +bool ShouldRunHeuristicsForSingleFields(const FormStructure& form) { + return internal::ShouldRunHeuristicsForSingleFields(form); +} + +bool ShouldBeQueried(const FormStructure& form) { + return internal::ShouldBeQueried(form); +} + +bool ShouldBeUploaded(const FormStructure& form) { + return internal::ShouldBeUploaded(form); +} + +bool ShouldUploadUkm(const FormStructure& form, bool require_classified_field) { + return internal::ShouldUploadUkm(form, require_classified_field); +} + +bool IsAutofillable(const FormStructure& form) { + static constexpr size_t kMinRequiredFields = + std::min({kMinRequiredFieldsForHeuristics, kMinRequiredFieldsForQuery, + kMinRequiredFieldsForUpload}); + return internal::AtLeastNumFieldsSatisfy(form, kMinRequiredFields, + &AutofillField::IsFieldFillable) && + internal::ShouldBeParsed(form, {}, nullptr); +} + +bool ShouldBeParsedForTest(const FormData& form, // IN-TEST + ShouldBeParsedParams params, + LogManager* log_manager) { + return internal::ShouldBeParsed(form, params, log_manager); +} + +bool ShouldBeParsedForTest(const FormStructure& form, // IN-TEST + ShouldBeParsedParams params, + LogManager* log_manager) { + return internal::ShouldBeParsed(form, params, log_manager); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/form_qualifiers.h b/components/autofill/core/browser/form_qualifiers.h new file mode 100644 index 0000000..0ff9808 --- /dev/null +++ b/components/autofill/core/browser/form_qualifiers.h
@@ -0,0 +1,90 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_QUALIFIERS_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_QUALIFIERS_H_ + +#include <algorithm> +#include <cstddef> + +#include "components/autofill/core/common/autofill_constants.h" + +namespace autofill { + +// This file contains several functions that test properties of FormData and +// FormStructure. +// +// Since some functions exist for both FormData and FormStructure and their, +// this file contains both implementations. Otherwise, we'd have to maintain +// equivalent implementations in both classes. +// +// TODO(crbug.com/40232021): Simplify this redundancy when FormData and +// FormStructure have a formal relationship (like composition or inheritance). + +class FormData; +class FormStructure; +class LogManager; + +// Returns true if this form matches the structural requirements for Autofill. +[[nodiscard]] bool ShouldBeParsed(const FormData& form, + LogManager* log_manager); +[[nodiscard]] bool ShouldBeParsed(const FormStructure& form, + LogManager* log_manager); + +// Returns true if heuristic autofill type detection should be attempted for +// this form. +[[nodiscard]] bool ShouldRunHeuristics(const FormData& form); +[[nodiscard]] bool ShouldRunHeuristics(const FormStructure& form); + +// Returns true if autofill's heuristic field type detection should be attempted +// for this form given that `kMinRequiredFieldsForHeuristics` is not met. +[[nodiscard]] bool ShouldRunHeuristicsForSingleFields(const FormData& form); +[[nodiscard]] bool ShouldRunHeuristicsForSingleFields( + const FormStructure& form); + +// Returns true if we should query the crowd-sourcing server to determine this +// form's field types. If the form includes author-specified types, this will +// return false unless there are password fields in the form. If there are no +// password fields the assumption is that the author has expressed their intent +// and crowdsourced data should not be used to override this. Password fields +// are different because there is no way to specify password generation +// directly. +[[nodiscard]] bool ShouldBeQueried(const FormStructure& form); + +// Returns true if we should upload Autofill votes for this form to the +// crowd-sourcing server. It is not applied for Password Manager votes. +[[nodiscard]] bool ShouldBeUploaded(const FormStructure& form); + +// Returns whether the form is considered parseable and meets a couple of other +// requirements which makes uploading UKM data worthwhile. For example, the form +// should not be a search form, the forms should have at least one focusable +// input field with a type from heuristics or the server. +[[nodiscard]] bool ShouldUploadUkm(const FormStructure& form, + bool require_classified_field); + +// Runs a quick heuristic to rule out forms that are obviously not +// autofillable, like google/yahoo/msn search, etc. +[[nodiscard]] bool IsAutofillable(const FormStructure& form); + +// Production code only uses the default parameters. +// Exposed publicly for testing. Production code only uses the default values. +struct ShouldBeParsedParams { + size_t min_required_fields = + std::min({kMinRequiredFieldsForHeuristics, kMinRequiredFieldsForQuery, + kMinRequiredFieldsForUpload}); + size_t required_fields_for_forms_with_only_password_fields = + kRequiredFieldsForFormsWithOnlyPasswordFields; +}; + +// Variants of ShouldBeParsed() that additionally take ShouldBeParsedParams. +[[nodiscard]] bool ShouldBeParsedForTest(const FormData& form, // IN-TEST + ShouldBeParsedParams params, + LogManager* log_manager); +[[nodiscard]] bool ShouldBeParsedForTest(const FormStructure& form, // IN-TEST + ShouldBeParsedParams params, + LogManager* log_manager); + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_QUALIFIERS_H_
diff --git a/components/autofill/core/browser/form_qualifiers_unittest.cc b/components/autofill/core/browser/form_qualifiers_unittest.cc new file mode 100644 index 0000000..8901d6b9 --- /dev/null +++ b/components/autofill/core/browser/form_qualifiers_unittest.cc
@@ -0,0 +1,366 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/form_qualifiers.h" + +#include "components/autofill/core/browser/form_parsing/determine_regex_types.h" +#include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/form_structure_test_api.h" +#include "components/autofill/core/common/autofill_test_utils.h" +#include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/form_data_test_api.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace autofill { +namespace { + +class FormStructureShouldTest : public testing::Test { + public: + static bool ShouldBeParsed(const FormStructure& form, + ShouldBeParsedParams params = {}) { + const bool r = ShouldBeParsedForTest(form, params, nullptr); + CHECK_EQ(r, ShouldBeParsedForTest(form.ToFormData(), params, nullptr)) + << "ShouldBeParsed(FormStructure) and ShouldBeParsed(FormData) must be " + "equivalent"; + return r; + } + + static bool ShouldRunHeuristics(const FormStructure& form) { + const bool r = autofill::ShouldRunHeuristics(form); + CHECK_EQ(r, autofill::ShouldRunHeuristics(form.ToFormData())) + << "ShouldRunHeuristics(FormStructure) and " + "ShouldRunHeuristics(FormData) must be equivalent"; + return r; + } + + static bool FormIsAutofillable(const FormData& form) { + const RegexPredictions regex_predictions = DetermineRegexTypes( + GeoIpCountryCode(""), LanguageCode(""), form, nullptr); + FormStructure form_structure(form); + regex_predictions.ApplyTo(form_structure.fields()); + form_structure.RationalizeAndAssignSections(GeoIpCountryCode(""), + LanguageCode(""), nullptr); + return IsAutofillable(form_structure); + } + + private: + test::AutofillUnitTestEnvironment autofill_test_environment_; +}; + +class FormShouldBeParsedTest : public FormStructureShouldTest { + public: + FormShouldBeParsedTest() { + form_.set_url(GURL("http://www.foo.com/")); + form_structure_ = std::make_unique<FormStructure>(form_); + } + + ~FormShouldBeParsedTest() override = default; + + void SetAction(GURL action) { + form_.set_action(action); + form_structure_ = nullptr; + } + + void AddField(FormFieldData field) { + field.set_renderer_id(test::MakeFieldRendererId()); + test_api(form_).Append(std::move(field)); + form_structure_ = nullptr; + } + + void AddTextField() { + FormFieldData field; + field.set_form_control_type(FormControlType::kInputText); + AddField(field); + } + + FormStructure& form_structure() { + if (!form_structure_) { + form_structure_ = std::make_unique<FormStructure>(form_); + } + return *form_structure_.get(); + } + + private: + FormData form_; + std::unique_ptr<FormStructure> form_structure_; +}; + +// Empty forms should not be parsed. +TEST_F(FormShouldBeParsedTest, FalseIfNoFields) { + EXPECT_FALSE(ShouldBeParsed(form_structure())); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); +} + +// Forms with only checkable fields should not be parsed. +TEST_F(FormShouldBeParsedTest, IgnoresCheckableFields) { + // Start with a single checkable field. + { + FormFieldData field; + field.set_check_status(FormFieldData::CheckStatus::kCheckableButUnchecked); + field.set_form_control_type(FormControlType::kInputRadio); + AddField(field); + } + EXPECT_FALSE(ShouldBeParsed(form_structure())); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); + + // Add a second checkable field. + { + FormFieldData field; + field.set_check_status(FormFieldData::CheckStatus::kCheckableButUnchecked); + field.set_form_control_type(FormControlType::kInputCheckbox); + AddField(field); + } + EXPECT_FALSE(ShouldBeParsed(form_structure())); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); + + // Add one text field. + AddTextField(); + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); +} + +// Forms with at least one text field should be parsed. +TEST_F(FormShouldBeParsedTest, TrueIfOneTextField) { + AddTextField(); + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); + + AddTextField(); + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); +} + +// Forms that have only select fields should not be parsed. +TEST_F(FormShouldBeParsedTest, FalseIfOnlySelectField) { + { + FormFieldData field; + field.set_form_control_type(FormControlType::kSelectOne); + AddField(field); + } + EXPECT_FALSE(ShouldBeParsed(form_structure())); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); + + AddTextField(); + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); +} + +// Form whose action is a search URL should not be parsed. +TEST_F(FormShouldBeParsedTest, FalseIfSearchURL) { + AddTextField(); + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); + + // The target cannot include http(s)://*/search... + SetAction(GURL("http://google.com/search?q=hello")); + EXPECT_FALSE(ShouldBeParsed(form_structure())); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); + + // But search can be in the URL. + SetAction(GURL("http://search.com/?q=hello")); + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 1})); +} + +// Forms with two password fields and no other fields should be parsed. +TEST_F(FormShouldBeParsedTest, TrueIfOnlyPasswordFields) { + { + FormFieldData field; + field.set_form_control_type(FormControlType::kInputPassword); + AddField(field); + } + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed( + form_structure(), + {.min_required_fields = 2, + .required_fields_for_forms_with_only_password_fields = 1})); + EXPECT_FALSE(ShouldBeParsed( + form_structure(), + {.min_required_fields = 2, + .required_fields_for_forms_with_only_password_fields = 2})); + + { + FormFieldData field; + field.set_form_control_type(FormControlType::kInputPassword); + AddField(field); + } + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed( + form_structure(), + {.min_required_fields = 2, + .required_fields_for_forms_with_only_password_fields = 1})); + EXPECT_TRUE(ShouldBeParsed( + form_structure(), + {.min_required_fields = 2, + .required_fields_for_forms_with_only_password_fields = 2})); +} + +// Forms with at least one field with an autocomplete attribute should be +// parsed. +TEST_F(FormShouldBeParsedTest, TrueIfOneFieldHasAutocomplete) { + AddTextField(); + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); + EXPECT_FALSE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); + + { + FormFieldData field; + field.set_parsed_autocomplete(AutocompleteParsingResult{ + .section = "my-billing-section", .field_type = HtmlFieldType::kName}); + field.set_form_control_type(FormControlType::kInputText); + AddField(field); + } + EXPECT_TRUE(ShouldBeParsed(form_structure())); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); + EXPECT_TRUE(ShouldBeParsed(form_structure(), {.min_required_fields = 2})); +} + +TEST_F(FormStructureShouldTest, ShouldBeParsed_BadScheme) { + std::unique_ptr<FormStructure> form_structure; + FormData form; + form.set_fields( + {test::CreateTestFormField("Name", "name", "", + FormControlType::kInputText, "name"), + test::CreateTestFormField("Email", "email", "", + FormControlType::kInputText, "email"), + test::CreateTestFormField("Address", "address", "", + FormControlType::kInputText, + "address-line1")}); + + // Baseline, HTTP should work. + form.set_url(GURL("http://wwww.foo.com/myform")); + form_structure = std::make_unique<FormStructure>(form); + EXPECT_TRUE(ShouldBeParsed(*form_structure)); + EXPECT_TRUE(ShouldRunHeuristics(*form_structure)); + EXPECT_TRUE(ShouldBeQueried(*form_structure)); + EXPECT_TRUE(ShouldBeUploaded(*form_structure)); + + // Baseline, HTTPS should work. + form.set_url(GURL("https://wwww.foo.com/myform")); + form_structure = std::make_unique<FormStructure>(form); + EXPECT_TRUE(ShouldBeParsed(*form_structure)); + EXPECT_TRUE(ShouldRunHeuristics(*form_structure)); + EXPECT_TRUE(ShouldBeQueried(*form_structure)); + EXPECT_TRUE(ShouldBeUploaded(*form_structure)); + + // Chrome internal urls shouldn't be parsed. + form.set_url(GURL("chrome://settings")); + form_structure = std::make_unique<FormStructure>(form); + EXPECT_FALSE(ShouldBeParsed(*form_structure)); + EXPECT_FALSE(ShouldRunHeuristics(*form_structure)); + EXPECT_FALSE(ShouldBeQueried(*form_structure)); + EXPECT_FALSE(ShouldBeUploaded(*form_structure)); + + // FTP urls shouldn't be parsed. + form.set_url(GURL("ftp://ftp.foo.com/form.html")); + form_structure = std::make_unique<FormStructure>(form); + EXPECT_FALSE(ShouldBeParsed(*form_structure)); + EXPECT_FALSE(ShouldRunHeuristics(*form_structure)); + EXPECT_FALSE(ShouldBeQueried(*form_structure)); + EXPECT_FALSE(ShouldBeUploaded(*form_structure)); + + // Blob urls shouldn't be parsed. + form.set_url(GURL("blob://blob.foo.com/form.html")); + form_structure = std::make_unique<FormStructure>(form); + EXPECT_FALSE(ShouldBeParsed(*form_structure)); + EXPECT_FALSE(ShouldRunHeuristics(*form_structure)); + EXPECT_FALSE(ShouldBeQueried(*form_structure)); + EXPECT_FALSE(ShouldBeUploaded(*form_structure)); + + // About urls shouldn't be parsed. + form.set_url(GURL("about://about.foo.com/form.html")); + form_structure = std::make_unique<FormStructure>(form); + EXPECT_FALSE(ShouldBeParsed(*form_structure)); + EXPECT_FALSE(ShouldRunHeuristics(*form_structure)); + EXPECT_FALSE(ShouldBeQueried(*form_structure)); + EXPECT_FALSE(ShouldBeUploaded(*form_structure)); +} + +// Tests that ShouldBeParsed returns true for a form containing less than three +// fields if at least one has an autocomplete attribute. +TEST_F(FormStructureShouldTest, ShouldBeParsed_TwoFields_HasAutocomplete) { + std::unique_ptr<FormStructure> form_structure; + FormData form; + form.set_url(GURL("http://www.foo.com/")); + form.set_fields({test::CreateTestFormField( + "Name", "name", "", FormControlType::kInputText, "name"), + test::CreateTestFormField("Address", "Address", "", + FormControlType::kSelectOne, "")}); + form_structure = std::make_unique<FormStructure>(form); + EXPECT_TRUE(ShouldBeParsed(*form_structure)); +} + +TEST_F(FormStructureShouldTest, IsAutofillable) { + FormData form; + form.set_url(GURL("http://www.foo.com/")); + FormFieldData field; + + // Start with a username field. It should be picked up by the password but + // not by autofill. + field.set_label(u"username"); + field.set_name(u"username"); + field.set_form_control_type(FormControlType::kInputText); + field.set_renderer_id(test::MakeFieldRendererId()); + test_api(form).Append(field); + + // With min required fields enabled. + EXPECT_FALSE(FormIsAutofillable(form)); + + // Add a password field. The form should be picked up by the password but + // not by autofill. + field.set_label(u"password"); + field.set_name(u"password"); + field.set_form_control_type(FormControlType::kInputPassword); + field.set_renderer_id(test::MakeFieldRendererId()); + test_api(form).Append(field); + + EXPECT_FALSE(FormIsAutofillable(form)); + + // Add an auto-fillable fields. With just one auto-fillable field, this should + // be picked up by autofill only if there is no minimum field enforcement. + field.set_label(u"Full Name"); + field.set_name(u"fullname"); + field.set_form_control_type(FormControlType::kInputText); + field.set_renderer_id(test::MakeFieldRendererId()); + test_api(form).Append(field); + + EXPECT_FALSE(FormIsAutofillable(form)); + + // Add an auto-fillable fields. With just one auto-fillable field, this should + // be picked up by autofill only if there is no minimum field enforcement. + field.set_label(u"Address Line 1"); + field.set_name(u"address1"); + field.set_form_control_type(FormControlType::kInputText); + field.set_renderer_id(test::MakeFieldRendererId()); + test_api(form).Append(field); + + EXPECT_FALSE(FormIsAutofillable(form)); + + // We now have three auto-fillable fields. It's always autofillable. + field.set_label(u"Email"); + field.set_name(u"email"); + field.set_form_control_type(FormControlType::kInputEmail); + field.set_renderer_id(test::MakeFieldRendererId()); + test_api(form).Append(field); + + EXPECT_TRUE(FormIsAutofillable(form)); + + // The target cannot include http(s)://*/search... + form.set_action(GURL("http://google.com/search?q=hello")); + + EXPECT_FALSE(FormIsAutofillable(form)); + + // But search can be in the URL. + form.set_action(GURL("http://search.com/?q=hello")); + + EXPECT_TRUE(FormIsAutofillable(form)); +} + +} // namespace +} // namespace autofill
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index fe58ad0..58a09b4 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -89,12 +89,6 @@ namespace { -// Returns true if the scheme given by |url| is one for which autofill is -// allowed to activate. By default this only returns true for HTTP and HTTPS. -bool HasAllowedScheme(const GURL& url) { - return url.SchemeIsHTTPOrHTTPS(); -} - raw_ptr<const FormFieldData> to_form_field_data( const std::unique_ptr<AutofillField>& field) { return field.get(); @@ -129,36 +123,6 @@ return value ? "Yes" : "No"; } -bool has_autocomplete(const std::unique_ptr<AutofillField>& field) { - return field->parsed_autocomplete().has_value(); -} - -bool is_password_field(const std::unique_ptr<AutofillField>& field) { - return field->form_control_type() == FormControlType::kInputPassword; -} - -// A field is active if it contributes to the form signature and it is are -// included in queries to the Autofill server. -bool is_active(const FormFieldData& field) { - return !IsCheckable(field.check_status()); -} - -// Returns true if at least `num` fields satisfy `p`. -// This is useful if `num` is significantly smaller than `fields.size()` because -// it may avoid iterating over all of `fields`. It's equivalent to -// `std::range::count_if(fields, [](auto& f) { p(*f); }) >= num`. -template <typename Predicate> -bool AtLeastNumSatisfy(base::span<const std::unique_ptr<AutofillField>> fields, - size_t num, - Predicate p) { - for (auto it = fields.begin(); it != fields.end() && num > 0; ++it) { - if (std::invoke(p, **it)) { - --num; - } - } - return num == 0; -} - } // namespace FormStructure::FormStructure(const FormData& form) @@ -384,15 +348,6 @@ return base::NumberToString(form_signature().value()); } -bool FormStructure::IsAutofillable() const { - size_t min_required_fields = - std::min({kMinRequiredFieldsForHeuristics, kMinRequiredFieldsForQuery, - kMinRequiredFieldsForUpload}); - return AtLeastNumSatisfy(fields_, min_required_fields, - &AutofillField::IsFieldFillable) && - ShouldBeParsed(); -} - bool FormStructure::IsCompleteCreditCardForm( CreditCardFormCompleteness credit_card_form_completeness) const { FieldTypeSet all_cc_types = FieldTypeSet(fields_, [](const auto& field) { @@ -420,123 +375,6 @@ } } -bool FormStructure::ShouldBeParsed(ShouldBeParsedParams params, - LogManager* log_manager) const { - // Exclude URLs not on the web via HTTP(S). - if (!HasAllowedScheme(source_url_)) { - LOG_AF(log_manager) << LoggingScope::kAbortParsing - << LogMessage::kAbortParsingNotAllowedScheme << *this; - return false; - } - - if (!AtLeastNumSatisfy(fields(), params.min_required_fields, is_active) && - (!AtLeastNumSatisfy( - fields(), params.required_fields_for_forms_with_only_password_fields, - is_active) || - !std::ranges::all_of(fields_, is_password_field)) && - std::ranges::none_of(fields_, has_autocomplete)) { - LOG_AF(log_manager) << LoggingScope::kAbortParsing - << LogMessage::kAbortParsingNotEnoughFields - << std::ranges::count_if(fields_, - [](const auto& field) { - return is_active(*field); - }) - << *this; - return false; - } - - // Rule out search forms. - if (MatchesRegex<kUrlSearchActionRe>( - base::UTF8ToUTF16(target_url_.path_piece()))) { - LOG_AF(log_manager) << LoggingScope::kAbortParsing - << LogMessage::kAbortParsingUrlMatchesSearchRegex - << *this; - return false; - } - - bool has_text_field = std::ranges::any_of( - *this, [](const auto& field) { return !field->IsSelectElement(); }); - if (!has_text_field) { - LOG_AF(log_manager) << LoggingScope::kAbortParsing - << LogMessage::kAbortParsingFormHasNoTextfield << *this; - } - return has_text_field; -} - -bool FormStructure::ShouldRunHeuristics() const { - // Must be identical to FormData::ShouldRunHeuristics()! - return AtLeastNumSatisfy(fields(), kMinRequiredFieldsForHeuristics, - is_active) && - HasAllowedScheme(source_url_); -} - -bool FormStructure::ShouldRunHeuristicsForSingleFields() const { - // Must be identical to FormData::ShouldRunHeuristicsForSingleFields()! - return AtLeastNumSatisfy(fields(), 1, is_active) && - HasAllowedScheme(source_url_); -} - -bool FormStructure::ShouldBeQueried() const { - return (AtLeastNumSatisfy(fields(), kMinRequiredFieldsForQuery, is_active) || - std::ranges::any_of(fields_, is_password_field)) && - ShouldBeParsed(); -} - -bool FormStructure::ShouldBeUploaded() const { - return AtLeastNumSatisfy(fields(), kMinRequiredFieldsForUpload, is_active) && - ShouldBeParsed(); -} - -bool FormStructure::ShouldUploadUkm(bool require_classified_field) const { - if (!ShouldBeParsed()) { - return false; - } - - auto is_focusable_text_field = - [](const std::unique_ptr<AutofillField>& field) { - return field->IsTextInputElement() && field->IsFocusable(); - }; - - // Return true if the field is a visible text input field which has predicted - // types from heuristics or the server. - auto is_focusable_predicted_text_field = - [](const std::unique_ptr<AutofillField>& field) { - return field->IsTextInputElement() && field->IsFocusable() && - ((field->server_type() != NO_SERVER_DATA && - field->server_type() != UNKNOWN_TYPE) || - field->heuristic_type() != UNKNOWN_TYPE || - field->html_type() != HtmlFieldType::kUnspecified); - }; - - size_t num_text_fields = std::ranges::count_if( - fields(), require_classified_field ? is_focusable_predicted_text_field - : is_focusable_text_field); - if (num_text_fields == 0) { - return false; - } - - // If the form contains a single text field and this contains the string - // "search" in its name/id/placeholder, the function return false and the form - // is not recorded into UKM. The form is considered a search box. - if (num_text_fields == 1) { - auto it = std::ranges::find_if( - fields(), require_classified_field ? is_focusable_predicted_text_field - : is_focusable_text_field); - if (base::ToLowerASCII((*it)->placeholder()).find(u"search") != - std::string::npos || - base::ToLowerASCII((*it)->name()).find(u"search") != - std::string::npos || - base::ToLowerASCII((*it)->label()).find(u"search") != - std::string::npos || - base::ToLowerASCII((*it)->aria_label()).find(u"search") != - std::string::npos) { - return false; - } - } - - return true; -} - void FormStructure::RetrieveFromCache(const FormStructure& cached_form, RetrieveFromCacheReason reason) { // Build a table to lookup AutofillFields by their FieldGlobalId.
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index 2f2a5eb..255681f 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -91,10 +91,6 @@ // Return the form signature as string. std::string FormSignatureAsStr() const; - // Runs a quick heuristic to rule out forms that are obviously not - // auto-fillable, like google/yahoo/msn search, etc. - bool IsAutofillable() const; - // This enum defines two different states of completeness for a credit card // form, each used for a distinct purpose to check if the required credit card // fields exist. @@ -114,39 +110,6 @@ bool IsCompleteCreditCardForm( CreditCardFormCompleteness credit_card_form_completeness) const; - // Returns true if this form matches the structural requirements for Autofill. - [[nodiscard]] bool ShouldBeParsed(LogManager* log_manager = nullptr) const { - return ShouldBeParsed({}, log_manager); - } - - // Returns true if heuristic autofill type detection should be attempted for - // this form. - bool ShouldRunHeuristics() const; - - // Returns true if autofill's heuristic field type detection should be - // attempted for this form given that |kMinRequiredFieldsForHeuristics| is not - // met. - bool ShouldRunHeuristicsForSingleFields() const; - - // Returns true if we should query the crowd-sourcing server to determine this - // form's field types. If the form includes author-specified types, this will - // return false unless there are password fields in the form. If there are no - // password fields the assumption is that the author has expressed their - // intent and crowdsourced data should not be used to override this. Password - // fields are different because there is no way to specify password generation - // directly. - bool ShouldBeQueried() const; - - // Returns true if we should upload Autofill votes for this form to the - // crowd-sourcing server. It is not applied for Password Manager votes. - bool ShouldBeUploaded() const; - - // Returns whether the form is considered parseable and meets a couple of - // other requirements which makes uploading UKM data worthwhile. E.g. the - // form should not be a search form, the forms should have at least one - // focusable input field with a type from heuristics or the server. - bool ShouldUploadUkm(bool require_classified_field) const; - // This enum defines the behavior of RetrieveFromCache, which needs to adapt // to the reason for retrieving data from the cache. enum class RetrieveFromCacheReason { @@ -356,22 +319,9 @@ // `parsed_autocomplete` member. void SetFieldTypesFromAutocompleteAttribute(); - // Production code only uses the default parameters. - // Unit tests also test other parameters. - struct ShouldBeParsedParams { - size_t min_required_fields = - std::min({kMinRequiredFieldsForHeuristics, kMinRequiredFieldsForQuery, - kMinRequiredFieldsForUpload}); - size_t required_fields_for_forms_with_only_password_fields = - kRequiredFieldsForFormsWithOnlyPasswordFields; - }; - FormStructure(FormSignature form_signature, const std::vector<FieldSignature>& field_signatures); - [[nodiscard]] bool ShouldBeParsed(ShouldBeParsedParams params, - LogManager* log_manager = nullptr) const; - // Extracts the parseable field name by removing a common affix. void ExtractParseableFieldNames();
diff --git a/components/autofill/core/browser/form_structure_fuzzer.cc b/components/autofill/core/browser/form_structure_fuzzer.cc index 8f1e68c0..642457eca 100644 --- a/components/autofill/core/browser/form_structure_fuzzer.cc +++ b/components/autofill/core/browser/form_structure_fuzzer.cc
@@ -18,6 +18,7 @@ #include "base/path_service.h" #include "components/autofill/core/browser/country_type.h" #include "components/autofill/core/browser/form_parsing/determine_regex_types.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_data_fuzzed_producer.h" #include "components/autofill/core/common/form_field_data.h" @@ -81,17 +82,14 @@ form_structure.RationalizeAndAssignSections( GenerateGeoIpCountryCode(data_provider), LanguageCode(""), /*log_manager=*/nullptr); - std::ignore = form_structure.IsAutofillable(); + std::ignore = IsAutofillable(form_structure); std::ignore = form_structure.IsCompleteCreditCardForm( FormStructure::CreditCardFormCompleteness::kCompleteCreditCardForm); - std::ignore = form_structure.ShouldBeParsed(); - std::ignore = form_structure.ToFormData().ShouldRunHeuristics(); - std::ignore = form_structure.ShouldRunHeuristics(); - std::ignore = - form_structure.ToFormData().ShouldRunHeuristicsForSingleFields(); - std::ignore = form_structure.ShouldRunHeuristicsForSingleFields(); - std::ignore = form_structure.ShouldBeQueried(); - std::ignore = form_structure.ShouldBeUploaded(); + std::ignore = ShouldBeParsed(form_structure, /*log_manager=*/nullptr); + std::ignore = ShouldRunHeuristics(form_structure); + std::ignore = ShouldRunHeuristicsForSingleFields(form_structure); + std::ignore = ShouldBeQueried(form_structure); + std::ignore = ShouldBeUploaded(form_structure); return 0; }
diff --git a/components/autofill/core/browser/form_structure_test_api.h b/components/autofill/core/browser/form_structure_test_api.h index 2694fed..4976b8b 100644 --- a/components/autofill/core/browser/form_structure_test_api.h +++ b/components/autofill/core/browser/form_structure_test_api.h
@@ -19,8 +19,6 @@ // Exposes some testing operations for FormStructure. class FormStructureTestApi { public: - using ShouldBeParsedParams = FormStructure::ShouldBeParsedParams; - explicit FormStructureTestApi(FormStructure& form_structure) : form_structure_(form_structure) {} @@ -35,11 +33,6 @@ return *form_structure_->fields_.back(); } - [[nodiscard]] bool ShouldBeParsed(ShouldBeParsedParams params = {}, - LogManager* log_manager = nullptr) { - return form_structure_->ShouldBeParsed(params, log_manager); - } - // Set the heuristic and server types for each field. The `heuristic_types` // and `server_types` vectors must be aligned with the indices of the fields // in the form. For each field in `heuristic_types` there must be exactly one
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc index 55a633c..b9bf5e77 100644 --- a/components/autofill/core/browser/form_structure_unittest.cc +++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -20,7 +20,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "base/unguessable_token.h" #include "build/build_config.h" #include "components/autofill/core/browser/autofill_field.h" @@ -30,6 +29,7 @@ #include "components/autofill/core/browser/form_parsing/determine_regex_types.h" #include "components/autofill/core/browser/form_parsing/form_field_parser.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/browser/form_structure_test_api.h" #include "components/autofill/core/browser/heuristic_source.h" #include "components/autofill/core/browser/proto/api_v1.pb.h" @@ -79,20 +79,7 @@ return base::NumberToString(StrToHash64Bit(str)); } - protected: - bool FormIsAutofillable(const FormData& form) { - FormStructure form_structure(form); - const RegexPredictions regex_predictions = - DetermineRegexTypes(GeoIpCountryCode(""), LanguageCode(""), - form_structure.ToFormData(), nullptr); - regex_predictions.ApplyTo(form_structure.fields()); - form_structure.RationalizeAndAssignSections(GeoIpCountryCode(""), - LanguageCode(""), nullptr); - return form_structure.IsAutofillable(); - } - private: - base::test::ScopedFeatureList scoped_feature_list_; test::AutofillUnitTestEnvironment autofill_test_environment_; }; @@ -174,346 +161,6 @@ EXPECT_EQ(form.full_url(), form_structure.full_source_url()); } -TEST_F(FormStructureTestImpl, IsAutofillable) { - FormData form; - form.set_url(GURL("http://www.foo.com/")); - FormFieldData field; - - // Start with a username field. It should be picked up by the password but - // not by autofill. - field.set_label(u"username"); - field.set_name(u"username"); - field.set_form_control_type(FormControlType::kInputText); - field.set_renderer_id(test::MakeFieldRendererId()); - test_api(form).Append(field); - - // With min required fields enabled. - EXPECT_FALSE(FormIsAutofillable(form)); - - // Add a password field. The form should be picked up by the password but - // not by autofill. - field.set_label(u"password"); - field.set_name(u"password"); - field.set_form_control_type(FormControlType::kInputPassword); - field.set_renderer_id(test::MakeFieldRendererId()); - test_api(form).Append(field); - - EXPECT_FALSE(FormIsAutofillable(form)); - - // Add an auto-fillable fields. With just one auto-fillable field, this should - // be picked up by autofill only if there is no minimum field enforcement. - field.set_label(u"Full Name"); - field.set_name(u"fullname"); - field.set_form_control_type(FormControlType::kInputText); - field.set_renderer_id(test::MakeFieldRendererId()); - test_api(form).Append(field); - - EXPECT_FALSE(FormIsAutofillable(form)); - - // Add an auto-fillable fields. With just one auto-fillable field, this should - // be picked up by autofill only if there is no minimum field enforcement. - field.set_label(u"Address Line 1"); - field.set_name(u"address1"); - field.set_form_control_type(FormControlType::kInputText); - field.set_renderer_id(test::MakeFieldRendererId()); - test_api(form).Append(field); - - EXPECT_FALSE(FormIsAutofillable(form)); - - // We now have three auto-fillable fields. It's always autofillable. - field.set_label(u"Email"); - field.set_name(u"email"); - field.set_form_control_type(FormControlType::kInputEmail); - field.set_renderer_id(test::MakeFieldRendererId()); - test_api(form).Append(field); - - EXPECT_TRUE(FormIsAutofillable(form)); - - // The target cannot include http(s)://*/search... - form.set_action(GURL("http://google.com/search?q=hello")); - - EXPECT_FALSE(FormIsAutofillable(form)); - - // But search can be in the URL. - form.set_action(GURL("http://search.com/?q=hello")); - - EXPECT_TRUE(FormIsAutofillable(form)); -} - -class FormStructureTestImpl_ShouldBeParsed_Test : public FormStructureTestImpl { - public: - FormStructureTestImpl_ShouldBeParsed_Test() { - form_.set_url(GURL("http://www.foo.com/")); - form_structure_ = std::make_unique<FormStructure>(form_); - } - - ~FormStructureTestImpl_ShouldBeParsed_Test() override = default; - - void SetAction(GURL action) { - form_.set_action(action); - form_structure_ = nullptr; - } - - void AddField(FormFieldData field) { - field.set_renderer_id(test::MakeFieldRendererId()); - test_api(form_).Append(std::move(field)); - form_structure_ = nullptr; - } - - void AddTextField() { - FormFieldData field; - field.set_form_control_type(FormControlType::kInputText); - AddField(field); - } - - FormStructure& form_structure() { - if (!form_structure_) { - form_structure_ = std::make_unique<FormStructure>(form_); - } - return *form_structure_.get(); - } - - private: - FormData form_; - std::unique_ptr<FormStructure> form_structure_; -}; - -// Empty forms should not be parsed. -TEST_F(FormStructureTestImpl_ShouldBeParsed_Test, FalseIfNoFields) { - EXPECT_FALSE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); -} - -// Forms with only checkable fields should not be parsed. -TEST_F(FormStructureTestImpl_ShouldBeParsed_Test, IgnoresCheckableFields) { - // Start with a single checkable field. - { - FormFieldData field; - field.set_check_status(FormFieldData::CheckStatus::kCheckableButUnchecked); - field.set_form_control_type(FormControlType::kInputRadio); - AddField(field); - } - EXPECT_FALSE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); - - // Add a second checkable field. - { - FormFieldData field; - field.set_check_status(FormFieldData::CheckStatus::kCheckableButUnchecked); - field.set_form_control_type(FormControlType::kInputCheckbox); - AddField(field); - } - EXPECT_FALSE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); - - // Add one text field. - AddTextField(); - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); -} - -// Forms with at least one text field should be parsed. -TEST_F(FormStructureTestImpl_ShouldBeParsed_Test, TrueIfOneTextField) { - AddTextField(); - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); - - AddTextField(); - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); -} - -// Forms that have only select fields should not be parsed. -TEST_F(FormStructureTestImpl_ShouldBeParsed_Test, FalseIfOnlySelectField) { - { - FormFieldData field; - field.set_form_control_type(FormControlType::kSelectOne); - AddField(field); - } - EXPECT_FALSE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); - - AddTextField(); - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); -} - -// Form whose action is a search URL should not be parsed. -TEST_F(FormStructureTestImpl_ShouldBeParsed_Test, FalseIfSearchURL) { - AddTextField(); - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); - - // The target cannot include http(s)://*/search... - SetAction(GURL("http://google.com/search?q=hello")); - EXPECT_FALSE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); - - // But search can be in the URL. - SetAction(GURL("http://search.com/?q=hello")); - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 1})); -} - -// Forms with two password fields and no other fields should be parsed. -TEST_F(FormStructureTestImpl_ShouldBeParsed_Test, TrueIfOnlyPasswordFields) { - { - FormFieldData field; - field.set_form_control_type(FormControlType::kInputPassword); - AddField(field); - } - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()) - .ShouldBeParsed( - {.min_required_fields = 2, - .required_fields_for_forms_with_only_password_fields = 1})); - EXPECT_FALSE( - test_api(form_structure()) - .ShouldBeParsed( - {.min_required_fields = 2, - .required_fields_for_forms_with_only_password_fields = 2})); - - { - FormFieldData field; - field.set_form_control_type(FormControlType::kInputPassword); - AddField(field); - } - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()) - .ShouldBeParsed( - {.min_required_fields = 2, - .required_fields_for_forms_with_only_password_fields = 1})); - EXPECT_TRUE( - test_api(form_structure()) - .ShouldBeParsed( - {.min_required_fields = 2, - .required_fields_for_forms_with_only_password_fields = 2})); -} - -// Forms with at least one field with an autocomplete attribute should be -// parsed. -TEST_F(FormStructureTestImpl_ShouldBeParsed_Test, - TrueIfOneFieldHasAutocomplete) { - AddTextField(); - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); - EXPECT_FALSE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); - - { - FormFieldData field; - field.set_parsed_autocomplete(AutocompleteParsingResult{ - .section = "my-billing-section", .field_type = HtmlFieldType::kName}); - field.set_form_control_type(FormControlType::kInputText); - AddField(field); - } - EXPECT_TRUE(test_api(form_structure()).ShouldBeParsed()); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); - EXPECT_TRUE( - test_api(form_structure()).ShouldBeParsed({.min_required_fields = 2})); -} - -TEST_F(FormStructureTestImpl, ShouldBeParsed_BadScheme) { - std::unique_ptr<FormStructure> form_structure; - FormData form; - form.set_fields( - {CreateTestFormField("Name", "name", "", FormControlType::kInputText, - "name"), - CreateTestFormField("Email", "email", "", FormControlType::kInputText, - "email"), - CreateTestFormField("Address", "address", "", - FormControlType::kInputText, "address-line1")}); - - // Baseline, HTTP should work. - form.set_url(GURL("http://wwww.foo.com/myform")); - form_structure = std::make_unique<FormStructure>(form); - EXPECT_TRUE(form_structure->ShouldBeParsed()); - EXPECT_TRUE(form_structure->ToFormData().ShouldRunHeuristics()); - EXPECT_TRUE(form_structure->ShouldRunHeuristics()); - EXPECT_TRUE(form_structure->ShouldBeQueried()); - EXPECT_TRUE(form_structure->ShouldBeUploaded()); - - // Baseline, HTTPS should work. - form.set_url(GURL("https://wwww.foo.com/myform")); - form_structure = std::make_unique<FormStructure>(form); - EXPECT_TRUE(form_structure->ShouldBeParsed()); - EXPECT_TRUE(form_structure->ToFormData().ShouldRunHeuristics()); - EXPECT_TRUE(form_structure->ShouldRunHeuristics()); - EXPECT_TRUE(form_structure->ShouldBeQueried()); - EXPECT_TRUE(form_structure->ShouldBeUploaded()); - - // Chrome internal urls shouldn't be parsed. - form.set_url(GURL("chrome://settings")); - form_structure = std::make_unique<FormStructure>(form); - EXPECT_FALSE(form_structure->ShouldBeParsed()); - EXPECT_FALSE(form_structure->ToFormData().ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldBeQueried()); - EXPECT_FALSE(form_structure->ShouldBeUploaded()); - - // FTP urls shouldn't be parsed. - form.set_url(GURL("ftp://ftp.foo.com/form.html")); - form_structure = std::make_unique<FormStructure>(form); - EXPECT_FALSE(form_structure->ShouldBeParsed()); - EXPECT_FALSE(form_structure->ToFormData().ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldBeQueried()); - EXPECT_FALSE(form_structure->ShouldBeUploaded()); - - // Blob urls shouldn't be parsed. - form.set_url(GURL("blob://blob.foo.com/form.html")); - form_structure = std::make_unique<FormStructure>(form); - EXPECT_FALSE(form_structure->ShouldBeParsed()); - EXPECT_FALSE(form_structure->ToFormData().ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldBeQueried()); - EXPECT_FALSE(form_structure->ShouldBeUploaded()); - - // About urls shouldn't be parsed. - form.set_url(GURL("about://about.foo.com/form.html")); - form_structure = std::make_unique<FormStructure>(form); - EXPECT_FALSE(form_structure->ShouldBeParsed()); - EXPECT_FALSE(form_structure->ToFormData().ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldRunHeuristics()); - EXPECT_FALSE(form_structure->ShouldBeQueried()); - EXPECT_FALSE(form_structure->ShouldBeUploaded()); -} - -// Tests that ShouldBeParsed returns true for a form containing less than three -// fields if at least one has an autocomplete attribute. -TEST_F(FormStructureTestImpl, ShouldBeParsed_TwoFields_HasAutocomplete) { - std::unique_ptr<FormStructure> form_structure; - FormData form; - form.set_url(GURL("http://www.foo.com/")); - form.set_fields({CreateTestFormField("Name", "name", "", - FormControlType::kInputText, "name"), - CreateTestFormField("Address", "Address", "", - FormControlType::kSelectOne, "")}); - form_structure = std::make_unique<FormStructure>(form); - EXPECT_TRUE(form_structure->ShouldBeParsed()); -} - // Tests that ShouldBeParsed returns true for a form containing less than three // fields if at least one has an autocomplete attribute. TEST_F(FormStructureTestImpl, DetermineHeuristicTypes_AutocompleteFalse) { @@ -878,10 +525,9 @@ field.set_renderer_id(test::MakeFieldRendererId()); test_api(form).Append(field); - EXPECT_FALSE(FormStructure(form).ShouldRunHeuristics()); - EXPECT_FALSE(form.ShouldRunHeuristics()); + EXPECT_FALSE(ShouldRunHeuristics(FormStructure(form))); - EXPECT_TRUE(FormStructure(form).ShouldBeQueried()); + EXPECT_TRUE(ShouldBeQueried(FormStructure(form))); // Default configuration. { @@ -898,7 +544,7 @@ EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(1)->heuristic_type()); EXPECT_EQ(NO_SERVER_DATA, form_structure.field(0)->server_type()); EXPECT_EQ(NO_SERVER_DATA, form_structure.field(1)->server_type()); - EXPECT_FALSE(form_structure.IsAutofillable()); + EXPECT_FALSE(IsAutofillable(form_structure)); } } @@ -915,9 +561,8 @@ FormControlType::kInputText, "given-name"), CreateTestFormField("Last Name", "lastname", "", FormControlType::kInputText, "")}); - EXPECT_FALSE(FormStructure(form).ShouldRunHeuristics()); - EXPECT_FALSE(form.ShouldRunHeuristics()); - EXPECT_TRUE(FormStructure(form).ShouldBeQueried()); + EXPECT_FALSE(ShouldRunHeuristics(FormStructure(form))); + EXPECT_TRUE(ShouldBeQueried(FormStructure(form))); // As a side effect of parsing small forms, if any of the heuristics, query, // or upload minimums are disabled, we'll autofill fields with an @@ -938,7 +583,7 @@ EXPECT_EQ(NO_SERVER_DATA, form_structure.field(0)->server_type()); EXPECT_THAT(form_structure.field(0)->Type().GetTypes(), ElementsAre(NAME_FIRST)); - EXPECT_TRUE(form_structure.IsAutofillable()); + EXPECT_TRUE(IsAutofillable(form_structure)); } } @@ -956,8 +601,8 @@ field.set_renderer_id(test::MakeFieldRendererId()); test_api(form).Append(field); - EXPECT_TRUE(FormStructure(form).ShouldRunHeuristicsForSingleFields()); - EXPECT_TRUE(form.ShouldRunHeuristicsForSingleFields()); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(FormStructure(form))); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(form)); // Default configuration. { @@ -972,7 +617,7 @@ ASSERT_EQ(1U, AutofillCount(form_structure)); EXPECT_EQ(MERCHANT_PROMO_CODE, form_structure.field(0)->heuristic_type()); EXPECT_EQ(NO_SERVER_DATA, form_structure.field(0)->server_type()); - EXPECT_TRUE(form_structure.IsAutofillable()); + EXPECT_TRUE(IsAutofillable(form_structure)); } } @@ -1002,8 +647,8 @@ std::ranges::any_of(form_structure.fields(), [](const auto& field) { return field->form_control_type() == FormControlType::kInputPassword; })); - EXPECT_TRUE(form_structure.ShouldBeQueried()); - EXPECT_TRUE(form_structure.ShouldBeUploaded()); + EXPECT_TRUE(ShouldBeQueried(form_structure)); + EXPECT_TRUE(ShouldBeUploaded(form_structure)); } // Verify that we can correctly process a degenerate section listed in the @@ -1146,7 +791,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(10U, form_structure->field_count()); ASSERT_EQ(9U, AutofillCount(*form_structure)); @@ -1225,7 +870,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(7U, form_structure->field_count()); ASSERT_EQ(6U, AutofillCount(*form_structure)); @@ -1304,7 +949,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(8U, form_structure->field_count()); ASSERT_EQ(7U, AutofillCount(*form_structure)); @@ -1373,7 +1018,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(6U, form_structure->field_count()); ASSERT_EQ(5U, AutofillCount(*form_structure)); @@ -1446,7 +1091,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(7U, form_structure->field_count()); ASSERT_EQ(5U, AutofillCount(*form_structure)); @@ -1503,7 +1148,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(4U, form_structure->field_count()); ASSERT_EQ(4U, AutofillCount(*form_structure)); @@ -1606,7 +1251,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(4U, form_structure->field_count()); EXPECT_EQ(4U, AutofillCount(*form_structure)); @@ -1653,7 +1298,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(3U, form_structure->field_count()); ASSERT_EQ(3U, AutofillCount(*form_structure)); @@ -1695,7 +1340,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(3U, form_structure->field_count()); ASSERT_EQ(3U, AutofillCount(*form_structure)); @@ -1778,7 +1423,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(11U, form_structure->field_count()); ASSERT_EQ(11U, AutofillCount(*form_structure)); @@ -1837,7 +1482,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(4U, form_structure->field_count()); ASSERT_EQ(4U, AutofillCount(*form_structure)); @@ -1889,7 +1534,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); // Expect the correct number of fields. ASSERT_EQ(5U, form_structure->field_count()); @@ -1955,7 +1600,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); // Expect the correct number of fields. ASSERT_EQ(6U, form_structure->field_count()); @@ -2025,7 +1670,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); // Expect the correct number of fields. ASSERT_EQ(6U, form_structure->field_count()); @@ -2295,7 +1940,7 @@ field.set_renderer_id(test::MakeFieldRendererId()); test_api(form).Append(field); - EXPECT_FALSE(FormStructure(form).ShouldBeUploaded()); + EXPECT_FALSE(ShouldBeUploaded(FormStructure(form))); } @@ -2505,10 +2150,10 @@ // The form has too few fields; it should not run heuristics, falling back to // the single field parsing. - EXPECT_FALSE(FormStructure(form).ShouldRunHeuristics()); - EXPECT_FALSE(form.ShouldRunHeuristics()); - EXPECT_TRUE(FormStructure(form).ShouldRunHeuristicsForSingleFields()); - EXPECT_TRUE(form.ShouldRunHeuristicsForSingleFields()); + EXPECT_FALSE(ShouldRunHeuristics(FormStructure(form))); + EXPECT_FALSE(ShouldRunHeuristics(form)); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(FormStructure(form))); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(form)); { FormStructure form_structure(form); @@ -2521,7 +2166,7 @@ ASSERT_EQ(1U, form_structure.field_count()); ASSERT_EQ(1U, AutofillCount(form_structure)); EXPECT_EQ(EMAIL_ADDRESS, form_structure.field(0)->heuristic_type()); - EXPECT_TRUE(form_structure.IsAutofillable()); + EXPECT_TRUE(IsAutofillable(form_structure)); } } @@ -2533,10 +2178,10 @@ // The form has too few fields; it should not run heuristics, falling back to // the single field parsing. - EXPECT_FALSE(FormStructure(form).ShouldRunHeuristics()); - EXPECT_FALSE(form.ShouldRunHeuristics()); - EXPECT_TRUE(FormStructure(form).ShouldRunHeuristicsForSingleFields()); - EXPECT_TRUE(form.ShouldRunHeuristicsForSingleFields()); + EXPECT_FALSE(ShouldRunHeuristics(FormStructure(form))); + EXPECT_FALSE(ShouldRunHeuristics(form)); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(FormStructure(form))); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(form)); { FormStructure form_structure(form); @@ -2550,7 +2195,7 @@ ASSERT_EQ(1U, AutofillCount(form_structure)); EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(0)->heuristic_type()); EXPECT_EQ(EMAIL_ADDRESS, form_structure.field(1)->heuristic_type()); - EXPECT_TRUE(form_structure.IsAutofillable()); + EXPECT_TRUE(IsAutofillable(form_structure)); } } @@ -2563,10 +2208,10 @@ // The form has too few fields; it should not run heuristics, falling back to // the single field parsing. - EXPECT_FALSE(FormStructure(form).ShouldRunHeuristics()); - EXPECT_FALSE(form.ShouldRunHeuristics()); - EXPECT_TRUE(FormStructure(form).ShouldRunHeuristicsForSingleFields()); - EXPECT_TRUE(form.ShouldRunHeuristicsForSingleFields()); + EXPECT_FALSE(ShouldRunHeuristics(FormStructure(form))); + EXPECT_FALSE(ShouldRunHeuristics(form)); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(FormStructure(form))); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(form)); { FormStructure form_structure(form); @@ -2580,7 +2225,7 @@ ASSERT_EQ(1U, AutofillCount(form_structure)); EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(0)->heuristic_type()); EXPECT_EQ(EMAIL_ADDRESS, form_structure.field(1)->heuristic_type()); - EXPECT_TRUE(form_structure.IsAutofillable()); + EXPECT_TRUE(IsAutofillable(form_structure)); } } @@ -2593,10 +2238,10 @@ // The form has too few fields; it should not run heuristics, falling back to // the single field parsing. - EXPECT_FALSE(FormStructure(form).ShouldRunHeuristics()); - EXPECT_FALSE(form.ShouldRunHeuristics()); - EXPECT_TRUE(FormStructure(form).ShouldRunHeuristicsForSingleFields()); - EXPECT_TRUE(form.ShouldRunHeuristicsForSingleFields()); + EXPECT_FALSE(ShouldRunHeuristics(FormStructure(form))); + EXPECT_FALSE(ShouldRunHeuristics(form)); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(FormStructure(form))); + EXPECT_TRUE(ShouldRunHeuristicsForSingleFields(form)); { FormStructure form_structure(form); const RegexPredictions regex_predictions = @@ -2610,7 +2255,7 @@ // it should be autofillable when the feature is enabled. ASSERT_EQ(1U, AutofillCount(form_structure)); EXPECT_EQ(EMAIL_ADDRESS, form_structure.field(0)->heuristic_type()); - EXPECT_TRUE(form_structure.IsAutofillable()); + EXPECT_TRUE(IsAutofillable(form_structure)); } } @@ -2665,7 +2310,7 @@ regex_predictions.ApplyTo(form_structure->fields()); form_structure->RationalizeAndAssignSections(GeoIpCountryCode(""), LanguageCode(""), nullptr); - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); ASSERT_EQ(5U, form_structure->field_count()); ASSERT_EQ(5U, AutofillCount(*form_structure));
diff --git a/components/autofill/core/browser/foundations/autofill_client.h b/components/autofill/core/browser/foundations/autofill_client.h index cabc7033..d3d151a 100644 --- a/components/autofill/core/browser/foundations/autofill_client.h +++ b/components/autofill/core/browser/foundations/autofill_client.h
@@ -249,9 +249,15 @@ // Specifies the type of the address save prompt. enum class SaveAddressBubbleType { + // The standard "Save address" bubble. kSave = 0, + // An altered save bubble, that offers migrating a profile to the Google + // Account. kMigrateToAccount = 1, - kMaxValue = kMigrateToAccount + // A bubble offering to merge the `kAccountNameEmail` and + // `kAccountHome/kAccountName` profiles into a single profile. + kHomeWorkNameEmailMerge = 2, + kMaxValue = kHomeWorkNameEmailMerge }; // Callback to run when the user makes a decision on whether to save the
diff --git a/components/autofill/core/browser/foundations/autofill_manager.cc b/components/autofill/core/browser/foundations/autofill_manager.cc index be004f7..14f43027 100644 --- a/components/autofill/core/browser/foundations/autofill_manager.cc +++ b/components/autofill/core/browser/foundations/autofill_manager.cc
@@ -22,6 +22,7 @@ #include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.h" #include "components/autofill/core/browser/data_model/payments/credit_card.h" #include "components/autofill/core/browser/form_parsing/determine_regex_types.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/form_structure_sectioning_util.h" #include "components/autofill/core/browser/logging/log_manager.h" @@ -301,7 +302,7 @@ // Configure the query encoding for this form and add it to the appropriate // collection of forms: queryable vs non-queryable. - if (form_structure.ShouldBeQueried()) { + if (ShouldBeQueried(form_structure)) { queryable_forms.push_back(&form_structure); } @@ -588,7 +589,7 @@ } auto form_structure = std::make_unique<FormStructure>(form_data); - if (!form_structure->ShouldBeParsed(log_manager())) { + if (!ShouldBeParsed(*form_structure, log_manager())) { LogCurrentFieldTypes(*form_structure); continue; } @@ -622,14 +623,6 @@ parsed_forms.push_back(form_data); } - // Remove duplicates by their FormGlobalId. Otherwise, after moving the forms - // into `form_structures_`, duplicates may be destroyed and we'd end up with - // dangling pointers. - std::ranges::sort(form_structures, {}, &FormStructure::global_id); - auto repeated = - std::ranges::unique(form_structures, {}, &FormStructure::global_id); - form_structures.erase(repeated.begin(), repeated.end()); - ParseFormsAsyncCommon( std::move(form_structures), base::BindOnce( @@ -655,7 +648,7 @@ } auto form_structure = std::make_unique<FormStructure>(form_data); - if (!form_structure->ShouldBeParsed(log_manager())) { + if (!ShouldBeParsed(*form_structure, log_manager())) { LogCurrentFieldTypes(*form_structure); // For Autocomplete, events need to be handled even for forms that cannot be // parsed.
diff --git a/components/autofill/core/browser/foundations/browser_autofill_manager.cc b/components/autofill/core/browser/foundations/browser_autofill_manager.cc index cf4bb61..bf76f23 100644 --- a/components/autofill/core/browser/foundations/browser_autofill_manager.cc +++ b/components/autofill/core/browser/foundations/browser_autofill_manager.cc
@@ -91,6 +91,7 @@ #include "components/autofill/core/browser/filling/form_filler.h" #include "components/autofill/core/browser/filling/payments/field_filling_payments_util.h" #include "components/autofill/core/browser/form_import/form_data_importer.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/foundations/autofill_client.h" #include "components/autofill/core/browser/geo/phone_number_i18n.h" @@ -1115,7 +1116,9 @@ // Don't send suggestions or track forms that should not be parsed. const bool got_autofillable_form = - form_structure && form_structure->ShouldBeParsed() && autofill_field; + form_structure && + ShouldBeParsed(*form_structure, /*log_manager=*/nullptr) && + autofill_field; if (!ShouldShowSuggestionsForAutocompleteUnrecognizedFields(trigger_source) && got_autofillable_form && @@ -2653,7 +2656,7 @@ bool BrowserAutofillManager::ShouldUploadForm(const FormStructure& form) { return client().IsAutofillEnabled() && !client().IsOffTheRecord() && - form.ShouldBeUploaded(); + ShouldBeUploaded(form); } void BrowserAutofillManager:: @@ -3450,7 +3453,7 @@ // effort. bool should_upload_ukm = autofill_metrics::ShouldRecordUkm() && - form_structure.ShouldUploadUkm(/*require_classified_field=*/true); + ShouldUploadUkm(form_structure, /*require_classified_field=*/true); for (const auto& autofill_field : form_structure) { if (should_upload_ukm) { @@ -3483,8 +3486,8 @@ if (base::FeatureList::IsEnabled(features::kAutofillUKMExperimentalFields) && !metrics_->form_submitted_timestamp.is_null() && - form_structure.ShouldUploadUkm( - /*require_classified_field=*/false)) { + ShouldUploadUkm(form_structure, + /*require_classified_field=*/false)) { client() .GetFormInteractionsUkmLogger() .LogAutofillFormWithExperimentalFieldsCountAtFormRemove(
diff --git a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc index 7af37a2..db8d9c8 100644 --- a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc +++ b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc
@@ -17,6 +17,7 @@ #include "base/time/time.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/field_type_utils.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/foundations/autofill_client.h" #include "components/autofill/core/browser/foundations/autofill_driver.h" @@ -53,8 +54,7 @@ // applicable must not run heuristics normally (i.e., their field count is // below `kMinRequiredFieldsForHeuristics`), but must be eligible for single // field form heuristics. - if (form.ShouldRunHeuristics() || - !form.ShouldRunHeuristicsForSingleFields()) { + if (ShouldRunHeuristics(form) || !ShouldRunHeuristicsForSingleFields(form)) { return false; } // Having met the prerequisites, now determine if there's a field whose @@ -257,7 +257,7 @@ } // Log UKM metrics for only autofillable form events. - if (form.IsAutofillable()) { + if (IsAutofillable(form)) { client().GetFormInteractionsUkmLogger().LogFormEvent( driver().GetPageUkmSourceId(), event, GetFormTypesForLogging(form), form.form_parsed_timestamp());
diff --git a/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc b/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc index 7e8a1d39..ccf3b8f 100644 --- a/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc +++ b/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc
@@ -74,6 +74,14 @@ std::u16string text; }; +// Used to hold the relevant data for address on typing suggestions between +// fetching and generating phases of the suggestion generation. +struct AddressOnTypingSuggestionData { + std::u16string suggestion_text; + FieldType type; + std::string guid; +}; + Suggestion CreateUndoOrClearFormSuggestion() { #if BUILDFLAG(IS_IOS) std::u16string value = @@ -622,10 +630,7 @@ : SuggestionType::kAddressEntry; } -} // namespace - -// TODO(crbug.com/409962888): Handle address suggestions on typing. -std::vector<Suggestion> GetSuggestionsOnTypingForProfile( +std::vector<AddressOnTypingSuggestionData> GetAddressOnTypingSuggestionData( const AddressDataManager& address_data_manager, const std::u16string& field_contents) { // Get the profiles to suggest, which are already sorted by relevance. @@ -674,8 +679,8 @@ static constexpr FieldTypeSet kTypesWithLessRequiredMatchingCharacters = { ADDRESS_HOME_ZIP}; - std::vector<Suggestion> suggestions; std::set<std::u16string> suggestions_text; + std::vector<AddressOnTypingSuggestionData> suggestion_data; // The number of profiles that data will be derived from when generating // suggestions. static constexpr size_t kMaxNumberProfilesToUse = 2; @@ -728,15 +733,31 @@ // `ADDRESS_HOME_LINE1` and // `ADDRESS_HOME_STREET_ADDRESS` hold the same data. if (!suggestions_text.contains(suggestion_text)) { - suggestions.emplace_back(suggestion_text, - SuggestionType::kAddressEntryOnTyping); - suggestions.back().field_by_field_filling_type_used = type; - suggestions.back().payload = Suggestion::AutofillProfilePayload( - Suggestion::Guid(profile->guid())); + suggestion_data.push_back({suggestion_text, type, profile->guid()}); suggestions_text.insert(suggestion_text); } } } + + return suggestion_data; +} + +} // namespace + +// TODO(crbug.com/409962888): Handle address suggestions on typing. +std::vector<Suggestion> GetSuggestionsOnTypingForProfile( + const AddressDataManager& address_data_manager, + const std::u16string& field_contents) { + std::vector<Suggestion> suggestions; + + for (const AddressOnTypingSuggestionData& data : + GetAddressOnTypingSuggestionData(address_data_manager, field_contents)) { + suggestions.emplace_back(data.suggestion_text, + SuggestionType::kAddressEntryOnTyping); + suggestions.back().field_by_field_filling_type_used = data.type; + suggestions.back().payload = + Suggestion::AutofillProfilePayload(Suggestion::Guid(data.guid)); + } if (suggestions.size() > 0) { // TODO(crbug.com/381994105): Consider adding undo. std::ranges::move(GetAddressFooterSuggestions(/*is_autofilled=*/false),
diff --git a/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc b/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc index a593410..f214c22 100644 --- a/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc +++ b/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc
@@ -7,6 +7,7 @@ #include "base/containers/to_vector.h" #include "components/autofill/core/browser/country_type.h" #include "components/autofill/core/browser/form_parsing/determine_regex_types.h" +#include "components/autofill/core/browser/form_qualifiers.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/test_utils/autofill_test_utils.h" #include "components/autofill/core/common/autocomplete_parsing_util.h" @@ -234,16 +235,16 @@ } if (test_case.form_flags.is_autofillable) { - EXPECT_TRUE(form_structure->IsAutofillable()); + EXPECT_TRUE(IsAutofillable(*form_structure)); } if (test_case.form_flags.should_be_parsed) { - EXPECT_TRUE(form_structure->ShouldBeParsed()); + EXPECT_TRUE(ShouldBeParsed(*form_structure, /*log_manager=*/nullptr)); } if (test_case.form_flags.should_be_queried) { - EXPECT_TRUE(form_structure->ShouldBeQueried()); + EXPECT_TRUE(ShouldBeQueried(*form_structure)); } if (test_case.form_flags.should_be_uploaded) { - EXPECT_TRUE(form_structure->ShouldBeUploaded()); + EXPECT_TRUE(ShouldBeUploaded(*form_structure)); } if (test_case.form_flags.has_author_specified_types) { EXPECT_TRUE(
diff --git a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge.cc b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge.cc index 3c21107..2a307d30 100644 --- a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge.cc
@@ -57,19 +57,11 @@ } bool IsSyncWalletFlightReservationsEnabled() { -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) return base::FeatureList::IsEnabled(syncer::kSyncWalletFlightReservations); -#else - return false; -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) } bool IsSyncWalletVehicleRegistrationsEnabled() { -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) return base::FeatureList::IsEnabled(syncer::kSyncWalletVehicleRegistrations); -#else - return false; -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) } } // namespace
diff --git a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc index c05a221..7983da8 100644 --- a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc
@@ -103,14 +103,9 @@ public: // Creates the `bridge()` and mocks its `ValuablesTable`. void SetUp() override { - std::vector<base::test::FeatureRef> enabled_features = { - syncer::kSyncMoveValuablesToProfileDb -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - , - syncer::kSyncWalletVehicleRegistrations -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - }; - feature_list_.InitWithFeatures(enabled_features, /*disabled_features=*/{}); + feature_list_.InitWithFeatures({syncer::kSyncMoveValuablesToProfileDb, + syncer::kSyncWalletVehicleRegistrations}, + /*disabled_features=*/{}); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); db_.AddTable(&valuables_table_); db_.AddTable(&sync_metadata_table_); @@ -495,7 +490,6 @@ UnorderedElementsAre(local_vehicle)); } -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) // Tests that `GetAllDataForDebugging()` returns all vehicle registrations. TEST_F(ValuableSyncBridgeTest, GetAllDataForDebuggingForVehicleRegistrations) { EntityInstance local_vehicle = GetLocalVehicleEntityInstance( @@ -562,6 +556,5 @@ EXPECT_THAT(GetAllEntityInstancesFromTable(), UnorderedElementsAre(local_vehicle, new_wallet_vehicle)); } -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) } // namespace autofill
diff --git a/components/autofill/core/common/form_data.cc b/components/autofill/core/common/form_data.cc index df4c00c2..0bcd270 100644 --- a/components/autofill/core/common/form_data.cc +++ b/components/autofill/core/common/form_data.cc
@@ -75,34 +75,6 @@ << " FormData from pickle."; } -// Returns true if the scheme given by |url| is one for which autofill is -// allowed to activate. By default this only returns true for HTTP and HTTPS. -bool HasAllowedScheme(const GURL& url) { - return url.SchemeIsHTTPOrHTTPS(); -} - -// A field is active if it contributes to the form signature and it is are -// included in queries to the Autofill server. -bool is_active(const FormFieldData& field) { - return !IsCheckable(field.check_status()); -} - -// Returns true if at least `num` fields satisfy `p`. -// This is useful if `num` is significantly smaller than `fields.size()` because -// it may avoid iterating over all of `fields`. It's equivalent to -// `std::range::count_if(fields, [](auto& f) { p(*f); }) >= num`. -template <typename Predicate> -bool AtLeastNumSatisfy(base::span<const FormFieldData> fields, - size_t num, - Predicate p) { - for (auto it = fields.begin(); it != fields.end() && num > 0; ++it) { - if (std::invoke(p, *it)) { - --num; - } - } - return num == 0; -} - } // namespace FrameTokenWithPredecessor::FrameTokenWithPredecessor() = default; @@ -158,18 +130,6 @@ return fields_it != fields().end() ? &*fields_it : nullptr; } -bool FormData::ShouldRunHeuristics() const { - // Must be identical to FormStructure::ShouldRunHeuristics()! - return AtLeastNumSatisfy(fields(), kMinRequiredFieldsForHeuristics, - is_active) && - HasAllowedScheme(url()); -} - -bool FormData::ShouldRunHeuristicsForSingleFields() const { - // Must be identical to FormStructure::ShouldRunHeuristicsForSingleFields()! - return AtLeastNumSatisfy(fields(), 1, is_active) && HasAllowedScheme(url()); -} - bool FormHasNonEmptyPasswordField(const FormData& form) { for (const auto& field : form.fields()) { if (field.IsPasswordInputElement()) {
diff --git a/components/autofill/core/common/form_data.h b/components/autofill/core/common/form_data.h index 40c8cc5f..bf6031a3 100644 --- a/components/autofill/core/common/form_data.h +++ b/components/autofill/core/common/form_data.h
@@ -347,9 +347,6 @@ likely_contains_captcha_ = likely_contains_captcha; } - bool ShouldRunHeuristics() const; - bool ShouldRunHeuristicsForSingleFields() const; - private: friend class FormDataTestApi;
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 457d2a1..0a31811 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -668,6 +668,15 @@ <message name="IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL" desc="Label of the Cancel button in the prompt that offers the user to update an existing address."> No thanks </message> + <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_PROMPT_TITLE" desc="Title shown at the top of prompt that offers the user to save a new address which is a result of a merge between the AccountNameEmail and a Work/Home profile"> + Use this address in more places + </message> + <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_OK_BUTTON_LABEL" desc="Label of the save button shown in the prompt that offers the user to save a new address which is a result of a merge between the AccountNameEmail and a Work/Home profile"> + I'm in + </message> + <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_CANCEL_BUTTON_LABEL" desc="Label of the cancel button shown in the prompt that offers the user to save a new address which is a result of a merge between the AccountNameEmail and a Work/Home profile"> + Cancel + </message> <message name="IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_TITLE" desc="Title shown at the top of dialog that edits an address before saving it"> Edit address </message>
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_CANCEL_BUTTON_LABEL.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_CANCEL_BUTTON_LABEL.png.sha1 new file mode 100644 index 0000000..e92f0059 --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_CANCEL_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@ +8712b51cf5949b5bbc66350d43f60a7bfe17942b \ No newline at end of file
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_OK_BUTTON_LABEL.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_OK_BUTTON_LABEL.png.sha1 new file mode 100644 index 0000000..a92d00c --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_OK_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@ +aa93e77790917112402ee727d7985b2122147c68 \ No newline at end of file
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_PROMPT_TITLE.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_PROMPT_TITLE.png.sha1 new file mode 100644 index 0000000..f9141774 --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_NAME_EMAIL_HOME_WORK_MERGE_PROMPT_TITLE.png.sha1
@@ -0,0 +1 @@ +d7dbec9cfd6109020b7396b31e9ea5127c2d9b19 \ No newline at end of file
diff --git a/components/browser_sync/BUILD.gn b/components/browser_sync/BUILD.gn index 8c71e91..a8e2f149 100644 --- a/components/browser_sync/BUILD.gn +++ b/components/browser_sync/BUILD.gn
@@ -45,8 +45,6 @@ "//components/plus_addresses/core/browser/settings", "//components/plus_addresses/core/browser/sync_utils", "//components/plus_addresses/webdata", - "//components/power_bookmarks/core", - "//components/power_bookmarks/core:features", "//components/prefs", "//components/reading_list/core", "//components/saved_tab_groups/public",
diff --git a/components/browser_sync/DEPS b/components/browser_sync/DEPS index 637db42..46a30ba4 100644 --- a/components/browser_sync/DEPS +++ b/components/browser_sync/DEPS
@@ -15,7 +15,6 @@ "+components/keyed_service/core", "+components/password_manager/core/browser", "+components/plus_addresses", - "+components/power_bookmarks/core", "+components/prefs", "+components/reading_list/core", "+components/reading_list/features",
diff --git a/components/browser_sync/common_controller_builder.cc b/components/browser_sync/common_controller_builder.cc index 205b8eb..1e9bd92 100644 --- a/components/browser_sync/common_controller_builder.cc +++ b/components/browser_sync/common_controller_builder.cc
@@ -51,8 +51,6 @@ #include "components/plus_addresses/core/browser/settings/plus_address_setting_service.h" #include "components/plus_addresses/core/browser/sync_utils/plus_address_data_type_controller.h" #include "components/plus_addresses/webdata/plus_address_webdata_service.h" -#include "components/power_bookmarks/core/power_bookmark_features.h" -#include "components/power_bookmarks/core/power_bookmark_service.h" #include "components/prefs/pref_service.h" #include "components/reading_list/core/dual_reading_list_model.h" #include "components/reading_list/core/reading_list_local_data_batch_uploader.h" @@ -320,11 +318,6 @@ plus_address_webdata_service_.Set(plus_address_webdata_service); } -void CommonControllerBuilder::SetPowerBookmarkService( - power_bookmarks::PowerBookmarkService* power_bookmark_service) { - power_bookmark_service_.Set(power_bookmark_service); -} - void CommonControllerBuilder::SetPrefService(PrefService* pref_service) { pref_service_.Set(pref_service); } @@ -529,16 +522,6 @@ std::make_unique<sync_bookmarks::BookmarkLocalDataBatchUploader>( bookmark_model_.value(), pref_service_.value()))); } - - if (!disabled_types.Has(syncer::POWER_BOOKMARK) && - power_bookmark_service_.value() && - base::FeatureList::IsEnabled(power_bookmarks::kPowerBookmarkBackend)) { - // TODO(crbug.com/40261319): Support transport mode for POWER_BOOKMARK. - controllers.push_back(std::make_unique<DataTypeController>( - syncer::POWER_BOOKMARK, - power_bookmark_service_.value()->CreateSyncControllerDelegate(), - /*delegate_for_transport_mode=*/nullptr)); - } } if (!disabled_types.Has(syncer::HISTORY)) {
diff --git a/components/browser_sync/common_controller_builder.h b/components/browser_sync/common_controller_builder.h index 3fc83c9a..718f67d 100644 --- a/components/browser_sync/common_controller_builder.h +++ b/components/browser_sync/common_controller_builder.h
@@ -71,10 +71,6 @@ class PlusAddressWebDataService; } // namespace plus_addresses -namespace power_bookmarks { -class PowerBookmarkService; -} // namespace power_bookmarks - namespace reading_list { class DualReadingListModel; } // namespace reading_list @@ -187,8 +183,6 @@ plus_addresses::PlusAddressSettingService* plus_address_setting_service, const scoped_refptr<plus_addresses::PlusAddressWebDataService>& plus_address_webdata_service); - void SetPowerBookmarkService( - power_bookmarks::PowerBookmarkService* power_bookmark_service); void SetPrefService(PrefService* pref_service); void SetPrefServiceSyncable( sync_preferences::PrefServiceSyncable* pref_service_syncable); @@ -300,8 +294,6 @@ SafeOptional<raw_ptr<sync_bookmarks::BookmarkSyncService>> account_bookmark_sync_service_; SafeOptional<raw_ptr<bookmarks::BookmarkModel>> bookmark_model_; - SafeOptional<raw_ptr<power_bookmarks::PowerBookmarkService>> - power_bookmark_service_; SafeOptional<raw_ptr<supervised_user::SupervisedUserSettingsService>> supervised_user_settings_service_; SafeOptional<raw_ptr<plus_addresses::PlusAddressSettingService>>
diff --git a/components/collaboration/internal/collaboration_service_impl.cc b/components/collaboration/internal/collaboration_service_impl.cc index b7fbf74..06585c4 100644 --- a/components/collaboration/internal/collaboration_service_impl.cc +++ b/components/collaboration/internal/collaboration_service_impl.cc
@@ -389,6 +389,8 @@ } #endif + // TODO(crbug.com/40066949): Simplify this code once all users are migrated + // away from Sync-the-feature. if (sync_service_->IsSyncFeatureEnabled()) { // Sync-the-feature is enabled, but the required data types are not. // The user needs to enable them in settings. @@ -397,7 +399,9 @@ if (base::FeatureList::IsEnabled( syncer::kReplaceSyncPromosWithSignInPromos)) { // Sync-the-feature is not required, but the user needs to enable - // the required data types in settings. + // the required data types in settings. Note that this also includes cases + // where the user is not signed in at all - that is covered by + // GetSigninStatus(). return SyncStatus::kSyncWithoutTabGroup; } else { // The user needs to enable Sync-the-feature.
diff --git a/components/collaboration/public/service_status.h b/components/collaboration/public/service_status.h index a95d2e4..4e0057c3 100644 --- a/components/collaboration/public/service_status.h +++ b/components/collaboration/public/service_status.h
@@ -20,9 +20,15 @@ // GENERATED_JAVA_ENUM_PACKAGE: ( // org.chromium.components.collaboration) enum class SyncStatus { + // Sync-the-feature is disabled but required, or the Sync machinery is fully + // disabled (e.g. by command-line switch). kNotSyncing = 0, + // Syncing is available in principle, but the tab groups type is not enabled. + // This may also be returned for signed-out users. kSyncWithoutTabGroup = 1, + // Syncing of tab groups is enabled. kSyncEnabled = 2, + // Syncing is disabled due to Enterprise policy. kSyncDisabledByEnterprise = 3, };
diff --git a/components/lens/contextual_input.h b/components/lens/contextual_input.h index 5b792e66..87fceb53 100644 --- a/components/lens/contextual_input.h +++ b/components/lens/contextual_input.h
@@ -46,8 +46,13 @@ std::optional<std::string> page_title; // If the context is a pdf, this is the current viewed page. std::optional<uint32_t> pdf_current_page; +#if BUILDFLAG(IS_IOS) + // If the context is a webpage or pdf, this is the viewport screenshot. + std::optional<std::vector<uint8_t>> viewport_screenshot_bytes; +#else // If the context is a webpage or pdf, this is the viewport screenshot. std::optional<SkBitmap> viewport_screenshot; +#endif // BUILDFLAG(IS_IOS) // Whether or not webpage or pdf context is eligible. bool is_page_context_eligible; };
diff --git a/components/omnibox/composebox/composebox_query_controller.cc b/components/omnibox/composebox/composebox_query_controller.cc index bc3e37c3..5b32664 100644 --- a/components/omnibox/composebox/composebox_query_controller.cc +++ b/components/omnibox/composebox/composebox_query_controller.cc
@@ -295,12 +295,19 @@ UpdateFileUploadStatus(file_token, FileUploadStatus::kProcessing, std::nullopt); +#if BUILDFLAG(IS_IOS) + bool has_viewport_screenshot = + contextual_input_data->viewport_screenshot_bytes.has_value(); +#else + bool has_viewport_screenshot = + contextual_input_data->viewport_screenshot.has_value(); +#endif // BUILDFLAG(IS_IOS) // Unlike image uploads,PDF / page content uploads need to increment the // long context id instead of the image sequence id. current_file_info.request_id_ = GetNextRequestId( current_file_info.mime_type_ == lens::MimeType::kImage ? lens::RequestIdUpdateMode::kFullImageRequest - : (contextual_input_data->viewport_screenshot.has_value() + : (has_viewport_screenshot ? lens::RequestIdUpdateMode::kPageContentWithViewportRequest : lens::RequestIdUpdateMode::kPageContentRequest), current_file_info.mime_type_, @@ -664,14 +671,24 @@ return; } -#if !BUILDFLAG(IS_IOS) // If there is a viewport screenshot, create the viewport upload request body. - // TODO(crbug.com/442683956): Support alternative to SkBitmap for viewport - // screenshot, for iOS. + // TODO(crbug.com/442685171): Pass the pdf page number to the viewport + // upload request if available. +#if BUILDFLAG(IS_IOS) + if (contextual_input_data->viewport_screenshot_bytes.has_value()) { + CHECK(image_options.has_value()); + CreateImageUploadRequest( + file_token, + // Pass ownership of the viewport screenshot bytes to the callback. + std::move(contextual_input_data->viewport_screenshot_bytes.value()), + std::move(image_options), + base::BindOnce(&ComposeboxQueryController::OnUploadRequestBodyReady, + weak_ptr_factory_.GetWeakPtr(), file_token, + file_info->num_outstanding_network_requests_++)); + } +#else if (contextual_input_data->viewport_screenshot.has_value()) { CHECK(image_options.has_value()); - // TODO(crbug.com/442685171): Pass the pdf page number to the viewport - // upload request if available. ProcessDecodedImageAndContinue( *file_info->request_id_, image_options.value(), base::BindOnce(&ComposeboxQueryController::OnUploadRequestBodyReady,
diff --git a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc index dfe6ce5d..75eef574 100644 --- a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc +++ b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc
@@ -78,6 +78,10 @@ return visibility_at_activation_; } +bool FakePageLoadMetricsObserverDelegate::IsReloadAfterDiscard() const { + return is_discarded_page_reload_; +} + bool FakePageLoadMetricsObserverDelegate:: WasPrerenderedThenActivatedInForeground() const { return GetVisibilityAtActivation() == PageVisibility::kForeground;
diff --git a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h index 0f32e05..4faf0a3 100644 --- a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h +++ b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h
@@ -46,6 +46,7 @@ size_t index) const override; bool StartedInForeground() const override; PageVisibility GetVisibilityAtActivation() const override; + bool IsReloadAfterDiscard() const override; bool WasPrerenderedThenActivatedInForeground() const override; const UserInitiatedInfo& GetUserInitiatedInfo() const override; const GURL& GetUrl() const override; @@ -118,6 +119,7 @@ base::TimeTicks navigation_start_; std::optional<base::TimeTicks> first_background_time_ = std::nullopt; bool started_in_foreground_ = true; + bool is_discarded_page_reload_ = false; PrerenderingState prerendering_state_ = PrerenderingState::kNoPrerendering; PageVisibility visibility_at_activation_ = PageVisibility::kNotInitialized; std::optional<base::TimeDelta> activation_start_ = std::nullopt;
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc index 8c998c5..b6c0902 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -394,9 +394,12 @@ auto insertion_result = provisional_loads_.insert(std::make_pair( navigation_handle, std::make_unique<PageLoadTracker>( - in_foreground, embedder_interface_.get(), currently_committed_url, - !has_navigated_, navigation_handle, user_initiated_info, source_id, - parent_tracker))); + PageLoadTracker::InForegroundBool{in_foreground}, + embedder_interface_.get(), currently_committed_url, + PageLoadTracker::IsFirstNavigationInWebContentsBool{!has_navigated_}, + PageLoadTracker::IsReloadAfterDiscardBool{ + navigation_handle->ExistingDocumentWasDiscarded()}, + navigation_handle, user_initiated_info, source_id, parent_tracker))); CHECK(insertion_result.second) << "provisional_loads_ already contains NavigationHandle."; for (auto& observer : lifecycle_observers_) {
diff --git a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc index 178a8d3..aab35bfc 100644 --- a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc
@@ -109,6 +109,9 @@ "PageLoad.PaintTiming.NavigationToFirstContentfulPaint"; const char kBackgroundHistogramFirstContentfulPaint[] = "PageLoad.PaintTiming.NavigationToFirstContentfulPaint.Background"; +const char kHistogramFirstContentfulPaintExcludeReloadAfterDiscard[] = + "PageLoad.PaintTiming.NavigationToFirstContentfulPaint." + "ExcludeReloadAfterDiscard"; const char kHistogramFirstContentfulPaintInitiatingProcess[] = "PageLoad.Internal.PaintTiming.NavigationToFirstContentfulPaint." "InitiatingProcess"; @@ -117,6 +120,9 @@ const char kBackgroundHttpsOrDataOrFileSchemeHistogramLargestContentfulPaint[] = "PageLoad.PaintTiming.NavigationToLargestContentfulPaint2.Background." "HttpsOrDataOrFileScheme"; +const char kHistogramLargestContentfulPaintExcludeReloadAfterDiscard[] = + "PageLoad.PaintTiming.NavigationToLargestContentfulPaint2." + "ExcludeReloadAfterDiscard"; const char kHistogramLargestContentfulPaintContentType[] = "PageLoad.Internal.PaintTiming.LargestContentfulPaint.ContentType"; const char kHistogramLargestContentfulPaintMainFrame[] = @@ -450,6 +456,12 @@ timing.paint_timing->first_contentful_paint.value()); } + if (!GetDelegate().IsReloadAfterDiscard()) { + PAGE_LOAD_HISTOGRAM( + internal::kHistogramFirstContentfulPaintExcludeReloadAfterDiscard, + timing.paint_timing->first_contentful_paint.value()); + } + PAGE_LOAD_HISTOGRAM( internal::kHistogramTotalSubresourceLoadTimeAtFirstContentfulPaint, total_subresource_load_time_); @@ -941,6 +953,12 @@ lcp_time); } + if (!GetDelegate().IsReloadAfterDiscard()) { + PAGE_LOAD_HISTOGRAM( + internal::kHistogramLargestContentfulPaintExcludeReloadAfterDiscard, + lcp_time); + } + if (content::WebContents* web_contents = GetDelegate().GetWebContents()) { if (content::PreloadingData* preloading_data = content::PreloadingData::GetForWebContents(web_contents)) {
diff --git a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h index c370a9f..241a0911 100644 --- a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h +++ b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h
@@ -59,6 +59,9 @@ extern const char kBackgroundHistogramLoad[]; extern const char kBackgroundHistogramFirstPaint[]; +extern const char kHistogramFirstContentfulPaintExcludeReloadAfterDiscard[]; +extern const char kHistogramLargestContentfulPaintExcludeReloadAfterDiscard[]; + extern const char kHistogramLoadTypeFirstContentfulPaintReload[]; extern const char kHistogramLoadTypeFirstContentfulPaintForwardBack[]; extern const char kHistogramLoadTypeFirstContentfulPaintNewNavigation[];
diff --git a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc index 3f8b6a7..7f4c90f 100644 --- a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc +++ b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc
@@ -1773,6 +1773,72 @@ TestHistogram(kHistogram, {{kExpected, 1}}); } +TEST_P(UmaPageLoadMetricsObserverTest, ReloadAfterDiscard_ExcludeHistograms) { + page_load_metrics::mojom::PageLoadTiming timing; + page_load_metrics::InitPageLoadTimingForTest(&timing); + timing.navigation_start = base::Time::FromSecondsSinceUnixEpoch(1); + timing.response_start = base::Milliseconds(1); + timing.parse_timing->parse_start = base::Milliseconds(1); + timing.paint_timing->first_contentful_paint = base::Milliseconds(30); + timing.paint_timing->largest_contentful_paint->largest_text_paint = + base::Milliseconds(4780); + timing.paint_timing->largest_contentful_paint->largest_text_paint_size = 120u; + PopulateRequiredTimingFields(&timing); + + // Set the WebContents as discarded. + web_contents()->SetWasDiscarded(true); + + NavigateAndCommit(GURL(kDefaultTestUrl)); + tester()->SimulateTimingUpdate(timing); + + // Navigate again to force histogram recording. + NavigateAndCommit(GURL(kDefaultTestUrl2)); + + tester()->histogram_tester().ExpectTotalCount( + internal::kHistogramFirstContentfulPaint, 1); + tester()->histogram_tester().ExpectTotalCount( + internal::kHistogramFirstContentfulPaintExcludeReloadAfterDiscard, 0); + tester()->histogram_tester().ExpectTotalCount( + internal::kHistogramLargestContentfulPaint, 1); + tester()->histogram_tester().ExpectTotalCount( + internal::kHistogramLargestContentfulPaintExcludeReloadAfterDiscard, 0); +} + +TEST_P(UmaPageLoadMetricsObserverTest, + NotReloadAfterDiscard_IncludeHistograms) { + page_load_metrics::mojom::PageLoadTiming timing; + page_load_metrics::InitPageLoadTimingForTest(&timing); + timing.navigation_start = base::Time::FromSecondsSinceUnixEpoch(1); + timing.response_start = base::Milliseconds(1); + timing.parse_timing->parse_start = base::Milliseconds(1); + timing.paint_timing->first_contentful_paint = base::Milliseconds(30); + timing.paint_timing->largest_contentful_paint->largest_text_paint = + base::Milliseconds(4780); + timing.paint_timing->largest_contentful_paint->largest_text_paint_size = 120u; + PopulateRequiredTimingFields(&timing); + + // Unlike the previous test, do *not* set the WebContents as discarded. + + NavigateAndCommit(GURL(kDefaultTestUrl)); + tester()->SimulateTimingUpdate(timing); + + // Navigate again to force histogram recording. + NavigateAndCommit(GURL(kDefaultTestUrl2)); + + tester()->histogram_tester().ExpectTotalCount( + internal::kHistogramFirstContentfulPaint, 1); + tester()->histogram_tester().ExpectBucketCount( + internal::kHistogramFirstContentfulPaintExcludeReloadAfterDiscard, + timing.paint_timing->first_contentful_paint.value().InMilliseconds(), 1); + tester()->histogram_tester().ExpectTotalCount( + internal::kHistogramLargestContentfulPaint, 1); + tester()->histogram_tester().ExpectBucketCount( + internal::kHistogramLargestContentfulPaintExcludeReloadAfterDiscard, + timing.paint_timing->largest_contentful_paint->largest_text_paint.value() + .InMilliseconds(), + 1); +} + class UmaPageLoadMetricsObserverIncognitoTest : public UmaPageLoadMetricsObserverTest { protected:
diff --git a/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h b/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h index 44e25d4..c9f4e68 100644 --- a/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h +++ b/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
@@ -121,6 +121,9 @@ // Page's visibility at activation. virtual PageVisibility GetVisibilityAtActivation() const = 0; + // True if the page load is a reload of a page that was discarded. + virtual bool IsReloadAfterDiscard() const = 0; + // True if the page load was a prerender, that was later activated by a // navigation that started in the foreground. virtual bool WasPrerenderedThenActivatedInForeground() const = 0;
diff --git a/components/page_load_metrics/browser/page_load_tracker.cc b/components/page_load_metrics/browser/page_load_tracker.cc index 309cc8a..33881ff2 100644 --- a/components/page_load_metrics/browser/page_load_tracker.cc +++ b/components/page_load_metrics/browser/page_load_tracker.cc
@@ -257,10 +257,11 @@ } // namespace PageLoadTracker::PageLoadTracker( - bool in_foreground, + InForegroundBool in_foreground, PageLoadMetricsEmbedderInterface* embedder_interface, const GURL& currently_committed_url, - bool is_first_navigation_in_web_contents, + IsFirstNavigationInWebContentsBool is_first_navigation_in_web_contents, + IsReloadAfterDiscardBool is_reload_after_discard, content::NavigationHandle* navigation_handle, UserInitiatedInfo user_initiated_info, ukm::SourceId source_id, @@ -270,7 +271,8 @@ navigation_start_(navigation_handle->NavigationStart()), url_(navigation_handle->GetURL()), start_url_(navigation_handle->GetURL()), - visibility_tracker_(base::DefaultTickClock::GetInstance(), in_foreground), + visibility_tracker_(base::DefaultTickClock::GetInstance(), + *in_foreground), did_commit_(false), page_end_reason_(END_NONE), page_end_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), @@ -282,8 +284,9 @@ source_id_(source_id), web_contents_(navigation_handle->GetWebContents()), is_first_navigation_in_web_contents_(is_first_navigation_in_web_contents), + is_reload_after_discard_(is_reload_after_discard), is_origin_visit_( - CalculateIsOriginVisit(is_first_navigation_in_web_contents, + CalculateIsOriginVisit(*is_first_navigation_in_web_contents, navigation_handle->GetPageTransition())), soft_navigation_metrics_(CreateSoftNavigationMetrics()), page_type_(CalculatePageType(navigation_handle)), @@ -1227,6 +1230,10 @@ return visibility_at_activation_; } +bool PageLoadTracker::IsReloadAfterDiscard() const { + return *is_reload_after_discard_; +} + bool PageLoadTracker::WasPrerenderedThenActivatedInForeground() const { return GetVisibilityAtActivation() == PageVisibility::kForeground; } @@ -1363,7 +1370,7 @@ } bool PageLoadTracker::IsFirstNavigationInWebContents() const { - return is_first_navigation_in_web_contents_; + return *is_first_navigation_in_web_contents_; } bool PageLoadTracker::IsOriginVisit() const {
diff --git a/components/page_load_metrics/browser/page_load_tracker.h b/components/page_load_metrics/browser/page_load_tracker.h index 33ef707..12bd050 100644 --- a/components/page_load_metrics/browser/page_load_tracker.h +++ b/components/page_load_metrics/browser/page_load_tracker.h
@@ -181,17 +181,31 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client, public PageLoadMetricsObserverDelegate { public: + // Whether a page is in foreground when it starts loading. + using InForegroundBool = base::StrongAlias<struct ForegroundTag, bool>; + // Whether a navigation is the first to occur in a WebContents. + using IsFirstNavigationInWebContentsBool = + base::StrongAlias<struct FirstNavigationInWebContentsTag, bool>; + // Whether a navigation is a reload of a page that was previously discarded. + // This typically happens when a user re-activates a background page that the + // browser had discarded. See https://wicg.github.io/page-lifecycle/spec.html + // for the formal definition of discarding. + using IsReloadAfterDiscardBool = + base::StrongAlias<struct ReloadAfterDiscardTag, bool>; + // Caller must guarantee that the `embedder_interface` pointer outlives this // class. The PageLoadTracker must not hold on to `navigation_handle` beyond // the scope of the constructor. - PageLoadTracker(bool in_foreground, - PageLoadMetricsEmbedderInterface* embedder_interface, - const GURL& currently_committed_url, - bool is_first_navigation_in_web_contents, - content::NavigationHandle* navigation_handle, - UserInitiatedInfo user_initiated_info, - ukm::SourceId source_id, - base::WeakPtr<PageLoadTracker> parent_tracker); + PageLoadTracker( + InForegroundBool in_foreground, + PageLoadMetricsEmbedderInterface* embedder_interface, + const GURL& currently_committed_url, + IsFirstNavigationInWebContentsBool is_first_navigation_in_web_contents, + IsReloadAfterDiscardBool is_reload_after_discard, + content::NavigationHandle* navigation_handle, + UserInitiatedInfo user_initiated_info, + ukm::SourceId source_id, + base::WeakPtr<PageLoadTracker> parent_tracker); PageLoadTracker(const PageLoadTracker&) = delete; PageLoadTracker& operator=(const PageLoadTracker&) = delete; @@ -246,6 +260,7 @@ size_t index) const override; bool StartedInForeground() const override; PageVisibility GetVisibilityAtActivation() const override; + bool IsReloadAfterDiscard() const override; bool WasPrerenderedThenActivatedInForeground() const override; const UserInitiatedInfo& GetUserInitiatedInfo() const override; const GURL& GetUrl() const override; @@ -581,7 +596,8 @@ // instance is bound. content::GlobalRenderFrameHostId page_main_frame_id_; - const bool is_first_navigation_in_web_contents_; + const IsFirstNavigationInWebContentsBool is_first_navigation_in_web_contents_; + const IsReloadAfterDiscardBool is_reload_after_discard_; const bool is_origin_visit_; bool is_terminal_visit_ = true;
diff --git a/components/page_load_metrics/browser/page_load_tracker_unittest.cc b/components/page_load_metrics/browser/page_load_tracker_unittest.cc index a738f6a..fd7f792 100644 --- a/components/page_load_metrics/browser/page_load_tracker_unittest.cc +++ b/components/page_load_metrics/browser/page_load_tracker_unittest.cc
@@ -178,6 +178,19 @@ EXPECT_FALSE(GetEvents().was_committed); } +TEST_F(PageLoadTrackerTest, NotReloadAfterDiscard) { + SetTargetUrl(kTestUrl); + NavigateAndCommit(GURL(kTestUrl)); + EXPECT_FALSE(tester()->GetDelegateForCommittedLoad().IsReloadAfterDiscard()); +} + +TEST_F(PageLoadTrackerTest, ReloadAfterDiscard) { + SetTargetUrl(kTestUrl); + web_contents()->SetWasDiscarded(true); + NavigateAndCommit(GURL(kTestUrl)); + EXPECT_TRUE(tester()->GetDelegateForCommittedLoad().IsReloadAfterDiscard()); +} + TEST_F(PageLoadTrackerTest, EventForwarding) { ScopedPrerenderWebContentsDelegate web_contents_delegate(*web_contents());
diff --git a/components/paint_preview/browser/paint_preview_client.cc b/components/paint_preview/browser/paint_preview_client.cc index 6219a64d..4611d6b 100644 --- a/components/paint_preview/browser/paint_preview_client.cc +++ b/components/paint_preview/browser/paint_preview_client.cc
@@ -886,9 +886,10 @@ document_data.had_success = false; } - TRACE_EVENT_END("paint_preview", perfetto::Track::FromPointer(&document_data), - "success", document_data.had_success, "subframes", - document_data.finished_subframes.size()); + TRACE_EVENT_NESTABLE_ASYNC_END2( + "paint_preview", "PaintPreviewClient::CapturePaintPreview", + TRACE_ID_LOCAL(&document_data), "success", document_data.had_success, + "subframes", document_data.finished_subframes.size()); base::UmaHistogramBoolean("Browser.PaintPreview.Capture.Success", document_data.had_success);
diff --git a/components/password_manager/core/browser/password_form_cache.h b/components/password_manager/core/browser/password_form_cache.h index 0dba263b..d6159b1 100644 --- a/components/password_manager/core/browser/password_form_cache.h +++ b/components/password_manager/core/browser/password_form_cache.h
@@ -13,7 +13,6 @@ struct PasswordForm; class PasswordFormManager; -#if !BUILDFLAG(IS_IOS) // Allows observing events inside PasswordFormManager. Declared here to allow // adding observers to all form mangers in the cache. class PasswordFormManagerObserver : public base::CheckedObserver { @@ -23,17 +22,6 @@ // Invoked whenever `form_manager` parses a form. virtual void OnPasswordFormParsed(PasswordFormManager* form_manager) = 0; }; -#else -// Allows observing events inside PasswordFormManager. Declared here to allow -// adding observers to all form mangers in the cache. -class PasswordFormManagerObserver { - public: - virtual ~PasswordFormManagerObserver() {} - - // Invoked whenever `form_manager` parses a form. - virtual void OnPasswordFormParsed(PasswordFormManager* form_manager) = 0; -}; -#endif // Contains information about password forms detected on a web page. class PasswordFormCache { @@ -53,22 +41,14 @@ virtual const PasswordForm* GetPasswordForm( PasswordManagerDriver* driver, autofill::FieldRendererId field_id) const = 0; -#if !BUILDFLAG(IS_IOS) + // Allows adding an observer for all newly added password form managers. virtual void AddObserver(PasswordFormManagerObserver* observer) {} // Removes observer from all current form managers and prevents attaching // observer to newly added. virtual void RemoveObserver(PasswordFormManagerObserver* observer) {} -#else - // Allows adding an observer for all newly added password form managers. - virtual void SetObserver( - base::WeakPtr<PasswordFormManagerObserver> observer) {} - // Removes observer from all current form managers and prevents attaching - // observer to newly added. - virtual void ResetObserver() {} -#endif // Returns all the `PasswordFormManager`s for the current page. virtual base::span<const std::unique_ptr<PasswordFormManager>> GetFormManagers() const = 0;
diff --git a/components/password_manager/core/browser/password_form_cache_impl.cc b/components/password_manager/core/browser/password_form_cache_impl.cc index 779dc57..e70a203 100644 --- a/components/password_manager/core/browser/password_form_cache_impl.cc +++ b/components/password_manager/core/browser/password_form_cache_impl.cc
@@ -52,16 +52,10 @@ void PasswordFormCacheImpl::AddFormManager( std::unique_ptr<PasswordFormManager> manager) { -#if !BUILDFLAG(IS_IOS) for (PasswordFormManagerObserver& form_manager_observer : form_manager_observers_) { manager->AddObserver(&form_manager_observer); } -#else - if (form_manager_observer_) { - manager->SetObserver(form_manager_observer_); - } -#endif form_managers_.emplace_back(std::move(manager)); } @@ -92,13 +86,9 @@ // After PasswordFormManager is removed from cache it's impossible to // reset observation. Thus, it's safer to stop observing immediately. -#if !BUILDFLAG(IS_IOS) for (PasswordFormManagerObserver& observer : form_manager_observers_) { submitted_manager->RemoveObserver(&observer); } -#else - submitted_manager->ResetObserver(); -#endif return submitted_manager; } } @@ -113,7 +103,6 @@ return form_managers_.empty(); } -#if !BUILDFLAG(IS_IOS) void PasswordFormCacheImpl::AddObserver(PasswordFormManagerObserver* observer) { if (!form_manager_observers_.HasObserver(observer)) { form_manager_observers_.AddObserver(observer); @@ -130,19 +119,6 @@ manager->RemoveObserver(observer); } } -#else -void PasswordFormCacheImpl::SetObserver( - base::WeakPtr<PasswordFormManagerObserver> observer) { - form_manager_observer_ = observer; -} - -void PasswordFormCacheImpl::ResetObserver() { - form_manager_observer_.reset(); - for (const std::unique_ptr<PasswordFormManager>& manager : form_managers_) { - manager->ResetObserver(); - } -} -#endif base::span<const std::unique_ptr<PasswordFormManager>> PasswordFormCacheImpl::GetFormManagers() const {
diff --git a/components/password_manager/core/browser/password_form_cache_impl.h b/components/password_manager/core/browser/password_form_cache_impl.h index 7d7e83a..f0f75ee 100644 --- a/components/password_manager/core/browser/password_form_cache_impl.h +++ b/components/password_manager/core/browser/password_form_cache_impl.h
@@ -45,25 +45,16 @@ const PasswordForm* GetPasswordForm( PasswordManagerDriver* driver, autofill::FieldRendererId field_id) const override; -#if !BUILDFLAG(IS_IOS) void AddObserver(PasswordFormManagerObserver* observer) override; void RemoveObserver(PasswordFormManagerObserver* observer) override; -#else - void SetObserver( - base::WeakPtr<PasswordFormManagerObserver> observer) override; - void ResetObserver() override; -#endif base::span<const std::unique_ptr<PasswordFormManager>> GetFormManagers() const override; private: // TODO(b/330313855): Check if `unique_ptr` can be removed here. std::vector<std::unique_ptr<PasswordFormManager>> form_managers_; -#if !BUILDFLAG(IS_IOS) + base::ObserverList<PasswordFormManagerObserver> form_manager_observers_; -#else - base::WeakPtr<PasswordFormManagerObserver> form_manager_observer_; -#endif }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_form_cache_impl_unittest.cc b/components/password_manager/core/browser/password_form_cache_impl_unittest.cc index 4494494..522f920a 100644 --- a/components/password_manager/core/browser/password_form_cache_impl_unittest.cc +++ b/components/password_manager/core/browser/password_form_cache_impl_unittest.cc
@@ -260,11 +260,7 @@ // Test that the cache adds observers to newly added managers. TEST_F(PasswordFormCacheTest, ObservationOnFormManager) { MockPasswordFormManagerObserver observer; -#if !BUILDFLAG(IS_IOS) static_cast<PasswordFormCache*>(&cache())->AddObserver(&observer); -#else - static_cast<PasswordFormCache*>(&cache())->SetObserver(observer.GetWeakPtr()); -#endif auto form_manager = std::make_unique<PasswordFormManager>( &client(), driver().AsWeakPtr(), CreateTestPasswordFormData(), @@ -279,7 +275,7 @@ form_fetcher().NotifyFetchCompleted(); FastForwardUntilNoTasksRemain(); } -#if !BUILDFLAG(IS_IOS) + // Test that the cache adds observers to all existing managers. TEST_F(PasswordFormCacheTest, ObservationOnExistingFormManager) { MockPasswordFormManagerObserver observer; @@ -296,5 +292,5 @@ form_fetcher().NotifyFetchCompleted(); FastForwardUntilNoTasksRemain(); } -#endif + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 3620853c..0cd5565 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -1216,16 +1216,10 @@ if (!parsed_observed_form_) { return; } -#if !BUILDFLAG(IS_IOS) for (PasswordFormManagerObserver& form_parsed_observer : form_parsed_observers_) { form_parsed_observer.OnPasswordFormParsed(this); } -#else - if (form_parsed_observer_) { - form_parsed_observer_->OnPasswordFormParsed(this); - } -#endif metrics_recorder_->CacheParsingResultInFillingMode( *parsed_observed_form_.get()); @@ -1902,7 +1896,6 @@ return stored_usernames; } -#if !BUILDFLAG(IS_IOS) void PasswordFormManager::AddObserver(PasswordFormManagerObserver* observer) { if (!form_parsed_observers_.HasObserver(observer)) { form_parsed_observers_.AddObserver(observer); @@ -1913,15 +1906,5 @@ PasswordFormManagerObserver* observer) { form_parsed_observers_.RemoveObserver(observer); } -#else -void PasswordFormManager::SetObserver( - base::WeakPtr<PasswordFormManagerObserver> observer) { - form_parsed_observer_ = observer; -} - -void PasswordFormManager::ResetObserver() { - form_parsed_observer_.reset(); -} -#endif } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h index 01a5e7b..5482ea9b 100644 --- a/components/password_manager/core/browser/password_form_manager.h +++ b/components/password_manager/core/browser/password_form_manager.h
@@ -307,13 +307,9 @@ return votes_uploader_.has_value() ? &votes_uploader_.value() : nullptr; } #endif -#if !BUILDFLAG(IS_IOS) + void AddObserver(PasswordFormManagerObserver* observer); void RemoveObserver(PasswordFormManagerObserver* observer); -#else - void SetObserver(base::WeakPtr<PasswordFormManagerObserver> observer); - void ResetObserver(); -#endif protected: // Constructor for Credentials API. @@ -527,11 +523,8 @@ // For generating timing metrics on retrieving server-side predictions. std::unique_ptr<base::ElapsedTimer> server_side_predictions_timer_; -#if !BUILDFLAG(IS_IOS) + base::ObserverList<PasswordFormManagerObserver> form_parsed_observers_; -#else - base::WeakPtr<PasswordFormManagerObserver> form_parsed_observer_; -#endif }; // Returns whether `form_data` differs from the form observed by `form_manager`
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index f37b8287..098e65f 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -4777,7 +4777,6 @@ #endif -#if !BUILDFLAG(IS_IOS) TEST_P(PasswordFormManagerTest, NotifiesObservers) { MockPasswordFormManagerObserver observer; MockPasswordFormManagerObserver observer_2; @@ -4805,32 +4804,6 @@ task_environment_.FastForwardUntilNoTasksRemain(); } -#else -TEST_P(PasswordFormManagerTest, NotifiesObserver) { - MockPasswordFormManagerObserver observer; - - CreateFormManager(observed_form_); - form_manager_->SetObserver(observer.GetWeakPtr()); - - EXPECT_CALL(observer, OnPasswordFormParsed(form_manager_.get())); - SetNonFederatedAndNotifyFetchCompleted({saved_match_}); - - task_environment_.FastForwardUntilNoTasksRemain(); -} - -TEST_P(PasswordFormManagerTest, DoesNotNotifyAfterObserverRemoved) { - MockPasswordFormManagerObserver observer; - - CreateFormManager(observed_form_); - form_manager_->SetObserver(observer.GetWeakPtr()); - form_manager_->ResetObserver(); - - EXPECT_CALL(observer, OnPasswordFormParsed).Times(0); - SetNonFederatedAndNotifyFetchCompleted({saved_match_}); - - task_environment_.FastForwardUntilNoTasksRemain(); -} -#endif INSTANTIATE_TEST_SUITE_P(All, PasswordFormManagerTest, testing::Bool());
diff --git a/components/password_manager/core/browser/undo_password_change_controller.cc b/components/password_manager/core/browser/undo_password_change_controller.cc index 17c024d..1d753a69 100644 --- a/components/password_manager/core/browser/undo_password_change_controller.cc +++ b/components/password_manager/core/browser/undo_password_change_controller.cc
@@ -73,7 +73,6 @@ void UndoPasswordChangeController::OnLoginPotentiallyFailed( PasswordManagerDriver* driver, const PasswordForm& login_form) { -#if !BUILDFLAG(IS_IOS) auto password_field_it = std::ranges::find( login_form.form_data.fields(), login_form.password_element_renderer_id, &autofill::FormFieldData::renderer_id); @@ -87,7 +86,6 @@ failed_login_form_ = login_form; password_form_cache_ = driver_->GetPasswordManager()->GetPasswordFormCache(); password_form_cache_->AddObserver(this); -#endif } PasswordRecoveryState UndoPasswordChangeController::GetState( @@ -151,18 +149,15 @@ } void UndoPasswordChangeController::FinishObserving() { -#if !BUILDFLAG(IS_IOS) failed_login_form_ = std::nullopt; driver_ = nullptr; if (password_form_cache_) { password_form_cache_->RemoveObserver(this); } -#endif } void UndoPasswordChangeController::OnPasswordFormParsed( PasswordFormManager* form_manager) { -#if !BUILDFLAG(IS_IOS) CHECK(form_manager); if (!failed_login_form_ || !driver_) { return; @@ -199,7 +194,6 @@ form_manager->GetParsedObservedForm() ->password_element_renderer_id)); } -#endif } } // namespace password_manager
diff --git a/components/password_manager/core/browser/undo_password_change_controller_unittest.cc b/components/password_manager/core/browser/undo_password_change_controller_unittest.cc index 6f8e36b..75a731e 100644 --- a/components/password_manager/core/browser/undo_password_change_controller_unittest.cc +++ b/components/password_manager/core/browser/undo_password_change_controller_unittest.cc
@@ -302,7 +302,6 @@ PasswordRecoveryState::kIncludeBackup); } -#if !BUILDFLAG(IS_IOS) TEST_F(UndoPasswordChangeControllerTest, OnLoginPotentiallyFailedFlagOn) { base::test::ScopedFeatureList feature_list(features::kShowRecoveryPassword); best_match_form_.SetPasswordBackupNote(kBackupPassword); @@ -460,6 +459,5 @@ ChangeRecoveryUkmEntry::kPasswordChangeRecoveryFlowName, static_cast<int>(expected_metric_state)); } -#endif } // namespace password_manager
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h index 55399fc..7e62812d 100644 --- a/components/signin/core/browser/account_reconcilor.h +++ b/components/signin/core/browser/account_reconcilor.h
@@ -460,11 +460,6 @@ #if BUILDFLAG(IS_CHROMEOS) // On Ash, this is a pointer to `AccountManagerFacadeImpl`. - // Note: On Lacros too, this is a pointer to `AccountManagerFacadeImpl`, and - // not `ProfileAccountManager`. This was done to simplify the design since - // this pointer is only used to observe the closure of the OS/Ash-level signin - // dialog and nothing else. Reconsider this decision if this usage changes in - // the future. raw_ptr<account_manager::AccountManagerFacade> account_manager_facade_; #endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index 40c1574..e0fe51f 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -2237,8 +2237,7 @@ ASSERT_FALSE(reconcilor->is_reconcile_started_); } -// Check that token error on primary account results in a logout to all accounts -// on Lacros. For other mirror platforms, reconcile is aborted. +// Check that token error on primary account results in aborted reconcile TEST_F(AccountReconcilorMirrorTest, TokenErrorOnPrimary) { AccountInfo account_info = ConnectProfileToAccount(kFakeEmail); signin::UpdatePersistentErrorOfRefreshTokenForAccount(
diff --git a/components/signin/core/browser/mirror_account_reconcilor_delegate.cc b/components/signin/core/browser/mirror_account_reconcilor_delegate.cc index 0707cac..e6661135 100644 --- a/components/signin/core/browser/mirror_account_reconcilor_delegate.cc +++ b/components/signin/core/browser/mirror_account_reconcilor_delegate.cc
@@ -44,11 +44,7 @@ // Ash. return ConsentLevel::kSync; #else - // For mobile (iOS, Android) and Lacros. - // - // Whenever Mirror is enabled on a Lacros Profile, the Primary Account may or - // may not have consented to Chrome Sync. But we want to enable - // `AccountReconcilor` regardless - for minting Gaia cookies. + // For mobile (iOS, Android). return ConsentLevel::kSignin; #endif }
diff --git a/components/signin/internal/identity_manager/primary_account_manager.cc b/components/signin/internal/identity_manager/primary_account_manager.cc index 1c62d5a..09adbfc 100644 --- a/components/signin/internal/identity_manager/primary_account_manager.cc +++ b/components/signin/internal/identity_manager/primary_account_manager.cc
@@ -661,8 +661,7 @@ if (abort_signout) { // TODO(crbug.com/40240858): Add 'NOTREACHED()' after updating the - // 'SigninManager', 'Dice Response Handler', - // 'Lacros Profile Account Mapper'. + // 'SigninManager', 'Dice Response Handler'. VLOG(1) << "Ignoring attempt to sign out while signout disallowed"; return; }
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc index 972e17c..8bccc03e 100644 --- a/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc +++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
@@ -144,7 +144,7 @@ account_manager_facade, is_regular_profile); #elif BUILDFLAG(ENABLE_DICE_SUPPORT) // Fall back to |MutableProfileOAuth2TokenServiceDelegate| on all platforms - // other than Android, iOS, and Chrome OS (Ash and Lacros). + // other than Android, iOS, and Chrome OS (Ash). return CreateMutableProfileOAuthDelegate( account_tracker_service, account_consistency, delete_signin_cookies_on_exit, token_web_data, signin_client,
diff --git a/components/signin/public/identity_manager/BUILD.gn b/components/signin/public/identity_manager/BUILD.gn index 768578fb..4216c44 100644 --- a/components/signin/public/identity_manager/BUILD.gn +++ b/components/signin/public/identity_manager/BUILD.gn
@@ -15,13 +15,13 @@ "access_token_restriction.h", "account_capabilities.cc", "account_capabilities.h", - "account_capability_fetcher.cc", - "account_capability_fetcher.h", "account_info.cc", "account_info.h", "account_managed_status_finder.cc", "account_managed_status_finder.h", "account_managed_status_finder_outcome.h", + "account_state_fetcher.cc", + "account_state_fetcher.h", "accounts_cookie_mutator.h", "accounts_in_cookie_jar_info.cc", "accounts_in_cookie_jar_info.h", @@ -113,9 +113,9 @@ "access_token_fetcher_unittest.cc", "access_token_restriction_unittest.cc", "account_capabilities_unittest.cc", - "account_capability_fetcher_unittest.cc", "account_info_unittest.cc", "account_managed_status_finder_unittest.cc", + "account_state_fetcher_unittest.cc", "accounts_cookie_mutator_unittest.cc", "accounts_in_cookie_jar_info_unittest.cc", "accounts_mutator_unittest.cc",
diff --git a/components/signin/public/identity_manager/account_capability_fetcher.cc b/components/signin/public/identity_manager/account_capability_fetcher.cc deleted file mode 100644 index b725301..0000000 --- a/components/signin/public/identity_manager/account_capability_fetcher.cc +++ /dev/null
@@ -1,101 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/signin/public/identity_manager/account_capability_fetcher.h" - -#include "base/functional/bind.h" -#include "base/functional/callback.h" -#include "base/scoped_observation.h" -#include "components/signin/public/identity_manager/account_info.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/signin/public/identity_manager/tribool.h" - -namespace { -base::TimeDelta g_account_capability_fetch_delay = base::Seconds(3); -} // namespace - -AccountCapabilityFetcher::AccountCapabilityFetcher( - signin::IdentityManager* identity_manager, - CoreAccountInfo core_account_info, - base::RepeatingCallback<signin::Tribool(const AccountInfo&)> - get_capability_state_callback, - base::OnceCallback<void(signin::Tribool)> on_capability_fetched_callback) - : identity_manager_(identity_manager), - core_account_info_(core_account_info), - get_capability_state_callback_(std::move(get_capability_state_callback)), - on_capability_fetched_callback_( - std::move(on_capability_fetched_callback)) { - CHECK(identity_manager_); - CHECK(on_capability_fetched_callback_); - CHECK(get_capability_state_callback_); -} - -AccountCapabilityFetcher::~AccountCapabilityFetcher() = default; - -void AccountCapabilityFetcher::FetchCapability() { - // Start a timeout for the capability fetching. - capability_available_timeout_timer_.Start( - FROM_HERE, g_account_capability_fetch_delay, - base::BindOnce(&AccountCapabilityFetcher::OnCapabilityFetchedTimeout, - // Unretained is fine as this class owns the timer. - base::Unretained(this))); - // Wait for the capability to arrive. - GetOrWaitForCapability(core_account_info_); -} - -void AccountCapabilityFetcher::EnforceTimeoutReachedForTesting() { - capability_available_timeout_timer_.FireNow(); -} - -void AccountCapabilityFetcher::OnExtendedAccountInfoUpdated( - const AccountInfo& account_info) { - if (account_info.account_id != core_account_info_.account_id) { - return; - } - GetOrWaitForCapability(account_info); -} - -void AccountCapabilityFetcher::OnIdentityManagerShutdown( - signin::IdentityManager* identity_manager) { - CHECK(identity_manager == identity_manager_.get()); - account_info_update_observation_.Reset(); - identity_manager_ = nullptr; -} - -void AccountCapabilityFetcher::GetOrWaitForCapability( - const CoreAccountInfo& core_account_info) { - CHECK(core_account_info.account_id == core_account_info_.account_id); - AccountInfo extended_account_info = - identity_manager_->FindExtendedAccountInfo(core_account_info); - signin::Tribool capability_value = - get_capability_state_callback_.Run(extended_account_info); - - if (capability_value == signin::Tribool::kUnknown) { - if (!account_info_update_observation_.IsObserving()) { - account_info_update_observation_.Observe(identity_manager_); - } - return; - } - CHECK(capability_value != signin::Tribool::kUnknown); - account_info_update_observation_.Reset(); - OnCapabilityFetched(capability_value); -} - -void AccountCapabilityFetcher::OnCapabilityFetched( - signin::Tribool account_capability_value) { - // TODO(434964019): Confirm whether the capability is expected to remain - // unchanged, or whether we should observe and handle updates of the - // capability. - // Cancel the timeout callback. - capability_available_timeout_timer_.Stop(); - - CHECK(!on_capability_fetched_callback_.is_null()); - std::move(on_capability_fetched_callback_).Run(account_capability_value); -} - -void AccountCapabilityFetcher::OnCapabilityFetchedTimeout() { - account_info_update_observation_.Reset(); - OnCapabilityFetched(signin::Tribool::kUnknown); - // TODO(anthie): Maybe record metrics for this case. -}
diff --git a/components/signin/public/identity_manager/account_capability_fetcher.h b/components/signin/public/identity_manager/account_capability_fetcher.h deleted file mode 100644 index 0c33f3c..0000000 --- a/components/signin/public/identity_manager/account_capability_fetcher.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_CAPABILITY_FETCHER_H_ -#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_CAPABILITY_FETCHER_H_ - -#include "base/functional/callback_forward.h" -#include "base/scoped_observation.h" -#include "base/timer/timer.h" -#include "components/signin/public/identity_manager/account_info.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/signin/public/identity_manager/tribool.h" - -// Waits until a capability is fetched. -// The capability state is computed through the input callback -// `get_capability_state_callback_`. -// When the capability is fetched or we timeout while waiting for it, -// it executes the provided callback `on_capability_fetched_callback` -// and stops observing for further updates. -// Expected to be used for a single fetch only. -class AccountCapabilityFetcher : public signin::IdentityManager::Observer { - public: - AccountCapabilityFetcher( - signin::IdentityManager* identity_manager, - CoreAccountInfo core_account_info, - base::RepeatingCallback<signin::Tribool(const AccountInfo&)> - get_capability_state_callback, - base::OnceCallback<void(signin::Tribool)> on_capability_fetched_callback); - - AccountCapabilityFetcher(); - ~AccountCapabilityFetcher() override; - - // Starts fetching the capability. Returns the result through - // `on_capability_fetched_callback_` when ready and may - // return right away if already available. Should be called once. - void FetchCapability(); - - void EnforceTimeoutReachedForTesting(); - - private: - // signin::IdentityManager::Observer: - void OnExtendedAccountInfoUpdated(const AccountInfo& account_info) override; - void OnIdentityManagerShutdown( - signin::IdentityManager* identity_manager) override; - - void GetOrWaitForCapability(const CoreAccountInfo& core_account_info); - - void OnCapabilityFetched(signin::Tribool account_capability_value); - - void OnCapabilityFetchedTimeout(); - - base::ScopedObservation<signin::IdentityManager, - signin::IdentityManager::Observer> - account_info_update_observation_{this}; - - raw_ptr<signin::IdentityManager> identity_manager_; - CoreAccountInfo core_account_info_; - base::RepeatingCallback<signin::Tribool(const AccountInfo&)> - get_capability_state_callback_; - base::OnceCallback<void(signin::Tribool)> on_capability_fetched_callback_; - base::OneShotTimer capability_available_timeout_timer_; -}; - -#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_CAPABILITY_FETCHER_H_
diff --git a/components/signin/public/identity_manager/account_capability_fetcher_unittest.cc b/components/signin/public/identity_manager/account_capability_fetcher_unittest.cc deleted file mode 100644 index a1ad60c39..0000000 --- a/components/signin/public/identity_manager/account_capability_fetcher_unittest.cc +++ /dev/null
@@ -1,131 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/signin/public/identity_manager/account_capability_fetcher.h" - -#include <memory> - -#include "base/functional/bind.h" -#include "base/test/bind.h" -#include "base/test/task_environment.h" -#include "base/test/test_future.h" -#include "components/signin/public/identity_manager/identity_test_environment.h" -#include "components/signin/public/identity_manager/tribool.h" - -namespace { -constexpr char kTestEmail[] = "test@example.com"; -} // namespace - -class AccountCapabilityFetcherTest : public testing::Test { - public: - AccountCapabilityFetcherTest() = default; - - void SetUp() override { - test_account_ = identity_test_env_.MakeAccountAvailable(kTestEmail); - } - - // Helper to set the value that `get_capability_state_callback_` will return. - void set_capability_state(signin::Tribool state) { - capability_state_ = state; - // Update a test account field, so that subsequent calls to - // UpdateAccountInfoForAccount will trigger the extended info account - // update. In production the extended account info updating would be triggered - // by the capability update, however the capability value is mocked on this - // test suite. - test_account_.full_name = std::string("name") + TriboolToString(state); - } - - // The callback passed to the fetcher to get the capability state. - base::RepeatingCallback<signin::Tribool(const AccountInfo&)> - get_capability_state_callback() { - return base::BindRepeating( - [](signin::Tribool* state, const AccountInfo&) { return *state; }, - &capability_state_); - } - - protected: - base::test::SingleThreadTaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - signin::IdentityTestEnvironment identity_test_env_; - AccountInfo test_account_; - - // The current state of the capability. - signin::Tribool capability_state_ = signin::Tribool::kUnknown; -}; - -// Tests that the callback is executed immediately if the capability is already -// known. -TEST_F(AccountCapabilityFetcherTest, RunsCallbackWhenCapabilityAlreadyKnown) { - set_capability_state(signin::Tribool::kTrue); - base::test::TestFuture<signin::Tribool> capability_fetched_callback; - - AccountCapabilityFetcher fetcher(identity_test_env_.identity_manager(), - test_account_, - get_capability_state_callback(), - capability_fetched_callback.GetCallback()); - fetcher.FetchCapability(); - EXPECT_TRUE(capability_fetched_callback.Wait()); - EXPECT_EQ(signin::Tribool::kTrue, - capability_fetched_callback.Get<signin::Tribool>()); -} - -// Tests that the fetcher waits for an account update. -TEST_F(AccountCapabilityFetcherTest, - RunsCallbackWhenCapabilityBecomesAvailable) { - base::test::TestFuture<signin::Tribool> capability_fetched_callback; - AccountCapabilityFetcher fetcher(identity_test_env_.identity_manager(), - test_account_, - get_capability_state_callback(), - capability_fetched_callback.GetCallback()); - // Start the fetching. No callback is executed because the - // capability's value is unknown. - fetcher.FetchCapability(); - - // Setting the account capability triggers the callback. - set_capability_state(signin::Tribool::kTrue); - identity_test_env_.UpdateAccountInfoForAccount(test_account_); - EXPECT_TRUE(capability_fetched_callback.Wait()); - EXPECT_EQ(signin::Tribool::kTrue, - capability_fetched_callback.Get<signin::Tribool>()); -} - -// Tests that the fetcher correctly handles a timeout. -TEST_F(AccountCapabilityFetcherTest, RunsCallbackOnTimeout) { - base::test::TestFuture<signin::Tribool> capability_fetched_callback; - AccountCapabilityFetcher fetcher(identity_test_env_.identity_manager(), - test_account_, - get_capability_state_callback(), - capability_fetched_callback.GetCallback()); - // Start the fetching. No callback is executed because the - // capability's value is unknown. - fetcher.FetchCapability(); - - // Expect the callback to be called after the timeout. - task_environment_.FastForwardBy(base::Seconds(5)); - EXPECT_TRUE(capability_fetched_callback.Wait()); - EXPECT_EQ(signin::Tribool::kUnknown, - capability_fetched_callback.Get<signin::Tribool>()); -} - -TEST_F(AccountCapabilityFetcherTest, IgnoresUpdateForOtherAccount) { - bool is_cb_executed = false; - base::OnceCallback<void(signin::Tribool)> callback = - base::BindLambdaForTesting( - [&](signin::Tribool) { is_cb_executed = true; }); - std::unique_ptr<AccountCapabilityFetcher> fetcher( - std::make_unique<AccountCapabilityFetcher>( - identity_test_env_.identity_manager(), test_account_, - get_capability_state_callback(), std::move(callback))); - - fetcher->FetchCapability(); - - set_capability_state(signin::Tribool::kTrue); - // Simulate an update for an unrelated account. - AccountInfo other_account = - identity_test_env_.MakeAccountAvailable("other@example.com"); - identity_test_env_.UpdateAccountInfoForAccount(other_account); - - // The callback has not been executed. - EXPECT_FALSE(is_cb_executed); -}
diff --git a/components/signin/public/identity_manager/account_state_fetcher.cc b/components/signin/public/identity_manager/account_state_fetcher.cc new file mode 100644 index 0000000..4f3c6a43 --- /dev/null +++ b/components/signin/public/identity_manager/account_state_fetcher.cc
@@ -0,0 +1,102 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/signin/public/identity_manager/account_state_fetcher.h" + +#include "base/functional/bind.h" +#include "base/functional/callback.h" +#include "base/scoped_observation.h" +#include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/tribool.h" + +namespace { +base::TimeDelta g_account_info_fetch_delay = base::Seconds(3); +} // namespace + +AccountStateFetcher::AccountStateFetcher( + signin::IdentityManager* identity_manager, + CoreAccountInfo core_account_info, + base::RepeatingCallback<signin::Tribool(const AccountInfo&)> + get_account_state_callback, + base::OnceCallback<void(signin::Tribool)> + on_account_info_fetched_callback) + : identity_manager_(identity_manager), + core_account_info_(core_account_info), + get_account_state_callback_(std::move(get_account_state_callback)), + on_account_info_fetched_callback_( + std::move(on_account_info_fetched_callback)) { + CHECK(identity_manager_); + CHECK(on_account_info_fetched_callback_); + CHECK(get_account_state_callback_); +} + +AccountStateFetcher::~AccountStateFetcher() = default; + +void AccountStateFetcher::FetchAccountInfo() { + // Start a timeout for the account info fetching. + account_info_timeout_timer_.Start( + FROM_HERE, g_account_info_fetch_delay, + base::BindOnce(&AccountStateFetcher::OnAccountInfoFetchTimeout, + // Unretained is fine as this class owns the timer. + base::Unretained(this))); + // Wait for the account info to arrive. + GetOrWaitForAccountInfo(core_account_info_); +} + +void AccountStateFetcher::EnforceTimeoutReachedForTesting() { + account_info_timeout_timer_.FireNow(); +} + +void AccountStateFetcher::OnExtendedAccountInfoUpdated( + const AccountInfo& account_info) { + if (account_info.account_id != core_account_info_.account_id) { + return; + } + GetOrWaitForAccountInfo(account_info); +} + +void AccountStateFetcher::OnIdentityManagerShutdown( + signin::IdentityManager* identity_manager) { + CHECK(identity_manager == identity_manager_.get()); + account_info_update_observation_.Reset(); + identity_manager_ = nullptr; +} + +void AccountStateFetcher::GetOrWaitForAccountInfo( + const CoreAccountInfo& core_account_info) { + CHECK(core_account_info.account_id == core_account_info_.account_id); + AccountInfo extended_account_info = + identity_manager_->FindExtendedAccountInfo(core_account_info); + signin::Tribool account_info_value = + get_account_state_callback_.Run(extended_account_info); + + if (account_info_value == signin::Tribool::kUnknown) { + if (!account_info_update_observation_.IsObserving()) { + account_info_update_observation_.Observe(identity_manager_); + } + return; + } + CHECK(account_info_value != signin::Tribool::kUnknown); + account_info_update_observation_.Reset(); + OnAccountInfoFetched(account_info_value); +} + +void AccountStateFetcher::OnAccountInfoFetched( + signin::Tribool account_info_value) { + // TODO(434964019): Confirm whether the account info is expected to remain + // unchanged, or whether we should observe and handle updates of the + // account info. + // Cancel the timeout callback. + account_info_timeout_timer_.Stop(); + + CHECK(!on_account_info_fetched_callback_.is_null()); + std::move(on_account_info_fetched_callback_).Run(account_info_value); +} + +void AccountStateFetcher::OnAccountInfoFetchTimeout() { + account_info_update_observation_.Reset(); + OnAccountInfoFetched(signin::Tribool::kUnknown); + // TODO(anthie): Maybe record metrics for this case. +}
diff --git a/components/signin/public/identity_manager/account_state_fetcher.h b/components/signin/public/identity_manager/account_state_fetcher.h new file mode 100644 index 0000000..7ab33aa9 --- /dev/null +++ b/components/signin/public/identity_manager/account_state_fetcher.h
@@ -0,0 +1,66 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_STATE_FETCHER_H_ +#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_STATE_FETCHER_H_ + +#include "base/functional/callback_forward.h" +#include "base/scoped_observation.h" +#include "base/timer/timer.h" +#include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/tribool.h" + +// Waits until some account info is fetched. +// The account state is computed through the input callback +// `get_account_state_callback_`. +// When the account info is fetched or we timeout while waiting for it, +// it executes the provided callback `on_account_info_fetched_callback_` +// and stops observing for further updates. +// Expected to be used for a single fetch only. +class AccountStateFetcher : public signin::IdentityManager::Observer { + public: + AccountStateFetcher( + signin::IdentityManager* identity_manager, + CoreAccountInfo core_account_info, + base::RepeatingCallback<signin::Tribool(const AccountInfo&)> + get_account_state_callback, + base::OnceCallback<void(signin::Tribool)> + on_account_info_fetched_callback); + + AccountStateFetcher(); + ~AccountStateFetcher() override; + + // Starts fetching the account info. Returns the result through + // `on_account_info_fetched_callback_` when ready and may + // return right away if already available. Should be called once. + void FetchAccountInfo(); + + void EnforceTimeoutReachedForTesting(); + + private: + // signin::IdentityManager::Observer: + void OnExtendedAccountInfoUpdated(const AccountInfo& account_info) override; + void OnIdentityManagerShutdown( + signin::IdentityManager* identity_manager) override; + + void GetOrWaitForAccountInfo(const CoreAccountInfo& core_account_info); + + void OnAccountInfoFetched(signin::Tribool account_info_value); + + void OnAccountInfoFetchTimeout(); + + base::ScopedObservation<signin::IdentityManager, + signin::IdentityManager::Observer> + account_info_update_observation_{this}; + + raw_ptr<signin::IdentityManager> identity_manager_; + CoreAccountInfo core_account_info_; + base::RepeatingCallback<signin::Tribool(const AccountInfo&)> + get_account_state_callback_; + base::OnceCallback<void(signin::Tribool)> on_account_info_fetched_callback_; + base::OneShotTimer account_info_timeout_timer_; +}; + +#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_STATE_FETCHER_H_
diff --git a/components/signin/public/identity_manager/account_state_fetcher_unittest.cc b/components/signin/public/identity_manager/account_state_fetcher_unittest.cc new file mode 100644 index 0000000..8dce9e7 --- /dev/null +++ b/components/signin/public/identity_manager/account_state_fetcher_unittest.cc
@@ -0,0 +1,125 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/signin/public/identity_manager/account_state_fetcher.h" + +#include <memory> + +#include "base/functional/bind.h" +#include "base/test/bind.h" +#include "base/test/task_environment.h" +#include "base/test/test_future.h" +#include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/signin/public/identity_manager/tribool.h" + +namespace { +constexpr char kTestEmail[] = "test@example.com"; +} // namespace + +class AccountStateFetcherTest : public testing::Test { + public: + AccountStateFetcherTest() = default; + + void SetUp() override { + test_account_ = identity_test_env_.MakeAccountAvailable(kTestEmail); + } + + // Helper to set the value that `get_account_state_callback` will return. + void set_account_info_state(signin::Tribool state) { + account_info_state_ = state; + // Update a test account field, so that subsequent calls to + // UpdateAccountInfoForAccount will trigger the extended info account + // update. + test_account_.full_name = std::string("name") + TriboolToString(state); + } + + // The callback passed to the fetcher to get the account info state. + base::RepeatingCallback<signin::Tribool(const AccountInfo&)> + get_account_state_callback() { + return base::BindRepeating( + [](signin::Tribool* state, const AccountInfo&) { return *state; }, + &account_info_state_); + } + + protected: + base::test::SingleThreadTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + signin::IdentityTestEnvironment identity_test_env_; + AccountInfo test_account_; + + // The current state of the account info we are awaiting for. + signin::Tribool account_info_state_ = signin::Tribool::kUnknown; +}; + +// Tests that the callback is executed immediately if the account info is already +// known. +TEST_F(AccountStateFetcherTest, RunsCallbackWhenAccountInfoAlreadyKnown) { + set_account_info_state(signin::Tribool::kTrue); + base::test::TestFuture<signin::Tribool> info_fetched_callback; + + AccountStateFetcher fetcher(identity_test_env_.identity_manager(), + test_account_, get_account_state_callback(), + info_fetched_callback.GetCallback()); + fetcher.FetchAccountInfo(); + EXPECT_TRUE(info_fetched_callback.Wait()); + EXPECT_EQ(signin::Tribool::kTrue, + info_fetched_callback.Get<signin::Tribool>()); +} + +// Tests that the fetcher waits for an account info update. +TEST_F(AccountStateFetcherTest, RunsCallbackWhenAccountInfoBecomesAvailable) { + base::test::TestFuture<signin::Tribool> info_fetched_callback; + AccountStateFetcher fetcher(identity_test_env_.identity_manager(), + test_account_, get_account_state_callback(), + info_fetched_callback.GetCallback()); + // Start the fetching. No callback is executed because the + // account info's value is unknown. + fetcher.FetchAccountInfo(); + + // Setting the account info triggers the callback. + set_account_info_state(signin::Tribool::kTrue); + identity_test_env_.UpdateAccountInfoForAccount(test_account_); + EXPECT_TRUE(info_fetched_callback.Wait()); + EXPECT_EQ(signin::Tribool::kTrue, + info_fetched_callback.Get<signin::Tribool>()); +} + +// Tests that the fetcher correctly handles a timeout. +TEST_F(AccountStateFetcherTest, RunsCallbackOnTimeout) { + base::test::TestFuture<signin::Tribool> info_fetched_callback; + AccountStateFetcher fetcher(identity_test_env_.identity_manager(), + test_account_, get_account_state_callback(), + info_fetched_callback.GetCallback()); + // Start the fetching. No callback is executed because the + // account info's value is unknown. + fetcher.FetchAccountInfo(); + + // Expect the callback to be called after the timeout. + task_environment_.FastForwardBy(base::Seconds(5)); + EXPECT_TRUE(info_fetched_callback.Wait()); + EXPECT_EQ(signin::Tribool::kUnknown, + info_fetched_callback.Get<signin::Tribool>()); +} + +TEST_F(AccountStateFetcherTest, IgnoresUpdateForOtherAccount) { + bool is_cb_executed = false; + base::OnceCallback<void(signin::Tribool)> callback = + base::BindLambdaForTesting( + [&](signin::Tribool) { is_cb_executed = true; }); + std::unique_ptr<AccountStateFetcher> fetcher( + std::make_unique<AccountStateFetcher>( + identity_test_env_.identity_manager(), test_account_, + get_account_state_callback(), std::move(callback))); + + fetcher->FetchAccountInfo(); + + set_account_info_state(signin::Tribool::kTrue); + // Simulate an update for an unrelated account. + AccountInfo other_account = + identity_test_env_.MakeAccountAvailable("other@example.com"); + identity_test_env_.UpdateAccountInfoForAccount(other_account); + + // The callback has not been executed. + EXPECT_FALSE(is_cb_executed); +}
diff --git a/components/signin/public/identity_manager/identity_test_environment.cc b/components/signin/public/identity_manager/identity_test_environment.cc index a39b81355..a5d458c 100644 --- a/components/signin/public/identity_manager/identity_test_environment.cc +++ b/components/signin/public/identity_manager/identity_test_environment.cc
@@ -362,8 +362,6 @@ std::move(gaia_cookie_manager_service); init_params.primary_account_manager = std::move(primary_account_manager); init_params.token_service = std::move(token_service); - // TODO: Set the account_manager_facade on Lacros once Mirror is enabled by - // default. #if BUILDFLAG(IS_CHROMEOS) init_params.account_manager_facade = account_manager_facade; #endif
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc index 9276a38..0a65a59 100644 --- a/components/sync/base/features.cc +++ b/components/sync/base/features.cc
@@ -88,6 +88,14 @@ #endif // BUILDFLAG(IS_CHROMEOS) ); +BASE_FEATURE(kSyncWalletFlightReservations, + "SyncWalletFlightReservations", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kSyncWalletVehicleRegistrations, + "SyncWalletVehicleRegistrations", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kEnableBookmarksSelectedTypeOnSigninForTesting, "EnableBookmarksSelectedTypeOnSigninForTesting", base::FEATURE_DISABLED_BY_DEFAULT); @@ -158,16 +166,6 @@ base::FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_IOS) -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -BASE_FEATURE(kSyncWalletFlightReservations, - "SyncWalletFlightReservations", - base::FEATURE_DISABLED_BY_DEFAULT); - -BASE_FEATURE(kSyncWalletVehicleRegistrations, - "SyncWalletVehicleRegistrations", - base::FEATURE_DISABLED_BY_DEFAULT); -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - BASE_FEATURE(kSyncDetermineAccountManagedStatus, "SyncDetermineAccountManagedStatus", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/sync/base/features.h b/components/sync/base/features.h index a3c0cfdc..13792b9e 100644 --- a/components/sync/base/features.h +++ b/components/sync/base/features.h
@@ -69,6 +69,12 @@ // kEnablePreferencesAccountStorage is enabled. BASE_DECLARE_FEATURE(kSyncSupportAlwaysSyncingPriorityPreferences); +// Enables syncing of flight reservations coming from Google Wallet. +BASE_DECLARE_FEATURE(kSyncWalletFlightReservations); + +// Enables syncing of vehicle registrations coming from Google Wallet. +BASE_DECLARE_FEATURE(kSyncWalletVehicleRegistrations); + // Normally, if kReplaceSyncPromosWithSignInPromos is disabled, // UserSelectableType::kBookmarks is disabled by default upon sign-in. This // flag makes the type enabled by default, for manual testing. @@ -165,13 +171,6 @@ BASE_DECLARE_FEATURE(kSyncTrustedVaultInfobarMessageImprovements); #endif // BUILDFLAG(IS_IOS) -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -// Enables syncing of flight reservations coming from Google Wallet. -BASE_DECLARE_FEATURE(kSyncWalletFlightReservations); -// Enables syncing of vehicle registrations coming from Google Wallet. -BASE_DECLARE_FEATURE(kSyncWalletVehicleRegistrations); -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - BASE_DECLARE_FEATURE(kSyncDetermineAccountManagedStatus); BASE_DECLARE_FEATURE_PARAM(base::TimeDelta, kSyncDetermineAccountManagedStatusTimeout);
diff --git a/components/viz/common/gpu/context_cache_controller.cc b/components/viz/common/gpu/context_cache_controller.cc index 09e0687e..01d8c04 100644 --- a/components/viz/common/gpu/context_cache_controller.cc +++ b/components/viz/common/gpu/context_cache_controller.cc
@@ -13,12 +13,10 @@ #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "gpu/command_buffer/client/context_support.h" -#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h" namespace viz { namespace { static const int kIdleCleanupDelaySeconds = 1; -static const int kOldResourceCleanupDelaySeconds = 15; } // namespace ContextCacheController::ScopedToken::ScopedToken() = default; @@ -49,10 +47,6 @@ ClientBecameNotVisible(std::move(held_visibility_)); } -void ContextCacheController::SetGrContext(GrDirectContext* gr_context) { - gr_context_ = gr_context; -} - void ContextCacheController::SetLock(base::Lock* lock) { context_lock_ = lock; } @@ -98,8 +92,6 @@ // We are freeing resources now - cancel any pending idle callbacks. InvalidatePendingIdleCallbacks(); - if (gr_context_) - gr_context_->freeGpuResources(); context_support_->SetAggressivelyFreeResources(true); context_support_->FlushPendingWork(); } @@ -138,13 +130,6 @@ DCHECK_GT(num_clients_busy_, 0u); --num_clients_busy_; - // Here we ask GrContext to free any resources that haven't been used in - // a long while even if it is under budget. - if (gr_context_) { - gr_context_->performDeferredCleanup( - std::chrono::seconds(kOldResourceCleanupDelaySeconds)); - } - // If we have become idle and we are visible, queue a task to drop resources // after a delay. If are not visible, we have already dropped resources. if (num_clients_busy_ == 0 && num_clients_visible_ > 0 && task_runner_) { @@ -205,9 +190,6 @@ return; } - if (gr_context_) - gr_context_->freeGpuResources(); - // Toggle SetAggressivelyFreeResources to drop command buffer data. context_support_->SetAggressivelyFreeResources(true); context_support_->FlushPendingWork();
diff --git a/components/viz/common/gpu/context_cache_controller.h b/components/viz/common/gpu/context_cache_controller.h index 7375def0..e0d3880 100644 --- a/components/viz/common/gpu/context_cache_controller.h +++ b/components/viz/common/gpu/context_cache_controller.h
@@ -16,8 +16,6 @@ #include "base/task/single_thread_task_runner.h" #include "components/viz/common/viz_common_export.h" -class GrDirectContext; - namespace base { class Lock; } @@ -54,7 +52,6 @@ scoped_refptr<base::SequencedTaskRunner> task_runner); virtual ~ContextCacheController(); - void SetGrContext(GrDirectContext* gr_context); void SetLock(base::Lock* lock); // Clients of the owning ContextProvider should call this function when they @@ -94,7 +91,6 @@ raw_ptr<gpu::ContextSupport> context_support_; scoped_refptr<base::SequencedTaskRunner> task_runner_; - raw_ptr<GrDirectContext> gr_context_ = nullptr; std::unique_ptr<ScopedVisibility> held_visibility_;
diff --git a/components/viz/common/gpu/context_cache_controller_unittest.cc b/components/viz/common/gpu/context_cache_controller_unittest.cc index af24b64..9e5ce67 100644 --- a/components/viz/common/gpu/context_cache_controller_unittest.cc +++ b/components/viz/common/gpu/context_cache_controller_unittest.cc
@@ -157,54 +157,5 @@ cache_controller.ClientBecameNotVisible(std::move(visible)); } -// Confirms that the Skia performDeferredCleanup API used by the cache -// controller behaves as expected. -TEST(ContextCacheControllerTest, CheckSkiaResourcePurgeAPI) { - StrictMock<MockContextSupport> context_support; - auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); - - // Must outlive `cache_controller`. - auto context_provider = TestContextProvider::Create(); - context_provider->BindToCurrentSequence(); - - ContextCacheController cache_controller(&context_support, task_runner); - auto* gr_context = context_provider->GrContext(); - cache_controller.SetGrContext(gr_context); - - // Make us visible. - EXPECT_CALL(context_support, SetAggressivelyFreeResources(false)); - auto visibility = cache_controller.ClientBecameVisible(); - Mock::VerifyAndClearExpectations(&context_support); - - // Now that we're visible, become busy, create and release a skia resource. - auto busy = cache_controller.ClientBecameBusy(); - { - auto image_info = SkImageInfo::MakeN32Premul(200, 200); - std::vector<uint8_t> image_data(image_info.computeMinByteSize()); - SkPixmap pixmap(image_info, image_data.data(), image_info.minRowBytes()); - auto image = SkImages::RasterFromPixmapCopy(pixmap); - auto image_gpu = SkImages::TextureFromImage(gr_context, std::move(image)); - gr_context->flushAndSubmit(); - } - - // Ensure we see size taken up for the image (now released, but cached for - // re-use). - EXPECT_GT(gr_context->getResourceCachePurgeableBytes(), 0u); - - // Make the client idle and wait for the idle callback to trigger. - cache_controller.ClientBecameNotBusy(std::move(busy)); - EXPECT_CALL(context_support, SetAggressivelyFreeResources(true)); - EXPECT_CALL(context_support, SetAggressivelyFreeResources(false)); - task_runner->FastForwardBy(base::Seconds(5)); - Mock::VerifyAndClearExpectations(&context_support); - - // The Skia resource cache should now be empty. - EXPECT_EQ(gr_context->getResourceCachePurgeableBytes(), 0u); - - // Set not-visible. - EXPECT_CALL(context_support, SetAggressivelyFreeResources(true)); - cache_controller.ClientBecameNotVisible(std::move(visibility)); -} - } // namespace } // namespace viz
diff --git a/components/viz/test/test_context_provider.cc b/components/viz/test/test_context_provider.cc index b30cd85..dcb53697 100644 --- a/components/viz/test/test_context_provider.cc +++ b/components/viz/test/test_context_provider.cc
@@ -349,7 +349,6 @@ gr_context_ = std::make_unique<skia_bindings::GrContextForGLES2Interface>( context_gl_.get(), support_.get(), context_gl_->test_capabilities(), max_resource_cache_bytes, max_glyph_cache_texture_bytes, true); - cache_controller_->SetGrContext(gr_context_->get()); // If GlContext is already lost, also abandon the new GrContext. if (ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
diff --git a/components/viz/test/test_in_process_context_provider.cc b/components/viz/test/test_in_process_context_provider.cc index 37fac54..d7f357a5 100644 --- a/components/viz/test/test_in_process_context_provider.cc +++ b/components/viz/test/test_in_process_context_provider.cc
@@ -108,24 +108,7 @@ } class GrDirectContext* TestInProcessContextProvider::GrContext() { - CheckValidThreadOrLockAcquired(); - if (gr_context_) { - return gr_context_->get(); - } - - if (!gles2_context_) { - return nullptr; - } - - size_t max_resource_cache_bytes; - size_t max_glyph_cache_texture_bytes; - gpu::DefaultGrCacheLimitsForTests(&max_resource_cache_bytes, - &max_glyph_cache_texture_bytes); - gr_context_ = std::make_unique<skia_bindings::GrContextForGLES2Interface>( - ContextGL(), ContextSupport(), ContextCapabilities(), - max_resource_cache_bytes, max_glyph_cache_texture_bytes); - cache_controller_->SetGrContext(gr_context_->get()); - return gr_context_->get(); + return nullptr; } gpu::SharedImageInterface*
diff --git a/components/viz/test/test_in_process_context_provider.h b/components/viz/test/test_in_process_context_provider.h index dfadd346..aac1d12 100644 --- a/components/viz/test/test_in_process_context_provider.h +++ b/components/viz/test/test_in_process_context_provider.h
@@ -30,10 +30,6 @@ } } // namespace gpu -namespace skia_bindings { -class GrContextForGLES2Interface; -} - namespace viz { class GpuServiceImpl; @@ -96,7 +92,6 @@ // Used for GLES2 contexts only. std::unique_ptr<gpu::GLInProcessContext> gles2_context_; - std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_; // Used for raster contexts only. std::unique_ptr<gpu::RasterInProcessContext> raster_context_;
diff --git a/content/browser/client_hints/client_hints.cc b/content/browser/client_hints/client_hints.cc index 93c2917..bf15a0ce 100644 --- a/content/browser/client_hints/client_hints.cc +++ b/content/browser/client_hints/client_hints.cc
@@ -44,6 +44,7 @@ #include "net/nqe/effective_connection_type.h" #include "net/nqe/network_quality_estimator_params.h" #include "services/network/public/cpp/client_hints.h" +#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "services/network/public/cpp/network_quality_tracker.h" #include "services/network/public/cpp/permissions_policy/client_hints_permissions_policy_mapping.h" @@ -1100,9 +1101,19 @@ // origin-level or "browser-level" policies like disabling JS or other // features. for (const auto& [hint, _] : client_hints_map) { + // `enabled_client_hints.hints` are client hints that are enabled for the + // origin and allowed to be attached to the request. if (ShouldAddClientHint(data, hint)) { enabled_client_hints.hints.push_back(hint); } + // `enabled_client_hints.not_allowed_hints` are client hints that are + // currently not allowed to be attached to the request. + if (base::FeatureList::IsEnabled( + network::features::kOffloadAcceptCHFrameCheck) && + network::features::kAcceptCHFrameOffloadNotAllowedHints.Get() && + !IsClientHintAllowed(data, hint)) { + enabled_client_hints.not_allowed_hints.push_back(hint); + } } enabled_client_hints.origin = data.main_frame_origin; return enabled_client_hints;
diff --git a/content/browser/client_hints/client_hints_unittest.cc b/content/browser/client_hints/client_hints_unittest.cc index d8f9f70..df87056 100644 --- a/content/browser/client_hints/client_hints_unittest.cc +++ b/content/browser/client_hints/client_hints_unittest.cc
@@ -10,6 +10,7 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "content/public/test/mock_client_hints_controller_delegate.h" #include "content/public/test/test_browser_context.h" @@ -19,6 +20,7 @@ #include "net/http/http_response_headers.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/cpp/client_hints.h" +#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "services/network/public/cpp/permissions_policy/permissions_policy_declaration.h" #include "testing/gmock/include/gmock/gmock-matchers.h" @@ -345,6 +347,7 @@ // We do not care the order of contents. EXPECT_THAT(actual_hints.hints, testing::UnorderedElementsAreArray(expected_types)); + EXPECT_TRUE(actual_hints.not_allowed_hints.empty()); } TEST_F(ClientHintsTest, GetEnabledClientHintsSubframe) { @@ -537,4 +540,47 @@ CriticalHintsMissingStatus::kPresent); } +TEST_F(ClientHintsTest, GetEnabledClientHintsSubframeNotAllowed) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeaturesAndParameters( + {{network::features::kOffloadAcceptCHFrameCheck, + {{network::features::kAcceptCHFrameOffloadNotAllowedHints.name, + "true"}}}}, + {}); + + GURL main_url(kOriginUrl); + contents()->NavigateAndCommit(main_url); + url::Origin main_origin = url::Origin::Create(main_url); + + FrameTree& frame_tree = contents()->GetPrimaryFrameTree(); + FrameTreeNode* main_frame_node = frame_tree.root(); + AddOneChildNode(); + FrameTreeNode* sub_frame_node = main_frame_node->child_at(0); + + blink::UserAgentMetadata ua_metadata; + MockClientHintsControllerDelegate delegate(ua_metadata); + + GURL sub_url("https://sub.example.com"); + const auto& actual_hints = GetEnabledClientHints(url::Origin::Create(sub_url), + sub_frame_node, &delegate); + + std::vector<network::mojom::WebClientHintsType> expected_allowed_hints; + std::vector<network::mojom::WebClientHintsType> expected_not_allowed_hints; + + for (const auto& [hint, _] : network::GetClientHintToNameMap()) { + if (blink::IsClientHintSentByDefault(hint)) { + expected_allowed_hints.push_back(hint); + } else { + expected_not_allowed_hints.push_back(hint); + } + } + + EXPECT_EQ(main_origin, actual_hints.origin); + EXPECT_FALSE(actual_hints.is_outermost_main_frame); + EXPECT_THAT(actual_hints.hints, + testing::UnorderedElementsAreArray(expected_allowed_hints)); + EXPECT_THAT(actual_hints.not_allowed_hints, + testing::UnorderedElementsAreArray(expected_not_allowed_hints)); +} + } // namespace content
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index 63deb592..8eaaec01 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -1463,6 +1463,9 @@ head_update_params_.load_timing_info .service_worker_router_evaluation_start; } + if (head_update_params_.is_synthetic_response_dry_run_mode) { + head->from_synthetic_response = true; + } // If the default loader (network) was used to handle the URL load request // we need to see if the interceptors want to potentially create a new
diff --git a/content/browser/loader/response_head_update_params.h b/content/browser/loader/response_head_update_params.h index 08c78bf..7601228f 100644 --- a/content/browser/loader/response_head_update_params.h +++ b/content/browser/loader/response_head_update_params.h
@@ -25,6 +25,7 @@ network::mojom::ServiceWorkerRouterInfoPtr router_info; std::optional<network::mojom::ServiceWorkerStatus> initial_service_worker_status; + bool is_synthetic_response_dry_run_mode = false; }; } // namespace content
diff --git a/content/browser/renderer_host/OWNERS b/content/browser/renderer_host/OWNERS index 177aa74..44812a9 100644 --- a/content/browser/renderer_host/OWNERS +++ b/content/browser/renderer_host/OWNERS
@@ -55,3 +55,6 @@ # View transitions test. per-file view_transition_browsertest.cc=vmpstr@chromium.org + +# Local Network Access +per-file private_network_access*.*=file://content/browser/security/local_network_access/OWNERS
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index 6ab2e63..063a6476 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -20,7 +20,9 @@ #include "base/functional/bind.h" #include "base/memory/weak_ptr.h" #include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_functions.h" #include "base/rand_util.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -758,12 +760,34 @@ features::kDeviceBoundSessionTerminationEvictBackForwardCache)) { result.No(BackForwardCacheMetrics::NotRestoredReason:: kCacheControlNoStoreDeviceBoundSessionTerminated); - } else if (render_frame_host->GetCookieChangeInfo() - .http_only_cookie_modification_count_ > 0) { + return; + } + + const RenderFrameHostImpl::CookieChangeListener::CookieChangeInfo& + cookie_change_info = render_frame_host->GetCookieChangeInfo(); + const std::string kCookieCHangeInfoMetricName = + "BackForwardCache.CCNS.CookieChangeInfo."; + base::UmaHistogramCounts1000( + base::StrCat({kCookieCHangeInfoMetricName, "AllCookies"}), + cookie_change_info.cookie_modification_count); + base::UmaHistogramCounts1000( + base::StrCat( + {kCookieCHangeInfoMetricName, "AllCookiesFromMainFrameNavigation"}), + cookie_change_info.cookie_modification_removing_count); + base::UmaHistogramCounts1000( + base::StrCat({kCookieCHangeInfoMetricName, "HttpOnlyCookies"}), + cookie_change_info.http_only_cookie_modification_count); + base::UmaHistogramCounts1000( + base::StrCat({kCookieCHangeInfoMetricName, + "HttpOnlyCookiesFromMainFrameNavigation"}), + cookie_change_info.http_only_cookie_modification_removing_count); + + if (cookie_change_info.http_only_cookie_modification_count > + cookie_change_info.http_only_cookie_modification_removing_count) { result.No(BackForwardCacheMetrics::NotRestoredReason:: kCacheControlNoStoreHTTPOnlyCookieModified); - } else if (render_frame_host->GetCookieChangeInfo() - .cookie_modification_count_ > 0) { + } else if (cookie_change_info.cookie_modification_count > + cookie_change_info.cookie_modification_removing_count) { // JavaScript cookies are modified but not HTTP cookies. Only restore based // on the experiment level. if (GetCacheControlNoStoreLevel() <=
diff --git a/content/browser/renderer_host/private_network_access_browsertest.cc b/content/browser/renderer_host/private_network_access_browsertest.cc index 861686f..bcddb971 100644 --- a/content/browser/renderer_host/private_network_access_browsertest.cc +++ b/content/browser/renderer_host/private_network_access_browsertest.cc
@@ -44,6 +44,10 @@ #include "url/gurl.h" #include "url/origin.h" +// Note: tests in this file are being migrated to work for Local Network Access; +// please do not add new tests to this file. Instead, tests should be added to +// content/browser/renderer_host/local_network_access_browsertest.cc + namespace content { namespace { @@ -782,39 +786,6 @@ // These tests verify the contents of `ClientSecurityState` for top-level // documents in various different circumstances. -// This test verifies the contents of the ClientSecurityState for the initial -// empty document in a new main frame created by the browser. -// -// Note: the renderer-created main frame case is exercised by the -// OpeneeInherits* tests below. -IN_PROC_BROWSER_TEST_F(PrivateNetworkAccessBrowserTest, - ClientSecurityStateForInitialEmptyDoc) { - // Start a navigation. This forces the RenderFrameHost to initialize its - // RenderFrame. The navigation is then cancelled by a HTTP 204 code. - // We're left with a RenderFrameHost containing the default - // ClientSecurityState values. - // - // Serve the response from a secure public server, to confirm that none of - // the connection's properties are reflected in the committed document, which - // is not a secure context and belongs to the `loopback` address space. - EXPECT_TRUE( - NavigateToURLAndExpectNoCommit(shell(), SecurePublicURL("/nocontent"))); - - const network::mojom::ClientSecurityStatePtr security_state = - root_frame_host()->BuildClientSecurityState(); - ASSERT_FALSE(security_state.is_null()); - EXPECT_FALSE(security_state->is_web_secure_context); - EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone, - security_state->cross_origin_embedder_policy.value); - EXPECT_EQ(network::mojom::PrivateNetworkRequestPolicy::kBlock, - security_state->private_network_request_policy); - - // Browser-created empty main frames are trusted to access the local network, - // if they execute code injected via DevTools, WebView APIs or extensions. - EXPECT_EQ(network::mojom::IPAddressSpace::kLoopback, - security_state->ip_address_space); -} - // This test verifies the contents of the ClientSecurityState for `about:blank` // in a new main frame created by the browser. // @@ -4236,48 +4207,4 @@ IsEmpty()); } -class LocalNetworkAccessBrowserTest - : public PrivateNetworkAccessBrowserTestBase { - public: - LocalNetworkAccessBrowserTest() - : PrivateNetworkAccessBrowserTestBase( - { - network::features::kLocalNetworkAccessChecks, - }, - {}) {} -}; - -IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, CheckSecurityState) { - EXPECT_TRUE(NavigateToURL(shell(), SecurePublicURL(kDefaultPath))); - - const network::mojom::ClientSecurityStatePtr security_state = - root_frame_host()->BuildClientSecurityState(); - ASSERT_FALSE(security_state.is_null()); - - EXPECT_TRUE(security_state->is_web_secure_context); - EXPECT_EQ(network::mojom::IPAddressSpace::kPublic, - security_state->ip_address_space); - - EXPECT_EQ(security_state->private_network_request_policy, - network::mojom::PrivateNetworkRequestPolicy::kPermissionWarn); -} - -IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, CheckBlockInsteadOfWarn) { - PolicyTestContentBrowserClient client; - client.SetBlockInsteadOfWarn(); - - EXPECT_TRUE(NavigateToURL(shell(), SecurePublicURL(kDefaultPath))); - - const network::mojom::ClientSecurityStatePtr security_state = - root_frame_host()->BuildClientSecurityState(); - ASSERT_FALSE(security_state.is_null()); - - EXPECT_TRUE(security_state->is_web_secure_context); - EXPECT_EQ(network::mojom::IPAddressSpace::kPublic, - security_state->ip_address_space); - - EXPECT_EQ(security_state->private_network_request_policy, - network::mojom::PrivateNetworkRequestPolicy::kPermissionBlock); -} - } // namespace content
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 43065b5b..80bcf15 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -18759,9 +18759,9 @@ // TODO (https://crbug.com/1399741): After adding the invalidation signals // API, we could mark the page as ineligible for BFCache as soon as the cookie // change event is received after the navigation is committed. - cookie_change_info_.cookie_modification_count_++; + cookie_change_info_.cookie_modification_count++; if (change.cookie.IsHttpOnly()) { - cookie_change_info_.http_only_cookie_modification_count_++; + cookie_change_info_.http_only_cookie_modification_count++; } }
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 43feed9..0675d4d 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -1535,9 +1535,13 @@ public: struct CookieChangeInfo { // The number of observed cookie modifications. - int64_t cookie_modification_count_ = 0; - // The number of observed HTTPOnly cookie modifications. - int64_t http_only_cookie_modification_count_ = 0; + int64_t cookie_modification_count = 0; + int64_t http_only_cookie_modification_count = 0; + // The number of observed cookie modifications that should be removed + // since we want to adjust the count by subtracting the number of cookie + // modification from the navigation itself. + int64_t cookie_modification_removing_count = 0; + int64_t http_only_cookie_modification_removing_count = 0; }; CookieChangeListener(StoragePartition* storage_partition, GURL& url); @@ -1557,9 +1561,9 @@ base::PassKey<content::NavigationRequest> navigation_request, uint64_t cookie_modification_count_delta, uint64_t http_only_cookie_modification_count_delta) { - cookie_change_info_.cookie_modification_count_ -= + cookie_change_info_.cookie_modification_removing_count += cookie_modification_count_delta; - cookie_change_info_.http_only_cookie_modification_count_ -= + cookie_change_info_.http_only_cookie_modification_removing_count += http_only_cookie_modification_count_delta; }
diff --git a/content/browser/security/local_network_access/OWNERS b/content/browser/security/local_network_access/OWNERS new file mode 100644 index 0000000..c8542ff --- /dev/null +++ b/content/browser/security/local_network_access/OWNERS
@@ -0,0 +1,5 @@ +clamy@chromium.org +cthomp@chromium.org +estark@chromium.org +hchao@chromium.org +jdeblasio@chromium.org
diff --git a/content/browser/security/local_network_access/local_network_access_browsertest.cc b/content/browser/security/local_network_access/local_network_access_browsertest.cc new file mode 100644 index 0000000..7557fac5 --- /dev/null +++ b/content/browser/security/local_network_access/local_network_access_browsertest.cc
@@ -0,0 +1,555 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <set> +#include <string> +#include <string_view> +#include <vector> + +#include "base/command_line.h" +#include "base/memory/raw_ptr.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/synchronization/lock.h" +#include "base/test/scoped_feature_list.h" +#include "base/thread_annotations.h" +#include "build/build_config.h" +#include "content/browser/renderer_host/frame_tree_node.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/public/common/content_client.h" +#include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/url_constants.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_content_browser_client.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/public/test/resource_load_observer.h" +#include "content/shell/browser/shell.h" +#include "content/test/content_browser_test_utils_internal.h" +#include "net/dns/mock_host_resolver.h" +#include "net/http/http_byte_range.h" +#include "net/http/http_util.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h" +#include "net/test/embedded_test_server/http_request.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/ip_address_space_overrides_test_utils.h" +#include "services/network/public/cpp/network_switches.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace content { +namespace { + +using ::net::test_server::METHOD_GET; +using ::net::test_server::METHOD_OPTIONS; +using ::testing::ElementsAre; +using ::testing::IsEmpty; + +// These domains are mapped to the IP addresses above using the +// `--host-resolver-rules` command-line switch. The exact values come from the +// embedded HTTPS server, which has certificates for these domains +constexpr char kLoopbackHost[] = "a.test"; +constexpr char kOtherLoopbackHost[] = "d.test"; +// not localhost, but a host with IP address space = kLocal +constexpr char kLocalHost[] = "b.test"; +constexpr char kPublicHost[] = "c.test"; + +// Path to a default response served by all servers in this test. +constexpr char kDefaultPath[] = "/defaultresponse"; + +// A |ContentBrowserClient| implementation that allows modifying the return +// value of |ShouldAllowInsecurePrivateNetworkRequests()| at will. +class PolicyTestContentBrowserClient + : public ContentBrowserTestContentBrowserClient { + public: + PolicyTestContentBrowserClient() = default; + + PolicyTestContentBrowserClient(const PolicyTestContentBrowserClient&) = + delete; + PolicyTestContentBrowserClient& operator=( + const PolicyTestContentBrowserClient&) = delete; + + ~PolicyTestContentBrowserClient() override = default; + + // Adds an origin to the allowlist. + void SetAllowInsecurePrivateNetworkRequestsFrom(const url::Origin& origin) { + allowlisted_origins_.insert(origin); + } + + void SetBlockInsteadOfWarn() { block_instead_of_warn_ = true; } + + ContentBrowserClient::PrivateNetworkRequestPolicyOverride + ShouldOverridePrivateNetworkRequestPolicy( + content::BrowserContext* browser_context, + const url::Origin& origin) override { + if (block_instead_of_warn_) { + return ContentBrowserClient::PrivateNetworkRequestPolicyOverride:: + kBlockInsteadOfWarn; + } + return allowlisted_origins_.find(origin) != allowlisted_origins_.end() + ? ContentBrowserClient::PrivateNetworkRequestPolicyOverride:: + kForceAllow + : ContentBrowserClient::PrivateNetworkRequestPolicyOverride:: + kDefault; + } + + private: + bool block_instead_of_warn_ = false; + std::set<url::Origin> allowlisted_origins_; +}; + +// An embedded test server connection listener that simply counts connections. +// Thread-safe. +class ConnectionCounter + : public net::test_server::EmbeddedTestServerConnectionListener { + public: + ConnectionCounter() = default; + + // Instances of this class are neither copyable nor movable. + ConnectionCounter(const ConnectionCounter&) = delete; + ConnectionCounter& operator=(const ConnectionCounter&) = delete; + ConnectionCounter(ConnectionCounter&&) = delete; + ConnectionCounter& operator=(ConnectionCounter&&) = delete; + + // Returns the number of sockets accepted by the servers we are listening to. + int count() const { + base::AutoLock guard(lock_); + return count_; + } + + private: + // EmbeddedTestServerConnectionListener implementation. + + std::unique_ptr<net::StreamSocket> AcceptedSocket( + std::unique_ptr<net::StreamSocket> socket) override { + { + base::AutoLock guard(lock_); + count_++; + } + return socket; + } + + void ReadFromSocket(const net::StreamSocket& socket, int rv) override {} + + // `count_` is incremented on the embedded test server thread and read on the + // test thread, so we synchronize accesses with a lock. + mutable base::Lock lock_; + int count_ GUARDED_BY(lock_) = 0; +}; + +class RequestObserver { + public: + RequestObserver() = default; + + // The returned callback must not outlive this instance. + net::test_server::EmbeddedTestServer::MonitorRequestCallback BindCallback() { + return base::BindRepeating(&RequestObserver::Observe, + base::Unretained(this)); + } + + // The origin of the URL is not checked for equality. + std::vector<net::test_server::HttpMethod> RequestMethodsForUrl( + const GURL& url) const { + std::string path = url.PathForRequest(); + std::vector<net::test_server::HttpMethod> methods; + { + base::AutoLock guard(lock_); + for (const auto& request : requests_) { + if (request.GetURL().PathForRequest() == path) { + methods.push_back(request.method); + } + } + } + return methods; + } + + private: + void Observe(const net::test_server::HttpRequest& request) { + base::AutoLock guard(lock_); + requests_.push_back(request); + } + + // `requests_` is mutated on the embedded test server thread and read on the + // test thread, so we synchronize accesses with a lock. + mutable base::Lock lock_; + std::vector<net::test_server::HttpRequest> requests_ GUARDED_BY(lock_); +}; + +// Removes `prefix` from the start of `str`, if present. +// Returns nullopt otherwise. +std::optional<std::string_view> StripPrefix(std::string_view str, + std::string_view prefix) { + if (!base::StartsWith(str, prefix)) { + return std::nullopt; + } + + return str.substr(prefix.size()); +} + +// Returns a pointer to the value of the `header` header in `request`, if any. +// Returns nullptr otherwise. +const std::string* FindRequestHeader( + const net::test_server::HttpRequest& request, + std::string_view header) { + const auto it = request.headers.find(header); + if (it == request.headers.end()) { + return nullptr; + } + + return &it->second; +} + +// Returns the `Content-Range` header value for a given `range` of bytes out of +// the given `total_size` number of bytes. +std::string GetContentRangeHeader(const net::HttpByteRange& range, + size_t total_size) { + std::string first = base::NumberToString(range.first_byte_position()); + std::string last = base::NumberToString(range.last_byte_position()); + std::string total = base::NumberToString(total_size); + return base::StrCat({"bytes ", first, "-", last, "/", total}); +} + +// An `EmbeddedTestServer` request handler function. +// +// Knows how to respond to CORS and PNA preflight requests, as well as regular +// and range requests. +// +// Route: /echorange?<body> +std::unique_ptr<net::test_server::HttpResponse> HandleRangeRequest( + const net::test_server::HttpRequest& request) { + std::optional<std::string_view> query = + StripPrefix(request.relative_url, "/echorange?"); + if (!query) { + return nullptr; + } + + auto response = std::make_unique<net::test_server::BasicHttpResponse>(); + + constexpr std::pair<std::string_view, std::string_view> kCopiedHeaders[] = { + {"Origin", "Access-Control-Allow-Origin"}, + {"Access-Control-Request-Private-Network", + "Access-Control-Allow-Private-Network"}, + {"Access-Control-Request-Headers", "Access-Control-Allow-Headers"}, + }; + for (const auto& pair : kCopiedHeaders) { + const std::string* value = FindRequestHeader(request, pair.first); + if (value) { + response->AddCustomHeader(pair.second, *value); + } + } + + // No body for a preflight response. + if (request.method == net::test_server::METHOD_OPTIONS) { + response->AddCustomHeader("Access-Control-Max-Age", "60"); + return response; + } + + // Cache-Control: max-age=X does not work for range request caching. Use a + // strong ETag instead, along with a last modified date. Both are required. + response->AddCustomHeader("ETag", "foo"); + response->AddCustomHeader("Last-Modified", "Fri, 1 Apr 2022 12:34:56 UTC"); + + const std::string* range_header = FindRequestHeader(request, "Range"); + if (!range_header) { + // Not a range request. Respond with 200 and the whole query as the body. + response->set_content(*query); + return response; + } + + std::vector<net::HttpByteRange> ranges; + if (!net::HttpUtil::ParseRangeHeader(*range_header, &ranges) || + ranges.size() != 1) { + response->set_code(net::HTTP_BAD_REQUEST); + return response; + } + + net::HttpByteRange& range = ranges[0]; + if (!range.ComputeBounds(query->size())) { + response->set_code(net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE); + return response; + } + + response->set_code(net::HTTP_PARTIAL_CONTENT); + response->AddCustomHeader("Content-Range", + GetContentRangeHeader(range, query->size())); + response->set_content(query->substr(range.first_byte_position(), + range.last_byte_position() + 1)); + return response; +} + +// A `net::EmbeddedTestServer` that pretends to be in a given IP address space. +// +// Set up of the command line in order for this server to be considered a part +// of `ip_address_space` must be done outside of server creation. +class FakeAddressSpaceServer { + public: + FakeAddressSpaceServer(net::EmbeddedTestServer::Type type, + net::test_server::HttpConnection::Protocol protocol, + network::mojom::IPAddressSpace ip_address_space, + const base::FilePath& test_data_path) + : server_(type, protocol), ip_address_space_(ip_address_space) { + // Use a certificate valid for multiple domains, which we can use to + // distinguish `loopback`, `local` and `public` address spaces. + server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); + + server_.SetConnectionListener(&connection_counter_); + server_.RegisterRequestMonitor(request_observer_.BindCallback()); + server_.RegisterRequestHandler(base::BindRepeating(&HandleRangeRequest)); + server_.AddDefaultHandlers(test_data_path); + CHECK(server_.Start()); + } + + std::string GenerateCommandLineSwitchOverride() const { + return network::GenerateIpAddressSpaceOverride(server_, ip_address_space_); + } + + // Returns the underlying test server. + net::EmbeddedTestServer& Get() { return server_; } + + // Returns the total number of sockets accepted by this server. + int ConnectionCount() const { return connection_counter_.count(); } + + const RequestObserver& request_observer() const { return request_observer_; } + + private: + ConnectionCounter connection_counter_; + RequestObserver request_observer_; + net::EmbeddedTestServer server_; + const network::mojom::IPAddressSpace ip_address_space_; +}; + +} // namespace + +// This being an integration/browser test, we concentrate on a few behaviors +// relevant to Local Network Access: +// +// - testing the values of important properties on top-level documents: +// - address space +// - secure context bit +// - private network request policy +// - testing the inheritance semantics of these properties +// - testing the correct handling of the CSP: treat-as-public-address directive +// - testing that subresource requests are subject to LNA checks +// - and a few other odds and ends +// +// We use the `--ip-address-space-overrides` command-line switch to test against +// `local` and `public` address spaces, even though all responses are actually +// served from localhost. Combined with host resolver rules, this lets us define +// three different domains that map to the different address spaces: +// +// - `a.test` is `loopback` +// - `b.test` is `local` +// - `c.test` is `public` +// +// We also have unit tests that test all possible combinations of source and +// destination IP address spaces in services/network/url_loader_unittest.cc. +class LocalNetworkAccessBrowserTestBase : public ContentBrowserTest { + public: + RenderFrameHostImpl* root_frame_host() { + return static_cast<RenderFrameHostImpl*>( + shell()->web_contents()->GetPrimaryMainFrame()); + } + + protected: + // Allows subclasses to construct instances with different features enabled. + explicit LocalNetworkAccessBrowserTestBase() + : insecure_loopback_server_( + net::EmbeddedTestServer::TYPE_HTTP, + net::test_server::HttpConnection::Protocol::kHttp1, + network::mojom::IPAddressSpace::kLoopback, + GetTestDataFilePath()), + insecure_local_server_( + net::EmbeddedTestServer::TYPE_HTTP, + net::test_server::HttpConnection::Protocol::kHttp1, + network::mojom::IPAddressSpace::kLocal, + GetTestDataFilePath()), + insecure_public_server_( + net::EmbeddedTestServer::TYPE_HTTP, + net::test_server::HttpConnection::Protocol::kHttp1, + network::mojom::IPAddressSpace::kPublic, + GetTestDataFilePath()), + secure_loopback_server_( + net::EmbeddedTestServer::TYPE_HTTPS, + net::test_server::HttpConnection::Protocol::kHttp1, + network::mojom::IPAddressSpace::kLoopback, + GetTestDataFilePath()), + secure_local_server_(net::EmbeddedTestServer::TYPE_HTTPS, + net::test_server::HttpConnection::Protocol::kHttp1, + network::mojom::IPAddressSpace::kLocal, + GetTestDataFilePath()), + secure_public_server_( + net::EmbeddedTestServer::TYPE_HTTPS, + net::test_server::HttpConnection::Protocol::kHttp1, + network::mojom::IPAddressSpace::kPublic, + GetTestDataFilePath()) {} + + void SetUpOnMainThread() override { + ContentBrowserTest::SetUpOnMainThread(); + + // Rules must be added on the main thread, otherwise `AddRule()` segfaults. + host_resolver()->AddRule(kLoopbackHost, "127.0.0.1"); + host_resolver()->AddRule(kOtherLoopbackHost, "127.0.0.1"); + host_resolver()->AddRule(kLocalHost, "127.0.0.1"); + host_resolver()->AddRule(kPublicHost, "127.0.0.1"); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + ContentBrowserTest::SetUpCommandLine(command_line); + // Add correct ip address space overrides. + network::AddIpAddressSpaceOverridesToCommandLine( + {insecure_loopback_server_.GenerateCommandLineSwitchOverride(), + insecure_local_server_.GenerateCommandLineSwitchOverride(), + insecure_public_server_.GenerateCommandLineSwitchOverride(), + secure_loopback_server_.GenerateCommandLineSwitchOverride(), + secure_local_server_.GenerateCommandLineSwitchOverride(), + secure_public_server_.GenerateCommandLineSwitchOverride()}, + *command_line); + } + + const FakeAddressSpaceServer& InsecureLoopbackServer() const { + return insecure_loopback_server_; + } + + const FakeAddressSpaceServer& InsecureLocalServer() const { + return insecure_local_server_; + } + + const FakeAddressSpaceServer& InsecurePublicServer() const { + return insecure_public_server_; + } + + const FakeAddressSpaceServer& SecureLoopbackServer() const { + return secure_loopback_server_; + } + + const FakeAddressSpaceServer& SecureLocalServer() const { + return secure_local_server_; + } + + const FakeAddressSpaceServer& SecurePublicServer() const { + return secure_public_server_; + } + + GURL InsecureLoopbackURL(const std::string& path) { + return insecure_loopback_server_.Get().GetURL(kLoopbackHost, path); + } + + GURL InsecureLocalURL(const std::string& path) { + return insecure_local_server_.Get().GetURL(kLocalHost, path); + } + + GURL InsecurePublicURL(const std::string& path) { + return insecure_public_server_.Get().GetURL(kPublicHost, path); + } + + GURL SecureLoopbackURL(const std::string& path) { + return secure_loopback_server_.Get().GetURL(kLoopbackHost, path); + } + + GURL OtherSecureLoopbackURL(const std::string& path) { + return secure_loopback_server_.Get().GetURL(kOtherLoopbackHost, path); + } + + GURL SecureLocalURL(const std::string& path) { + return secure_local_server_.Get().GetURL(kLocalHost, path); + } + + GURL SecurePublicURL(const std::string& path) { + return secure_public_server_.Get().GetURL(kPublicHost, path); + } + + GURL NullIPURL(const std::string& path) { + return insecure_public_server_.Get().GetURL("0.0.0.0", path); + } + + private: + base::test::ScopedFeatureList feature_list_; + + FakeAddressSpaceServer insecure_loopback_server_; + FakeAddressSpaceServer insecure_local_server_; + FakeAddressSpaceServer insecure_public_server_; + FakeAddressSpaceServer secure_loopback_server_; + FakeAddressSpaceServer secure_local_server_; + FakeAddressSpaceServer secure_public_server_; +}; + +// Test with insecure local network subresource requests from the `public` +// address space blocked. +class LocalNetworkAccessBrowserTest : public LocalNetworkAccessBrowserTestBase { + public: + LocalNetworkAccessBrowserTest() : LocalNetworkAccessBrowserTestBase() { + // Some builders run with field_trial disabled, need to enable this + // manually. + base::FieldTrialParams params; + params["LocalNetworkAccessChecksWarn"] = "false"; + feature_list_.InitAndEnableFeatureWithParameters( + network::features::kLocalNetworkAccessChecks, params); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// =========================== +// CLIENT SECURITY STATE TESTS +// =========================== +// +// These tests verify the contents of `ClientSecurityState` for top-level +// documents in various different circumstances. + +// This test verifies the contents of the ClientSecurityState for the initial +// empty document in a new main frame created by the browser. +// +// Note: the renderer-created main frame case is exercised by the +// OpeneeInherits* tests below. +IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, + ClientSecurityStateForInitialEmptyDoc) { + // Start a navigation. This forces the RenderFrameHost to initialize its + // RenderFrame. The navigation is then cancelled by a HTTP 204 code. + // We're left with a RenderFrameHost containing the default + // ClientSecurityState values. + // + // Serve the response from a secure public server, to confirm that none of + // the connection's properties are reflected in the committed document, which + // is not a secure context and belongs to the `loopback` address space. + EXPECT_TRUE( + NavigateToURLAndExpectNoCommit(shell(), SecurePublicURL("/nocontent"))); + + const network::mojom::ClientSecurityStatePtr security_state = + root_frame_host()->BuildClientSecurityState(); + ASSERT_FALSE(security_state.is_null()); + EXPECT_FALSE(security_state->is_web_secure_context); + EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone, + security_state->cross_origin_embedder_policy.value); + EXPECT_EQ(network::mojom::PrivateNetworkRequestPolicy::kBlock, + security_state->private_network_request_policy); + + // Browser-created empty main frames are trusted to access the local network, + // if they execute code injected via DevTools, WebView APIs or extensions. + EXPECT_EQ(network::mojom::IPAddressSpace::kLoopback, + security_state->ip_address_space); +} + +IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, CheckSecurityState) { + EXPECT_TRUE(NavigateToURL(shell(), SecurePublicURL(kDefaultPath))); + + const network::mojom::ClientSecurityStatePtr security_state = + root_frame_host()->BuildClientSecurityState(); + ASSERT_FALSE(security_state.is_null()); + + EXPECT_TRUE(security_state->is_web_secure_context); + EXPECT_EQ(network::mojom::IPAddressSpace::kPublic, + security_state->ip_address_space); + + EXPECT_EQ(security_state->private_network_request_policy, + network::mojom::PrivateNetworkRequestPolicy::kPermissionBlock); +} + +} // namespace content
diff --git a/content/browser/renderer_host/local_network_access_browsertest.cc b/content/browser/security/local_network_access/local_network_access_deprecation_browsertest.cc similarity index 100% rename from content/browser/renderer_host/local_network_access_browsertest.cc rename to content/browser/security/local_network_access/local_network_access_deprecation_browsertest.cc
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index 5895e8c4..069b62c 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -56,6 +56,7 @@ #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_controllee_request_handler.h" #include "content/browser/service_worker/service_worker_fetch_dispatcher.h" +#include "content/browser/service_worker/service_worker_loader_helpers.h" #include "content/browser/service_worker/service_worker_registration.h" #include "content/browser/service_worker/service_worker_test_utils.h" #include "content/browser/service_worker/service_worker_version.h" @@ -7615,7 +7616,8 @@ // Test class for synthetic response (crbug.com/352578800) browsertest. class ServiceWorkerSyntheticResponseBrowserTest - : public ServiceWorkerBrowserTest { + : public ServiceWorkerBrowserTest, + public ::testing::WithParamInterface<bool> { public: static constexpr char kHostname[] = "synthetic-response.test"; static constexpr char kTargetPath[] = @@ -7643,6 +7645,7 @@ ASSERT_TRUE(https_server_->InitializeAndListen()); https_server_->StartAcceptingConnections(); ServiceWorkerBrowserTest::SetUpOnMainThread(); + ServiceWorkerSyntheticResponseManager::SetDryRunMode(IsDryRunMode()); } RenderFrameHost* GetPrimaryMainFrame() { @@ -7680,6 +7683,7 @@ mock_content_browser_client = std::make_unique<MockContentBrowserClient>(); mock_content_browser_client->set_synthetic_response_enabled(true); } + bool IsDryRunMode() { return GetParam(); } std::unique_ptr<MockContentBrowserClient> mock_content_browser_client; @@ -7759,7 +7763,11 @@ base::HistogramTester histogram_tester_; }; -IN_PROC_BROWSER_TEST_F(ServiceWorkerSyntheticResponseBrowserTest, +INSTANTIATE_TEST_SUITE_P(All, + ServiceWorkerSyntheticResponseBrowserTest, + testing::Bool()); + +IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, FakeRegistration) { GURL::Replacements replacements; replacements.ClearQuery(); @@ -7794,7 +7802,7 @@ blink::ServiceWorkerStatusCode::kErrorNotFound); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerSyntheticResponseBrowserTest, +IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, MatchedPageIsServiceWorkerControlled) { SetUpMockContentBrowserClient(); // Navigated URL matched with the URL in the allowlist is controlled by @@ -7807,7 +7815,7 @@ EXPECT_EQ("[SyntheticResponse] Response from the network", GetInnerText()); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerSyntheticResponseBrowserTest, +IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, ResponseHeaderIsStored) { SetUpMockContentBrowserClient(); // Navigate and store the response header. @@ -7826,8 +7834,10 @@ static_cast<int>(ServiceWorkerMetrics::SyntheticResponseEligibility:: kNotEligibleByNoHeaderStored), 1); + // If dry run mode, `IsHeaderStored` is not recorded. histogram_tester().ExpectBucketCount( - "ServiceWorker.SyntheticResponse.IsHeaderStored", true, 1); + "ServiceWorker.SyntheticResponse.IsHeaderStored", true, + IsDryRunMode() ? 0 : 1); // The second navigation. The browser should have stored the response header // from the previous navigation, and receive the response header locally. @@ -7848,7 +7858,7 @@ 1); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerSyntheticResponseBrowserTest, +IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, InlineScriptIsNotAllowedUntilMetaCSPScriptSrc) { SetUpMockContentBrowserClient(); // Navigate and store the response header. @@ -7878,7 +7888,7 @@ "window.is_inline_script_executed")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerSyntheticResponseBrowserTest, +IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, HeaderMismatch) { SetUpMockContentBrowserClient(); // Navigate and store the response header. @@ -7902,7 +7912,8 @@ kHostname, base::StrCat( {kTargetPath, "foo&echo=bar&server_slow&header_mismatch"})), - /*number_of_navigations=*/2, /*ignore_uncommitted_navigations=*/false); + /*number_of_navigations=*/IsDryRunMode() ? 1 : 2, + /*ignore_uncommitted_navigations=*/false); EXPECT_EQ("[SyntheticResponse] bar", GetInnerText()); // After the reload, synthetic response is not enabled. `responseStart` is // 2000ms due to the server delay. @@ -7918,7 +7929,7 @@ 0); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerSyntheticResponseBrowserTest, +IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, HeaderMismatch_DuplicatedHeader) { SetUpMockContentBrowserClient(); // Navigate and store the response header. @@ -7942,7 +7953,8 @@ base::StrCat({kTargetPath, "foo&echo=bar&server_slow&header_" "mismatch_with_duplicated_header"})), - /*number_of_navigations=*/2, /*ignore_uncommitted_navigations=*/false); + /*number_of_navigations=*/IsDryRunMode() ? 1 : 2, + /*ignore_uncommitted_navigations=*/false); EXPECT_EQ("[SyntheticResponse] bar", GetInnerText()); // After the reload, synthetic response is not enabled. `responseStart` is // 2000ms due to the server delay. @@ -7951,7 +7963,7 @@ "responseStart) >= 2000")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerSyntheticResponseBrowserTest, +IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, HeaderMismatch_IgnoredHeader) { SetUpMockContentBrowserClient(); // Navigate and store the response header.
diff --git a/content/browser/service_worker/service_worker_loader_helpers.cc b/content/browser/service_worker/service_worker_loader_helpers.cc index 03851ff5..133d762 100644 --- a/content/browser/service_worker/service_worker_loader_helpers.cc +++ b/content/browser/service_worker/service_worker_loader_helpers.cc
@@ -17,6 +17,7 @@ #include "content/browser/devtools/devtools_instrumentation.h" #include "content/browser/loader/browser_initiated_resource_request.h" #include "content/browser/service_worker/service_worker_consts.h" +#include "content/browser/service_worker/service_worker_synthetic_response_manager.h" #include "content/common/features.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" @@ -456,6 +457,16 @@ return false; } +bool IsSyntheticResponseDryRunModeEnabled() { + if (ServiceWorkerSyntheticResponseManager::IsDryRunModeEnabledForTesting()) { + return true; + } + static const bool is_dry_run( + blink::features::kServiceWorkerSyntheticResponseDryRun.Get()); + + return is_dry_run; +} + } // namespace service_worker_loader_helpers } // namespace content
diff --git a/content/browser/service_worker/service_worker_loader_helpers.h b/content/browser/service_worker/service_worker_loader_helpers.h index c3bcaf7..df2e50a20 100644 --- a/content/browser/service_worker/service_worker_loader_helpers.h +++ b/content/browser/service_worker/service_worker_loader_helpers.h
@@ -106,7 +106,7 @@ const GURL& client_url, const std::string& allowed_url, const base::flat_set<std::string>& denied_url_params); - +bool IsSyntheticResponseDryRunModeEnabled(); } // namespace service_worker_loader_helpers } // namespace content
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.cc b/content/browser/service_worker/service_worker_main_resource_loader.cc index acc6acb..d3a6922 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader.cc
@@ -48,6 +48,7 @@ #include "services/network/public/mojom/fetch_api.mojom.h" #include "services/network/public/mojom/service_worker_router_info.mojom-shared.h" #include "services/network/public/mojom/service_worker_router_info.mojom.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/service_worker/service_worker_loader_helpers.h" #include "third_party/blink/public/mojom/service_worker/service_worker_fetch_handler_bypass_option.mojom-shared.h" #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-shared.h" @@ -323,6 +324,8 @@ head_update_params.load_timing_info = response_head_->load_timing; head_update_params.initial_service_worker_status = initial_service_worker_status_.value(); + head_update_params.is_synthetic_response_dry_run_mode = + is_synthetic_response_used_; Fallback(std::move(head_update_params)); // If the kServiceWorkerStaticRouterStartServiceWorker feature is @@ -1036,6 +1039,29 @@ return false; } + if (service_worker_loader_helpers::IsSyntheticResponseDryRunModeEnabled()) { + if (version->GetResponseHeadForSyntheticResponse()) { + // With dry-run mode, update `is_synthetic_response_used_` here. This will + // update the actual response head through `ResponseHeadUpdateParams` and + // pass the information to the renderer. + is_synthetic_response_used_ = true; + RecordSyntheticResponseEligibility( + SyntheticResponseEligibility::kEligible); + } else { + // If dry-run mode, do not dispatch a network request for the synthetic + // response. Instead, set a fake response headers to + // `ServiceWorkerVersion` if it doesn't exist in order to simulate the + // next navigation is eligible for the synthetic response. + network::mojom::URLResponseHeadPtr fake_response_head = + network::mojom::URLResponseHead::New(); + version->SetResponseHeadForSyntheticResponse( + std::move(fake_response_head)); + RecordSyntheticResponseEligibility( + SyntheticResponseEligibility::kNotEligibleByNoHeaderStored); + } + return false; + } + is_synthetic_response_used_ = true; synthetic_response_manager_.emplace(
diff --git a/content/browser/service_worker/service_worker_synthetic_response_manager.cc b/content/browser/service_worker/service_worker_synthetic_response_manager.cc index d41023c..e694673 100644 --- a/content/browser/service_worker/service_worker_synthetic_response_manager.cc +++ b/content/browser/service_worker/service_worker_synthetic_response_manager.cc
@@ -458,4 +458,13 @@ } OnCloneCompleted(); } + +bool ServiceWorkerSyntheticResponseManager::dry_run_mode_for_testing_ = false; +void ServiceWorkerSyntheticResponseManager::SetDryRunMode(bool enabled) { + dry_run_mode_for_testing_ = enabled; +} +bool ServiceWorkerSyntheticResponseManager::IsDryRunModeEnabledForTesting() { + return dry_run_mode_for_testing_; +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_synthetic_response_manager.h b/content/browser/service_worker/service_worker_synthetic_response_manager.h index 0929f22..0a8c48a9 100644 --- a/content/browser/service_worker/service_worker_synthetic_response_manager.h +++ b/content/browser/service_worker/service_worker_synthetic_response_manager.h
@@ -64,6 +64,10 @@ void StartSyntheticResponse(FetchCallback callback); SyntheticResponseStatus Status() const { return status_; } + // The static function to override the dry run mode. + static void SetDryRunMode(bool enabled); + static bool IsDryRunModeEnabledForTesting(); + private: class SyntheticResponseURLLoaderClient; @@ -105,6 +109,8 @@ mojo::Remote<blink::mojom::ServiceWorkerStreamCallback> stream_callback_; std::optional<RaceNetworkRequestSimpleBufferManager> simple_buffer_manager_; + static bool dry_run_mode_for_testing_; + base::WeakPtrFactory<ServiceWorkerSyntheticResponseManager> weak_factory_{ this}; };
diff --git a/content/browser/webauth/authenticator_common_impl.cc b/content/browser/webauth/authenticator_common_impl.cc index 900591c..ef816b4 100644 --- a/content/browser/webauth/authenticator_common_impl.cc +++ b/content/browser/webauth/authenticator_common_impl.cc
@@ -1510,6 +1510,18 @@ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR); return; } + + if (public_key_options->extensions->remote_desktop_client_override && + options->mediation == Mediation::IMMEDIATE) { + mojo::ReportBadMessage( + "Immediate mediation cannot be used with a remote desktop override " + "request"); + req_state_->request_outcome = GetAssertionOutcome::kOtherFailure; + CompleteGetAssertionRequest( + blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR); + return; + } + req_state_->mediation_ = options->mediation; if (public_key_options->challenge_url.has_value() &&
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index ec521c8..27b17a6 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -3181,6 +3181,38 @@ } } +TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest, + GetAssertionImmediateMediation) { + // Verify that an authorized origin may not use the extension with immediate + // mediation. + NavigateAndCommit(GURL(kCorpCrdOrigin)); + + PublicKeyCredentialRequestOptionsPtr options = + GetTestPublicKeyCredentialRequestOptions(); + options->allow_credentials.clear(); + options->relying_party_id = kExampleRpId; + options->extensions->remote_desktop_client_override = + RemoteDesktopClientOverride::New( + url::Origin::Create(GURL(kExampleOrigin)), true); + + mojo::Remote<blink::mojom::Authenticator> authenticator = + ConnectToAuthenticator(); + base::test::TestFuture<void> mojo_error_future; + SetMojoErrorHandler(base::BindLambdaForTesting([&](const std::string& error) { + EXPECT_EQ(error, + "Immediate mediation cannot be used with a remote desktop " + "override request"); + mojo_error_future.SetValue(); + })); + + auto get_credential_options = GetCredentialOptions::New(); + get_credential_options->public_key = std::move(options); + get_credential_options->mediation = blink::mojom::Mediation::IMMEDIATE; + authenticator->GetCredential(std::move(get_credential_options), + base::DoNothing()); + EXPECT_TRUE(mojo_error_future.Wait()); +} + class MockAuthenticatorRequestDelegateObserver : public TestAuthenticatorRequestDelegate { public:
diff --git a/content/browser/webrtc/resources/stats_rates_calculator.js b/content/browser/webrtc/resources/stats_rates_calculator.js index 4a81214..e201712c 100644 --- a/content/browser/webrtc/resources/stats_rates_calculator.js +++ b/content/browser/webrtc/resources/stats_rates_calculator.js
@@ -467,188 +467,164 @@ constructor() { this.previousReport = null; this.currentReport = null; - this.statsCalculators = [ - { - type: 'data-channel', - metricCalculators: { - messagesSent: new RateCalculator('messagesSent', 'timestamp'), - messagesReceived: new RateCalculator('messagesReceived', 'timestamp'), - bytesSent: new RateCalculator( - 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), - bytesReceived: new RateCalculator( - 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), - }, + this.statsCalculators = { + 'data-channel': { + messagesSent: new RateCalculator('messagesSent', 'timestamp'), + messagesReceived: new RateCalculator('messagesReceived', 'timestamp'), + bytesSent: new RateCalculator( + 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), + bytesReceived: new RateCalculator( + 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), }, - { - type: 'media-source', - metricCalculators: { - totalAudioEnergy: new AudioLevelRmsCalculator(), - }, + 'media-source': { + totalAudioEnergy: new AudioLevelRmsCalculator(), }, - { - type: 'media-playout', - metricCalculators: { - totalPlayoutDelay: new RateCalculator('totalPlayoutDelay', - 'totalSamplesCount'), - }, + 'media-playout': { + totalPlayoutDelay: new RateCalculator('totalPlayoutDelay', + 'totalSamplesCount'), }, - { - type: 'outbound-rtp', - metricCalculators: { - bytesSent: new RateCalculator( - 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), - headerBytesSent: new RateCalculator( - 'headerBytesSent', 'timestamp', CalculatorModifier.kBytesToBits), - retransmittedBytesSent: new RateCalculator( - 'retransmittedBytesSent', 'timestamp', - CalculatorModifier.kBytesToBits), - packetsSent: new RateCalculator('packetsSent', 'timestamp'), - retransmittedPacketsSent: - new RateCalculator('retransmittedPacketsSent', 'timestamp'), - totalPacketSendDelay: new RateCalculator( - 'totalPacketSendDelay', 'packetsSent', - CalculatorModifier.kMillisecondsFromSeconds), - framesEncoded: new RateCalculator('framesEncoded', 'timestamp'), - framesSent: new RateCalculator('framesSent', 'timestamp'), - totalEncodedBytesTarget: new RateCalculator( - 'totalEncodedBytesTarget', 'timestamp', - CalculatorModifier.kBytesToBits), - totalEncodeTime: new RateCalculator( - 'totalEncodeTime', 'framesEncoded', - CalculatorModifier.kMillisecondsFromSeconds), - qpSum: new RateCalculator('qpSum', 'framesEncoded'), - // Currently limited to a single output. - psnrSum: new PsnrRateCalculator('y'), - codecId: new CodecCalculator(), - }, - }, - { - type: 'inbound-rtp', - metricCalculators: { - bytesReceived: new RateCalculator( - 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), - headerBytesReceived: new RateCalculator( - 'headerBytesReceived', 'timestamp', - CalculatorModifier.kBytesToBits), - retransmittedBytesReceived: new RateCalculator( - 'retransmittedBytesReceived', 'timestamp', + 'outbound-rtp': { + bytesSent: new RateCalculator( + 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), + headerBytesSent: new RateCalculator( + 'headerBytesSent', 'timestamp', CalculatorModifier.kBytesToBits), + retransmittedBytesSent: new RateCalculator( + 'retransmittedBytesSent', 'timestamp', CalculatorModifier.kBytesToBits), - fecBytesReceived: new RateCalculator( - 'fecBytesReceived', 'timestamp', - CalculatorModifier.kBytesToBits), - packetsReceived: new RateCalculator('packetsReceived', 'timestamp'), - packetsDiscarded: new RateCalculator('packetsDiscarded', 'timestamp'), - retransmittedPacketsReceived: - new RateCalculator('retransmittedPacketsReceived', 'timestamp'), - fecPacketsReceived: - new RateCalculator('fecPacketsReceived', 'timestamp'), - fecPacketsDiscarded: - new RateCalculator('fecPacketsDiscarded', 'timestamp'), - framesReceived: [ - new RateCalculator('framesReceived', 'timestamp'), - new DifferenceCalculator('framesReceived', - 'framesDecoded', 'framesDropped'), - ], - framesDecoded: new RateCalculator('framesDecoded', 'timestamp'), - keyFramesDecoded: new RateCalculator('keyFramesDecoded', 'timestamp'), - totalDecodeTime: new RateCalculator( - 'totalDecodeTime', 'framesDecoded', - CalculatorModifier.kMillisecondsFromSeconds), - totalInterFrameDelay: new RateCalculator( - 'totalInterFrameDelay', 'framesDecoded', - CalculatorModifier.kMillisecondsFromSeconds), - totalSquaredInterFrameDelay: new StandardDeviationCalculator( - 'totalSquaredInterFrameDelay', 'totalInterFrameDelay', - 'framesDecoded', 'interFrameDelay'), - totalSamplesReceived: - new RateCalculator('totalSamplesReceived', 'timestamp'), - concealedSamples: [ - new RateCalculator('concealedSamples', 'timestamp'), - new RateCalculator('concealedSamples', 'totalSamplesReceived'), - ], - silentConcealedSamples: - new RateCalculator('silentConcealedSamples', 'timestamp'), - insertedSamplesForDeceleration: - new RateCalculator('insertedSamplesForDeceleration', 'timestamp'), - removedSamplesForAcceleration: - new RateCalculator('removedSamplesForAcceleration', 'timestamp'), - qpSum: new RateCalculator('qpSum', 'framesDecoded'), - totalCorruptionProbability: - new RateCalculator( - 'totalCorruptionProbability', 'corruptionMeasurements'), - codecId: new CodecCalculator(), - totalAudioEnergy: new AudioLevelRmsCalculator(), - jitterBufferDelay: new RateCalculator( - 'jitterBufferDelay', 'jitterBufferEmittedCount', - CalculatorModifier.kMillisecondsFromSeconds), - jitterBufferTargetDelay: new RateCalculator( - 'jitterBufferTargetDelay', 'jitterBufferEmittedCount', - CalculatorModifier.kMillisecondsFromSeconds), - jitterBufferMinimumDelay: new RateCalculator( - 'jitterBufferMinimumDelay', 'jitterBufferEmittedCount', - CalculatorModifier.kMillisecondsFromSeconds), - lastPacketReceivedTimestamp: new DateCalculator( - 'lastPacketReceivedTimestamp'), - estimatedPlayoutTimestamp: new DateCalculator( - 'estimatedPlayoutTimestamp', kNtpToUnixTimeOffsetMs), - totalProcessingDelay: new RateCalculator( - 'totalProcessingDelay', 'jitterBufferEmittedCount', - CalculatorModifier.kMillisecondsFromSeconds), - totalAssemblyTime: new RateCalculator( - 'totalAssemblyTime', 'framesAssembledFromMultiplePackets', - CalculatorModifier.kMillisecondsFromSeconds), - }, + packetsSent: new RateCalculator('packetsSent', 'timestamp'), + retransmittedPacketsSent: + new RateCalculator('retransmittedPacketsSent', 'timestamp'), + totalPacketSendDelay: new RateCalculator( + 'totalPacketSendDelay', 'packetsSent', + CalculatorModifier.kMillisecondsFromSeconds), + framesEncoded: new RateCalculator('framesEncoded', 'timestamp'), + framesSent: new RateCalculator('framesSent', 'timestamp'), + totalEncodedBytesTarget: new RateCalculator( + 'totalEncodedBytesTarget', 'timestamp', + CalculatorModifier.kBytesToBits), + totalEncodeTime: new RateCalculator( + 'totalEncodeTime', 'framesEncoded', + CalculatorModifier.kMillisecondsFromSeconds), + qpSum: new RateCalculator('qpSum', 'framesEncoded'), + psnrSum: [ + new PsnrRateCalculator('y'), + new PsnrRateCalculator('u'), + new PsnrRateCalculator('v'), + ], + codecId: new CodecCalculator(), }, - { - type: 'remote-inbound-rtp', - metricCalculators: { - totalRoundTripTime: - new RateCalculator('totalRoundTripTime', - 'roundTripTimeMeasurements'), - }, + 'inbound-rtp': { + bytesReceived: new RateCalculator( + 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), + headerBytesReceived: new RateCalculator( + 'headerBytesReceived', 'timestamp', + CalculatorModifier.kBytesToBits), + retransmittedBytesReceived: new RateCalculator( + 'retransmittedBytesReceived', 'timestamp', + CalculatorModifier.kBytesToBits), + fecBytesReceived: new RateCalculator( + 'fecBytesReceived', 'timestamp', + CalculatorModifier.kBytesToBits), + packetsReceived: new RateCalculator('packetsReceived', 'timestamp'), + packetsDiscarded: new RateCalculator('packetsDiscarded', 'timestamp'), + retransmittedPacketsReceived: + new RateCalculator('retransmittedPacketsReceived', 'timestamp'), + fecPacketsReceived: + new RateCalculator('fecPacketsReceived', 'timestamp'), + fecPacketsDiscarded: + new RateCalculator('fecPacketsDiscarded', 'timestamp'), + framesReceived: [ + new RateCalculator('framesReceived', 'timestamp'), + new DifferenceCalculator('framesReceived', + 'framesDecoded', 'framesDropped'), + ], + framesDecoded: new RateCalculator('framesDecoded', 'timestamp'), + keyFramesDecoded: new RateCalculator('keyFramesDecoded', 'timestamp'), + totalDecodeTime: new RateCalculator( + 'totalDecodeTime', 'framesDecoded', + CalculatorModifier.kMillisecondsFromSeconds), + totalInterFrameDelay: new RateCalculator( + 'totalInterFrameDelay', 'framesDecoded', + CalculatorModifier.kMillisecondsFromSeconds), + totalSquaredInterFrameDelay: new StandardDeviationCalculator( + 'totalSquaredInterFrameDelay', 'totalInterFrameDelay', + 'framesDecoded', 'interFrameDelay'), + totalSamplesReceived: + new RateCalculator('totalSamplesReceived', 'timestamp'), + concealedSamples: [ + new RateCalculator('concealedSamples', 'timestamp'), + new RateCalculator('concealedSamples', 'totalSamplesReceived'), + ], + silentConcealedSamples: + new RateCalculator('silentConcealedSamples', 'timestamp'), + insertedSamplesForDeceleration: + new RateCalculator('insertedSamplesForDeceleration', 'timestamp'), + removedSamplesForAcceleration: + new RateCalculator('removedSamplesForAcceleration', 'timestamp'), + qpSum: new RateCalculator('qpSum', 'framesDecoded'), + totalCorruptionProbability: + new RateCalculator( + 'totalCorruptionProbability', 'corruptionMeasurements'), + codecId: new CodecCalculator(), + totalAudioEnergy: new AudioLevelRmsCalculator(), + jitterBufferDelay: new RateCalculator( + 'jitterBufferDelay', 'jitterBufferEmittedCount', + CalculatorModifier.kMillisecondsFromSeconds), + jitterBufferTargetDelay: new RateCalculator( + 'jitterBufferTargetDelay', 'jitterBufferEmittedCount', + CalculatorModifier.kMillisecondsFromSeconds), + jitterBufferMinimumDelay: new RateCalculator( + 'jitterBufferMinimumDelay', 'jitterBufferEmittedCount', + CalculatorModifier.kMillisecondsFromSeconds), + lastPacketReceivedTimestamp: new DateCalculator( + 'lastPacketReceivedTimestamp'), + estimatedPlayoutTimestamp: new DateCalculator( + 'estimatedPlayoutTimestamp', kNtpToUnixTimeOffsetMs), + totalProcessingDelay: new RateCalculator( + 'totalProcessingDelay', 'jitterBufferEmittedCount', + CalculatorModifier.kMillisecondsFromSeconds), + totalAssemblyTime: new RateCalculator( + 'totalAssemblyTime', 'framesAssembledFromMultiplePackets', + CalculatorModifier.kMillisecondsFromSeconds), }, - { - type: 'remote-outbound-rtp', - metricCalculators: { - remoteTimestamp: new DateCalculator('remoteTimestamp'), - totalRoundTripTime: - new RateCalculator('totalRoundTripTime', - 'roundTripTimeMeasurements'), - }, + 'remote-inbound-rtp': { + totalRoundTripTime: + new RateCalculator('totalRoundTripTime', + 'roundTripTimeMeasurements'), }, - { - type: 'transport', - metricCalculators: { - bytesSent: new RateCalculator( - 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), - bytesReceived: new RateCalculator( - 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), - packetsSent: new RateCalculator( - 'packetsSent', 'timestamp'), - packetsReceived: new RateCalculator( - 'packetsReceived', 'timestamp'), - }, + 'remote-outbound-rtp': { + remoteTimestamp: new DateCalculator('remoteTimestamp'), + totalRoundTripTime: + new RateCalculator('totalRoundTripTime', + 'roundTripTimeMeasurements'), }, - { - type: 'candidate-pair', - metricCalculators: { - bytesSent: new RateCalculator( - 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), - bytesReceived: new RateCalculator( - 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), - packetsSent: new RateCalculator( - 'packetsSent', 'timestamp'), - packetsReceived: new RateCalculator( - 'packetsReceived', 'timestamp'), - totalRoundTripTime: - new RateCalculator('totalRoundTripTime', 'responsesReceived'), - lastPacketReceivedTimestamp: new DateCalculator( - 'lastPacketReceivedTimestamp'), - lastPacketSentTimestamp: new DateCalculator( - 'lastPacketSentTimestamp'), - }, + 'transport': { + bytesSent: new RateCalculator( + 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), + bytesReceived: new RateCalculator( + 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), + packetsSent: new RateCalculator( + 'packetsSent', 'timestamp'), + packetsReceived: new RateCalculator( + 'packetsReceived', 'timestamp'), }, - ]; + 'candidate-pair': { + bytesSent: new RateCalculator( + 'bytesSent', 'timestamp', CalculatorModifier.kBytesToBits), + bytesReceived: new RateCalculator( + 'bytesReceived', 'timestamp', CalculatorModifier.kBytesToBits), + packetsSent: new RateCalculator( + 'packetsSent', 'timestamp'), + packetsReceived: new RateCalculator( + 'packetsReceived', 'timestamp'), + totalRoundTripTime: + new RateCalculator('totalRoundTripTime', 'responsesReceived'), + lastPacketReceivedTimestamp: new DateCalculator( + 'lastPacketReceivedTimestamp'), + lastPacketSentTimestamp: new DateCalculator( + 'lastPacketSentTimestamp'), + }, + }; } addStatsReport(report) { @@ -661,12 +637,12 @@ // values, such as converting total counters (e.g. bytesSent) to rates (e.g. // bytesSent/s). updateCalculatedMetrics_() { - this.statsCalculators.forEach(statsCalculator => { - this.currentReport.getByType(statsCalculator.type).forEach(stats => { - Object.keys(statsCalculator.metricCalculators) + Object.keys(this.statsCalculators).forEach(statsType => { + this.currentReport.getByType(statsType).forEach(stats => { + Object.keys(this.statsCalculators[statsType]) .forEach(originalMetric => { let metricCalculators = - statsCalculator.metricCalculators[originalMetric]; + this.statsCalculators[statsType][originalMetric]; if (!Array.isArray(metricCalculators)) { metricCalculators = [metricCalculators]; }
diff --git a/content/renderer/accessibility/annotations/ax_image_annotator.cc b/content/renderer/accessibility/annotations/ax_image_annotator.cc index edb9d9e..429fe9f 100644 --- a/content/renderer/accessibility/annotations/ax_image_annotator.cc +++ b/content/renderer/accessibility/annotations/ax_image_annotator.cc
@@ -410,6 +410,12 @@ return; } + if (GetImageData(src).isNull()) { + dst->SetImageAnnotationStatus( + ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation); + return; + } + if (HasAnnotationInCache(src)) { dst->AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation, GetImageAnnotation(src));
diff --git a/content/renderer/accessibility/annotations/ax_image_annotator_browsertest.cc b/content/renderer/accessibility/annotations/ax_image_annotator_browsertest.cc index 5d75dd1..00a530e6 100644 --- a/content/renderer/accessibility/annotations/ax_image_annotator_browsertest.cc +++ b/content/renderer/accessibility/annotations/ax_image_annotator_browsertest.cc
@@ -4,7 +4,9 @@ #include "content/renderer/accessibility/annotations/ax_image_annotator.h" +#include "base/strings/stringprintf.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_discardable_memory_allocator.h" #include "content/renderer/accessibility/annotations/ax_annotators_manager.h" #include "content/renderer/accessibility/render_accessibility_impl_test.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -17,6 +19,18 @@ using blink::WebDocument; using testing::ElementsAre; +namespace { + +constexpr char kImage1[] = + "data:imagepng;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/" + "w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; +constexpr char kImage2[] = + "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAALEwEAmpwYAA" + "AAB3RJTUUH4gcVABQvx8CBmAAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBk" + "LmUHAAAAFUlEQVQY02P8//8/A27AxIAXjFRpAKXjAxH/0Dm5AAAAAElFTkSuQmCC"; + class TestAXImageAnnotator : public AXImageAnnotator { public: TestAXImageAnnotator(RenderAccessibilityImpl* const render_accessibility) @@ -85,6 +99,8 @@ mojo::ReceiverSet<image_annotation::mojom::Annotator> receivers_; }; +} // namespace + class AXImageAnnotatorTest : public RenderAccessibilityImplTest { public: AXImageAnnotatorTest() = default; @@ -107,10 +123,14 @@ ->ax_annotators_manager_for_testing() ->AddAnnotatorForTesting(std::move(annotator)); AXImageAnnotator::IgnoreProtocolChecksForTesting(); + base::DiscardableMemoryAllocator::SetInstance( + &discardable_memory_allocator); + task_environment_.RunUntilIdle(); } void TearDown() override { + base::DiscardableMemoryAllocator::SetInstance(nullptr); GetRenderAccessibilityImpl() ->ax_annotators_manager_for_testing() ->ClearAnnotatorsForTesting(); @@ -125,6 +145,7 @@ private: base::test::ScopedFeatureList scoped_feature_list_; MockImageAnnotationService mock_annotator_service_; + base::TestDiscardableMemoryAllocator discardable_memory_allocator; }; // TODO(crbug.com/1477047, fuchsia:132924): Reenable test on Fuchsia once @@ -135,22 +156,24 @@ #define MAYBE_OnImageAdded OnImageAdded #endif TEST_F(AXImageAnnotatorTest, MAYBE_OnImageAdded) { - LoadHTMLAndRefreshAccessibilityTree(R"HTML( + LoadHTMLAndRefreshAccessibilityTree(base::StringPrintf(R"HTML( <body> <p>Test document</p> - <img id="A" src="test1.jpg" + <img id="A" src="%s" style="width: 200px; height: 150px;"> - <img id="B" src="test2.jpg" + <img id="B" src="%s" style="visibility: hidden; width: 200px; height: 150px;"> </body> - )HTML"); + )HTML", + kImage1, kImage2) + .c_str()); // Every time we call a method on a Mojo interface, a message is posted to the // current task queue. We need to ask the queue to drain itself before we // check test expectations. task_environment_.RunUntilIdle(); - EXPECT_THAT(mock_annotator_service().image_ids_, ElementsAre("test1.jpg")); + EXPECT_THAT(mock_annotator_service().image_ids_, ElementsAre(kImage1)); ASSERT_EQ(1u, mock_annotator_service().image_processors_.size()); EXPECT_TRUE(mock_annotator_service().image_processors_[0].is_bound()); EXPECT_EQ(1u, mock_annotator_service().callbacks_.size()); @@ -171,7 +194,7 @@ SendPendingAccessibilityEvents(); EXPECT_THAT(mock_annotator_service().image_ids_, - ElementsAre("test1.jpg", "test2.jpg", "test1.jpg", "test2.jpg")); + ElementsAre(kImage1, kImage2, kImage1, kImage2)); ASSERT_EQ(4u, mock_annotator_service().image_processors_.size()); EXPECT_TRUE(mock_annotator_service().image_processors_[0].is_bound()); EXPECT_TRUE(mock_annotator_service().image_processors_[1].is_bound()); @@ -181,20 +204,21 @@ } TEST_F(AXImageAnnotatorTest, OnImageUpdated) { - LoadHTMLAndRefreshAccessibilityTree(R"HTML( + LoadHTMLAndRefreshAccessibilityTree(base::StringPrintf(R"HTML( <body> <p>Test document</p> - <img id="A" src="test1.jpg" - style="width: 200px; height: 150px;"> + <img src="%s" style="width: 200px; height: 150px;"> </body> - )HTML"); + )HTML", + kImage1) + .c_str()); // Every time we call a method on a Mojo interface, a message is posted to the // current task queue. We need to ask the queue to drain itself before we // check test expectations. task_environment_.RunUntilIdle(); - EXPECT_THAT(mock_annotator_service().image_ids_, ElementsAre("test1.jpg")); + EXPECT_THAT(mock_annotator_service().image_ids_, ElementsAre(kImage1)); ASSERT_EQ(1u, mock_annotator_service().image_processors_.size()); EXPECT_TRUE(mock_annotator_service().image_processors_[0].is_bound()); EXPECT_EQ(1u, mock_annotator_service().callbacks_.size()); @@ -209,24 +233,24 @@ SendPendingAccessibilityEvents(); EXPECT_THAT(mock_annotator_service().image_ids_, - ElementsAre("test1.jpg", "test1.jpg")); + ElementsAre(kImage1, kImage1)); ASSERT_EQ(2u, mock_annotator_service().image_processors_.size()); EXPECT_TRUE(mock_annotator_service().image_processors_[0].is_bound()); EXPECT_TRUE(mock_annotator_service().image_processors_[1].is_bound()); EXPECT_EQ(2u, mock_annotator_service().callbacks_.size()); // Update node "A". - ExecuteJavaScriptForTests("document.querySelector('img').src = 'test2.jpg';"); + ExecuteJavaScriptForTests( + base::StringPrintf("document.querySelector('img').src = '%s';", kImage2)); SendPendingAccessibilityEvents(); ClearHandledUpdates(); // This should update the annotations of all images on the page, including the // now updated image src. - MarkSubtreeDirty(root_obj); SendPendingAccessibilityEvents(); EXPECT_THAT(mock_annotator_service().image_ids_, - ElementsAre("test1.jpg", "test1.jpg", "test2.jpg")); + ElementsAre(kImage1, kImage1, kImage2)); ASSERT_EQ(3u, mock_annotator_service().image_processors_.size()); EXPECT_TRUE(mock_annotator_service().image_processors_[0].is_bound()); EXPECT_TRUE(mock_annotator_service().image_processors_[1].is_bound());
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 34f755ea..679f0e1 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1668,7 +1668,6 @@ "../browser/renderer_host/input/wheel_scroll_latching_browsertest.cc", "../browser/renderer_host/isolated_web_app_throttle_browsertest.cc", "../browser/renderer_host/jit_policy_browsertest.cc", - "../browser/renderer_host/local_network_access_browsertest.cc", "../browser/renderer_host/media/video_capture_browsertest.cc", "../browser/renderer_host/navigation_controller_history_intervention_browsertest.cc", "../browser/renderer_host/navigation_controller_impl_browsertest.cc", @@ -1702,6 +1701,8 @@ "../browser/screen_orientation/screen_orientation_browsertest.cc", "../browser/security/coop/cross_origin_opener_policy_browsertest.cc", "../browser/security/dip/document_isolation_policy_browsertest.cc", + "../browser/security/local_network_access/local_network_access_browsertest.cc", + "../browser/security/local_network_access/local_network_access_deprecation_browsertest.cc", "../browser/security_exploit_browsertest.cc", "../browser/serial/serial_browsertest.cc", "../browser/service_host/service_process_host_browsertest.cc",
diff --git a/gpu/ipc/service/arc_shared_image_interface.cc b/gpu/ipc/service/arc_shared_image_interface.cc index 89a1568..2f12403 100644 --- a/gpu/ipc/service/arc_shared_image_interface.cc +++ b/gpu/ipc/service/arc_shared_image_interface.cc
@@ -5,6 +5,8 @@ #include "gpu/ipc/service/arc_shared_image_interface.h" #include "base/notimplemented.h" +#include "base/synchronization/waitable_event.h" +#include "base/task/single_thread_task_runner.h" #include "gpu/command_buffer/client/client_shared_image.h" #include "gpu/command_buffer/service/shared_context_state.h" #include "gpu/ipc/service/gpu_channel_manager.h" @@ -15,34 +17,74 @@ // static scoped_refptr<ArcSharedImageInterface> ArcSharedImageInterface::Create( - GpuChannelManager* gpu_channel_manager) { - gpu::ContextResult result; - auto context_state = gpu_channel_manager->GetSharedContextState(&result); + GpuChannelManager* gpu_channel_manager, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner) { + scoped_refptr<ArcSharedImageInterface> arc_sii; + base::WaitableEvent completion( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); - if (!context_state) { - return nullptr; + gpu_task_runner->PostTask( + FROM_HERE, base::BindOnce(&ArcSharedImageInterface::CreateOnGpuThread, + &arc_sii, gpu_channel_manager, + std::move(gpu_task_runner), &completion)); + + completion.Wait(); + return arc_sii; +} + +// static +void ArcSharedImageInterface::CreateOnGpuThread( + scoped_refptr<ArcSharedImageInterface>* arc_sii, + GpuChannelManager* gpu_channel_manager, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner, + base::WaitableEvent* completion) { + gpu::ContextResult result; + scoped_refptr<SharedContextState> context_state = + gpu_channel_manager->GetSharedContextState(&result); + + if (context_state) { + *arc_sii = base::MakeRefCounted<ArcSharedImageInterface>( + std::make_unique<gpu::SharedImageFactory>( + gpu_channel_manager->gpu_preferences(), + gpu_channel_manager->gpu_driver_bug_workarounds(), + gpu_channel_manager->gpu_feature_info(), context_state.get(), + gpu_channel_manager->shared_image_manager(), + context_state->memory_tracker(), + /*is_for_display_compositor=*/false), + std::move(gpu_task_runner)); } - return base::MakeRefCounted<gpu::ArcSharedImageInterface>( - std::make_unique<gpu::SharedImageFactory>( - gpu_channel_manager->gpu_preferences(), - gpu_channel_manager->gpu_driver_bug_workarounds(), - gpu_channel_manager->gpu_feature_info(), context_state.get(), - gpu_channel_manager->shared_image_manager(), - context_state->memory_tracker(), - /*is_for_display_compositor=*/false)); + completion->Signal(); } ArcSharedImageInterface::ArcSharedImageInterface( - std::unique_ptr<SharedImageFactory> shared_image_factory) - : shared_image_factory_(std::move(shared_image_factory)) {} + std::unique_ptr<SharedImageFactory> shared_image_factory, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner) + : shared_image_factory_(std::move(shared_image_factory)), + gpu_task_runner_(std::move(gpu_task_runner)) {} ArcSharedImageInterface::~ArcSharedImageInterface() { + base::WaitableEvent completion( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + + gpu_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&ArcSharedImageInterface::DestroyOnGpuThread, + base::Unretained(this), &completion)); + + completion.Wait(); +} + +void ArcSharedImageInterface::DestroyOnGpuThread( + base::WaitableEvent* completion) { if (shared_image_factory_->HasImages()) { // Some of the backings might require a current GL context to be destroyed. - bool have_context = MakeContextCurrent(/*needs_gl=*/true); + bool have_context = MakeContextCurrentOnGpuThread(/*needs_gl=*/true); shared_image_factory_->DestroyAllSharedImages(have_context); } + shared_image_factory_.reset(); + completion->Signal(); } scoped_refptr<ClientSharedImage> ArcSharedImageInterface::CreateSharedImage( @@ -50,6 +92,10 @@ gpu::SurfaceHandle surface_handle, gfx::BufferUsage buffer_usage, gfx::GpuMemoryBufferHandle buffer_handle) { + if (encountered_error_.load(std::memory_order_relaxed)) { + return nullptr; + } + auto client_buffer_handle = buffer_handle.Clone(); auto mailbox = Mailbox::Generate(); // Copy which can be modified. @@ -57,8 +103,26 @@ // Set CPU read/write usage based on buffer usage. si_info_copy.meta.usage |= GetCpuSIUsage(buffer_usage); - if (!MakeContextCurrent()) { - return nullptr; + gpu_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&ArcSharedImageInterface::CreateSharedImageOnGpuThread, + base::Unretained(this), mailbox, si_info_copy, + buffer_usage, std::move(buffer_handle))); + + return base::MakeRefCounted<ClientSharedImage>( + mailbox, si_info_copy, gpu::SyncToken(), + GpuMemoryBufferHandleInfo(std::move(client_buffer_handle), buffer_usage), + holder_); +} + +void ArcSharedImageInterface::CreateSharedImageOnGpuThread( + const Mailbox& mailbox, + const SharedImageInfo& si_info, + gfx::BufferUsage buffer_usage, + gfx::GpuMemoryBufferHandle buffer_handle) { + if (!MakeContextCurrentOnGpuThread()) { + encountered_error_.store(true, std::memory_order_relaxed); + return; } if (!shared_image_factory_->CreateSharedImage( @@ -67,13 +131,9 @@ si_info.meta.alpha_type, si_info.meta.usage, std::move(si_info.debug_label), std::move(buffer_handle))) { shared_image_factory_->shared_context_state()->MarkContextLost(); - return nullptr; + encountered_error_.store(true, std::memory_order_relaxed); + return; } - - return base::MakeRefCounted<ClientSharedImage>( - mailbox, si_info_copy, gpu::SyncToken(), - GpuMemoryBufferHandleInfo(std::move(client_buffer_handle), buffer_usage), - holder_); } void ArcSharedImageInterface::DestroySharedImage( @@ -130,7 +190,15 @@ } void ArcSharedImageInterface::DestroySharedImage(const SyncToken& sync_token, const Mailbox& mailbox) { - if (!MakeContextCurrent()) { + gpu_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&ArcSharedImageInterface::DestroySharedImageOnGpuThread, + base::Unretained(this), mailbox)); +} + +void ArcSharedImageInterface::DestroySharedImageOnGpuThread( + const Mailbox& mailbox) { + if (!MakeContextCurrentOnGpuThread()) { return; } @@ -173,7 +241,8 @@ NOTREACHED(); } -bool ArcSharedImageInterface::MakeContextCurrent(bool needs_gl /*=false*/) { +bool ArcSharedImageInterface::MakeContextCurrentOnGpuThread( + bool needs_gl /*=false*/) { auto* context_state = shared_image_factory_->shared_context_state(); if (!context_state) { return false;
diff --git a/gpu/ipc/service/arc_shared_image_interface.h b/gpu/ipc/service/arc_shared_image_interface.h index e71fa9d..b0477091 100644 --- a/gpu/ipc/service/arc_shared_image_interface.h +++ b/gpu/ipc/service/arc_shared_image_interface.h
@@ -5,10 +5,17 @@ #ifndef GPU_IPC_SERVICE_ARC_SHARED_IMAGE_INTERFACE_H_ #define GPU_IPC_SERVICE_ARC_SHARED_IMAGE_INTERFACE_H_ +#include <atomic> + +#include "base/task/single_thread_task_runner.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/service/shared_image/shared_image_factory.h" #include "gpu/ipc/service/gpu_ipc_service_export.h" +namespace base { +class WaitableEvent; +} + namespace gpu { class GpuChannelManager; @@ -19,10 +26,12 @@ : public SharedImageInterface { public: static scoped_refptr<ArcSharedImageInterface> Create( - GpuChannelManager* gpu_channel_manager); + GpuChannelManager* gpu_channel_manager, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner); - explicit ArcSharedImageInterface( - std::unique_ptr<SharedImageFactory> shared_image_factory); + ArcSharedImageInterface( + std::unique_ptr<SharedImageFactory> shared_image_factory, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner); ArcSharedImageInterface(const ArcSharedImageInterface&) = delete; ArcSharedImageInterface& operator=(const ArcSharedImageInterface&) = delete; @@ -86,9 +95,22 @@ private: ~ArcSharedImageInterface() override; - bool MakeContextCurrent(bool needs_gl = false); + static void CreateOnGpuThread( + scoped_refptr<ArcSharedImageInterface>* arc_sii, + GpuChannelManager* gpu_channel_manager, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner, + base::WaitableEvent* completion); + void DestroyOnGpuThread(base::WaitableEvent* completion); + void CreateSharedImageOnGpuThread(const Mailbox& mailbox, + const SharedImageInfo& si_info, + gfx::BufferUsage buffer_usage, + gfx::GpuMemoryBufferHandle buffer_handle); + void DestroySharedImageOnGpuThread(const Mailbox& mailbox); + bool MakeContextCurrentOnGpuThread(bool needs_gl = false); std::unique_ptr<gpu::SharedImageFactory> shared_image_factory_; + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; + std::atomic_bool encountered_error_{false}; }; } // namespace gpu
diff --git a/internal b/internal index ee7ed772..5b3a093 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit ee7ed7723eb64518a8ca03d91fd4041e3a319574 +Subproject commit 5b3a0932dc6e77ec5474737c28832c127f9eba80
diff --git a/ios/chrome/browser/authentication/ui_bundled/account_menu/account_menu_coordinator_unittests.mm b/ios/chrome/browser/authentication/ui_bundled/account_menu/account_menu_coordinator_unittests.mm index ca754a9..403182c 100644 --- a/ios/chrome/browser/authentication/ui_bundled/account_menu/account_menu_coordinator_unittests.mm +++ b/ios/chrome/browser/authentication/ui_bundled/account_menu/account_menu_coordinator_unittests.mm
@@ -71,10 +71,15 @@ @end -// Base class for `AccountMenuCoordinatorNonManagedTest` and -// `AccountMenuCoordinatorManagedTest`. -class AccountMenuCoordinatorTest : public PlatformTest { +// The test param determines whether `kSeparateProfilesForManagedAccounts` is +// enabled. +class AccountMenuCoordinatorTest : public PlatformTest, + public testing::WithParamInterface<bool> { public: + AccountMenuCoordinatorTest() { + feature_list_.InitWithFeatureState(kSeparateProfilesForManagedAccounts, + GetParam()); + } void SetUp() override { PlatformTest::SetUp(); scene_state_ = [[SceneState alloc] initWithAppState:nil]; @@ -157,8 +162,6 @@ PlatformTest::TearDown(); } - virtual const FakeSystemIdentity* primary_identity() = 0; - protected: void VerifyMock() { EXPECT_OCMOCK_VERIFY((id)presentation_delegate_); @@ -213,10 +216,10 @@ coordinator_ = nil; } - // Signs in primary_identity() as primary identity. + // Signs in kPrimaryIdentity as primary identity. void SigninWithPrimaryIdentity() { - fake_system_identity_manager_->AddIdentity(primary_identity()); - authentication_service_->SignIn(primary_identity(), + fake_system_identity_manager_->AddIdentity(kPrimaryIdentity); + authentication_service_->SignIn(kPrimaryIdentity, signin_metrics::AccessPoint::kUnknown); } @@ -232,39 +235,11 @@ std::unique_ptr<TestBrowser> browser_; }; -// The test param determines whether `kSeparateProfilesForManagedAccounts` is -// enabled. -class AccountMenuCoordinatorNonManagedTest - : public AccountMenuCoordinatorTest, - public testing::WithParamInterface<bool> { - public: - AccountMenuCoordinatorNonManagedTest() { - feature_list_.InitWithFeatureState(kSeparateProfilesForManagedAccounts, - GetParam()); - } - const FakeSystemIdentity* primary_identity() override { - return kPrimaryIdentity; - } -}; - -class AccountMenuCoordinatorManagedTest : public AccountMenuCoordinatorTest { - public: - AccountMenuCoordinatorManagedTest() { - // TODO(crbug.com/374281861): This class needs to run with multi profile - // enabled. To do that, account switching needs to be supported in unttests. - feature_list_.InitWithFeatureState(kSeparateProfilesForManagedAccounts, - false); - } - const FakeSystemIdentity* primary_identity() override { - return kManagedIdentity; - } -}; - #pragma mark - AccountMenuMediatorDelegate // Tests that `didTapManageYourGoogleAccount` requests the view controller to // present a view. -TEST_P(AccountMenuCoordinatorNonManagedTest, testManageYourGoogleAccount) { +TEST_P(AccountMenuCoordinatorTest, testManageYourGoogleAccount) { OCMExpect([view_controller_ presentViewController:[OCMArg any] animated:YES completion:nil]); @@ -274,14 +249,14 @@ // Tests that `didTapManageAccounts` has no impact on the view controller and // mediator. -TEST_P(AccountMenuCoordinatorNonManagedTest, testEditAccountList) { +TEST_P(AccountMenuCoordinatorTest, testEditAccountList) { [coordinator_ didTapManageAccounts]; AssertOpenAndStop(); } // Tests that `signOutFromTargetRect` requests the delegate to be stopped and // shows a snackbar and calls its completion. -TEST_P(AccountMenuCoordinatorNonManagedTest, testSignOut) { +TEST_P(AccountMenuCoordinatorTest, testSignOut) { base::RunLoop run_loop; base::RepeatingClosure closure = run_loop.QuitClosure(); CGRect rect = CGRect(); @@ -301,13 +276,13 @@ // Tests that `mediatorWantsToBeDismissed` requests to the delegate to stop the // coordinator. -TEST_P(AccountMenuCoordinatorNonManagedTest, testMediatorWantsToBeDismissed) { +TEST_P(AccountMenuCoordinatorTest, testMediatorWantsToBeDismissed) { AssertOpenAndStop(); } // Tests that `triggerSignoutWithTargetRect` calls its // callback. -TEST_P(AccountMenuCoordinatorNonManagedTest, testTriggerSignout) { +TEST_P(AccountMenuCoordinatorTest, testTriggerSignout) { OCMExpect([mock_snackbar_commands_handler_ showCustomSnackbarMessageOverBrowserToolbar:[OCMArg any]]); @@ -329,7 +304,7 @@ // view controller and mediator. Tests also that the // `SyncEncryptionPassphraseTableViewController` is allocated, and the view is // correctly closed when the coordinator is stopped. -TEST_P(AccountMenuCoordinatorNonManagedTest, testPassphrase) { +TEST_P(AccountMenuCoordinatorTest, testPassphrase) { SyncEncryptionPassphraseTableViewController* passphraseViewController = [SyncEncryptionPassphraseTableViewController alloc]; passphraseViewController.presentationDelegate = presentation_delegate_; @@ -343,27 +318,27 @@ // Tests that `openTrustedVaultReauthForFetchKeys` calls // `showTrustedVaultReauthForFetchKeysFromViewController`. -TEST_P(AccountMenuCoordinatorNonManagedTest, testFetchKeys) { +TEST_P(AccountMenuCoordinatorTest, testFetchKeys) { [coordinator_ openTrustedVaultReauthForFetchKeys]; AssertOpenAndStop(); } // Tests that `openTrustedVaultReauthForDegradedRecoverability` calls // `showTrustedVaultReauthForDegradedRecoverabilityFromViewController`. -TEST_P(AccountMenuCoordinatorNonManagedTest, testDegradedRecoverability) { +TEST_P(AccountMenuCoordinatorTest, testDegradedRecoverability) { [coordinator_ openTrustedVaultReauthForDegradedRecoverability]; AssertOpenAndStop(); } // Tests that `openMDMErrodDialogWithSystemIdentity` has no effects on the // mediator and view controller. -TEST_P(AccountMenuCoordinatorNonManagedTest, testMDMError) { +TEST_P(AccountMenuCoordinatorTest, testMDMError) { [coordinator_ openMDMErrodDialogWithSystemIdentity:kPrimaryIdentity]; AssertOpenAndStop(); } INSTANTIATE_TEST_SUITE_P(, - AccountMenuCoordinatorNonManagedTest, + AccountMenuCoordinatorTest, testing::Bool(), [](const testing::TestParamInfo<bool>& info) { return info.param ? "WithSeparateProfiles"
diff --git a/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.cc b/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.cc index 3f0ed26..e8de61f06 100644 --- a/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.cc +++ b/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.cc
@@ -19,14 +19,12 @@ namespace ios { namespace { -std::unique_ptr<KeyedService> BuildAutocompleteClassifier( - web::BrowserState* context) { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); +std::unique_ptr<KeyedService> BuildAutocompleteClassifier(ProfileIOS* profile) { return std::make_unique<AutocompleteClassifier>( - base::WrapUnique(new AutocompleteController( - base::WrapUnique(new AutocompleteProviderClientImpl(profile)), - AutocompleteClassifier::DefaultOmniboxProviders())), - base::WrapUnique(new AutocompleteSchemeClassifierImpl)); + std::make_unique<AutocompleteController>( + std::make_unique<AutocompleteProviderClientImpl>(profile), + AutocompleteClassifier::DefaultOmniboxProviders()), + std::make_unique<AutocompleteSchemeClassifierImpl>()); } } // namespace @@ -45,9 +43,9 @@ } // static -ProfileKeyedServiceFactoryIOS::TestingFactory +ProfileKeyedServiceFactoryIOS::ProfileTestingFactory AutocompleteClassifierFactory::GetDefaultFactory() { - return base::BindRepeating(&BuildAutocompleteClassifier); + return base::BindOnce(&BuildAutocompleteClassifier); } AutocompleteClassifierFactory::AutocompleteClassifierFactory() @@ -63,8 +61,8 @@ std::unique_ptr<KeyedService> AutocompleteClassifierFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return BuildAutocompleteClassifier(context); + ProfileIOS* profile) const { + return BuildAutocompleteClassifier(profile); } } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.h b/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.h index 30ead1f..42004cb89 100644 --- a/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.h +++ b/ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.h
@@ -24,7 +24,7 @@ // Returns the default factory used to build AutocompleteClassifiers. Can be // registered with AddTestingFactory to use real instances during testing. - static TestingFactory GetDefaultFactory(); + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<AutocompleteClassifierFactory>; @@ -32,9 +32,9 @@ AutocompleteClassifierFactory(); ~AutocompleteClassifierFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.h b/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.h index fbb58fd..d237b8f 100644 --- a/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.h +++ b/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.h
@@ -28,10 +28,10 @@ AutocompleteScoringModelServiceFactory(); ~AutocompleteScoringModelServiceFactory() override; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS: // Returns nullptr if `OptimizationGuideKeyedService` is null. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.mm b/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.mm index 98b0353..8d9c6c4 100644 --- a/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.mm +++ b/ios/chrome/browser/autocomplete/model/autocomplete_scoring_model_service_factory.mm
@@ -37,8 +37,7 @@ std::unique_ptr<KeyedService> AutocompleteScoringModelServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { OptimizationGuideService* optimization_guide = OptimizationGuideServiceFactory::GetForProfile(profile); return optimization_guide ? std::make_unique<AutocompleteScoringModelService>(
diff --git a/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc b/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc index 5769a1e..3341dbd1 100644 --- a/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc +++ b/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc
@@ -21,10 +21,7 @@ namespace { -std::unique_ptr<KeyedService> BuildInMemoryURLIndex( - web::BrowserState* context) { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); - +std::unique_ptr<KeyedService> BuildInMemoryURLIndex(ProfileIOS* profile) { SchemeSet allowed_schemes; allowed_schemes.insert(kChromeUIScheme); @@ -65,14 +62,14 @@ InMemoryURLIndexFactory::~InMemoryURLIndexFactory() = default; // static -ProfileKeyedServiceFactoryIOS::TestingFactory +ProfileKeyedServiceFactoryIOS::ProfileTestingFactory InMemoryURLIndexFactory::GetDefaultFactory() { - return base::BindRepeating(&BuildInMemoryURLIndex); + return base::BindOnce(&BuildInMemoryURLIndex); } std::unique_ptr<KeyedService> InMemoryURLIndexFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return BuildInMemoryURLIndex(context); + ProfileIOS* profile) const { + return BuildInMemoryURLIndex(profile); } } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.h b/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.h index 8c8a66d..1d51ede8 100644 --- a/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.h +++ b/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.h
@@ -23,7 +23,7 @@ // Returns the default factory used to build InMemoryURLIndexes. Can be // registered with AddTestingFactory to use real instances during testing. - static TestingFactory GetDefaultFactory(); + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<InMemoryURLIndexFactory>; @@ -31,9 +31,9 @@ InMemoryURLIndexFactory(); ~InMemoryURLIndexFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.h b/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.h index 047c16e..a2781ff 100644 --- a/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.h +++ b/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.h
@@ -34,7 +34,7 @@ // // Returns nullptr if `OptimizationGuideKeyedService` is null. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_AUTOCOMPLETE_MODEL_ON_DEVICE_TAIL_MODEL_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.mm b/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.mm index 3d320fb..da560db3 100644 --- a/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.mm +++ b/ios/chrome/browser/autocomplete/model/on_device_tail_model_service_factory.mm
@@ -40,13 +40,12 @@ std::unique_ptr<KeyedService> OnDeviceTailModelServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { const std::string locale = GetApplicationContext()->GetApplicationLocaleStorage()->Get(); if (!OmniboxFieldTrial::IsOnDeviceTailSuggestEnabled(locale)) { return nullptr; } - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); OptimizationGuideService* optimization_guide = OptimizationGuideServiceFactory::GetForProfile(profile); return optimization_guide
diff --git a/ios/chrome/browser/autocomplete/model/provider_state_service_factory.h b/ios/chrome/browser/autocomplete/model/provider_state_service_factory.h index f3f4d5a..4aeaae19 100644 --- a/ios/chrome/browser/autocomplete/model/provider_state_service_factory.h +++ b/ios/chrome/browser/autocomplete/model/provider_state_service_factory.h
@@ -27,9 +27,9 @@ ProviderStateServiceFactory(); ~ProviderStateServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/provider_state_service_factory.mm b/ios/chrome/browser/autocomplete/model/provider_state_service_factory.mm index 4077fc31..56230b17 100644 --- a/ios/chrome/browser/autocomplete/model/provider_state_service_factory.mm +++ b/ios/chrome/browser/autocomplete/model/provider_state_service_factory.mm
@@ -29,7 +29,7 @@ std::unique_ptr<KeyedService> ProviderStateServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { return std::make_unique<ProviderStateService>(); }
diff --git a/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.h b/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.h index 44cdf306..9a353aad 100644 --- a/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.h +++ b/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.h
@@ -25,9 +25,9 @@ RemoteSuggestionsServiceFactory(); ~RemoteSuggestionsServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_AUTOCOMPLETE_MODEL_REMOTE_SUGGESTIONS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.mm b/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.mm index 4fe5928..da94b530 100644 --- a/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.mm +++ b/ios/chrome/browser/autocomplete/model/remote_suggestions_service_factory.mm
@@ -26,8 +26,7 @@ std::unique_ptr<KeyedService> RemoteSuggestionsServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { return std::make_unique<RemoteSuggestionsService>( /*document_suggestions_service=*/nullptr, /*enterprise_search_aggregator_suggestions_service=*/nullptr,
diff --git a/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.h b/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.h index 4e88299..468a6f732 100644 --- a/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.h +++ b/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.h
@@ -22,7 +22,7 @@ ProfileIOS* profile); static ShortcutsBackendFactory* GetInstance(); // Returns the default factory, useful in tests where it's null by default. - static TestingFactory GetDefaultFactory(); + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<ShortcutsBackendFactory>; @@ -30,9 +30,9 @@ ShortcutsBackendFactory(); ~ShortcutsBackendFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // RefcountedProfileKeyedServiceFactoryIOS implementation. scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.mm b/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.mm index dd5edc61..fcca20cd 100644 --- a/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.mm +++ b/ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.mm
@@ -31,8 +31,7 @@ } scoped_refptr<RefcountedKeyedService> BuildShortcutsBackend( - web::BrowserState* context) { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) { return CreateShortcutsBackend(profile, /*suppress_db=*/false); } @@ -59,9 +58,9 @@ } // static -ShortcutsBackendFactory::TestingFactory +ShortcutsBackendFactory::ProfileTestingFactory ShortcutsBackendFactory::GetDefaultFactory() { - return base::BindRepeating(&BuildShortcutsBackend); + return base::BindOnce(&BuildShortcutsBackend); } ShortcutsBackendFactory::ShortcutsBackendFactory() @@ -75,9 +74,8 @@ ShortcutsBackendFactory::~ShortcutsBackendFactory() {} scoped_refptr<RefcountedKeyedService> -ShortcutsBackendFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return BuildShortcutsBackend(context); +ShortcutsBackendFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { + return BuildShortcutsBackend(profile); } } // namespace ios
diff --git a/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.cc b/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.cc index a6f2895..59d6952 100644 --- a/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.cc +++ b/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.cc
@@ -32,8 +32,7 @@ std::unique_ptr<KeyedService> ZeroSuggestCacheServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { return std::make_unique<ZeroSuggestCacheService>( std::make_unique<AutocompleteSchemeClassifierImpl>(), profile->GetPrefs(), OmniboxFieldTrial::kZeroSuggestCacheMaxSize.Get());
diff --git a/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.h b/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.h index ac11385..ec8b6648 100644 --- a/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.h +++ b/ios/chrome/browser/autocomplete/model/zero_suggest_cache_service_factory.h
@@ -18,9 +18,6 @@ public: static ZeroSuggestCacheService* GetForProfile(ProfileIOS* profile); static ZeroSuggestCacheServiceFactory* GetInstance(); - // Returns the default factory used to build ZeroSuggestCacheService. Can be - // registered with AddTestingFactory to use real instances during testing. - static TestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<ZeroSuggestCacheServiceFactory>; @@ -30,7 +27,7 @@ // BrowerStateKeyedServiceFactory implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; } // namespace ios
diff --git a/ios/chrome/browser/autofill/ui_bundled/manual_fill/card_view_controller_egtest.mm b/ios/chrome/browser/autofill/ui_bundled/manual_fill/card_view_controller_egtest.mm index df45724..5542680 100644 --- a/ios/chrome/browser/autofill/ui_bundled/manual_fill/card_view_controller_egtest.mm +++ b/ios/chrome/browser/autofill/ui_bundled/manual_fill/card_view_controller_egtest.mm
@@ -724,6 +724,10 @@ if (base::ios::IsRunningOnIOS17OrLater() && [ChromeEarlGrey isIPadIdiom]) { EARL_GREY_TEST_DISABLED(@"Fails on iOS 17 iPad simulator."); } + // TODO(crbug.com/443204278): Fails on iOS 26 simulator. + if (base::ios::IsRunningOnIOS26OrLater()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 26."); + } [AutofillAppInterface saveLocalCreditCard]; // Bring up the keyboard.
diff --git a/ios/chrome/browser/bookmarks/ui_bundled/editor/BUILD.gn b/ios/chrome/browser/bookmarks/ui_bundled/editor/BUILD.gn index 923073b..7ac9af3 100644 --- a/ios/chrome/browser/bookmarks/ui_bundled/editor/BUILD.gn +++ b/ios/chrome/browser/bookmarks/ui_bundled/editor/BUILD.gn
@@ -28,11 +28,11 @@ "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/public/commands", + "//ios/chrome/browser/shared/public/snackbar", "//ios/chrome/browser/shared/ui/table_view", "//ios/chrome/browser/signin/model:authentication_service", "//ios/chrome/browser/signin/model:authentication_service_factory", "//ios/chrome/browser/sync/model", - "//ios/third_party/material_components_ios", "//ui/base", "//url", ]
diff --git a/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_coordinator.mm b/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_coordinator.mm index 6efc06d..cd76d92 100644 --- a/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_coordinator.mm +++ b/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_coordinator.mm
@@ -4,8 +4,6 @@ #import "ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_coordinator.h" -#import <MaterialComponents/MaterialSnackbar.h> - #import "base/memory/raw_ptr.h" #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h"
diff --git a/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_mediator_delegate.h b/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_mediator_delegate.h index da3f4cb..99e2d625 100644 --- a/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_mediator_delegate.h +++ b/ios/chrome/browser/bookmarks/ui_bundled/editor/bookmarks_editor_mediator_delegate.h
@@ -8,7 +8,6 @@ #import <UIKit/UIKit.h> @class BookmarksEditorMediator; -@class MDCSnackbarMessage; // Delegate allowing the bookmarks editor mediator to update the coordinator if // needed.
diff --git a/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.h b/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.h index 1d03361..8e81fa9 100644 --- a/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.h +++ b/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.h
@@ -27,9 +27,9 @@ BrowsingDataRemoverFactory(); ~BrowsingDataRemoverFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_BROWSING_DATA_MODEL_BROWSING_DATA_REMOVER_FACTORY_H_
diff --git a/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.mm b/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.mm index 01563d3..0df6e35c9 100644 --- a/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.mm +++ b/ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.mm
@@ -38,10 +38,8 @@ BrowsingDataRemoverFactory::~BrowsingDataRemoverFactory() = default; std::unique_ptr<KeyedService> -BrowsingDataRemoverFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { +BrowsingDataRemoverFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { // TODO(crbug.com/40940855): the factory should declare the services // used by BrowsingDataRemoverImpl and inject them in the constructor. - return std::make_unique<BrowsingDataRemoverImpl>( - ProfileIOS::FromBrowserState(context)); + return std::make_unique<BrowsingDataRemoverImpl>(profile); }
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_ranking_model_unittest.mm b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_ranking_model_unittest.mm index b4e63bf2..cc6857c 100644 --- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_ranking_model_unittest.mm +++ b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_ranking_model_unittest.mm
@@ -400,10 +400,9 @@ PlatformTest::TearDown(); } - web::BrowserState* SetUpEnvironment(web::BrowserState* context) { - ProfileIOS* setup_profile = ProfileIOS::FromBrowserState(context); - segmentation_test_utils_->SetupForProfile(setup_profile); - return context; + ProfileIOS* SetUpEnvironment(ProfileIOS* profile) { + segmentation_test_utils_->SetupForProfile(profile); + return profile; } ProfileIOS* GetProfile() { return profile_.get(); }
diff --git a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h index e4b00c0..9e7cae3 100644 --- a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h +++ b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h
@@ -23,9 +23,9 @@ SamplePanelModelFactory(); ~SamplePanelModelFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_CONTEXTUAL_PANEL_SAMPLE_MODEL_SAMPLE_PANEL_MODEL_FACTORY_H_
diff --git a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm index f1afefb..75cfc998 100644 --- a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm +++ b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm
@@ -26,6 +26,6 @@ SamplePanelModelFactory::~SamplePanelModelFactory() {} std::unique_ptr<KeyedService> SamplePanelModelFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { return std::make_unique<SamplePanelModel>(); }
diff --git a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h index 92a1295..8cf26910 100644 --- a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h +++ b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h
@@ -26,9 +26,9 @@ DiscoverFeedServiceFactory(); ~DiscoverFeedServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_DISCOVER_FEED_MODEL_DISCOVER_FEED_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm index fae40e74..644518d 100644 --- a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm +++ b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm
@@ -47,10 +47,7 @@ DiscoverFeedServiceFactory::~DiscoverFeedServiceFactory() = default; std::unique_ptr<KeyedService> -DiscoverFeedServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); - +DiscoverFeedServiceFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { DiscoverFeedConfiguration* configuration = [[DiscoverFeedConfiguration alloc] init]; configuration.profilePrefService = profile->GetPrefs();
diff --git a/ios/chrome/browser/download/model/background_service/background_download_service_factory.cc b/ios/chrome/browser/download/model/background_service/background_download_service_factory.cc index b5aa7c6c..de5bb05a 100644 --- a/ios/chrome/browser/download/model/background_service/background_download_service_factory.cc +++ b/ios/chrome/browser/download/model/background_service/background_download_service_factory.cc
@@ -61,31 +61,31 @@ std::unique_ptr<KeyedService> BackgroundDownloadServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - DCHECK(!context->IsOffTheRecord()); + ProfileIOS* profile) const { + DCHECK(!profile->IsOffTheRecord()); auto clients = std::make_unique<download::DownloadClientMap>(); // Clients should be registered here. auto prediction_model_download_client = std::make_unique<optimization_guide::PredictionModelDownloadClient>( - ProfileIOS::FromBrowserState(context)); + profile); clients->insert(std::make_pair( download::DownloadClient::OPTIMIZATION_GUIDE_PREDICTION_MODELS, std::move(prediction_model_download_client))); - return BuildServiceWithClients(context, std::move(clients)); + return BuildServiceWithClients(profile, std::move(clients)); } std::unique_ptr<KeyedService> BackgroundDownloadServiceFactory::BuildServiceWithClients( - web::BrowserState* context, + ProfileIOS* profile, std::unique_ptr<download::DownloadClientMap> clients) const { auto client_set = std::make_unique<download::ClientSet>(std::move(clients)); base::FilePath storage_dir = - context->GetStatePath().Append(kDownloadServiceStorageDir); + profile->GetStatePath().Append(kDownloadServiceStorageDir); scoped_refptr<base::SequencedTaskRunner> background_task_runner = base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); - auto entry_db = context->GetProtoDatabaseProvider()->GetDB<protodb::Entry>( + auto entry_db = profile->GetProtoDatabaseProvider()->GetDB<protodb::Entry>( leveldb_proto::ProtoDbType::DOWNLOAD_STORE, storage_dir.Append(kEntryDBStorageDir), background_task_runner); auto store = std::make_unique<download::DownloadStore>(std::move(entry_db));
diff --git a/ios/chrome/browser/download/model/background_service/background_download_service_factory.h b/ios/chrome/browser/download/model/background_service/background_download_service_factory.h index 9f439725..4213109 100644 --- a/ios/chrome/browser/download/model/background_service/background_download_service_factory.h +++ b/ios/chrome/browser/download/model/background_service/background_download_service_factory.h
@@ -32,12 +32,12 @@ BackgroundDownloadServiceFactory(); ~BackgroundDownloadServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; std::unique_ptr<KeyedService> BuildServiceWithClients( - web::BrowserState* context, + ProfileIOS* profile, std::unique_ptr<download::DownloadClientMap> clients) const; };
diff --git a/ios/chrome/browser/download/model/background_service/background_download_service_test.cc b/ios/chrome/browser/download/model/background_service/background_download_service_test.cc index 07ff2daa..5aed65b 100644 --- a/ios/chrome/browser/download/model/background_service/background_download_service_test.cc +++ b/ios/chrome/browser/download/model/background_service/background_download_service_test.cc
@@ -144,14 +144,14 @@ // service. A pointer to the FakeClient object is kept in the test fixture // instance to allow test cases to manipulate it. std::unique_ptr<KeyedService> MakeBackgroundDowloadService( - web::BrowserState* browser_state) { + ProfileIOS* profile) { DCHECK(!fake_client_); auto fake_client = std::make_unique<NiceMock<FakeClient>>(); fake_client_ = fake_client.get(); auto clients = std::make_unique<download::DownloadClientMap>(); clients->emplace(download::DownloadClient::TEST, std::move(fake_client)); return BackgroundDownloadServiceFactory::GetInstance() - ->BuildServiceWithClients(browser_state, std::move(clients)); + ->BuildServiceWithClients(profile, std::move(clients)); } private:
diff --git a/ios/chrome/browser/download/model/browser_download_service_factory.h b/ios/chrome/browser/download/model/browser_download_service_factory.h index 708af55b..c4d326b 100644 --- a/ios/chrome/browser/download/model/browser_download_service_factory.h +++ b/ios/chrome/browser/download/model/browser_download_service_factory.h
@@ -19,7 +19,7 @@ static BrowserDownloadServiceFactory* GetInstance(); // Returns a default testing factory. - static TestingFactory GetDefaultFactory(); + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<BrowserDownloadServiceFactory>; @@ -27,9 +27,9 @@ BrowserDownloadServiceFactory(); ~BrowserDownloadServiceFactory() override; - // BrowserStateKeyedServiceFactory overrides: + // ProfileKeyedServiceFactoryIOS overrides: std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_DOWNLOAD_MODEL_BROWSER_DOWNLOAD_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/download/model/browser_download_service_factory.mm b/ios/chrome/browser/download/model/browser_download_service_factory.mm index c29419c..c6d13f6 100644 --- a/ios/chrome/browser/download/model/browser_download_service_factory.mm +++ b/ios/chrome/browser/download/model/browser_download_service_factory.mm
@@ -12,10 +12,9 @@ namespace { // Default factory. -std::unique_ptr<KeyedService> BuildBrowserDownloadService( - web::BrowserState* context) { +std::unique_ptr<KeyedService> BuildBrowserDownloadService(ProfileIOS* profile) { return std::make_unique<BrowserDownloadService>( - web::DownloadController::FromBrowserState(context)); + web::DownloadController::FromBrowserState(profile)); } } // namespace @@ -34,7 +33,7 @@ } // static -ProfileKeyedServiceFactoryIOS::TestingFactory +ProfileKeyedServiceFactoryIOS::ProfileTestingFactory BrowserDownloadServiceFactory::GetDefaultFactory() { return base::BindOnce(&BuildBrowserDownloadService); } @@ -49,6 +48,6 @@ std::unique_ptr<KeyedService> BrowserDownloadServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return BuildBrowserDownloadService(context); + ProfileIOS* profile) const { + return BuildBrowserDownloadService(profile); }
diff --git a/ios/chrome/browser/download/model/download_file_service_factory.h b/ios/chrome/browser/download/model/download_file_service_factory.h index a646b87a..eed82bd 100644 --- a/ios/chrome/browser/download/model/download_file_service_factory.h +++ b/ios/chrome/browser/download/model/download_file_service_factory.h
@@ -28,7 +28,7 @@ ~DownloadFileServiceFactory() override; std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_DOWNLOAD_MODEL_DOWNLOAD_FILE_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/download/model/download_file_service_factory.mm b/ios/chrome/browser/download/model/download_file_service_factory.mm index c5eef5e3..56905f9 100644 --- a/ios/chrome/browser/download/model/download_file_service_factory.mm +++ b/ios/chrome/browser/download/model/download_file_service_factory.mm
@@ -35,9 +35,7 @@ DownloadFileServiceFactory::~DownloadFileServiceFactory() = default; std::unique_ptr<KeyedService> -DownloadFileServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); +DownloadFileServiceFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { // DownloadRecordService may be nullptr if IsDownloadListEnabled() is false. DownloadRecordService* download_record_service = nullptr; if (IsDownloadListEnabled()) {
diff --git a/ios/chrome/browser/download/model/download_record_service_factory.h b/ios/chrome/browser/download/model/download_record_service_factory.h index 3ab16f0..178f9c8 100644 --- a/ios/chrome/browser/download/model/download_record_service_factory.h +++ b/ios/chrome/browser/download/model/download_record_service_factory.h
@@ -24,7 +24,7 @@ ~DownloadRecordServiceFactory() override; std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_DOWNLOAD_MODEL_DOWNLOAD_RECORD_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/download/model/download_record_service_factory.mm b/ios/chrome/browser/download/model/download_record_service_factory.mm index 47a91732..50f356e 100644 --- a/ios/chrome/browser/download/model/download_record_service_factory.mm +++ b/ios/chrome/browser/download/model/download_record_service_factory.mm
@@ -30,7 +30,6 @@ std::unique_ptr<KeyedService> DownloadRecordServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { return std::make_unique<DownloadRecordServiceImpl>(profile->GetStatePath()); }
diff --git a/ios/chrome/browser/enterprise/connectors/connectors_service_factory.h b/ios/chrome/browser/enterprise/connectors/connectors_service_factory.h index 0c79a1b2..add8863 100644 --- a/ios/chrome/browser/enterprise/connectors/connectors_service_factory.h +++ b/ios/chrome/browser/enterprise/connectors/connectors_service_factory.h
@@ -22,9 +22,9 @@ ConnectorsServiceFactory(); ~ConnectorsServiceFactory() override; - // ProfileKeyedServiceFactoryIOS: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; } // namespace enterprise_connectors
diff --git a/ios/chrome/browser/enterprise/connectors/connectors_service_factory.mm b/ios/chrome/browser/enterprise/connectors/connectors_service_factory.mm index baa8c72daf..6d7a58af 100644 --- a/ios/chrome/browser/enterprise/connectors/connectors_service_factory.mm +++ b/ios/chrome/browser/enterprise/connectors/connectors_service_factory.mm
@@ -30,8 +30,7 @@ ConnectorsServiceFactory::~ConnectorsServiceFactory() = default; std::unique_ptr<KeyedService> ConnectorsServiceFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { - auto* profile = ProfileIOS::FromBrowserState(browser_state); + ProfileIOS* profile) const { return std::make_unique<ConnectorsService>(profile); }
diff --git a/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.h b/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.h index 12e89e42..039584b3 100644 --- a/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.h +++ b/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.h
@@ -28,18 +28,17 @@ // Returns the default factory used to build IOSRealtimeReportingClient. Can // be registered with AddTestingFactory to use real instances during testing. - static TestingFactory GetDefaultFactory(); - - protected: - // BrowserStateKeyedServiceFactory overrides. - std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<IOSRealtimeReportingClientFactory>; IOSRealtimeReportingClientFactory(); ~IOSRealtimeReportingClientFactory() override; + + // ProfileKeyedServiceFactoryIOS overrides. + std::unique_ptr<KeyedService> BuildServiceInstanceFor( + ProfileIOS* profile) const override; }; } // namespace enterprise_connectors
diff --git a/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.mm b/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.mm index eaeb2963..a343cc0 100644 --- a/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.mm +++ b/ios/chrome/browser/enterprise/connectors/reporting/ios_realtime_reporting_client_factory.mm
@@ -16,9 +16,7 @@ namespace { std::unique_ptr<KeyedService> BuildRealtimeReportingClient( - web::BrowserState* browser_state) { - auto* profile = ProfileIOS::FromBrowserState(browser_state); - DCHECK(profile); + ProfileIOS* profile) { return std::make_unique<IOSRealtimeReportingClient>(profile); } @@ -39,9 +37,9 @@ } // static -ProfileKeyedServiceFactoryIOS::TestingFactory +ProfileKeyedServiceFactoryIOS::ProfileTestingFactory IOSRealtimeReportingClientFactory::GetDefaultFactory() { - return base::BindRepeating(&BuildRealtimeReportingClient); + return base::BindOnce(&BuildRealtimeReportingClient); } IOSRealtimeReportingClientFactory::IOSRealtimeReportingClientFactory() @@ -56,9 +54,8 @@ std::unique_ptr<KeyedService> IOSRealtimeReportingClientFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { - auto* profile = ProfileIOS::FromBrowserState(browser_state); - return std::make_unique<IOSRealtimeReportingClient>(profile); + ProfileIOS* profile) const { + return BuildRealtimeReportingClient(profile); } } // namespace enterprise_connectors
diff --git a/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.h b/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.h index 57facd06..5ca03b95 100644 --- a/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.h +++ b/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.h
@@ -26,9 +26,9 @@ IOSReportingEventRouterFactory(); ~IOSReportingEventRouterFactory() override; - // BrowserStateKeyedServiceFactory overrides. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; } // namespace enterprise_connectors
diff --git a/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.mm b/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.mm index 4674cfc..b0f5b241 100644 --- a/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.mm +++ b/ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.mm
@@ -37,8 +37,7 @@ std::unique_ptr<KeyedService> IOSReportingEventRouterFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { - auto* profile = ProfileIOS::FromBrowserState(browser_state); + ProfileIOS* profile) const { return std::make_unique<ReportingEventRouter>( IOSRealtimeReportingClientFactory::GetForProfile(profile)); }
diff --git a/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.cc b/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.cc index 65bd487..c1cd27f7 100644 --- a/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.cc +++ b/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.cc
@@ -37,10 +37,9 @@ std::unique_ptr<KeyedService> IOSChromeInstanceIDProfileServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - DCHECK(!context->IsOffTheRecord()); + ProfileIOS* profile) const { + DCHECK(!profile->IsOffTheRecord()); - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); return std::make_unique<instance_id::InstanceIDProfileService>( IOSChromeGCMProfileServiceFactory::GetForProfile(profile)->driver(), profile->IsOffTheRecord());
diff --git a/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.h b/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.h index d1edc73..4da6aa0 100644 --- a/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.h +++ b/ios/chrome/browser/gcm/model/instance_id/ios_chrome_instance_id_profile_service_factory.h
@@ -29,9 +29,9 @@ IOSChromeInstanceIDProfileServiceFactory(); ~IOSChromeInstanceIDProfileServiceFactory() override; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_GCM_MODEL_INSTANCE_ID_IOS_CHROME_INSTANCE_ID_PROFILE_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h index a27f2b4c..869f902 100644 --- a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h +++ b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h
@@ -35,9 +35,9 @@ IOSChromeGCMProfileServiceFactory(); ~IOSChromeGCMProfileServiceFactory() override; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_GCM_MODEL_IOS_CHROME_GCM_PROFILE_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm index 2100d0f2..e23354ab 100644 --- a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm +++ b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm
@@ -56,14 +56,13 @@ std::unique_ptr<KeyedService> IOSChromeGCMProfileServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - DCHECK(!context->IsOffTheRecord()); + ProfileIOS* profile) const { + DCHECK(!profile->IsOffTheRecord()); scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})); - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); return std::make_unique<gcm::GCMProfileService>( profile->GetPrefs(), profile->GetStatePath(), // This callback may be invoked on a background sequence, but it calls
diff --git a/ios/chrome/browser/language/model/accept_languages_service_factory.cc b/ios/chrome/browser/language/model/accept_languages_service_factory.cc index e81509a9..594b070 100644 --- a/ios/chrome/browser/language/model/accept_languages_service_factory.cc +++ b/ios/chrome/browser/language/model/accept_languages_service_factory.cc
@@ -65,8 +65,7 @@ std::unique_ptr<KeyedService> AcceptLanguagesServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { return std::make_unique<AcceptLanguagesServiceForProfile>( profile->GetPrefs()); }
diff --git a/ios/chrome/browser/language/model/accept_languages_service_factory.h b/ios/chrome/browser/language/model/accept_languages_service_factory.h index 0cdd30d..55b5feac 100644 --- a/ios/chrome/browser/language/model/accept_languages_service_factory.h +++ b/ios/chrome/browser/language/model/accept_languages_service_factory.h
@@ -27,9 +27,9 @@ AcceptLanguagesServiceFactory(); ~AcceptLanguagesServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_LANGUAGE_MODEL_ACCEPT_LANGUAGES_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/language/model/language_model_manager_factory.h b/ios/chrome/browser/language/model/language_model_manager_factory.h index 7192b7b..6740006 100644 --- a/ios/chrome/browser/language/model/language_model_manager_factory.h +++ b/ios/chrome/browser/language/model/language_model_manager_factory.h
@@ -27,9 +27,9 @@ LanguageModelManagerFactory(); ~LanguageModelManagerFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_LANGUAGE_MODEL_LANGUAGE_MODEL_MANAGER_FACTORY_H_
diff --git a/ios/chrome/browser/language/model/language_model_manager_factory.mm b/ios/chrome/browser/language/model/language_model_manager_factory.mm index 94bcae93..43f2d2d 100644 --- a/ios/chrome/browser/language/model/language_model_manager_factory.mm +++ b/ios/chrome/browser/language/model/language_model_manager_factory.mm
@@ -53,8 +53,7 @@ std::unique_ptr<KeyedService> LanguageModelManagerFactory::BuildServiceInstanceFor( - web::BrowserState* const state) const { - ProfileIOS* const profile = ProfileIOS::FromBrowserState(state); + ProfileIOS* profile) const { std::unique_ptr<language::LanguageModelManager> manager = std::make_unique<language::LanguageModelManager>( profile->GetPrefs(),
diff --git a/ios/chrome/browser/language/model/url_language_histogram_factory.cc b/ios/chrome/browser/language/model/url_language_histogram_factory.cc index eac02c6..b339b969 100644 --- a/ios/chrome/browser/language/model/url_language_histogram_factory.cc +++ b/ios/chrome/browser/language/model/url_language_histogram_factory.cc
@@ -29,8 +29,7 @@ std::unique_ptr<KeyedService> UrlLanguageHistogramFactory::BuildServiceInstanceFor( - web::BrowserState* const context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { return std::make_unique<language::UrlLanguageHistogram>(profile->GetPrefs()); }
diff --git a/ios/chrome/browser/language/model/url_language_histogram_factory.h b/ios/chrome/browser/language/model/url_language_histogram_factory.h index 21afb85f..d85dcad 100644 --- a/ios/chrome/browser/language/model/url_language_histogram_factory.h +++ b/ios/chrome/browser/language/model/url_language_histogram_factory.h
@@ -29,9 +29,9 @@ UrlLanguageHistogramFactory(); ~UrlLanguageHistogramFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) override; };
diff --git a/ios/chrome/browser/photos/model/photos_service_factory.h b/ios/chrome/browser/photos/model/photos_service_factory.h index 3c9c8bf..94f0e50 100644 --- a/ios/chrome/browser/photos/model/photos_service_factory.h +++ b/ios/chrome/browser/photos/model/photos_service_factory.h
@@ -20,7 +20,7 @@ static PhotosServiceFactory* GetInstance(); // Returns the default factory. - static TestingFactory GetDefaultFactory(); + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<PhotosServiceFactory>; @@ -28,9 +28,9 @@ PhotosServiceFactory(); ~PhotosServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_PHOTOS_MODEL_PHOTOS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/photos/model/photos_service_factory.mm b/ios/chrome/browser/photos/model/photos_service_factory.mm index 62cb93c..b2c3fce 100644 --- a/ios/chrome/browser/photos/model/photos_service_factory.mm +++ b/ios/chrome/browser/photos/model/photos_service_factory.mm
@@ -16,11 +16,10 @@ namespace { // Build a PhotosService instance. -std::unique_ptr<KeyedService> BuildPhotosService(web::BrowserState* context) { +std::unique_ptr<KeyedService> BuildPhotosService(ProfileIOS* profile) { PhotosServiceConfiguration* configuration = [[PhotosServiceConfiguration alloc] init]; ApplicationContext* application_context = GetApplicationContext(); - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); configuration.singleSignOnService = application_context->GetSingleSignOnService(); configuration.prefService = profile->GetPrefs(); @@ -46,7 +45,7 @@ } // static -ProfileKeyedServiceFactoryIOS::TestingFactory +ProfileKeyedServiceFactoryIOS::ProfileTestingFactory PhotosServiceFactory::GetDefaultFactory() { return base::BindOnce(&BuildPhotosService); } @@ -63,6 +62,6 @@ PhotosServiceFactory::~PhotosServiceFactory() = default; std::unique_ptr<KeyedService> PhotosServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return BuildPhotosService(context); + ProfileIOS* profile) const { + return BuildPhotosService(profile); }
diff --git a/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn b/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn index 93abb7c..7e07b04 100644 --- a/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn +++ b/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn
@@ -24,10 +24,10 @@ "//ios/chrome/browser/shared/model/application_context", "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/prefs:pref_names", + "//ios/chrome/browser/shared/public/snackbar", "//ios/chrome/browser/shared/ui/util", "//ios/chrome/browser/shared/ui/util:snackbar_util", "//ios/chrome/browser/signin/model", - "//ios/third_party/material_components_ios", "//ios/web/public", "//ui/base", ]
diff --git a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm index bb8593e0..2407f7e 100644 --- a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm +++ b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm
@@ -4,7 +4,6 @@ #import "ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.h" -#import <MaterialComponents/MaterialSnackbar.h> #import <UIKit/UIKit.h> #import "base/time/time.h" @@ -33,6 +32,7 @@ #import "ios/chrome/browser/shared/public/commands/application_commands.h" #import "ios/chrome/browser/shared/public/commands/command_dispatcher.h" #import "ios/chrome/browser/shared/public/commands/snackbar_commands.h" +#import "ios/chrome/browser/shared/public/snackbar/snackbar_message.h" #import "ios/chrome/browser/shared/ui/util/snackbar_util.h" #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/signin/model/identity_manager_factory.h" @@ -284,10 +284,10 @@ } - (void)showSnackbar:(NSString*)messageText { - MDCSnackbarMessage* message = CreateSnackbarMessage(messageText); + SnackbarMessage* message = CreateCustomSnackbarMessage(messageText); message.duration = kIdleTimeoutSnackbarDuration; message.accessibilityLabel = messageText; - [_snackbarHandler showSnackbarMessage:message]; + [_snackbarHandler showCustomSnackbarMessage:message]; } // Returns whether the scene and app states allow for the idle timeout
diff --git a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent_unittest.mm b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent_unittest.mm index b67c0b1..c5c14482 100644 --- a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent_unittest.mm +++ b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent_unittest.mm
@@ -233,7 +233,8 @@ // after actions ran since the app is foregrounded and active. idle_service_->RunActionsForStateForTesting( enterprise_idle::IdleService::LastState::kIdleOnBackground); - OCMExpect([mock_snackbar_handler_ showSnackbarMessage:[OCMArg isNotNil]]); + OCMExpect( + [mock_snackbar_handler_ showCustomSnackbarMessage:[OCMArg isNotNil]]); idle_service_->OnActionsCompleted(); EXPECT_FALSE(idle_service_->ShouldIdleTimeoutSnackbarBePresented()); EXPECT_OCMOCK_VERIFY(mock_snackbar_handler_); @@ -248,7 +249,7 @@ // Simulate that app ran actions on reforeground. The snack bar does not show // after actions run since the app is not foregrounded. The snackbar will be // pending display. - OCMReject([mock_snackbar_handler_ showSnackbarMessage:[OCMArg any]]); + OCMReject([mock_snackbar_handler_ showCustomSnackbarMessage:[OCMArg any]]); idle_service_->RunActionsForStateForTesting( enterprise_idle::IdleService::LastState::kIdleOnBackground); idle_service_->OnActionsCompleted(); @@ -267,7 +268,8 @@ // transitions to `SceneActivationLevelForegroundActive`. idle_service_->RunActionsForStateForTesting( enterprise_idle::IdleService::LastState::kIdleOnBackground); - OCMExpect([mock_snackbar_handler_ showSnackbarMessage:[OCMArg isNotNil]]); + OCMExpect( + [mock_snackbar_handler_ showCustomSnackbarMessage:[OCMArg isNotNil]]); idle_service_->OnActionsCompleted(); EXPECT_TRUE(idle_service_->ShouldIdleTimeoutSnackbarBePresented()); scene_state_.activationLevel = SceneActivationLevelForegroundActive;
diff --git a/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.h b/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.h index 8409671..1747bae 100644 --- a/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.h +++ b/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.h
@@ -25,9 +25,9 @@ PowerBookmarkServiceFactory(); ~PowerBookmarkServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_POWER_BOOKMARKS_MODEL_POWER_BOOKMARK_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm b/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm index 4543aa7..59f89e4 100644 --- a/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm +++ b/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm
@@ -37,14 +37,12 @@ std::unique_ptr<KeyedService> PowerBookmarkServiceFactory::BuildServiceInstanceFor( - web::BrowserState* state) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(state); - + ProfileIOS* profile) const { bookmarks::BookmarkModel* bookmark_model = ios::BookmarkModelFactory::GetForProfile(profile); return std::make_unique<power_bookmarks::PowerBookmarkService>( - bookmark_model, state->GetStatePath().AppendASCII("power_bookmarks"), + bookmark_model, profile->GetStatePath().AppendASCII("power_bookmarks"), base::SequencedTaskRunner::GetCurrentDefault(), base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
diff --git a/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.h b/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.h index 94740e0..f11fe84 100644 --- a/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.h +++ b/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.h
@@ -27,11 +27,11 @@ TrackingProtectionSettingsFactory(); ~TrackingProtectionSettingsFactory() override; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS: void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) override; std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_PRIVACY_SANDBOX_TRACKING_PROTECTION_SETTINGS_FACTORY_H_
diff --git a/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.mm b/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.mm index db48775..ffa79bf9 100644 --- a/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.mm +++ b/ios/chrome/browser/privacy_sandbox/tracking_protection_settings_factory.mm
@@ -48,9 +48,7 @@ std::unique_ptr<KeyedService> TrackingProtectionSettingsFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); - + ProfileIOS* profile) const { return std::make_unique<privacy_sandbox::TrackingProtectionSettings>( profile->GetPrefs(), ios::HostContentSettingsMapFactory::GetForProfile(profile),
diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.h b/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.h index 1e67ce0..3441fef3 100644 --- a/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.h +++ b/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.h
@@ -23,9 +23,9 @@ ReaderModeModelFactory(); ~ReaderModeModelFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_READER_MODE_MODEL_READER_MODE_MODEL_FACTORY_H_
diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.mm b/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.mm index 918aa34f..d8411b0 100644 --- a/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.mm +++ b/ios/chrome/browser/reader_mode/model/reader_mode_model_factory.mm
@@ -26,6 +26,6 @@ ReaderModeModelFactory::~ReaderModeModelFactory() = default; std::unique_ptr<KeyedService> ReaderModeModelFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { return std::make_unique<ReaderModeModel>(); }
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_entry_point_mediator_unittest.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_entry_point_mediator_unittest.mm index 46eb307..95bf75c 100644 --- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_entry_point_mediator_unittest.mm +++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_entry_point_mediator_unittest.mm
@@ -35,7 +35,6 @@ promos_manager_ = std::make_unique<MockPromosManager>(); tracker_ = feature_engagement::CreateTestTracker(); tracker_->AddOnInitializedCallback(BoolArgumentQuitClosure()); - run_loop_.Run(); mediator_ = [[SafariDataImportEntryPointMediator alloc] initWithUIBlockerTarget:scene_state_ @@ -62,8 +61,15 @@ }; // Tests that the Safari import reminder is registered on request. +// TODO(crbug.com/442365426): Test is flaky on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_TestRegisterSafariImportReminder \ + DISABLED_TestRegisterSafariImportReminder +#else +#define MAYBE_TestRegisterSafariImportReminder TestRegisterSafariImportReminder +#endif TEST_F(SafariDataImportEntryPointMediatorTest, - TestRegisterSafariImportReminder) { + MAYBE_TestRegisterSafariImportReminder) { EXPECT_CALL(*promos_manager_.get(), RegisterPromoForSingleDisplay( promos_manager::Promo::SafariImportRemindMeLater)); @@ -72,7 +78,7 @@ task_environment_.FastForwardBy(base::Days(1.1)); EXPECT_FALSE(tracker_->ShouldTriggerHelpUI( feature_engagement::kIPHiOSSafariImportFeature)); - task_environment_.FastForwardBy(base::Days(1)); + task_environment_.FastForwardBy(base::Days(1.1)); EXPECT_TRUE(tracker_->ShouldTriggerHelpUI( feature_engagement::kIPHiOSSafariImportFeature)); }
diff --git a/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.h b/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.h index fd77283..e802113 100644 --- a/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.h +++ b/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.h
@@ -34,9 +34,9 @@ ChromeEnterpriseRealTimeUrlLookupServiceFactory(); ~ChromeEnterpriseRealTimeUrlLookupServiceFactory() override; - // ProfileKeyedServiceFactoryIOS: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; } // namespace safe_browsing
diff --git a/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.mm b/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.mm index b0f02ed..3540432 100644 --- a/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/chrome_enterprise_url_lookup_service_factory.mm
@@ -83,14 +83,13 @@ std::unique_ptr<KeyedService> ChromeEnterpriseRealTimeUrlLookupServiceFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { + ProfileIOS* profile) const { SafeBrowsingService* safe_browsing_service = GetApplicationContext()->GetSafeBrowsingService(); if (!safe_browsing_service) { return nullptr; } - ProfileIOS* profile = ProfileIOS::FromBrowserState(browser_state); signin::IdentityManager* identity_manager = IdentityManagerFactory::GetForProfile(profile);
diff --git a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.h b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.h index d81a5e0..b20bf62 100644 --- a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.h +++ b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.h
@@ -30,9 +30,9 @@ ChromePasswordProtectionServiceFactory(); ~ChromePasswordProtectionServiceFactory() override = default; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_CHROME_PASSWORD_PROTECTION_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.mm b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.mm index 3bc0b6b..7d56853d 100644 --- a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_factory.mm
@@ -45,13 +45,12 @@ std::unique_ptr<KeyedService> ChromePasswordProtectionServiceFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { + ProfileIOS* profile) const { SafeBrowsingService* safe_browsing_service = GetApplicationContext()->GetSafeBrowsingService(); if (!safe_browsing_service) { return nullptr; } - ProfileIOS* profile = ProfileIOS::FromBrowserState(browser_state); return std::make_unique<ChromePasswordProtectionService>( safe_browsing_service, profile, ios::HistoryServiceFactory::GetForProfile(
diff --git a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h index a1e1d15..baf3986 100644 --- a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h +++ b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h
@@ -29,9 +29,9 @@ HashRealTimeServiceFactory(); ~HashRealTimeServiceFactory() override = default; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_HASH_REALTIME_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm index 4b4e3e6..f6dc2496 100644 --- a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm
@@ -42,14 +42,12 @@ } std::unique_ptr<KeyedService> -HashRealTimeServiceFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { +HashRealTimeServiceFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { SafeBrowsingService* safe_browsing_service = GetApplicationContext()->GetSafeBrowsingService(); if (!safe_browsing_service) { return nullptr; } - ProfileIOS* profile = ProfileIOS::FromBrowserState(browser_state); return std::make_unique<safe_browsing::HashRealTimeService>( base::BindRepeating(&GetNetworkContext), VerdictCacheManagerFactory::GetForProfile(profile),
diff --git a/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.h b/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.h index 8b24c5d3..a09878a7 100644 --- a/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.h +++ b/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.h
@@ -25,7 +25,7 @@ // Returns the default factory. Can be used to force instantiation during // testing. - static TestingFactory GetDefaultFactory(); + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<OhttpKeyServiceFactory>; @@ -33,9 +33,9 @@ OhttpKeyServiceFactory(); ~OhttpKeyServiceFactory() override = default; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_OHTTP_KEY_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.mm b/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.mm index d51e441..d04d29f 100644 --- a/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.mm
@@ -21,13 +21,12 @@ } // Default factory. -std::unique_ptr<KeyedService> BuildOhttpKeyService(web::BrowserState* context) { +std::unique_ptr<KeyedService> BuildOhttpKeyService(ProfileIOS* profile) { SafeBrowsingService* safe_browsing_service = GetApplicationContext()->GetSafeBrowsingService(); if (!safe_browsing_service) { return nullptr; } - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); auto url_loader_factory = std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>( safe_browsing_service->GetURLLoaderFactory()); @@ -54,7 +53,7 @@ } // static -OhttpKeyServiceFactory::TestingFactory +ProfileKeyedServiceFactoryIOS::ProfileTestingFactory OhttpKeyServiceFactory::GetDefaultFactory() { return base::BindOnce(&BuildOhttpKeyService); } @@ -66,6 +65,6 @@ TestingCreation::kNoServiceForTests) {} std::unique_ptr<KeyedService> OhttpKeyServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return BuildOhttpKeyService(context); + ProfileIOS* profile) const { + return BuildOhttpKeyService(profile); }
diff --git a/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.h b/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.h index 11a9e42..b3aa080 100644 --- a/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.h +++ b/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.h
@@ -29,9 +29,9 @@ RealTimeUrlLookupServiceFactory(); ~RealTimeUrlLookupServiceFactory() override = default; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_REAL_TIME_URL_LOOKUP_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.mm b/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.mm index 73c475d..186429e4 100644 --- a/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/real_time_url_lookup_service_factory.mm
@@ -53,7 +53,7 @@ std::unique_ptr<KeyedService> RealTimeUrlLookupServiceFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { + ProfileIOS* profile) const { SafeBrowsingService* safe_browsing_service = GetApplicationContext()->GetSafeBrowsingService(); if (!safe_browsing_service) { @@ -70,7 +70,6 @@ // requests. safe_browsing::ReferrerChainProvider* referrer_chain_provider = nullptr; - ProfileIOS* profile = ProfileIOS::FromBrowserState(browser_state); return std::make_unique<safe_browsing::RealTimeUrlLookupService>( safe_browsing_service->GetURLLoaderFactory(), VerdictCacheManagerFactory::GetForProfile(profile),
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.h b/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.h index bb9d4746..ba1be76f 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.h +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.h
@@ -26,9 +26,9 @@ SafeBrowsingClientFactory(); ~SafeBrowsingClientFactory() override = default; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_SAFE_BROWSING_CLIENT_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.mm b/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.mm index da0d4b5..6a082cd 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_client_factory.mm
@@ -74,9 +74,7 @@ } std::unique_ptr<KeyedService> -SafeBrowsingClientFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); +SafeBrowsingClientFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { safe_browsing::HashRealTimeService* hash_real_time_service = nullptr; if (base::FeatureList::IsEnabled(safe_browsing::kHashPrefixRealTimeLookups)) { hash_real_time_service = HashRealTimeServiceFactory::GetForProfile(profile);
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.h b/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.h index 4d550b68..33e58244 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.h +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.h
@@ -26,9 +26,9 @@ SafeBrowsingHelperFactory(); ~SafeBrowsingHelperFactory() override = default; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_SAFE_BROWSING_HELPER_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.mm b/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.mm index b1f18c0d..1b9796d 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_helper_factory.mm
@@ -31,9 +31,7 @@ } std::unique_ptr<KeyedService> -SafeBrowsingHelperFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); +SafeBrowsingHelperFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { return std::make_unique<SafeBrowsingHelper>( profile->GetPrefs(), GetApplicationContext()->GetSafeBrowsingService(), SafeBrowsingMetricsCollectorFactory::GetForProfile(profile));
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.h b/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.h index 4ab2367..09b6a9a 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.h +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.h
@@ -28,9 +28,9 @@ SafeBrowsingMetricsCollectorFactory(); ~SafeBrowsingMetricsCollectorFactory() override = default; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_SAFE_BROWSING_METRICS_COLLECTOR_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.mm b/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.mm index 2c19d58..8cb06ad 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.mm
@@ -28,8 +28,7 @@ std::unique_ptr<KeyedService> SafeBrowsingMetricsCollectorFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(browser_state); + ProfileIOS* profile) const { return std::make_unique<safe_browsing::SafeBrowsingMetricsCollector>( profile->GetPrefs()); }
diff --git a/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.h b/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.h index 142263f7..7625ee06 100644 --- a/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.h +++ b/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.h
@@ -30,9 +30,9 @@ TailoredSecurityServiceFactory(); ~TailoredSecurityServiceFactory() override = default; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_TAILORED_SECURITY_TAILORED_SECURITY_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.mm b/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.mm index 8dbf3393..1b68dc6 100644 --- a/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/tailored_security/tailored_security_service_factory.mm
@@ -32,8 +32,7 @@ std::unique_ptr<KeyedService> TailoredSecurityServiceFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(browser_state); + ProfileIOS* profile) const { return std::make_unique<safe_browsing::ChromeTailoredSecurityService>( profile, IdentityManagerFactory::GetForProfile(profile), SyncServiceFactory::GetForProfile(profile));
diff --git a/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.h b/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.h index 57942af..5f6b0cf 100644 --- a/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.h +++ b/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.h
@@ -26,9 +26,9 @@ VerdictCacheManagerFactory(); ~VerdictCacheManagerFactory() override = default; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* browser_state) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_VERDICT_CACHE_MANAGER_FACTORY_H_
diff --git a/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.mm b/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.mm index 82a313d6..d46edf18 100644 --- a/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.mm +++ b/ios/chrome/browser/safe_browsing/model/verdict_cache_manager_factory.mm
@@ -36,9 +36,7 @@ } std::unique_ptr<KeyedService> -VerdictCacheManagerFactory::BuildServiceInstanceFor( - web::BrowserState* browser_state) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(browser_state); +VerdictCacheManagerFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { return std::make_unique<safe_browsing::VerdictCacheManager>( ios::HistoryServiceFactory::GetForProfile( profile, ServiceAccessType::EXPLICIT_ACCESS),
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/bulk_upload/bulk_upload_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/google_services/bulk_upload/bulk_upload_coordinator.mm index d8c96b8e..b3bef54 100644 --- a/ios/chrome/browser/settings/ui_bundled/google_services/bulk_upload/bulk_upload_coordinator.mm +++ b/ios/chrome/browser/settings/ui_bundled/google_services/bulk_upload/bulk_upload_coordinator.mm
@@ -4,8 +4,6 @@ #import "ios/chrome/browser/settings/ui_bundled/google_services/bulk_upload/bulk_upload_coordinator.h" -#import <MaterialComponents/MaterialSnackbar.h> - #import "base/check.h" #import "base/metrics/user_metrics.h" #import "components/sync/service/sync_service.h" @@ -119,7 +117,7 @@ - (void)displayInSnackbar:(NSString*)message { [self.snackbarCommandsHandler - showSnackbarMessage:CreateSnackbarMessage(message)]; + showCustomSnackbarMessage:CreateCustomSnackbarMessage(message)]; } @end
diff --git a/ios/chrome/browser/shared/model/browser/browser_list_factory.h b/ios/chrome/browser/shared/model/browser/browser_list_factory.h index d40da06e..93f478f 100644 --- a/ios/chrome/browser/shared/model/browser/browser_list_factory.h +++ b/ios/chrome/browser/shared/model/browser/browser_list_factory.h
@@ -25,9 +25,9 @@ BrowserListFactory(); - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS: std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const final; + ProfileIOS* profile) const final; }; #endif // IOS_CHROME_BROWSER_SHARED_MODEL_BROWSER_BROWSER_LIST_FACTORY_H_
diff --git a/ios/chrome/browser/shared/model/browser/browser_list_factory.mm b/ios/chrome/browser/shared/model/browser/browser_list_factory.mm index b8933cd3..52c24d9f 100644 --- a/ios/chrome/browser/shared/model/browser/browser_list_factory.mm +++ b/ios/chrome/browser/shared/model/browser/browser_list_factory.mm
@@ -27,6 +27,6 @@ ProfileSelection::kRedirectedInIncognito) {} std::unique_ptr<KeyedService> BrowserListFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { return std::make_unique<BrowserList>(); }
diff --git a/ios/chrome/browser/shared/ui/util/identity_snackbar/identity_snackbar_message_egtest.mm b/ios/chrome/browser/shared/ui/util/identity_snackbar/identity_snackbar_message_egtest.mm index 8df47234..5dd43e08 100644 --- a/ios/chrome/browser/shared/ui/util/identity_snackbar/identity_snackbar_message_egtest.mm +++ b/ios/chrome/browser/shared/ui/util/identity_snackbar/identity_snackbar_message_egtest.mm
@@ -158,7 +158,8 @@ // Verifies no identity confirmation snackbar shows on startup when there is an // identity on the device but the user is signed-out. -- (void)testNoIdentity_IdentityConfirmationToast { +// TODO(crbug.com/443199219): Flaky on iPad. +- (void)DISABLED_testNoIdentity_IdentityConfirmationToast { // TODO(crbug.com/441260415): Re-enable the test on iOS26. if (base::ios::IsRunningOnIOS26OrLater()) { EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 26."); @@ -191,7 +192,8 @@ // Verifies identity confirmation snackbar shows on startup with multiple // identities on device with frequency limitations. -- (void)testFrequencyLimitation_IdentityConfirmationToast { +// TODO(crbug.com/443199219): Flaky on iPad. +- (void)DISABLED_testFrequencyLimitation_IdentityConfirmationToast { // TODO(crbug.com/433726717): Test disabled on iPhones. if (![ChromeEarlGrey isIPadIdiom]) { EARL_GREY_TEST_DISABLED(@"Fails on iPhones.");
diff --git a/ios/chrome/browser/supervised_user/model/child_account_service_factory.h b/ios/chrome/browser/supervised_user/model/child_account_service_factory.h index 028cb240..43af3b4 100644 --- a/ios/chrome/browser/supervised_user/model/child_account_service_factory.h +++ b/ios/chrome/browser/supervised_user/model/child_account_service_factory.h
@@ -26,9 +26,9 @@ ChildAccountServiceFactory(); ~ChildAccountServiceFactory() override = default; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SUPERVISED_USER_MODEL_CHILD_ACCOUNT_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/supervised_user/model/child_account_service_factory.mm b/ios/chrome/browser/supervised_user/model/child_account_service_factory.mm index 91700dc..22eaed8b 100644 --- a/ios/chrome/browser/supervised_user/model/child_account_service_factory.mm +++ b/ios/chrome/browser/supervised_user/model/child_account_service_factory.mm
@@ -35,9 +35,7 @@ } std::unique_ptr<KeyedService> -ChildAccountServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); +ChildAccountServiceFactory::BuildServiceInstanceFor(ProfileIOS* profile) const { CHECK(SupervisedUserServiceFactory::GetForProfile(profile)); return std::make_unique<supervised_user::ChildAccountService>( CHECK_DEREF(profile->GetPrefs()),
diff --git a/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.h b/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.h index d4e11e8..9da7b40 100644 --- a/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.h +++ b/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.h
@@ -26,9 +26,9 @@ ListFamilyMembersServiceFactory(); ~ListFamilyMembersServiceFactory() override = default; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SUPERVISED_USER_MODEL_LIST_FAMILY_MEMBERS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.mm b/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.mm index 9c4ba78..88c4a6f 100644 --- a/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.mm +++ b/ios/chrome/browser/supervised_user/model/list_family_members_service_factory.mm
@@ -32,8 +32,7 @@ std::unique_ptr<KeyedService> ListFamilyMembersServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { return std::make_unique<supervised_user::ListFamilyMembersService>( IdentityManagerFactory::GetForProfile(profile), profile->GetSharedURLLoaderFactory(), CHECK_DEREF(profile->GetPrefs()));
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.h b/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.h index 0f494be..b295652 100644 --- a/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.h +++ b/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.h
@@ -27,9 +27,9 @@ SupervisedUserMetricsServiceFactory(); ~SupervisedUserMetricsServiceFactory() override = default; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SUPERVISED_USER_MODEL_SUPERVISED_USER_METRICS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.mm b/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.mm index a653050..5a4204c4 100644 --- a/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.mm +++ b/ios/chrome/browser/supervised_user/model/supervised_user_metrics_service_factory.mm
@@ -31,8 +31,7 @@ std::unique_ptr<KeyedService> SupervisedUserMetricsServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { return std::make_unique<supervised_user::SupervisedUserMetricsService>( profile->GetPrefs(), *SupervisedUserServiceFactory::GetForProfile(profile),
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.h b/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.h index 620ae06..2c7575e 100644 --- a/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.h +++ b/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.h
@@ -26,9 +26,9 @@ SupervisedUserServiceFactory(); ~SupervisedUserServiceFactory() override = default; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SUPERVISED_USER_MODEL_SUPERVISED_USER_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.mm b/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.mm index 188faa41..6e097ff 100644 --- a/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.mm +++ b/ios/chrome/browser/supervised_user/model/supervised_user_service_factory.mm
@@ -55,9 +55,7 @@ std::unique_ptr<KeyedService> SupervisedUserServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); - + ProfileIOS* profile) const { std::unique_ptr<SupervisedUserServicePlatformDelegate> platform_delegate = std::make_unique<SupervisedUserServicePlatformDelegate>(profile); signin::IdentityManager* identity_manager =
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h index 0f8f137..4541bb33 100644 --- a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h +++ b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h
@@ -27,10 +27,10 @@ SupervisedUserSettingsServiceFactory(); ~SupervisedUserSettingsServiceFactory() override = default; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. bool ServiceIsRequiredForContextInitialization() const override; std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_SUPERVISED_USER_MODEL_SUPERVISED_USER_SETTINGS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm index d31346b9..5cd263e9 100644 --- a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm +++ b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm
@@ -38,6 +38,6 @@ std::unique_ptr<KeyedService> SupervisedUserSettingsServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { return std::make_unique<supervised_user::SupervisedUserSettingsService>(); }
diff --git a/ios/chrome/browser/sync/model/BUILD.gn b/ios/chrome/browser/sync/model/BUILD.gn index c5115bc..c09f79ee 100644 --- a/ios/chrome/browser/sync/model/BUILD.gn +++ b/ios/chrome/browser/sync/model/BUILD.gn
@@ -74,7 +74,6 @@ "//ios/chrome/browser/passwords/model:sharing_factory", "//ios/chrome/browser/passwords/model:store_factory", "//ios/chrome/browser/plus_addresses/model", - "//ios/chrome/browser/power_bookmarks/model", "//ios/chrome/browser/reading_list/model", "//ios/chrome/browser/saved_tab_groups/model", "//ios/chrome/browser/search_engines/model",
diff --git a/ios/chrome/browser/sync/model/DEPS b/ios/chrome/browser/sync/model/DEPS index ce0617a6..4a67b65a 100644 --- a/ios/chrome/browser/sync/model/DEPS +++ b/ios/chrome/browser/sync/model/DEPS
@@ -20,7 +20,6 @@ "+ios/chrome/browser/metrics/model", "+ios/chrome/browser/passwords/model", "+ios/chrome/browser/plus_addresses/model", - "+ios/chrome/browser/power_bookmarks/model", "+ios/chrome/browser/push_notification/model", "+ios/chrome/browser/reading_list/model", "+ios/chrome/browser/saved_tab_groups/model",
diff --git a/ios/chrome/browser/sync/model/sync_error_browser_agent.h b/ios/chrome/browser/sync/model/sync_error_browser_agent.h index 488283e0..4e55814 100644 --- a/ios/chrome/browser/sync/model/sync_error_browser_agent.h +++ b/ios/chrome/browser/sync/model/sync_error_browser_agent.h
@@ -91,8 +91,6 @@ __weak id<SyncPresenter> sync_presenter_provider_; // Used to observe the ProfileState. __strong SyncErrorBrowserAgentProfileStateObserver* profile_state_observer_; - - base::WeakPtrFactory<SyncErrorBrowserAgent> weak_ptr_factory_{this}; }; #endif // IOS_CHROME_BROWSER_SYNC_MODEL_SYNC_ERROR_BROWSER_AGENT_H_
diff --git a/ios/chrome/browser/sync/model/sync_error_browser_agent.mm b/ios/chrome/browser/sync/model/sync_error_browser_agent.mm index c199a696..0970995a 100644 --- a/ios/chrome/browser/sync/model/sync_error_browser_agent.mm +++ b/ios/chrome/browser/sync/model/sync_error_browser_agent.mm
@@ -263,7 +263,7 @@ password_manager::PasswordFormCache* password_form_cache = GetPasswordFormCacheFromWebState(web_state); if (password_form_cache) { - password_form_cache->SetObserver(weak_ptr_factory_.GetWeakPtr()); + password_form_cache->AddObserver(this); } } @@ -274,6 +274,6 @@ password_manager::PasswordFormCache* password_form_cache = GetPasswordFormCacheFromWebState(web_state); if (password_form_cache) { - password_form_cache->ResetObserver(); + password_form_cache->RemoveObserver(this); } }
diff --git a/ios/chrome/browser/sync/model/sync_service_factory.mm b/ios/chrome/browser/sync/model/sync_service_factory.mm index 9c95b06..897eb7b 100644 --- a/ios/chrome/browser/sync/model/sync_service_factory.mm +++ b/ios/chrome/browser/sync/model/sync_service_factory.mm
@@ -51,7 +51,6 @@ #import "ios/chrome/browser/passwords/model/ios_chrome_password_sender_service_factory.h" #import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h" #import "ios/chrome/browser/plus_addresses/model/plus_address_setting_service_factory.h" -#import "ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.h" #import "ios/chrome/browser/reading_list/model/reading_list_model_factory.h" #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h" #import "ios/chrome/browser/search_engines/model/template_url_service_factory.h" @@ -132,8 +131,6 @@ PlusAddressSettingServiceFactory::GetForProfile(profile), ios::WebDataServiceFactory::GetPlusAddressWebDataForProfile( profile, ServiceAccessType::IMPLICIT_ACCESS)); - builder.SetPowerBookmarkService( - PowerBookmarkServiceFactory::GetForProfile(profile)); builder.SetPrefService(profile->GetPrefs()); builder.SetPrefServiceSyncable(profile->GetSyncablePrefs()); // TODO(crbug.com/330201909) implement for iOS. @@ -352,7 +349,6 @@ DependsOn(IOSTrustedVaultServiceFactory::GetInstance()); DependsOn(IOSUserEventServiceFactory::GetInstance()); DependsOn(PlusAddressSettingServiceFactory::GetInstance()); - DependsOn(PowerBookmarkServiceFactory::GetInstance()); DependsOn(ReadingListModelFactory::GetInstance()); DependsOn(SendTabToSelfSyncServiceFactory::GetInstance()); DependsOn(SessionSyncServiceFactory::GetInstance());
diff --git a/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.h b/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.h index e7a0fdbd..4ab07a9 100644 --- a/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.h +++ b/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.h
@@ -24,9 +24,9 @@ TabsSearchServiceFactory(); ~TabsSearchServiceFactory() override; - // BrowserStateKeyedServiceFactory: + // ProfileKeyedServiceFactoryIOS: std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_TABS_SEARCH_MODEL_TABS_SEARCH_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.mm b/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.mm index a83bd639..167c0c6e 100644 --- a/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.mm +++ b/ios/chrome/browser/tabs_search/model/tabs_search_service_factory.mm
@@ -54,9 +54,7 @@ TabsSearchServiceFactory::~TabsSearchServiceFactory() = default; std::unique_ptr<KeyedService> TabsSearchServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); - + ProfileIOS* profile) const { const bool is_off_the_record = profile->IsOffTheRecord(); return std::make_unique<TabsSearchService>( is_off_the_record, BrowserListFactory::GetForProfile(profile),
diff --git a/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.h b/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.h index a40972cb..6ae412c 100644 --- a/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.h +++ b/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.h
@@ -25,9 +25,9 @@ TextClassifierModelServiceFactory(); ~TextClassifierModelServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation: + // ProfileKeyedServiceFactoryIOS implementation: std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_TEXT_SELECTION_MODEL_TEXT_CLASSIFIER_MODEL_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.mm b/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.mm index b2e6a6e9..0e15d48 100644 --- a/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.mm +++ b/ios/chrome/browser/text_selection/model/text_classifier_model_service_factory.mm
@@ -38,13 +38,12 @@ std::unique_ptr<KeyedService> TextClassifierModelServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { if (!IsExpKitTextClassifierEntityEnabled() || !optimization_guide::features::IsOptimizationTargetPredictionEnabled()) { return nullptr; } - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); // The optimization guide service must be available for the text classifier // model service to be created. OptimizationGuideService* opt_guide =
diff --git a/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.h b/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.h index 0c8fb84..b582a69b9 100644 --- a/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.h +++ b/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.h
@@ -13,7 +13,7 @@ // Fake implementation of TextClassifierModelService that can be used by tests. class TextClassifierModelServiceFake : public TextClassifierModelService { public: - using TestingFactory = ProfileKeyedServiceFactoryIOS::TestingFactory; + using TestingFactory = ProfileKeyedServiceFactoryIOS::ProfileTestingFactory; static TestingFactory GetTestingFactory(); ~TextClassifierModelServiceFake() override;
diff --git a/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.mm b/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.mm index 7fff441..835a008 100644 --- a/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.mm +++ b/ios/chrome/browser/text_selection/model/text_classifier_model_service_fake.mm
@@ -15,13 +15,10 @@ namespace { // Returns a new instance of TextClassifierModelServiceFake. -std::unique_ptr<KeyedService> BuildInstance(web::BrowserState* context) { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); +std::unique_ptr<KeyedService> BuildInstance(ProfileIOS* profile) { OptimizationGuideService* opt_guide = OptimizationGuideServiceFactory::GetForProfile(profile); - std::unique_ptr<TextClassifierModelService> service = - base::WrapUnique(new TextClassifierModelServiceFake(opt_guide)); - return service; + return std::make_unique<TextClassifierModelServiceFake>(opt_guide); } } // anonymous namespace
diff --git a/ios/chrome/browser/toolbar/ui_bundled/tab_groups/test/tab_group_indicator_egtest.mm b/ios/chrome/browser/toolbar/ui_bundled/tab_groups/test/tab_group_indicator_egtest.mm index 42999cb..0d97a712 100644 --- a/ios/chrome/browser/toolbar/ui_bundled/tab_groups/test/tab_group_indicator_egtest.mm +++ b/ios/chrome/browser/toolbar/ui_bundled/tab_groups/test/tab_group_indicator_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "base/ios/ios_util.h" #import "base/strings/sys_string_conversions.h" #import "components/data_sharing/public/features.h" #import "components/data_sharing/public/group_data.h" @@ -366,6 +367,11 @@ // Tests that renaming a tab group from the tab group indicator menu works. - (void)testTabGroupIndicatorMenuActionsRenameGroup { + // TODO(crbug.com/442817314): Re-enable this flaky test on iOS26. + if (base::ios::IsRunningOnIOS26OrLater()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 26."); + } + if ([ChromeEarlGrey isIPadIdiom]) { EARL_GREY_TEST_SKIPPED(@"On iPad, the tab group indicator is not displayed " @"if the tab strip is visible.");
diff --git a/ios/chrome/browser/web/model/error_page_egtest.mm b/ios/chrome/browser/web/model/error_page_egtest.mm index ce41369..a360823 100644 --- a/ios/chrome/browser/web/model/error_page_egtest.mm +++ b/ios/chrome/browser/web/model/error_page_egtest.mm
@@ -76,6 +76,11 @@ #define MAYBE_testBackForwardErrorPage testBackForwardErrorPage #endif - (void)MAYBE_testBackForwardErrorPage { + // TODO(crbug.com/443199230): Test Failing on iPad. + if ([ChromeEarlGrey isIPadIdiom]) { + EARL_GREY_TEST_DISABLED(@"Fails on iPads."); + } + // TODO(crbug.com/40159013): Going back/forward on the same host is failing. // Use chrome:// to have a different hosts. std::string errorText = net::ErrorToShortString(net::ERR_INVALID_URL);
diff --git a/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.h b/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.h index 54020ca..fa32d9c 100644 --- a/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.h +++ b/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.h
@@ -23,9 +23,9 @@ JavaScriptConsoleFeatureFactory(); ~JavaScriptConsoleFeatureFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_WEB_MODEL_JAVA_SCRIPT_CONSOLE_JAVA_SCRIPT_CONSOLE_FEATURE_FACTORY_H_
diff --git a/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.mm b/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.mm index 7497908..a7ac7e1 100644 --- a/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.mm +++ b/ios/chrome/browser/web/model/java_script_console/java_script_console_feature_factory.mm
@@ -31,6 +31,6 @@ std::unique_ptr<KeyedService> JavaScriptConsoleFeatureFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { + ProfileIOS* profile) const { return std::make_unique<JavaScriptConsoleFeature>(); }
diff --git a/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.cc b/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.cc index 24eea226..fd7515b7 100644 --- a/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.cc +++ b/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.cc
@@ -37,8 +37,7 @@ IOSPasskeyModelFactory::~IOSPasskeyModelFactory() {} std::unique_ptr<KeyedService> IOSPasskeyModelFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + ProfileIOS* profile) const { auto sync_bridge = std::make_unique<webauthn::PasskeySyncBridge>( DataTypeStoreServiceFactory::GetForProfile(profile)->GetStoreFactory());
diff --git a/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.h b/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.h index 5b457ddd..5015179 100644 --- a/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.h +++ b/ios/chrome/browser/webauthn/model/ios_passkey_model_factory.h
@@ -27,9 +27,9 @@ IOSPasskeyModelFactory(); ~IOSPasskeyModelFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; #endif // IOS_CHROME_BROWSER_WEBAUTHN_MODEL_IOS_PASSKEY_MODEL_FACTORY_H_
diff --git a/ios/chrome/browser/webdata_services/model/web_data_service_factory.h b/ios/chrome/browser/webdata_services/model/web_data_service_factory.h index 69e8e72..e39f5dc4 100644 --- a/ios/chrome/browser/webdata_services/model/web_data_service_factory.h +++ b/ios/chrome/browser/webdata_services/model/web_data_service_factory.h
@@ -66,7 +66,7 @@ static WebDataServiceFactory* GetInstance(); // Returns the default factory, useful in tests where it's null by default. - static TestingFactory GetDefaultFactory(); + static ProfileTestingFactory GetDefaultFactory(); private: friend class base::NoDestructor<WebDataServiceFactory>; @@ -74,9 +74,9 @@ WebDataServiceFactory(); ~WebDataServiceFactory() override; - // BrowserStateKeyedServiceFactory implementation. + // ProfileKeyedServiceFactoryIOS implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; + ProfileIOS* profile) const override; }; } // namespace ios
diff --git a/ios/chrome/browser/webdata_services/model/web_data_service_factory.mm b/ios/chrome/browser/webdata_services/model/web_data_service_factory.mm index d7db304..42a8148 100644 --- a/ios/chrome/browser/webdata_services/model/web_data_service_factory.mm +++ b/ios/chrome/browser/webdata_services/model/web_data_service_factory.mm
@@ -25,8 +25,8 @@ namespace { -std::unique_ptr<KeyedService> BuildWebDataService(web::BrowserState* context) { - const base::FilePath& state_path = context->GetStatePath(); +std::unique_ptr<KeyedService> BuildWebDataService(ProfileIOS* profile) { + const base::FilePath& state_path = profile->GetStatePath(); // On iOS (and Android), the account storage is persisted on disk. return std::make_unique<WebDataServiceWrapper>( state_path, GetApplicationContext()->GetApplicationLocaleStorage()->Get(), @@ -108,9 +108,9 @@ } // static -ProfileKeyedServiceFactoryIOS::TestingFactory +ProfileKeyedServiceFactoryIOS::ProfileTestingFactory WebDataServiceFactory::GetDefaultFactory() { - return base::BindRepeating(&BuildWebDataService); + return base::BindOnce(&BuildWebDataService); } WebDataServiceFactory::WebDataServiceFactory() @@ -121,8 +121,8 @@ WebDataServiceFactory::~WebDataServiceFactory() {} std::unique_ptr<KeyedService> WebDataServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return BuildWebDataService(context); + ProfileIOS* profile) const { + return BuildWebDataService(profile); } } // namespace ios
diff --git a/ios/web_view/internal/sync/web_view_sync_service_factory.mm b/ios/web_view/internal/sync/web_view_sync_service_factory.mm index fff0f0e..2fff513 100644 --- a/ios/web_view/internal/sync/web_view_sync_service_factory.mm +++ b/ios/web_view/internal/sync/web_view_sync_service_factory.mm
@@ -105,7 +105,6 @@ controller_builder.SetPasswordReceiverService(nullptr); controller_builder.SetPasswordSenderService(nullptr); controller_builder.SetPlusAddressServices(nullptr, nullptr); - controller_builder.SetPowerBookmarkService(nullptr); controller_builder.SetPrefServiceSyncable(nullptr); // TODO(crbug.com/330201909) implement for iOS. controller_builder.SetProductSpecificationsService(nullptr);
diff --git a/media/renderers/paint_canvas_video_renderer_unittest.cc b/media/renderers/paint_canvas_video_renderer_unittest.cc index be176a4..2dceb47 100644 --- a/media/renderers/paint_canvas_video_renderer_unittest.cc +++ b/media/renderers/paint_canvas_video_renderer_unittest.cc
@@ -45,7 +45,6 @@ #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h" #include "third_party/skia/include/private/chromium/SkPMColor.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/rect_f.h" @@ -1001,54 +1000,8 @@ texsubimage2d_callback_; }; -#if !BUILDFLAG(IS_ANDROID) -void MailboxHoldersReleased(const gpu::SyncToken& sync_token) {} -#endif } // namespace -// NOTE: The below test tests behavior when PaintCanvasVideoRenderer is used -// without GPU raster. It is not relevant on Android, where GPU raster is -// always used. -#if !BUILDFLAG(IS_ANDROID) -// Test that PaintCanvasVideoRenderer::Paint doesn't crash when GrContext is -// unable to wrap a video frame texture (eg due to being abandoned). -TEST_F(PaintCanvasVideoRendererTest, ContextLost) { - auto context_provider = viz::TestContextProvider::Create(); - CHECK(context_provider); - context_provider->BindToCurrentSequence(); - CHECK(context_provider->GrContext()); - context_provider->GrContext()->abandonContext(); - - cc::SkiaPaintCanvas canvas(AllocBitmap(kWidth, kHeight)); - - gfx::Size size(kWidth, kHeight); - // We try copying the contents of the source VideoFrame *into* the - // cached SI over the raster interface. - gpu::SharedImageMetadata metadata; - metadata.format = viz::SinglePlaneFormat::kRGBA_8888; - metadata.size = size; - metadata.color_space = gfx::ColorSpace::CreateSRGB(); - metadata.surface_origin = kTopLeft_GrSurfaceOrigin; - metadata.alpha_type = kOpaque_SkAlphaType; - metadata.usage = gpu::SHARED_IMAGE_USAGE_RASTER_READ; - scoped_refptr<gpu::ClientSharedImage> shared_image = - gpu::ClientSharedImage::CreateForTesting(metadata); - auto video_frame = VideoFrame::WrapSharedImage( - PIXEL_FORMAT_NV12, shared_image, gpu::SyncToken(), - base::BindOnce(MailboxHoldersReleased), size, gfx::Rect(size), size, - kNoTimestamp); - - cc::PaintFlags flags; - flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow); - PaintCanvasVideoRenderer::PaintParams params; - params.dest_rect = kNaturalRect; - renderer_.Paint(std::move(video_frame), &canvas, flags, params, - context_provider.get()); -} -#endif - -void EmptyCallback(const gpu::SyncToken& sync_token) {} - TEST_F(PaintCanvasVideoRendererTest, CorrectFrameSizeToVisibleRect) { constexpr int fWidth{16}, fHeight{16}; SkImageInfo imInfo =
diff --git a/services/data_decoder/public/cpp/json_sanitizer_non_android.cc b/services/data_decoder/public/cpp/json_sanitizer_non_android.cc index 7b7d1a2..b760e5c4 100644 --- a/services/data_decoder/public/cpp/json_sanitizer_non_android.cc +++ b/services/data_decoder/public/cpp/json_sanitizer_non_android.cc
@@ -28,11 +28,12 @@ value.type() != base::Value::Type::LIST) { return base::unexpected("Invalid top-level type"); } - std::string safe_json; - if (!base::JSONWriter::Write(value, &safe_json)) { + std::optional<std::string> safe_json = + base::WriteJson(value); + if (!safe_json.has_value()) { return base::unexpected("Encoding error"); } - return base::ok(std::move(safe_json)); + return base::ok(std::move(safe_json.value())); })); }, std::move(callback)));
diff --git a/services/device/geolocation/network_location_request.cc b/services/device/geolocation/network_location_request.cc index 39c6723..b0cef9b 100644 --- a/services/device/geolocation/network_location_request.cc +++ b/services/device/geolocation/network_location_request.cc
@@ -251,8 +251,7 @@ url_loader_->SetAllowHttpErrorResults(true); request_data_ = FormUploadData(wifi_data, wifi_timestamp); - std::string upload_data; - base::JSONWriter::Write(request_data_, &upload_data); + std::string upload_data = base::WriteJson(request_data_).value_or(""); url_loader_->AttachStringForUpload(upload_data, "application/json"); url_loader_->DownloadToString(
diff --git a/services/image_annotation/annotator.cc b/services/image_annotation/annotator.cc index fc49c4fb..7631ec6 100644 --- a/services/image_annotation/annotator.cc +++ b/services/image_annotation/annotator.cc
@@ -754,8 +754,7 @@ base::Value::Dict request; request.Set("imageRequests", std::move(image_request_list)); - std::string json_request; - base::JSONWriter::Write(request, &json_request); + std::string json_request = base::WriteJson(request).value_or(""); ReportServerRequestSizeKB(json_request.size() / 1024);
diff --git a/services/image_annotation/annotator_unittest.cc b/services/image_annotation/annotator_unittest.cc index ef2c0c5..a4db6ed 100644 --- a/services/image_annotation/annotator_unittest.cc +++ b/services/image_annotation/annotator_unittest.cc
@@ -362,13 +362,7 @@ // Returns a "canonically" formatted version of a JSON string by parsing and // then rewriting it. std::string ReformatJson(const std::string& in) { - const std::optional<base::Value> json = base::JSONReader::Read(in); - CHECK(json); - - std::string out; - base::JSONWriter::Write(*json, &out); - - return out; + return base::WriteJson(base::JSONReader::Read(in).value()).value_or(""); } // Receives the result of an annotation request and writes the result data into
diff --git a/services/network/accept_ch_frame_interceptor.cc b/services/network/accept_ch_frame_interceptor.cc index ff53ca4..88157900a 100644 --- a/services/network/accept_ch_frame_interceptor.cc +++ b/services/network/accept_ch_frame_interceptor.cc
@@ -167,17 +167,30 @@ } CHECK(base::FeatureList::IsEnabled(features::kOffloadAcceptCHFrameCheck)); - if (!std::all_of(hints.cbegin(), hints.cend(), - [&](const network::mojom::WebClientHintsType& h) { - const bool hint_enabled = - base::Contains(enabled_client_hints_->hints, h); - if (!hint_enabled) { - base::UmaHistogramEnumeration( - "Net.AcceptCHFrameInterceptor.MismatchClientHint", - h); - } - return hint_enabled; - })) { + // The Accept-CH frame can be offloaded (i.e., handled in the network + // service without an IPC to the browser process) if all hints in the frame + // are present in either the `hints` list (enabled and allowed) or the + // `not_allowed_hints` list (persisted but currently disallowed). If any hint + // is not in either list, we must fall back to the browser process to check. + bool needs_observer_check = false; + for (const auto& h : hints) { + const bool is_in_hints = base::Contains(enabled_client_hints_->hints, h); + const bool is_in_not_allowed_hints = + features::kAcceptCHFrameOffloadNotAllowedHints.Get() && + base::Contains(enabled_client_hints_->not_allowed_hints, h); + const bool is_valid_for_offload = is_in_hints || is_in_not_allowed_hints; + if (is_in_not_allowed_hints && !is_in_hints) { + base::UmaHistogramEnumeration( + "Net.AcceptCHFrameInterceptor.OffloadSuccessForNotAllowedHint", h); + } + if (!is_valid_for_offload) { + needs_observer_check = true; + base::UmaHistogramEnumeration( + "Net.AcceptCHFrameInterceptor.MismatchClientHint2", h); + } + } + + if (needs_observer_check) { return NeedsObserverCheckReason::kHintNotEnabled; }
diff --git a/services/network/accept_ch_frame_interceptor_unittest.cc b/services/network/accept_ch_frame_interceptor_unittest.cc index 7b1081f..24f87f7 100644 --- a/services/network/accept_ch_frame_interceptor_unittest.cc +++ b/services/network/accept_ch_frame_interceptor_unittest.cc
@@ -47,7 +47,7 @@ }; TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckNullOpt) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); Initialize(std::nullopt); EXPECT_EQ(NeedsObserverCheck(url::Origin::Create(kUrl), std::vector<mojom::WebClientHintsType>()), @@ -57,7 +57,7 @@ TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckEmptyHintsShouldBeFalse) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> added_hints = { network::mojom::WebClientHintsType::kUAArch, @@ -72,7 +72,7 @@ TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckAMatchHintShouldBeFalse) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> test_vector = { network::mojom::WebClientHintsType::kUAArch, @@ -84,7 +84,7 @@ TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckMultipleMatchHintsShouldBeFalse) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> test_vector = { network::mojom::WebClientHintsType::kUAArch, @@ -96,7 +96,7 @@ } TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckAMismatchShouldBeTrue) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> added_hints = { network::mojom::WebClientHintsType::kUAArch, @@ -114,7 +114,7 @@ TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckOneOfEntriesMismatchesShouldBeTrue) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> added_hints = { network::mojom::WebClientHintsType::kUAArch, @@ -133,13 +133,13 @@ TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckDifferentOriginShouldBeTrue) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> test_vector = { network::mojom::WebClientHintsType::kUAArch, }; Initialize(CreateEnabledClientHints(kOrigin, test_vector)); - const GURL kOther("https://b.com"); + const GURL kOther("https://b.test"); const url::Origin kOtherOrigin(url::Origin::Create(kOther)); EXPECT_EQ(NeedsObserverCheck(kOtherOrigin, test_vector), AcceptCHFrameInterceptor::NeedsObserverCheckReason:: @@ -148,7 +148,7 @@ TEST_F(AcceptCHFrameInterceptorTest, NeedsObserverCheckNotOutermostMainFrameShouldBeTrue) { - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> test_vector = { network::mojom::WebClientHintsType::kUAArch, @@ -166,14 +166,14 @@ feature_list.InitAndEnableFeatureWithParameters( features::kOffloadAcceptCHFrameCheck, {{"AcceptCHOffloadForSubframe", "false"}}); - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> test_vector = { network::mojom::WebClientHintsType::kUAArch, }; Initialize(CreateEnabledClientHints(kOrigin, test_vector, /*is_outermost_main_frame=*/false)); - const GURL kOther("https://b.com"); + const GURL kOther("https://b.test"); const url::Origin kOtherOrigin(url::Origin::Create(kOther)); EXPECT_EQ(NeedsObserverCheck(kOtherOrigin, test_vector), AcceptCHFrameInterceptor::NeedsObserverCheckReason:: @@ -186,17 +186,66 @@ feature_list.InitAndEnableFeatureWithParameters( features::kOffloadAcceptCHFrameCheck, {{"AcceptCHOffloadForSubframe", "true"}}); - const GURL kUrl("https://a.com"); + const GURL kUrl("https://a.test"); const url::Origin kOrigin(url::Origin::Create(kUrl)); std::vector<mojom::WebClientHintsType> test_vector = { network::mojom::WebClientHintsType::kUAArch, }; Initialize(CreateEnabledClientHints(kOrigin, test_vector, /*is_outermost_main_frame=*/false)); - const GURL kOther("https://b.com"); + const GURL kOther("https://b.test"); const url::Origin kOtherOrigin(url::Origin::Create(kOther)); EXPECT_EQ(NeedsObserverCheck(kOtherOrigin, test_vector), AcceptCHFrameInterceptor::NeedsObserverCheckReason::kNotNeeded); } +TEST_F(AcceptCHFrameInterceptorTest, + NeedsObserverCheckNotAllowedHintWithFeature) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + features::kOffloadAcceptCHFrameCheck, + {{"AcceptCHFrameOffloadNotAllowedHints", "true"}}); + + const GURL kUrl("https://a.test"); + const url::Origin kOrigin(url::Origin::Create(kUrl)); + auto enabled_client_hints = CreateEnabledClientHints( + kOrigin, {network::mojom::WebClientHintsType::kUAArch}); + enabled_client_hints.not_allowed_hints = { + network::mojom::WebClientHintsType::kUAPlatform}; + Initialize(std::move(enabled_client_hints)); + + // A hint that is only in `not_allowed_hints` should be considered enabled. + EXPECT_EQ(NeedsObserverCheck( + kOrigin, {network::mojom::WebClientHintsType::kUAPlatform}), + AcceptCHFrameInterceptor::NeedsObserverCheckReason::kNotNeeded); + + // A mix of hints from both lists should also be considered enabled. + EXPECT_EQ(NeedsObserverCheck( + kOrigin, {network::mojom::WebClientHintsType::kUAArch, + network::mojom::WebClientHintsType::kUAPlatform}), + AcceptCHFrameInterceptor::NeedsObserverCheckReason::kNotNeeded); +} + +TEST_F(AcceptCHFrameInterceptorTest, + NeedsObserverCheckNotAllowedHintWithoutFeature) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + features::kOffloadAcceptCHFrameCheck, + {{"AcceptCHFrameOffloadNotAllowedHints", "false"}}); + + const GURL kUrl("https://a.test"); + const url::Origin kOrigin(url::Origin::Create(kUrl)); + auto enabled_client_hints = CreateEnabledClientHints( + kOrigin, {network::mojom::WebClientHintsType::kUAArch}); + enabled_client_hints.not_allowed_hints = { + network::mojom::WebClientHintsType::kUAPlatform}; + Initialize(std::move(enabled_client_hints)); + + // A hint that is only in `not_allowed_hints` should be a mismatch. + EXPECT_EQ( + NeedsObserverCheck(kOrigin, + {network::mojom::WebClientHintsType::kUAPlatform}), + AcceptCHFrameInterceptor::NeedsObserverCheckReason::kHintNotEnabled); +} + } // namespace network
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index b681863..5c39cc7 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -166,6 +166,16 @@ "OffloadAcceptCHFrameCheck", base::FEATURE_DISABLED_BY_DEFAULT); +// When enabled, the network service will consider not-allowed but persisted +// client hints as "enabled" for the purpose of the Accept-CH frame offload +// check. +// See crbug.com/406407746 for details. +BASE_FEATURE_PARAM(bool, + kAcceptCHFrameOffloadNotAllowedHints, + &kOffloadAcceptCHFrameCheck, + "AcceptCHFrameOffloadNotAllowedHints", + false); + // Enable offloading the network layer to check enabled client hints even when // cross origin redirect happens. // See crbug.com/406407746 for details.
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h index 3f81a525..b0e9e73 100644 --- a/services/network/public/cpp/features.h +++ b/services/network/public/cpp/features.h
@@ -66,6 +66,8 @@ COMPONENT_EXPORT(NETWORK_CPP_FLAGS_AND_SWITCHES) BASE_DECLARE_FEATURE(kOffloadAcceptCHFrameCheck); COMPONENT_EXPORT(NETWORK_CPP_FLAGS_AND_SWITCHES) +BASE_DECLARE_FEATURE_PARAM(bool, kAcceptCHFrameOffloadNotAllowedHints); +COMPONENT_EXPORT(NETWORK_CPP_FLAGS_AND_SWITCHES) BASE_DECLARE_FEATURE_PARAM(bool, kAcceptCHOffloadWithRedirect); COMPONENT_EXPORT(NETWORK_CPP_FLAGS_AND_SWITCHES) BASE_DECLARE_FEATURE_PARAM(bool, kAcceptCHOffloadForSubframe);
diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h index 3137a61c..759539fe 100644 --- a/services/network/public/cpp/resource_request.h +++ b/services/network/public/cpp/resource_request.h
@@ -72,7 +72,15 @@ url::Origin origin; bool is_outermost_main_frame = false; + // The set of client hints that are enabled for the origin and currently + // allowed to be attached to the request (e.g., by Feature Policy). std::vector<network::mojom::WebClientHintsType> hints; + // The set of client hints that are persisted for the origin but are + // currently not allowed to be attached to the request (e.g., blocked by + // Feature Policy). This is used in the network service to avoid an + // unnecessary IPC to the browser process when an ACCEPT_CH frame contains + // such hints. + std::vector<network::mojom::WebClientHintsType> not_allowed_hints; }; TrustedParams();
diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc index 1d4476c..828d1d57 100644 --- a/services/network/public/cpp/url_request_mojom_traits.cc +++ b/services/network/public/cpp/url_request_mojom_traits.cc
@@ -49,6 +49,9 @@ if (!data.ReadHints(&out->hints)) { return false; } + if (!data.ReadNotAllowedHints(&out->not_allowed_hints)) { + return false; + } return true; }
diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h index 933a3cc..3a028b9 100644 --- a/services/network/public/cpp/url_request_mojom_traits.h +++ b/services/network/public/cpp/url_request_mojom_traits.h
@@ -72,6 +72,13 @@ return enabled_client_hints.hints; } + static const std::vector<network::mojom::WebClientHintsType>& + not_allowed_hints( + const network::ResourceRequest::TrustedParams::EnabledClientHints& + enabled_client_hints) { + return enabled_client_hints.not_allowed_hints; + } + static bool Read( network::mojom::EnabledClientHintsDataView data, network::ResourceRequest::TrustedParams::EnabledClientHints* out);
diff --git a/services/network/public/cpp/url_request_mojom_traits_unittest.cc b/services/network/public/cpp/url_request_mojom_traits_unittest.cc index 93e606b..f6b7cd6 100644 --- a/services/network/public/cpp/url_request_mojom_traits_unittest.cc +++ b/services/network/public/cpp/url_request_mojom_traits_unittest.cc
@@ -68,7 +68,7 @@ original.request_initiator = url::Origin::Create(original.url); original.isolated_world_origin = url::Origin::Create(GURL("chrome-extension://blah")); - original.referrer = GURL("https://referrer.com/"); + original.referrer = GURL("https://referrer.test/"); original.referrer_policy = net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN; original.headers.SetHeader("Accept", "text/xml"); @@ -127,16 +127,20 @@ original.trusted_params->include_request_cookies_with_response = true; original.trusted_params->enabled_client_hints.emplace(); original.trusted_params->enabled_client_hints->origin = - url::Origin::Create(GURL("https://a.com")); + url::Origin::Create(GURL("https://a.test")); original.trusted_params->enabled_client_hints->is_outermost_main_frame = true; original.trusted_params->enabled_client_hints->hints = { network::mojom::WebClientHintsType::kUAArch, network::mojom::WebClientHintsType::kUAWoW64, }; + original.trusted_params->enabled_client_hints->not_allowed_hints = { + network::mojom::WebClientHintsType::kUAPlatform, + network::mojom::WebClientHintsType::kUAModel, + }; original.trust_token_params = network::mojom::TrustTokenParams(); original.trust_token_params->issuers.push_back( - url::Origin::Create(GURL("https://issuer.com"))); + url::Origin::Create(GURL("https://issuer.test"))); original.trust_token_params->operation = mojom::TrustTokenOperationType::kRedemption; original.trust_token_params->include_timestamp_header = true; @@ -186,12 +190,16 @@ original.include_request_cookies_with_response = true; original.enabled_client_hints.emplace(); original.enabled_client_hints->origin = - url::Origin::Create(GURL("https://a.com")); + url::Origin::Create(GURL("https://a.test")); original.enabled_client_hints->is_outermost_main_frame = true; original.enabled_client_hints->hints = { network::mojom::WebClientHintsType::kUAArch, network::mojom::WebClientHintsType::kUAWoW64, }; + original.enabled_client_hints->not_allowed_hints = { + network::mojom::WebClientHintsType::kUAPlatform, + network::mojom::WebClientHintsType::kUAModel, + }; network::ResourceRequest::TrustedParams copied; EXPECT_TRUE( mojo::test::SerializeAndDeserialize<mojom::TrustedUrlRequestParams>(
diff --git a/services/network/public/mojom/url_request.mojom b/services/network/public/mojom/url_request.mojom index 02651c7..950d6e0 100644 --- a/services/network/public/mojom/url_request.mojom +++ b/services/network/public/mojom/url_request.mojom
@@ -52,8 +52,16 @@ // Whether this is for an outermost main frame. bool is_outermost_main_frame; - // The client hints enabled for the request. + // The set of client hints that are enabled for the origin and currently + // allowed to be attached to the request (e.g., by Feature Policy). array<WebClientHintsType> hints; + + // The set of client hints that are persisted for the origin but are + // currently not allowed to be attached to the request (e.g., blocked by + // Feature Policy). This is used in the network service to avoid an + // unnecessary IPC to the browser process when an ACCEPT_CH frame contains + // such hints. + array<WebClientHintsType> not_allowed_hints; }; // See documentation at `URLRequest.trusted_params`.
diff --git a/services/network/sct_auditing/sct_auditing_handler.cc b/services/network/sct_auditing/sct_auditing_handler.cc index e8d736dc..188b78d 100644 --- a/services/network/sct_auditing/sct_auditing_handler.cc +++ b/services/network/sct_auditing/sct_auditing_handler.cc
@@ -214,11 +214,7 @@ reports.Append(std::move(report_entry)); } - std::string output; - if (!base::JSONWriter::Write(reports, &output)) { - return std::nullopt; - } - return output; + return base::WriteJson(reports); } void SCTAuditingHandler::DeserializeData(const std::string& serialized) {
diff --git a/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc b/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc index 2c6f964ec..94d965d 100644 --- a/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc +++ b/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc
@@ -830,15 +830,12 @@ } void ParsesOneIssuerCorrectly(base::Value value) { - std::string output; - base::JSONWriter::Write(std::move(value), &output); - TrustTokenKeyCommitmentParser().Parse(output); + TrustTokenKeyCommitmentParser().Parse(base::WriteJson(value).value_or("")); } void ParsesMultipleIssuersCorrectly(base::Value value) { - std::string output; - base::JSONWriter::Write(std::move(value), &output); - TrustTokenKeyCommitmentParser().ParseMultipleIssuers(output); + TrustTokenKeyCommitmentParser().ParseMultipleIssuers( + base::WriteJson(value).value_or("")); } FUZZ_TEST(TrustTokenKeyCommitmentFuzzer, ParsesOneIssuerCorrectly);
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index 47a064d..74fbdb3 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -5975,6 +5975,64 @@ TestMode::kCredentialsModeOmitWorkaround, TestMode::kCredentialsModeOmitWithFeatureFix)); +TEST_F(URLLoaderTest, AcceptCHFrameNotAllowedHintWithFeature) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + features::kOffloadAcceptCHFrameCheck, + {{"AcceptCHFrameOffloadNotAllowedHints", "true"}}); + + net::TransportInfo info = net::DefaultTransportInfo(); + info.accept_ch_frame = "Sec-CH-UA-Platform"; + + const GURL url("http://accept-ch.test/"); + net::URLRequestFilter::GetInstance()->AddUrlInterceptor( + url, std::make_unique<FakeTransportInfoInterceptor>(info)); + + MockAcceptCHFrameObserver observer; + set_accept_ch_frame_observer_for_next_request(&observer); + + network::ResourceRequest::TrustedParams::EnabledClientHints enabled_hints; + enabled_hints.origin = url::Origin::Create(url); + enabled_hints.is_outermost_main_frame = true; + enabled_hints.hints = {network::mojom::WebClientHintsType::kUAArch}; + enabled_hints.not_allowed_hints = { + network::mojom::WebClientHintsType::kUAPlatform}; + set_enabled_client_hints_for_next_request(std::move(enabled_hints)); + + EXPECT_THAT(Load(url), IsOk()); + EXPECT_FALSE(observer.called()); +} + +TEST_F(URLLoaderTest, AcceptCHFrameNotAllowedHintWithoutFeature) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + features::kOffloadAcceptCHFrameCheck, + {{"AcceptCHFrameOffloadNotAllowedHints", "false"}}); + + net::TransportInfo info = net::DefaultTransportInfo(); + info.accept_ch_frame = "Sec-CH-UA-Platform"; + + const GURL url("http://accept-ch.test/"); + net::URLRequestFilter::GetInstance()->AddUrlInterceptor( + url, std::make_unique<FakeTransportInfoInterceptor>(info)); + + MockAcceptCHFrameObserver observer; + set_accept_ch_frame_observer_for_next_request(&observer); + + network::ResourceRequest::TrustedParams::EnabledClientHints enabled_hints; + enabled_hints.origin = url::Origin::Create(url); + enabled_hints.is_outermost_main_frame = true; + enabled_hints.hints = {network::mojom::WebClientHintsType::kUAArch}; + enabled_hints.not_allowed_hints = { + network::mojom::WebClientHintsType::kUAPlatform}; + set_enabled_client_hints_for_next_request(std::move(enabled_hints)); + + EXPECT_THAT(Load(url), IsOk()); + EXPECT_TRUE(observer.called()); + EXPECT_THAT(observer.accept_ch_frame(), + ElementsAre(network::mojom::WebClientHintsType::kUAPlatform)); +} + // Tests that a request with CredentialsMode::kOmit still sends client // certificates when features::kOmitCorsClientCert is disabled, and when the // feature is enabled client certificates are not sent. Also test that when
diff --git a/services/tracing/public/cpp/perfetto/metadata_data_source.cc b/services/tracing/public/cpp/perfetto/metadata_data_source.cc index e0978a4..28c0346 100644 --- a/services/tracing/public/cpp/perfetto/metadata_data_source.cc +++ b/services/tracing/public/cpp/perfetto/metadata_data_source.cc
@@ -218,9 +218,7 @@ } else if (value.is_string()) { metadata->set_string_value(value.GetString().c_str()); } else { - std::string json_value; - base::JSONWriter::Write(value, &json_value); - metadata->set_json_value(json_value.c_str()); + metadata->set_json_value(base::WriteJson(value).value_or("")); } }
diff --git a/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc b/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc index 2778844..ea6c697 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc
@@ -224,9 +224,7 @@ } else if (it.second.is_string()) { new_metadata->set_string_value(it.second.GetString().c_str()); } else { - std::string json_value; - base::JSONWriter::Write(it.second, &json_value); - new_metadata->set_json_value(json_value.c_str()); + new_metadata->set_json_value(base::WriteJson(it.second).value_or("")); } } };
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b5370aa..a2d19230 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2455,6 +2455,7 @@ "enable_features": [ "AutofillEnableEmailOrLoyaltyCardsFilling", "AutofillEnableLoyaltyCardsFilling", + "IPH_AutofillEnableLoyaltyCards", "SyncAutofillLoyaltyCard" ] } @@ -20775,13 +20776,45 @@ "RenderDocumentWithNavigationQueueing": [ { "platforms": [ - "android", "chromeos", + "fuchsia", + "ios", "linux", + "mac", "windows" ], "experiments": [ { + "name": "EnabledSubframeWithQueueing", + "params": { + "level": "subframe", + "queueing_level": "full" + }, + "enable_features": [ + "DelayLayerTreeViewDeletionOnLocalSwap", + "QueueNavigationsWhileWaitingForCommit", + "RenderDocument" + ], + "disable_features": [ + "RenderDocumentCompositorReuse" + ] + }, + { + "name": "EnabledCrashedFrameWithQueueing", + "params": { + "level": "crashed-frame", + "queueing_level": "full" + }, + "enable_features": [ + "DelayLayerTreeViewDeletionOnLocalSwap", + "QueueNavigationsWhileWaitingForCommit", + "RenderDocument" + ], + "disable_features": [ + "RenderDocumentCompositorReuse" + ] + }, + { "name": "EnabledAllFramesWithQueueing", "params": { "level": "all-frames", @@ -20799,16 +20832,16 @@ ] } ], - "RenderDocumentWithNavigationQueueing_Mac": [ + "RenderDocumentWithNavigationQueueing_Android": [ { "platforms": [ - "mac" + "android" ], "experiments": [ { - "name": "EnabledSubframeWithQueueing", + "name": "EnabledAllFramesWithQueueing", "params": { - "level": "subframe", + "level": "all-frames", "queueing_level": "full" }, "enable_features": [
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle index a7ba518..e0f56cb1 100644 --- a/third_party/androidx/build.gradle +++ b/third_party/androidx/build.gradle
@@ -310,7 +310,7 @@ google() maven { // This URL is generated by the fetch_all_androidx.py script. - url 'https://androidx.dev/snapshots/builds/14048353/artifacts/repository' + url 'https://androidx.dev/snapshots/builds/14050537/artifacts/repository' } mavenCentral() }
diff --git a/third_party/angle b/third_party/angle index e893313..fe30cd1 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit e893313ccef7686c9f4c4444c9a605b0578b1534 +Subproject commit fe30cd1a5fecfc2bb7581a742c15e0eb1fd77296
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 7e1c3d6..5fb3e60 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -2177,6 +2177,17 @@ "report_inconsistent_header", false); +// If true, the browser enables synthetic response with the dry run mode. With +// this mode, the navigation request is involved with the service worker code +// path, and the synthetic response eligiblity is evaluated as if the feature is +// enabled. But it doesn't store response headers and actually "synthesize" +// responses with them. This mode is used to compare the metrics. +BASE_FEATURE_PARAM(bool, + kServiceWorkerSyntheticResponseDryRun, + &kServiceWorkerSyntheticResponse, + "dry_run", + false); + // 'Mode' parameter for blink::features::kSoftNavigationHeuristics. const base::FeatureParam<SoftNavigationHeuristicsMode>::Option kSoftNavigationHeuristicsModes[] = {
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 2f501ddd..d7c6366 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -1683,6 +1683,10 @@ bool, kServiceWorkerSyntheticResponseReportInconsistentHeader); +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM( + bool, + kServiceWorkerSyntheticResponseDryRun); + // 'Mode' parameter for blink::features::kSoftNavigationHeuristics. enum class SoftNavigationHeuristicsMode : uint8_t { kBasic,
diff --git a/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc b/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc index 6abc77f..8ac4bdd 100644 --- a/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc +++ b/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc
@@ -732,6 +732,7 @@ {"distance_from_ptr_down_hi", "0"}, {"largest_anchor_threshold", "0.5"}}}}, {}); + config_scope_ = std::make_unique<ViewportHeuristicConfigTestingScope>(); } static constexpr int kViewportWidth = 400; @@ -851,6 +852,7 @@ private: base::test::ScopedFeatureList feature_list_; + std::unique_ptr<ViewportHeuristicConfigTestingScope> config_scope_; }; TEST_F(AnchorElementInteractionViewportHeuristicsTest, BasicTest) {
diff --git a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc index 3c87aed..3d9e84e 100644 --- a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc +++ b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc
@@ -40,22 +40,7 @@ const base::TimeDelta kMouseAccelerationAndVelocityInterval{ base::Milliseconds(50)}; -// Config for viewport heuristic derived from field trial params. -struct ViewportHeuristicConfig { - // Min/max values of distance_from_pointer_down_ratio for an anchor to be - // selected by the heuristic. - std::pair<float, float> distance_from_ptr_down_ratio_bounds; - // The largest anchor should be larger than the next largest anchor by this - // threshold to be selected by the heuristic. More specifically, for the - // largest anchor a1, and the next largest anchor a2: - // (size(a1) - size(a2)) / size(a2) >= `largest_anchor_threshold`. - double largest_anchor_threshold; - // Time to wait before informing the browser of the largest anchor element - // selected by the heuristic. - base::TimeDelta delay; -}; - -ViewportHeuristicConfig GetViewportHeuristicConfig() { +ViewportHeuristicConfig GetViewportHeuristicConfigFromFeatureParams() { // -0.3 is the lower bound of the middle 75% of distance_from_ptr_down_ratio // values of clicked anchors (i.e. the P12.5 value). const base::FeatureParam<double> kDistanceFromPointerDownLowerBound{ @@ -85,8 +70,28 @@ .delay = kDelay.Get()}; } +ViewportHeuristicConfig* g_config_for_testing = nullptr; + +const ViewportHeuristicConfig& GetViewportHeuristicConfig() { + static const ViewportHeuristicConfig config_from_feature_params = + GetViewportHeuristicConfigFromFeatureParams(); + return (g_config_for_testing == nullptr) ? config_from_feature_params + : *g_config_for_testing; +} + } // namespace +ViewportHeuristicConfigTestingScope::ViewportHeuristicConfigTestingScope() + : config_(GetViewportHeuristicConfigFromFeatureParams()) { // IN-TEST + DCHECK(!g_config_for_testing); + g_config_for_testing = &config_; +} + +ViewportHeuristicConfigTestingScope:: + ~ViewportHeuristicConfigTestingScope() { // IN-TEST + g_config_for_testing = nullptr; +} + AnchorElementInteractionTracker::MouseMotionEstimator::MouseMotionEstimator( scoped_refptr<base::SingleThreadTaskRunner> task_runner) : update_timer_( @@ -540,7 +545,7 @@ HeapVector<Member<AnchorPositionUpdate>>& position_updates) { CHECK(base::FeatureList::IsEnabled( blink::features::kPreloadingViewportHeuristics)); - static const ViewportHeuristicConfig config = GetViewportHeuristicConfig(); + const ViewportHeuristicConfig& config = GetViewportHeuristicConfig(); // Reset the delay timer (if active); this could happen if a programmatic // scroll happened after the timer started.
diff --git a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h index e410439..197d613 100644 --- a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h +++ b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h
@@ -29,6 +29,21 @@ CORE_EXPORT BASE_DECLARE_FEATURE(kPreloadingNoSamePageFragmentAnchorTracking); +// Config for viewport heuristic derived from field trial params. +struct ViewportHeuristicConfig { + // Min/max values of distance_from_pointer_down_ratio for an anchor to be + // selected by the heuristic. + std::pair<float, float> distance_from_ptr_down_ratio_bounds; + // The largest anchor should be larger than the next largest anchor by this + // threshold to be selected by the heuristic. More specifically, for the + // largest anchor a1, and the next largest anchor a2: + // (size(a1) - size(a2)) / size(a2) >= `largest_anchor_threshold`. + double largest_anchor_threshold; + // Time to wait before informing the browser of the largest anchor element + // selected by the heuristic. + base::TimeDelta delay; +}; + // Tracks pointerdown events anywhere on a document. On receiving a pointerdown // event, the tracker will retrieve the valid href from the anchor element from // the event and will report the href value to the browser process via Mojo. The @@ -144,6 +159,14 @@ viewport_heuristic_timer_; }; +struct BLINK_EXPORT ViewportHeuristicConfigTestingScope { + ViewportHeuristicConfigTestingScope(); + ~ViewportHeuristicConfigTestingScope(); + + private: + ViewportHeuristicConfig config_; +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_ANCHOR_ELEMENT_INTERACTION_TRACKER_H_
diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc index 3136758..f49612a 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc +++ b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
@@ -15,6 +15,7 @@ #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/html/html_anchor_element.h" #include "third_party/blink/renderer/core/url_pattern/url_pattern.h" +#include "third_party/blink/renderer/core/url_pattern/url_pattern_utils.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" #include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" @@ -297,71 +298,12 @@ const KURL& base_url, ExceptionState& exception_state, String* out_error) { - // If rawPattern is a string, then: - if (String raw_string; raw_pattern->AsString(&raw_string)) { - // Set pattern to the result of constructing a URLPattern using the - // URLPattern(input, baseURL) constructor steps given rawPattern and - // serializedBaseURL. - V8URLPatternInput* url_pattern_input = - MakeGarbageCollected<V8URLPatternInput>(raw_string); - return URLPattern::Create(isolate, url_pattern_input, base_url, - exception_state); + auto result = + ParseURLPatternFromJSON(isolate, *raw_pattern, base_url, exception_state); + if (result.has_value()) { + return result.value(); } - // Otherwise, if rawPattern is a map - if (JSONObject* pattern_object = JSONObject::Cast(raw_pattern)) { - // Let init be «[ "baseURL" → serializedBaseURL ]», representing a - // dictionary of type URLPatternInit. - URLPatternInit* init = URLPatternInit::Create(); - init->setBaseURL(base_url); - - // For each key -> value of rawPattern: - for (wtf_size_t i = 0; i < pattern_object->size(); i++) { - JSONObject::Entry entry = pattern_object->at(i); - String key = entry.first; - String value; - // If value is not a string - if (!entry.second->AsString(&value)) { - SetParseErrorMessage( - out_error, "Values for a URL pattern object must be strings."); - return nullptr; - } - - // Set init[key] to value. - if (key == "protocol") { - init->setProtocol(value); - } else if (key == "username") { - init->setUsername(value); - } else if (key == "password") { - init->setPassword(value); - } else if (key == "hostname") { - init->setHostname(value); - } else if (key == "port") { - init->setPort(value); - } else if (key == "pathname") { - init->setPathname(value); - } else if (key == "search") { - init->setSearch(value); - } else if (key == "hash") { - init->setHash(value); - } else if (key == "baseURL") { - init->setBaseURL(value); - } else { - SetParseErrorMessage(out_error, - StrCat({"Invalid key \"", key, - "\" for a URL pattern object found."})); - return nullptr; - } - } - - // Set pattern to the result of constructing a URLPattern using the - // URLPattern(input, baseURL) constructor steps given init. - V8URLPatternInput* url_pattern_input = - MakeGarbageCollected<V8URLPatternInput>(init); - return URLPattern::Create(isolate, url_pattern_input, exception_state); - } - SetParseErrorMessage(out_error, - "Value for \"href_matches\" should either be a " - "string, an object, or a list of strings and objects."); + SetParseErrorMessage(out_error, result.error()); return nullptr; }
diff --git a/third_party/blink/renderer/core/url_pattern/BUILD.gn b/third_party/blink/renderer/core/url_pattern/BUILD.gn index e4914818..708a302e 100644 --- a/third_party/blink/renderer/core/url_pattern/BUILD.gn +++ b/third_party/blink/renderer/core/url_pattern/BUILD.gn
@@ -16,6 +16,8 @@ "url_pattern_dummy_url_canon.cc", "url_pattern_dummy_url_canon.h", "url_pattern_options.h", + "url_pattern_utils.cc", + "url_pattern_utils.h", ] public_deps = [
diff --git a/third_party/blink/renderer/core/url_pattern/url_pattern_utils.cc b/third_party/blink/renderer/core/url_pattern/url_pattern_utils.cc new file mode 100644 index 0000000..60463399 --- /dev/null +++ b/third_party/blink/renderer/core/url_pattern/url_pattern_utils.cc
@@ -0,0 +1,83 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/url_pattern/url_pattern_utils.h" + +#include "third_party/blink/renderer/bindings/core/v8/v8_union_urlpatterninit_usvstring.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_url_pattern_init.h" +#include "third_party/blink/renderer/core/url_pattern/url_pattern.h" +#include "third_party/blink/renderer/platform/json/json_parser.h" +#include "third_party/blink/renderer/platform/json/json_values.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/text/strcat.h" + +namespace blink { + +base::expected<URLPattern*, String> ParseURLPatternFromJSON( + v8::Isolate* isolate, + const JSONValue& pattern_value, + const KURL& base_url, + ExceptionState& exception_state) { + // If pattern_value is a string, then: + if (String raw_string; pattern_value.AsString(&raw_string)) { + V8URLPatternInput* url_pattern_input = + MakeGarbageCollected<V8URLPatternInput>(raw_string); + return URLPattern::Create(isolate, url_pattern_input, base_url, + exception_state); + } + // Otherwise, if pattern_value is a map + if (const JSONObject* pattern_object = JSONObject::Cast(&pattern_value)) { + // Let init be «[ "baseURL" → serializedBaseURL ]», representing a + // dictionary of type URLPatternInit. + URLPatternInit* init = URLPatternInit::Create(); + init->setBaseURL(base_url); + + // For each key -> value of rawPattern: + for (wtf_size_t i = 0; i < pattern_object->size(); i++) { + JSONObject::Entry entry = pattern_object->at(i); + String key = entry.first; + String value; + // If value is not a string + if (!entry.second->AsString(&value)) { + return base::unexpected( + "Values for a URL pattern object must be strings."); + } + + // Set init[key] to value. + if (key == "protocol") { + init->setProtocol(value); + } else if (key == "username") { + init->setUsername(value); + } else if (key == "password") { + init->setPassword(value); + } else if (key == "hostname") { + init->setHostname(value); + } else if (key == "port") { + init->setPort(value); + } else if (key == "pathname") { + init->setPathname(value); + } else if (key == "search") { + init->setSearch(value); + } else if (key == "hash") { + init->setHash(value); + } else if (key == "baseURL") { + init->setBaseURL(value); + } else { + return base::unexpected(StrCat( + {"Invalid key \"", key, "\" for a URL pattern object found."})); + } + } + + // Set pattern to the result of constructing a URLPattern using the + // URLPattern(input, baseURL) constructor steps given init. + V8URLPatternInput* url_pattern_input = + MakeGarbageCollected<V8URLPatternInput>(init); + return URLPattern::Create(isolate, url_pattern_input, exception_state); + } + return base::unexpected( + "Value for \"href_matches\" should either be a " + "string, an object, or a list of strings and objects."); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/url_pattern/url_pattern_utils.h b/third_party/blink/renderer/core/url_pattern/url_pattern_utils.h new file mode 100644 index 0000000..86f5fe26 --- /dev/null +++ b/third_party/blink/renderer/core/url_pattern/url_pattern_utils.h
@@ -0,0 +1,29 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_URL_PATTERN_URL_PATTERN_UTILS_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_URL_PATTERN_URL_PATTERN_UTILS_H_ + +#include "base/types/expected.h" + +namespace v8 { +class Isolate; +} // namespace v8 + +namespace blink { +class ExceptionState; +class JSONValue; +class KURL; +class String; +class URLPattern; + +base::expected<URLPattern*, String> ParseURLPatternFromJSON( + v8::Isolate*, + const JSONValue&, + const KURL& base_url, + ExceptionState&); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_URL_PATTERN_URL_PATTERN_UTILS_H_
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc index c2825cf..6e910ef 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc
@@ -1988,6 +1988,14 @@ "An allowCredentials is not allowed with immediate mediation.")); return; } + if (options->hasPublicKey() && options->publicKey()->hasExtensions() && + options->publicKey()->extensions()->hasRemoteDesktopClientOverride()) { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNotAllowedError, + "Immediate mediation cannot be used with a remote desktop override " + "request.")); + return; + } if (!LocalFrame::ConsumeTransientUserActivation( To<LocalDOMWindow>(resolver->GetExecutionContext())->GetFrame(), UserActivationUpdateSource::kRenderer)) {
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_ascii_fast_path.h b/third_party/blink/renderer/platform/wtf/text/text_codec_ascii_fast_path.h index 38d07fc..d34846f 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_ascii_fast_path.h +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_ascii_fast_path.h
@@ -37,17 +37,18 @@ template <> struct UCharByteFiller<4> { - static void Copy(LChar* destination, const uint8_t* source) { + static void Copy(MachineWord word, LChar* destination) { // SAFETY: This is only used in a few places, and only copies // a MachineWord buffer, the caller guarantees that destination - // and source holds at least 4 elements. - UNSAFE_BUFFERS(memcpy(destination, source, 4)); + // holds at least 4 elements. + UNSAFE_BUFFERS(memcpy(destination, &word, 4)); } - static void Copy(UChar* destination, const uint8_t* source) { + static void Copy(MachineWord word, UChar* destination) { + auto source = base::byte_span_from_ref(word); // SAFETY: This is only used in a few places, and only copies // a MachineWord buffer, the caller guarantees that destination - // and source holds at least 4 elements. + // holds at least 4 elements. UNSAFE_BUFFERS({ destination[0] = source[0]; destination[1] = source[1]; @@ -59,17 +60,18 @@ template <> struct UCharByteFiller<8> { - static void Copy(LChar* destination, const uint8_t* source) { + static void Copy(MachineWord word, LChar* destination) { // SAFETY: This is only used in a few places, and only copies // a MachineWord buffer, the caller guarantees that destination - // and source holds at least 8 elements. - UNSAFE_BUFFERS(memcpy(destination, source, 8)); + // holds at least 8 elements. + UNSAFE_BUFFERS(memcpy(destination, &word, 8)); } - static void Copy(UChar* destination, const uint8_t* source) { + static void Copy(MachineWord word, UChar* destination) { + auto source = base::byte_span_from_ref(word); // SAFETY: This is only used in a few places, and only copies // a MachineWord buffer, the caller guarantees that destination - // and source holds at least 8 elements. + // holds at least 8 elements. UNSAFE_BUFFERS({ destination[0] = source[0]; destination[1] = source[1]; @@ -83,12 +85,12 @@ } }; -inline void CopyAsciiMachineWord(LChar* destination, const uint8_t* source) { - UCharByteFiller<sizeof(MachineWord)>::Copy(destination, source); +inline void CopyAsciiMachineWord(MachineWord word, LChar* destination) { + UCharByteFiller<sizeof(MachineWord)>::Copy(word, destination); } -inline void CopyAsciiMachineWord(UChar* destination, const uint8_t* source) { - UCharByteFiller<sizeof(MachineWord)>::Copy(destination, source); +inline void CopyAsciiMachineWord(MachineWord word, UChar* destination) { + UCharByteFiller<sizeof(MachineWord)>::Copy(word, destination); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc b/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc index 5e1ea03..04229eb 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_latin1.cc
@@ -137,8 +137,8 @@ static constexpr size_t kMachineWordSize = sizeof(MachineWord); CopyAsciiMachineWord( - destination.take_first<kMachineWordSize>().data(), - source.take_first<kMachineWordSize>().data()); + chunk, destination.take_first<kMachineWordSize>().data()); + source.take_first<kMachineWordSize>(); } if (source.empty()) { @@ -192,8 +192,8 @@ static constexpr size_t kMachineWordSize = sizeof(MachineWord); CopyAsciiMachineWord( - destination16.take_first<kMachineWordSize>().data(), - source.take_first<kMachineWordSize>().data()); + chunk, destination16.take_first<kMachineWordSize>().data()); + source.take_first<kMachineWordSize>(); } if (source.empty()) {
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc b/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc index 3f8d0222..c9635a5 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc
@@ -403,8 +403,8 @@ break; } CopyAsciiMachineWord( - destination.take_first<sizeof(MachineWord)>().data(), - source.take_first<sizeof(MachineWord)>().data()); + chunk, destination.take_first<sizeof(MachineWord)>().data()); + source.take_first<sizeof(MachineWord)>(); } if (source.empty()) { break; @@ -491,8 +491,8 @@ } CopyAsciiMachineWord( - destination16.take_first<sizeof(MachineWord)>().data(), - source.take_first<sizeof(MachineWord)>().data()); + chunk, destination16.take_first<sizeof(MachineWord)>().data()); + source.take_first<sizeof(MachineWord)>(); } if (source.empty()) { break;
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 27689adf..2908353 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -9642,17 +9642,10 @@ # Gardener 2025-08-29 crbug.com/441826647 [ Linux ] external/wpt/webdriver/tests/bidi/browsing_context/navigate/navigate.py [ Skip Timeout ] -# Disabled to unblock crrev.com/c/6903230 -crbug.com/442509324 http/tests/devtools/device-mode/device-mode-responsive.js [ Failure Pass ] -crbug.com/442509324 http/tests/devtools/device-mode/device-mode-switching-devices.js [ Failure Pass ] -crbug.com/442509324 http/tests/devtools/device-mode/device-mode-toolbar.js [ Failure Pass ] - # Gardener 2025-09-01 crbug.com/442030691 compositing/video/video-poster.html [ Failure Pass ] # Gardener 2025-09-05 crbug.com/443161677 [ Win11-arm64 ] http/tests/inspector-protocol/network/get-durable-response-gzip-body.js [ Failure Timeout ] - -# Temporarily disabled because RenderDocument is not enabled on mac bots just yet. -# TODO(crbug.com/40615943): Re-enable this test once RenderDocument is enabled on mac bots. -crbug.com/40615943 [ Mac ] http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-blocklisted-features-same-site.js [ Failure ] +crbug.com/443203688 external/wpt/accname/name/comp_name_from_content.html [ Failure Pass ] +crbug.com/443229243 inspector-protocol/page/reload-with-script.js [ Failure Pass ]
diff --git a/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-responsive.js b/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-responsive.js index 8be7de0..50fbcb7 100644 --- a/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-responsive.js +++ b/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-responsive.js
@@ -6,7 +6,7 @@ import {DeviceModeTestRunner} from 'device_mode_test_runner'; import * as Emulation from 'devtools/panels/emulation/emulation.js'; -import * as UIModule from 'devtools/ui/legacy/legacy.js'; +import * as Geometry from 'devtools/models/geometry/geometry.js' (async function() { TestRunner.addResult(`Test that device mode's responsive mode behaves correctly when adjusting inputs.\n`); @@ -17,7 +17,7 @@ var view = new Emulation.DeviceModeView.DeviceModeView(); var toolbar = view.toolbar; var model = view.model; - var viewportSize = new UIModule.Geometry.Size(320, 480); + var viewportSize = new Geometry.Size(320, 480); model.setAvailableSize(viewportSize, viewportSize); TestRunner.addResult(
diff --git a/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-switching-devices.js b/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-switching-devices.js index 6e34082..28d0830f 100644 --- a/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-switching-devices.js +++ b/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-switching-devices.js
@@ -6,7 +6,7 @@ import {DeviceModeTestRunner} from 'device_mode_test_runner'; import * as Emulation from 'devtools/panels/emulation/emulation.js'; -import * as UIModule from 'devtools/ui/legacy/legacy.js'; +import * as Geometry from 'devtools/models/geometry/geometry.js' (async function() { TestRunner.addResult(`Test preservation of orientation and scale when that switching devices in device mode.\n`); @@ -24,7 +24,7 @@ var view = new Emulation.DeviceModeView.DeviceModeView(); var toolbar = view.toolbar; var model = view.model; - var viewportSize = new UIModule.Geometry.Size(800, 600); + var viewportSize = new Geometry.Size(800, 600); model.setAvailableSize(viewportSize, viewportSize); TestRunner.addResult('\nTest that devices automatically zoom to fit.');
diff --git a/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-toolbar.js b/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-toolbar.js index 45ad862..01beda6 100644 --- a/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-toolbar.js +++ b/third_party/blink/web_tests/http/tests/devtools/device-mode/device-mode-toolbar.js
@@ -7,7 +7,7 @@ import * as Emulation from 'devtools/panels/emulation/emulation.js'; import * as EmulationModel from 'devtools/models/emulation/emulation.js'; -import * as UIModule from 'devtools/ui/legacy/legacy.js'; +import * as Geometry from 'devtools/models/geometry/geometry.js' (async function() { TestRunner.addResult(`Test toolbar state when switching modes.\n`); @@ -16,7 +16,7 @@ var view = new Emulation.DeviceModeView.DeviceModeView(); var toolbar = view.toolbar; var model = view.model; - var viewportSize = new UIModule.Geometry.Size(800, 600); + var viewportSize = new Geometry.Size(800, 600); model.setAvailableSize(viewportSize, viewportSize); // Check that default model has type None.
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-blocklisted-features-same-site-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-blocklisted-features-same-site-expected.txt index 91004f2..92bf4f5 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-blocklisted-features-same-site-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-blocklisted-features-same-site-expected.txt
@@ -33,10 +33,6 @@ loaderId : <string> notRestoredExplanations : [ [0] : { - reason : HTTPStatusNotOK - type : Circumstantial - } - [1] : { reason : BrowsingInstanceNotSwapped type : Circumstantial } @@ -46,10 +42,6 @@ ] explanations : [ [0] : { - reason : HTTPStatusNotOK - type : Circumstantial - } - [1] : { reason : BrowsingInstanceNotSwapped type : Circumstantial }
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index e5b234e..2a74451 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit e5b234e858cfd029bf8eafa13455f80f460643f2 +Subproject commit 2a744510a5faabae24e3c6d2ca34928f91392653
diff --git a/third_party/perfetto b/third_party/perfetto index 313e4b6..55c5924 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 313e4b6b9117daa3241863a5ce31c203c218164a +Subproject commit 55c592489062e1569fddcc59a4b9b5479a6b988f
diff --git a/third_party/skia b/third_party/skia index 2a9fe9c..845ec12 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 2a9fe9cde3e8e2184db9c225b638dabc1debd5fa +Subproject commit 845ec125e94ce32aa235aeca99409dabf15f9f76
diff --git a/third_party/webrtc b/third_party/webrtc index d7169bf..8d31c4a 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit d7169bf89fc40930c49e083ec7969dfdd7650407 +Subproject commit 8d31c4add2eb4685afff353a35b705b089d5f21f
diff --git a/tools/clang/spanify/Spanifier.cpp b/tools/clang/spanify/Spanifier.cpp index 90a315e7..94a2b6d 100644 --- a/tools/clang/spanify/Spanifier.cpp +++ b/tools/clang/spanify/Spanifier.cpp
@@ -168,12 +168,13 @@ parm_var_decl_matcher) { const clang::FunctionDecl& function_decl = Node; - unsigned num_params = function_decl.getNumParams(); + const unsigned num_params = function_decl.getNumParams(); bool is_matching = false; clang::ast_matchers::internal::BoundNodesTreeBuilder result; for (unsigned i = 0; i < num_params; i++) { const clang::ParmVarDecl* param = function_decl.getParamDecl(i); - clang::ast_matchers::internal::BoundNodesTreeBuilder param_matches; + clang::ast_matchers::internal::BoundNodesTreeBuilder param_matches( + *Builder); if (parm_var_decl_matcher.matches(*param, Finder, ¶m_matches)) { is_matching = true; result.addMatch(param_matches); @@ -733,6 +734,40 @@ assert(false && "Unexpected match in getSourceRange()"); } +// Unwraps typedef type locs and/or elaborated type locs, and returns the body +// type loc. +// +// Note that using-declared types are also represented with typedef types in +// clang, so this function works for both 'typedef' and 'using' declarations. +// +// Example TypeLoc structures: +// // Given T2 where typedef int T1; using T2 = T1; +// ElaboratedTypeLoc('T2') +// --(getNamedTypeLoc)--> TypedefTypeLoc('T2') +// --(getTypedefNameDecl)--> ElaboratedTypeLoc('T1') +// --(getNamedTypeLoc)--> TypedefTypeLoc('T1') +// --(getTypedefNameDecl)--> BuiltinTypeLoc('int') +// => returns BuiltinTypeLoc('int'). +// +// // Given base::raw_ptr<int>, +// ElaboratedTypeLoc('base::raw_ptr<int>') +// --(getNamedTypeLoc)--> TemplateSpecializationTypeLoc('raw_ptr<int>') +// --(getArgLoc)--> TemplateArgumentLoc('int') +// => returns TemplateSpecializationTypeLoc('raw_ptr<int>'). +clang::TypeLoc UnwrapTypedefTypeLoc(clang::TypeLoc type_loc) { + while (const clang::ElaboratedTypeLoc elaborated_type_loc = + type_loc.getAs<clang::ElaboratedTypeLoc>()) { + type_loc = elaborated_type_loc.getNamedTypeLoc(); + if (const clang::TypedefTypeLoc typedef_type_loc = + type_loc.getAs<clang::TypedefTypeLoc>()) { + const clang::TypedefNameDecl* typedef_name_decl = + typedef_type_loc.getTypedefNameDecl(); + type_loc = typedef_name_decl->getTypeSourceInfo()->getTypeLoc(); + } + } + return type_loc; +} + std::string getNodeFromPointerTypeLoc(const clang::PointerTypeLoc* type_loc, const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; @@ -2587,6 +2622,88 @@ EmitEdge(rhs, lhs); } +// When a function declaration (= function type) gets rewritten, rewrites +// variables of a function pointer type to which the function is assigned. +// +// Example: +// // function declaration being spanified +// int* func(int* arg); +// // function pointer variable to be spanified +// int* (*var)(int* arg) = func; +// In the following implementation, `var` is called LHS and `func` is called +// RHS. +// +// Tests are in: func-ptr-var-original.cc +void RewriteFunctionPointerType(const MatchFinder::MatchResult& result) { + const clang::VarDecl* lhs_var_decl = GetNodeOrCrash<clang::VarDecl>( + result, "lhs_funcptrvardecl", + "The rewriting target variable of function pointer type must be bound."); + + // Get the FunctionProtoTypeLoc of the LHS variable. + clang::FunctionProtoTypeLoc lhs_func_proto_type_loc; + { + const clang::TypeLoc var_type_loc = + UnwrapTypedefTypeLoc(lhs_var_decl->getTypeSourceInfo()->getTypeLoc()); + if (var_type_loc.getAs<clang::AutoTypeLoc>() || + var_type_loc.getAs<clang::DecltypeTypeLoc>()) { + return; // No need to rewrite auto/decltype types. + } + const clang::PointerTypeLoc pointer_type_loc = + var_type_loc.getAs<clang::PointerTypeLoc>(); + assert(pointer_type_loc && "Failed to get a PointerTypeLoc."); + clang::TypeLoc pointee_type_loc = pointer_type_loc.getPointeeLoc(); + // Unwrap paren type locs. + while (clang::ParenTypeLoc paren_type_loc = + pointee_type_loc.getAs<clang::ParenTypeLoc>()) { + pointee_type_loc = paren_type_loc.getInnerLoc(); + } + lhs_func_proto_type_loc = + pointee_type_loc.getAs<clang::FunctionProtoTypeLoc>(); + } + assert(lhs_func_proto_type_loc && "Failed to get a FunctionProtoTypeLoc."); + + // RHS matches with one of the parameter types or the return type of the + // function declaration. Rewrite the one matched. + const std::string& rhs_key = GetRHS(result); + + // LHS matches with the function pointer type variable (not a parameter type + // nor return type unlike RHS). Find the parameter or return type + // corresponding to the RHS match, and rewrite it. + std::string lhs_key; + if (const clang::ParmVarDecl* rhs_parm_var_decl = + result.Nodes.getNodeAs<clang::ParmVarDecl>("rhs_begin")) { + // One of the function parameter types matches on RHS. + const unsigned parm_index = rhs_parm_var_decl->getFunctionScopeIndex(); + const clang::ParmVarDecl* lhs_parm_var_decl = + lhs_func_proto_type_loc.getParam(parm_index); + const clang::TypeLoc lhs_parm_type_loc = UnwrapTypedefTypeLoc( + lhs_parm_var_decl->getTypeSourceInfo()->getTypeLoc()); + if (lhs_parm_type_loc.getAs<clang::ArrayTypeLoc>()) { + lhs_key = getNodeFromFunctionArrayParameter(&lhs_parm_type_loc, + lhs_parm_var_decl, result); + } else if (lhs_parm_type_loc.getAs<clang::PointerTypeLoc>()) { + lhs_key = getNodeFromDecl(lhs_parm_var_decl, result); + } else if (const clang::TemplateSpecializationTypeLoc lhs_raw_ptr_type_loc = + lhs_parm_type_loc + .getAs<clang::TemplateSpecializationTypeLoc>()) { + lhs_key = getNodeFromRawPtrTypeLoc(&lhs_raw_ptr_type_loc, result); + } else { + assert(false && "Unknown kind of clang::TypeLoc at `lhs_parm_type_loc`"); + } + } else { + // The function return type matches on RHS. + const clang::PointerTypeLoc lhs_return_type_loc = + lhs_func_proto_type_loc.getReturnLoc().getAs<clang::PointerTypeLoc>(); + assert(lhs_return_type_loc); + lhs_key = getNodeFromPointerTypeLoc(&lhs_return_type_loc, result); + } + + // Whenever RHS (function type) is rewritten, LHS (function pointer type) + // should be rewritten, too. + EmitEdge(lhs_key, rhs_key); + EmitEdge(rhs_key, lhs_key); +} + // Spanifies the matched function parameter/return type, and connects relevant // function declarations (forward declarations and overridden methods) to each // other bidirectionally per the matched function parameter/return type. Note @@ -2640,7 +2757,7 @@ // // A: Yes, it does suffice. But it's hard to build because GetRHS takes // `result` as the argument. When we find a match for arg1 at [2], we no longer -// have `result` for arg1 at [1]. It's easier to create node_arg1_{1st,2nd] than +// have `result` for arg1 at [1]. It's easier to create node_arg1_{1st,2nd} than // saving the results of GetRHS somewhere and retrieving it. void RewriteFunctionParamAndReturnType(const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; @@ -3379,7 +3496,7 @@ // a = fct(); // a = reinterpret_cast<>(b); // a = (cond) ? expr1 : expr2; - auto assignement_relationship = traverse( + auto assignment_relationship = traverse( clang::TK_IgnoreUnlessSpelledInSource, binaryOperation(hasOperatorName("="), hasOperands(lhs_expr_variations, @@ -3387,18 +3504,18 @@ conditionalOperator(hasTrueExpression( rhs_expr_variations)))), unless(isExpansionInSystemHeader()))); - Match(assignement_relationship, MatchAdjacency); + Match(assignment_relationship, MatchAdjacency); // Creates the edge from lhs to false_expr in a ternary conditional // operator. - auto assignement_relationship2 = traverse( + auto assignment_relationship2 = traverse( clang::TK_IgnoreUnlessSpelledInSource, binaryOperation(hasOperatorName("="), hasOperands(lhs_expr_variations, conditionalOperator(hasFalseExpression( rhs_expr_variations))), unless(isExpansionInSystemHeader()))); - Match(assignement_relationship2, MatchAdjacency); + Match(assignment_relationship2, MatchAdjacency); // Supports: // T* temp = member; @@ -3418,17 +3535,6 @@ unless(isExpansionInSystemHeader()))); Match(var_construction, MatchAdjacency); - // Supports: - // it == std::begin(c_array) - // it != std::end(c_array) - auto equality_op = - traverse(clang::TK_IgnoreUnlessSpelledInSource, - binaryOperation( - anyOf(hasOperatorName("=="), hasOperatorName("!=")), - hasOperands(ignoringParenCasts(lhs_expr_variations), - ignoringParenCasts(c_array_iter_call_expr)))); - Match(equality_op, RewriteComparisonWithCArrayIter); - // Creates the edge from lhs to false_expr in a ternary conditional // operator. auto var_construction2 = traverse( @@ -3443,6 +3549,17 @@ Match(var_construction2, MatchAdjacency); // Supports: + // it == std::begin(c_array) + // it != std::end(c_array) + auto equality_op = + traverse(clang::TK_IgnoreUnlessSpelledInSource, + binaryOperation( + anyOf(hasOperatorName("=="), hasOperatorName("!=")), + hasOperands(ignoringParenCasts(lhs_expr_variations), + ignoringParenCasts(c_array_iter_call_expr)))); + Match(equality_op, RewriteComparisonWithCArrayIter); + + // Supports: // return member; // return fct(); // return reinterpret_cast(expr); @@ -3545,20 +3662,58 @@ unless(cxxOperatorCallExpr(hasOperatorName("="))))); Match(call_expr, MatchAdjacency); + // Function pointer types to arbitrary function types, including typedef + // types and using-aliased types to function pointer types. No restriction + // to parameter types and return type, but the following queries require + // the function type to be compatible with the RHS function type. + auto fct_ptr_type = type(hasUnqualifiedDesugaredType( + pointerType(pointee(ignoringParens(functionProtoType()))))); + + // Function declaration with pointer/array/raw_ptr parameter types and/or + // pointer return type. + // + // Note that this query matches each of parameter types and return type + // respectively. + auto fct_decl = + functionDecl( + eachOf(forEachParmVarDecl(rhs_param), + hasReturnTypeLoc(pointer_type_loc.bind("rhs_type_loc"))), + unless(exclusions)) + .bind("fct_decl"); + auto fct_decl_expr = expr(ignoringParenCasts(declRefExpr(to(fct_decl)))); + + // Supports: + // void (*var)(int*) = func; + // int* (*var)() = func; + // and equivalent typedef/using variants like: + // using FuncType = void (*)(int*); + // FuncType var = func; + auto fct_ptr_var_construction = traverse( + clang::TK_IgnoreUnlessSpelledInSource, + varDecl(hasType(fct_ptr_type), has(fct_decl_expr), unless(exclusions)) + .bind("lhs_funcptrvardecl")); + Match(fct_ptr_var_construction, RewriteFunctionPointerType); + + // Supports: + // void (*var)(int*); var = func; + // int* (*var)(); var = func; + // and equivalent typedef/using variants like: + // typedef int* (*FuncType)(); + // FuncType var; + // var = func; + auto fct_ptr_var_assignment = traverse( + clang::TK_IgnoreUnlessSpelledInSource, + binaryOperator(hasOperatorName("="), + hasLHS(declRefExpr( + to(varDecl(hasType(fct_ptr_type), unless(exclusions)) + .bind("lhs_funcptrvardecl")))), + hasRHS(fct_decl_expr))); + Match(fct_ptr_var_assignment, RewriteFunctionPointerType); + // Map function declaration signature to function definition signature; // This is problematic in the case of callbacks defined in function. - auto fct_decls_params = - traverse(clang::TK_IgnoreUnlessSpelledInSource, - functionDecl(forEachParmVarDecl(rhs_param), unless(exclusions)) - .bind("fct_decl")); - Match(fct_decls_params, RewriteFunctionParamAndReturnType); - - auto fct_decls_returns = traverse( - clang::TK_IgnoreUnlessSpelledInSource, - functionDecl(hasReturnTypeLoc(pointer_type_loc.bind("rhs_type_loc")), - unless(exclusions)) - .bind("fct_decl")); - Match(fct_decls_returns, RewriteFunctionParamAndReturnType); + auto fct_decls = traverse(clang::TK_IgnoreUnlessSpelledInSource, fct_decl); + Match(fct_decls, RewriteFunctionParamAndReturnType); } private:
diff --git a/tools/clang/spanify/tests/func-ptr-var-expected.cc b/tools/clang/spanify/tests/func-ptr-var-expected.cc new file mode 100644 index 0000000..53218a2 --- /dev/null +++ b/tools/clang/spanify/tests/func-ptr-var-expected.cc
@@ -0,0 +1,197 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/containers/span.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" + +int UnsafeIndex(); // This function might return an out-of-bound index. + +// Expected rewrite: +// void FuncArg1Arr(base::span<int, 3> arg1) { +void FuncArg1Arr(base::span<int, 3> arg1) { + arg1[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// void FuncArg2Arr(int arg1, base::span<int, 3> arg2) { +void FuncArg2Arr(int arg1, base::span<int, 3> arg2) { + arg2[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// void FuncArg1Ptr(base::span<int> arg1) { +void FuncArg1Ptr(base::span<int> arg1) { + arg1[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// void FuncArg2Ptr(int arg1, base::span<int> arg2) { +void FuncArg2Ptr(int arg1, base::span<int> arg2) { + arg2[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// base::span<int> FuncRet() { +base::span<int> FuncRet() { + static int arr[] = {1, 2, 3}; + return arr; +} + +// Expected rewrite: +// base::span<int> FuncAll(base::span<int, 3> arg1, +// base::span<int> arg2, +// base::base::raw_span<int> arg3) { +base::span<int> FuncAll(base::span<int, 3> arg1, + base::span<int> arg2, + base::base::raw_span<int> arg3) { + arg1[UnsafeIndex()] = 3; + arg2[UnsafeIndex()] = 3; + arg3[UnsafeIndex()] = 3; + static int arr[] = {1, 2, 3}; + return arr; +} + +void test_type_alias() { + int arr[] = {1, 2, 3}; + + // TODO(yukishiino): Currently the following line is needed to get FuncRet + // spanified. This shouldn't be needed because we have other unsafe usages + // through function pointers. + FuncRet()[UnsafeIndex()] = 3; + FuncAll(arr, arr, arr)[UnsafeIndex()] = 3; + + // Without a typedef / using declaration + { + // Expected rewrite: + // void (*p_arg1arr_init)(base::span<int, 3> arg1) = FuncArg1Arr; + void (*p_arg1arr_init)(base::span<int, 3> arg1) = FuncArg1Arr; + p_arg1arr_init(arr); + + // Expected rewrite: + // void (*p_arg2ptr_assign)(int arg1, base::span<int> arg2); + void (*p_arg2ptr_assign)(int arg1, base::span<int> arg2); + p_arg2ptr_assign = FuncArg2Ptr; + p_arg2ptr_assign(3, arr); + + // Expected rewrite: + // void (*p_arg2arr_init)(int, base::span<int, 3>) = FuncArg2Arr; + void (*p_arg2arr_init)(int, base::span<int, 3>) = FuncArg2Arr; + p_arg2arr_init(3, arr); + + // Expected rewrite: + // base::span<int> (*p_ret_init)() = FuncRet; + base::span<int> (*p_ret_init)() = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_init = ... + int* ret_init = p_ret_init(); + ret_init[UnsafeIndex()] = 3; + + // Expected rewrite: + // base::span<int> (*p_ret_assign)(); + base::span<int> (*p_ret_assign)(); + p_ret_assign = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_assign = ... + int* ret_assign = p_ret_assign(); + ret_assign[UnsafeIndex()] = 3; + } + + // With typedef declarations + { + // Expected rewrite: + // typedef void (*Arg1ArrType)(base::span<int, 3> arg1); + typedef void (*Arg1ArrType)(base::span<int, 3> arg1); + Arg1ArrType p_arg1arr_init = FuncArg1Arr; + p_arg1arr_init(arr); + + // Expected rewrite: + // typedef void (*Arg2PtrType)(int arg1, base::span<int> arg2); + typedef void (*Arg2PtrType)(int arg1, base::span<int> arg2); + Arg2PtrType p_arg2ptr_assign; + p_arg2ptr_assign = FuncArg2Ptr; + p_arg2ptr_assign(3, arr); + + // Expected rewrite: + // typedef void (*Arg2ArrType)(int, base::span<int, 3>); + typedef void (*Arg2ArrType)(int, base::span<int, 3>); + Arg2ArrType p_arg2arr_init = FuncArg2Arr; + p_arg2arr_init(3, arr); + + // Expected rewrite: + // typedef base::span<int> (*RetInitType)(); + typedef base::span<int> (*RetInitType)(); + RetInitType p_ret_init = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_init = ... + int* ret_init = p_ret_init(); + ret_init[UnsafeIndex()] = 3; + + // Expected rewrite: + // typedef base::span<int> (*RetAssignType)(); + typedef base::span<int> (*RetAssignType)(); + RetAssignType p_ret_assign; + p_ret_assign = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_assign = ... + int* ret_assign = p_ret_assign(); + ret_assign[UnsafeIndex()] = 3; + } + + // With using declarations + { + // Expected rewrite: + // using Arg1ArrType = void (*)(base::span<int, 3> arg1); + using Arg1ArrType = void (*)(base::span<int, 3> arg1); + Arg1ArrType p_arg1arr_init = FuncArg1Arr; + p_arg1arr_init(arr); + + // Expected rewrite: + // using Arg2PtrType = void (*)(int arg1, base::span<int> arg2); + using Arg2PtrType = void (*)(int arg1, base::span<int> arg2); + Arg2PtrType p_arg2ptr_assign; + p_arg2ptr_assign = FuncArg2Ptr; + p_arg2ptr_assign(3, arr); + + // Expected rewrite: + // using Arg2ArrType = void (*)(int, base::span<int, 3>); + using Arg2ArrType = void (*)(int, base::span<int, 3>); + Arg2ArrType p_arg2arr_init = FuncArg2Arr; + p_arg2arr_init(3, arr); + + // Expected rewrite: + // using RetInitType = base::span<int> (*)(); + using RetInitType = base::span<int> (*)(); + RetInitType p_ret_init = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_init = ... + int* ret_init = p_ret_init(); + ret_init[UnsafeIndex()] = 3; + + // Expected rewrite: + // using RetAssignType = base::span<int> (*)(); + using RetAssignType = base::span<int> (*)(); + RetAssignType p_ret_assign; + p_ret_assign = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_assign = ... + int* ret_assign = p_ret_assign(); + ret_assign[UnsafeIndex()] = 3; + } + + // With nested typedef/using and multiple rewritings on the func ptr type + { + // Expected rewrite: + // typedef base::span<int> (*AllType1)(base::span<int, 3> arg1, + // base::span<int> arg2, + // base::base::raw_span<int> arg3); + typedef base::span<int> (*AllType1)(base::span<int, 3> arg1, + base::span<int> arg2, + base::base::raw_span<int> arg3); + using AllType2 = AllType1; + AllType2 p_all = FuncAll; + int* ret_all = p_all(arr, arr, arr); + ret_all[UnsafeIndex()] = 3; + } +}
diff --git a/tools/clang/spanify/tests/func-ptr-var-original.cc b/tools/clang/spanify/tests/func-ptr-var-original.cc new file mode 100644 index 0000000..fcaefcf --- /dev/null +++ b/tools/clang/spanify/tests/func-ptr-var-original.cc
@@ -0,0 +1,191 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/raw_ptr.h" + +int UnsafeIndex(); // This function might return an out-of-bound index. + +// Expected rewrite: +// void FuncArg1Arr(base::span<int, 3> arg1) { +void FuncArg1Arr(int arg1[3]) { + arg1[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// void FuncArg2Arr(int arg1, base::span<int, 3> arg2) { +void FuncArg2Arr(int arg1, int arg2[3]) { + arg2[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// void FuncArg1Ptr(base::span<int> arg1) { +void FuncArg1Ptr(int* arg1) { + arg1[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// void FuncArg2Ptr(int arg1, base::span<int> arg2) { +void FuncArg2Ptr(int arg1, int* arg2) { + arg2[UnsafeIndex()] = 3; +} + +// Expected rewrite: +// base::span<int> FuncRet() { +int* FuncRet() { + static int arr[] = {1, 2, 3}; + return arr; +} + +// Expected rewrite: +// base::span<int> FuncAll(base::span<int, 3> arg1, +// base::span<int> arg2, +// base::base::raw_span<int> arg3) { +int* FuncAll(int arg1[3], int* arg2, base::raw_ptr<int> arg3) { + arg1[UnsafeIndex()] = 3; + arg2[UnsafeIndex()] = 3; + arg3[UnsafeIndex()] = 3; + static int arr[] = {1, 2, 3}; + return arr; +} + +void test_type_alias() { + int arr[] = {1, 2, 3}; + + // TODO(yukishiino): Currently the following line is needed to get FuncRet + // spanified. This shouldn't be needed because we have other unsafe usages + // through function pointers. + FuncRet()[UnsafeIndex()] = 3; + FuncAll(arr, arr, arr)[UnsafeIndex()] = 3; + + // Without a typedef / using declaration + { + // Expected rewrite: + // void (*p_arg1arr_init)(base::span<int, 3> arg1) = FuncArg1Arr; + void (*p_arg1arr_init)(int arg1[3]) = FuncArg1Arr; + p_arg1arr_init(arr); + + // Expected rewrite: + // void (*p_arg2ptr_assign)(int arg1, base::span<int> arg2); + void (*p_arg2ptr_assign)(int arg1, int* arg2); + p_arg2ptr_assign = FuncArg2Ptr; + p_arg2ptr_assign(3, arr); + + // Expected rewrite: + // void (*p_arg2arr_init)(int, base::span<int, 3>) = FuncArg2Arr; + void (*p_arg2arr_init)(int, int[3]) = FuncArg2Arr; + p_arg2arr_init(3, arr); + + // Expected rewrite: + // base::span<int> (*p_ret_init)() = FuncRet; + int* (*p_ret_init)() = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_init = ... + int* ret_init = p_ret_init(); + ret_init[UnsafeIndex()] = 3; + + // Expected rewrite: + // base::span<int> (*p_ret_assign)(); + int* (*p_ret_assign)(); + p_ret_assign = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_assign = ... + int* ret_assign = p_ret_assign(); + ret_assign[UnsafeIndex()] = 3; + } + + // With typedef declarations + { + // Expected rewrite: + // typedef void (*Arg1ArrType)(base::span<int, 3> arg1); + typedef void (*Arg1ArrType)(int arg1[3]); + Arg1ArrType p_arg1arr_init = FuncArg1Arr; + p_arg1arr_init(arr); + + // Expected rewrite: + // typedef void (*Arg2PtrType)(int arg1, base::span<int> arg2); + typedef void (*Arg2PtrType)(int arg1, int* arg2); + Arg2PtrType p_arg2ptr_assign; + p_arg2ptr_assign = FuncArg2Ptr; + p_arg2ptr_assign(3, arr); + + // Expected rewrite: + // typedef void (*Arg2ArrType)(int, base::span<int, 3>); + typedef void (*Arg2ArrType)(int, int[3]); + Arg2ArrType p_arg2arr_init = FuncArg2Arr; + p_arg2arr_init(3, arr); + + // Expected rewrite: + // typedef base::span<int> (*RetInitType)(); + typedef int* (*RetInitType)(); + RetInitType p_ret_init = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_init = ... + int* ret_init = p_ret_init(); + ret_init[UnsafeIndex()] = 3; + + // Expected rewrite: + // typedef base::span<int> (*RetAssignType)(); + typedef int* (*RetAssignType)(); + RetAssignType p_ret_assign; + p_ret_assign = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_assign = ... + int* ret_assign = p_ret_assign(); + ret_assign[UnsafeIndex()] = 3; + } + + // With using declarations + { + // Expected rewrite: + // using Arg1ArrType = void (*)(base::span<int, 3> arg1); + using Arg1ArrType = void (*)(int arg1[3]); + Arg1ArrType p_arg1arr_init = FuncArg1Arr; + p_arg1arr_init(arr); + + // Expected rewrite: + // using Arg2PtrType = void (*)(int arg1, base::span<int> arg2); + using Arg2PtrType = void (*)(int arg1, int* arg2); + Arg2PtrType p_arg2ptr_assign; + p_arg2ptr_assign = FuncArg2Ptr; + p_arg2ptr_assign(3, arr); + + // Expected rewrite: + // using Arg2ArrType = void (*)(int, base::span<int, 3>); + using Arg2ArrType = void (*)(int, int[3]); + Arg2ArrType p_arg2arr_init = FuncArg2Arr; + p_arg2arr_init(3, arr); + + // Expected rewrite: + // using RetInitType = base::span<int> (*)(); + using RetInitType = int* (*)(); + RetInitType p_ret_init = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_init = ... + int* ret_init = p_ret_init(); + ret_init[UnsafeIndex()] = 3; + + // Expected rewrite: + // using RetAssignType = base::span<int> (*)(); + using RetAssignType = int* (*)(); + RetAssignType p_ret_assign; + p_ret_assign = FuncRet; + // TODO(yukishiino): The following should be + // base::span<int> ret_assign = ... + int* ret_assign = p_ret_assign(); + ret_assign[UnsafeIndex()] = 3; + } + + // With nested typedef/using and multiple rewritings on the func ptr type + { + // Expected rewrite: + // typedef base::span<int> (*AllType1)(base::span<int, 3> arg1, + // base::span<int> arg2, + // base::base::raw_span<int> arg3); + typedef int* (*AllType1)(int arg1[3], int* arg2, base::raw_ptr<int> arg3); + using AllType2 = AllType1; + AllType2 p_all = FuncAll; + int* ret_all = p_all(arr, arr, arr); + ret_all[UnsafeIndex()] = 3; + } +}
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index 320bcaf..26d79fb7 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -7351,13 +7351,14 @@ </histogram> <histogram name="Media.VideoCaptureManager.DesktopCaptureImplementationAndType" - enum="DesktopCaptureImplementationAndType" expires_after="2025-07-27"> + enum="DesktopCaptureImplementationAndType" expires_after="2026-09-01"> <owner>handellm@google.com</owner> <owner>ccameron@chromium.org</owner> <summary> Indicates which desktop capture implementation and DesktopID::Type was used for a desktop capture session. Recorded on instantiation of the desktop - capturer. + capturer. Warning: this histogram was expired from 2025-07-27 to 2025-09-05; + data may be missing. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index cf241b7..30facf1 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -277,6 +277,25 @@ </summary> </histogram> +<histogram name="BackForwardCache.CCNS.CookieChangeInfo.{CountType}" + units="count" expires_after="2026-01-20"> + <owner>leimy@chromium.org</owner> + <owner>bfcache-dev@chromium.org</owner> + <summary> + Logs the {CountType} cookie change details for a page. + + This is recorded during navigation away from any page configured with + Cache-Control: no-store, at the moment the browser checks if the page can be + stored in the BFCache. + </summary> + <token key="CountType"> + <variant name="AllCookies"/> + <variant name="AllCookiesFromMainFrameNavigation"/> + <variant name="HttpOnlyCookies"/> + <variant name="HttpOnlyCookiesFromMainFrameNavigation"/> + </token> +</histogram> + <histogram name="BackForwardCache.EvictedAfterDocumentRestoredReason" enum="BackForwardCacheEvictedAfterDocumentRestoredReason" expires_after="2024-09-15">
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml index c216c0e..6651717 100644 --- a/tools/metrics/histograms/metadata/net/histograms.xml +++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -1248,14 +1248,19 @@ </token> </histogram> -<histogram name="Net.AcceptCHFrameInterceptor.MismatchClientHint" - enum="WebClientHintsType" expires_after="2026-02-01"> +<histogram name="Net.AcceptCHFrameInterceptor.MismatchClientHint2" + enum="WebClientHintsType" expires_after="2026-08-01"> <owner>yyanagisawa@chromium.org</owner> <owner>chrome-loading@google.com</owner> <summary> - Records which client hint caused the Accept-CH frame offload to fail because - the hint was not in the enabled list. This is recorded when - AcceptCHFrameInterceptor::NeedsObserverCheck returns kHintNotEnabled. + To optimize performance, the network service can handle `Accept-CH` frames + directly without consulting the browser process (an optimization called + 'offloading'). This histogram is recorded when that optimization fails. It + identifies the specific client hint from the `Accept-CH` frame that was not + in the network service's cache of hints the browser had previously + identified as either allowed or disallowed for the origin. A value is + recorded each time this mismatch occurs, forcing a fallback to the browser + process. </summary> </histogram> @@ -1270,6 +1275,22 @@ </summary> </histogram> +<histogram name="Net.AcceptCHFrameInterceptor.OffloadSuccessForNotAllowedHint" + enum="WebClientHintsType" expires_after="2026-08-01"> + <owner>yyanagisawa@chromium.org</owner> + <owner>chrome-loading@google.com</owner> + <summary> + When handling an `Accept-CH` frame, the network service can sometimes avoid + a costly round-trip to the browser process by checking for required client + hints itself (an optimization called 'offloading'). This histogram is + recorded for each client hint that was successfully offloaded specifically + because of a mechanism enabled by the AcceptCHFrameOffloadNotAllowedHints + feature parameter. This mechanism allows offloading for hints that are + persisted for an origin but currently disabled by Permissions Policy. This + metric helps measure the effectiveness of this opt-in optimization. + </summary> +</histogram> + <histogram name="Net.AlternateProtocolBrokenLocation" enum="BrokenAlternateProtocolLocation" expires_after="2024-02-25"> <owner>dschinazi@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml index 372a5d8a..04df6b50 100644 --- a/tools/metrics/histograms/metadata/page/histograms.xml +++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -4338,6 +4338,18 @@ </histogram> <histogram + name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint.ExcludeReloadAfterDiscard" + units="ms" expires_after="2026-02-28"> + <owner>fdoray@chromium.org</owner> + <owner>catan-team@chromium.org</owner> + <summary> + This is recorded at the same time and with the same value as + PageLoad.PaintTiming.NavigationToFirstContentfulPaint, but only if the + navigation isn't a post-discard reload. + </summary> +</histogram> + +<histogram name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint.Incognito" units="ms" expires_after="2026-03-01"> <owner>kjarosz@google.com</owner> @@ -4555,6 +4567,18 @@ </histogram> <histogram + name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint2.ExcludeReloadAfterDiscard" + units="ms" expires_after="2026-02-28"> + <owner>fdoray@chromium.org</owner> + <owner>catan-team@chromium.org</owner> + <summary> + This is recorded at the same time and with the same value as + PageLoad.PaintTiming.NavigationToLargestContentfulPaint2, but only if the + navigation isn't a post-discard reload. + </summary> +</histogram> + +<histogram name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint2.Incognito" units="ms" expires_after="2026-01-21"> <owner>kjarosz@google.com</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 07d22fa..b4cda88 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@ "full_remote_path": "perfetto-luci-artifacts/d17b40b3b5e36f3744f1d010fe3ba2d3c55559c0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "8cc66584154f077d1cbfd36997dc762c69b002f0", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/313e4b6b9117daa3241863a5ce31c203c218164a/trace_processor_shell.exe" + "hash": "d71b23c07437afabbfb0536e4cd93fa5a734eadf", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/10197969fa01e9ba91d58b9e0a34716533ee332f/trace_processor_shell.exe" }, "linux_arm": { "hash": "d2819bf77c3920780f2b33cc43f328d24cc1e427", @@ -22,7 +22,7 @@ }, "linux": { "hash": "09dbe5feb30a573538ea9703aea58f8e6c4570fe", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/313e4b6b9117daa3241863a5ce31c203c218164a/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/10197969fa01e9ba91d58b9e0a34716533ee332f/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc index d92879b..00e8c0df 100644 --- a/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -2461,8 +2461,8 @@ // by the root window's gesture sequence. TEST_F(GestureRecognizerTest, GestureEventOutsideRootWindowTap) { TimedEvents tes; - std::unique_ptr<aura::Window> window(CreateTestWindowWithBounds( - gfx::Rect(-100, -100, 2000, 2000), root_window())); + std::unique_ptr<aura::Window> window( + CreateTestWindow({.bounds = {-100, -100, 2000, 2000}}, root_window())); gfx::Point pos1(-10, -10); ui::TouchEvent press1(ui::EventType::kTouchPressed, pos1, tes.Now(), @@ -2656,7 +2656,7 @@ EXPECT_TRUE(delegate->tap_down()); std::unique_ptr<aura::Window> capture( - CreateTestWindowWithBounds(gfx::Rect(10, 10, 200, 200), root_window())); + CreateTestWindow({.bounds = {10, 10, 200, 200}}, root_window())); capture->SetCapture(); RunAllPendingInMessageLoop(); @@ -2712,7 +2712,7 @@ // Create a new window and set it as the new capture window. std::unique_ptr<aura::Window> window2( - CreateTestWindowWithBounds(gfx::Rect(100, 100, 300, 300), root_window())); + CreateTestWindow({.bounds = {100, 100, 300, 300}}, root_window())); window2->SetCapture(); RunAllPendingInMessageLoop(); // Check that setting capture does not generate any synthetic touch-cancels
diff --git a/ui/aura/test/test_windows.cc b/ui/aura/test/test_windows.cc index 4751680..8d0eaf0c 100644 --- a/ui/aura/test/test_windows.cc +++ b/ui/aura/test/test_windows.cc
@@ -26,13 +26,7 @@ .Build(); } -Window* CreateTestWindowWithId(int id, Window* parent) { - return CreateTestWindowWithDelegate(NULL, id, gfx::Rect(), parent); -} -Window* CreateTestWindowWithBounds(const gfx::Rect& bounds, Window* parent) { - return CreateTestWindowWithDelegate(NULL, 0, bounds, parent); -} Window* CreateTestWindow(SkColor color, int id,
diff --git a/ui/aura/test/test_windows.h b/ui/aura/test/test_windows.h index 417b905..33ffc24 100644 --- a/ui/aura/test/test_windows.h +++ b/ui/aura/test/test_windows.h
@@ -30,8 +30,6 @@ // Creates a test window. If parent window is nullptr, then the caller must take // ownership of the created window. // Deprecated: Use CreateTestWindow above. -Window* CreateTestWindowWithId(int id, Window* parent); -Window* CreateTestWindowWithBounds(const gfx::Rect& bounds, Window* parent); Window* CreateTestWindow(SkColor color, int id, const gfx::Rect& bounds,
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc index 1f0f57e..77a8d2c 100644 --- a/ui/aura/window_event_dispatcher_unittest.cc +++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -312,10 +312,12 @@ : root_window_(root_window), lock_(false) { client::SetEventClient(root_window_, this); Window* lock_window = - test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_); + test::CreateTestWindow({.bounds = root_window_->bounds()}, root_window_) + .release(); lock_window->SetId(kLockWindowId); Window* non_lock_window = - test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_); + test::CreateTestWindow({.bounds = root_window_->bounds()}, root_window_) + .release(); non_lock_window->SetId(kNonLockWindowId); } @@ -365,11 +367,13 @@ client.GetNonLockWindow()->AddPreTargetHandler(&nonlock_ef); client.GetLockWindow()->AddPreTargetHandler(&lock_ef); - Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20), - client.GetNonLockWindow()); + Window* w1 = test::CreateTestWindow({.bounds = {10, 10, 20, 20}}, + client.GetNonLockWindow()) + .release(); w1->SetId(1); - Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20), - client.GetNonLockWindow()); + Window* w2 = test::CreateTestWindow({.bounds = {30, 30, 20, 20}}, + client.GetNonLockWindow()) + .release(); w2->SetId(2); std::unique_ptr<Window> w3(test::CreateTestWindowWithDelegate( &d, 3, gfx::Rect(30, 30, 20, 20), client.GetLockWindow())); @@ -3251,8 +3255,9 @@ // Create a window which has a focus, so should receive all KeyEvents. ConsumeKeyHandler key_handler; // Not using std::unique_ptr<> intentionally - aura::Window* focused(test::CreateTestWindowWithBounds( - gfx::Rect(200, 200, 100, 100), root_window())); + aura::Window* focused = + test::CreateTestWindow({.bounds = {200, 200, 100, 100}}, root_window()) + .release(); focused->SetProperty(client::kSkipImeProcessing, true); focused->AddPostTargetHandler(&key_handler); focused->Show();
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index a77c620..794ac6b1 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc
@@ -1289,9 +1289,9 @@ TEST_F(WindowTest, GetBoundsInRootWindow) { std::unique_ptr<Window> viewport( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 300, 300), root_window())); + CreateTestWindow({.bounds{0, 0, 300, 300}}, root_window())); std::unique_ptr<Window> child( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), viewport.get())); + CreateTestWindow({.bounds = {100, 100}}, viewport.get())); // Sanity check. EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString()); @@ -1306,14 +1306,14 @@ } TEST_F(WindowTest, GetBoundsInRootWindowWithLayers) { - std::unique_ptr<Window> viewport( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 300, 300), root_window())); + std::unique_ptr<Window> viewport = + CreateTestWindow({.bounds = gfx::Rect(0, 0, 300, 300)}, root_window()); std::unique_ptr<Window> widget( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 200, 200), viewport.get())); + CreateTestWindow({.bounds = {200, 200}}, viewport.get())); std::unique_ptr<Window> child( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), widget.get())); + CreateTestWindow({.bounds = {100, 100}}, widget.get())); // Sanity check. EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString()); @@ -1333,13 +1333,13 @@ TEST_F(WindowTest, GetBoundsInRootWindowWithLayersAndTranslations) { std::unique_ptr<Window> viewport( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 300, 300), root_window())); + CreateTestWindow({.bounds = {300, 300}}, root_window())); - std::unique_ptr<Window> widget( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 200, 200), viewport.get())); + std::unique_ptr<Window> widget = + CreateTestWindow({.bounds = {200, 200}}, viewport.get()); std::unique_ptr<Window> child( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), widget.get())); + CreateTestWindow({.bounds = {100, 100}}, widget.get())); // Sanity check. EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString()); @@ -1930,7 +1930,7 @@ ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); std::unique_ptr<Window> w1( - CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window())); + CreateTestWindow({.bounds = {100, 100}}, root_window())); EXPECT_TRUE(w1->layer()); w1->layer()->GetAnimator()->set_disable_timer_for_test(true); @@ -3758,12 +3758,10 @@ // WindowTest: void SetUp() override { WindowTest::SetUp(); - viewport_ = std::unique_ptr<Window>(CreateTestWindowWithBounds( - gfx::Rect(/*x=*/100, /*y=*/50, /*width=*/200, /*height=*/200), - root_window())); - child_ = std::unique_ptr<Window>(CreateTestWindowWithBounds( - gfx::Rect(/*x=*/0, /*y=*/0, /*width=*/100, /*height*/ 100), - viewport_.get())); + viewport_ = std::unique_ptr<Window>( + CreateTestWindow({.bounds = {100, 50, 200, 200}}, root_window())); + child_ = std::unique_ptr<Window>( + CreateTestWindow({.bounds = {100, 100}}, viewport_.get())); } void TearDown() override {
diff --git a/ui/base/models/image_model_utils.cc b/ui/base/models/image_model_utils.cc index 48960501..0644ec1 100644 --- a/ui/base/models/image_model_utils.cc +++ b/ui/base/models/image_model_utils.cc
@@ -14,8 +14,9 @@ namespace ui { // TODO(dpenning) consider parameterizing color choices for disabled defaults. -ImageModel GetDefaultDisabledIconFromImageModel(ImageModel icon_model, - ColorProvider* color_provider) { +ImageModel GetDefaultDisabledIconFromImageModel( + ImageModel icon_model, + const ColorProvider* color_provider) { if (icon_model.IsEmpty()) { return icon_model; }
diff --git a/ui/base/models/image_model_utils.h b/ui/base/models/image_model_utils.h index 7fe4a3b..798dc056 100644 --- a/ui/base/models/image_model_utils.h +++ b/ui/base/models/image_model_utils.h
@@ -13,7 +13,7 @@ COMPONENT_EXPORT(UI_BASE) ImageModel GetDefaultDisabledIconFromImageModel(ImageModel icon, - ColorProvider* = nullptr); + const ColorProvider* = nullptr); } // namespace ui
diff --git a/ui/wm/core/coordinate_conversion_unittest.cc b/ui/wm/core/coordinate_conversion_unittest.cc index 7beabf5..b9126bb 100644 --- a/ui/wm/core/coordinate_conversion_unittest.cc +++ b/ui/wm/core/coordinate_conversion_unittest.cc
@@ -13,23 +13,23 @@ typedef aura::test::AuraTestBase CoordinateConversionTest; TEST_F(CoordinateConversionTest, ConvertRect) { - aura::Window* w = aura::test::CreateTestWindowWithBounds( - gfx::Rect(10, 20, 100, 200), root_window()); + std::unique_ptr<aura::Window> w(aura::test::CreateTestWindow( + {.bounds = {10, 20, 100, 200}}, root_window())); gfx::Rect r1(10, 20, 100, 120); - ConvertRectFromScreen(w, &r1); + ConvertRectFromScreen(w.get(), &r1); EXPECT_EQ("0,0 100x120", r1.ToString()); gfx::Rect r2(0, 0, 100, 200); - ConvertRectFromScreen(w, &r2); + ConvertRectFromScreen(w.get(), &r2); EXPECT_EQ("-10,-20 100x200", r2.ToString()); gfx::Rect r3(30, 30, 100, 200); - ConvertRectToScreen(w, &r3); + ConvertRectToScreen(w.get(), &r3); EXPECT_EQ("40,50 100x200", r3.ToString()); gfx::Rect r4(-10, -20, 100, 200); - ConvertRectToScreen(w, &r4); + ConvertRectToScreen(w.get(), &r4); EXPECT_EQ("0,0 100x200", r4.ToString()); }
diff --git a/ui/wm/core/ime_util_chromeos_unittest.cc b/ui/wm/core/ime_util_chromeos_unittest.cc index 58af313..b34334f 100644 --- a/ui/wm/core/ime_util_chromeos_unittest.cc +++ b/ui/wm/core/ime_util_chromeos_unittest.cc
@@ -20,7 +20,7 @@ TEST_F(ImeUtilChromeosTest, RestoreWindowBounds) { const gfx::Rect bounds(10, 20, 100, 200); aura::Window* window = - aura::test::CreateTestWindowWithBounds(bounds, root_window()); + aura::test::CreateTestWindow({.bounds = bounds}, root_window()).release(); EXPECT_EQ(nullptr, window->GetProperty(kVirtualKeyboardRestoreBoundsKey)); EXPECT_EQ(bounds, window->bounds()); @@ -38,7 +38,7 @@ TEST_F(ImeUtilChromeosTest, EnsureWindowNotInRect_NotCovered) { const gfx::Rect bounds(0, 0, 100, 200); aura::Window* window = - aura::test::CreateTestWindowWithBounds(bounds, root_window()); + aura::test::CreateTestWindow({.bounds = bounds}, root_window()).release(); EXPECT_EQ(bounds, window->bounds()); EXPECT_EQ(bounds, window->GetBoundsInScreen()); @@ -54,7 +54,8 @@ TEST_F(ImeUtilChromeosTest, EnsureWindowNotInRect_MoveUp) { const gfx::Rect original_bounds(10, 100, 100, 10); aura::Window* window = - aura::test::CreateTestWindowWithBounds(original_bounds, root_window()); + aura::test::CreateTestWindow({.bounds = original_bounds}, root_window()) + .release(); EXPECT_EQ(original_bounds, window->bounds()); EXPECT_EQ(original_bounds, window->GetBoundsInScreen()); @@ -71,7 +72,8 @@ TEST_F(ImeUtilChromeosTest, EnsureWindowNotInRect_MoveToTop) { const gfx::Rect original_bounds(10, 10, 100, 100); aura::Window* window = - aura::test::CreateTestWindowWithBounds(original_bounds, root_window()); + aura::test::CreateTestWindow({.bounds = original_bounds}, root_window()) + .release(); EXPECT_EQ(original_bounds, window->bounds()); EXPECT_EQ(original_bounds, window->GetBoundsInScreen()); @@ -100,7 +102,8 @@ TEST_F(ImeUtilChromeosTest, MoveUpThenRestore) { const gfx::Rect original_bounds(50, 50, 100, 100); aura::Window* window = - aura::test::CreateTestWindowWithBounds(original_bounds, root_window()); + aura::test::CreateTestWindow({.bounds = original_bounds}, root_window()) + .release(); EXPECT_EQ(original_bounds, window->bounds()); EXPECT_EQ(original_bounds, window->GetBoundsInScreen());
diff --git a/ui/wm/core/shadow_controller_unittest.cc b/ui/wm/core/shadow_controller_unittest.cc index 2f9d469e..c2f0317 100644 --- a/ui/wm/core/shadow_controller_unittest.cc +++ b/ui/wm/core/shadow_controller_unittest.cc
@@ -127,7 +127,7 @@ TEST_F(ShadowControllerTest, ShadowBoundsDetached) { const gfx::Rect kInitialBounds(20, 30, 400, 300); std::unique_ptr<aura::Window> window( - aura::test::CreateTestWindowWithBounds(kInitialBounds, root_window())); + aura::test::CreateTestWindow({.bounds = kInitialBounds}, root_window())); window->Show(); const ui::Shadow* shadow = ShadowController::GetShadowForWindow(window.get()); ASSERT_TRUE(shadow);